Spring-Cloud(Finchley.SR1)でspring-boot(2.0.5)を試し、検出サーバーとしてEurekaを使用し、クライアントとしてFeign/Ribbonを使用して2つのサービス間の通信をセットアップしようとしています。セットアップは非常に簡単です(私が試したさまざまなことや他の答えによって少し混乱していますが):
Eurekaのapplication.yml
spring:
application:
name: eureka-service
server:
port: 8761
eureka:
instance:
hostname: localhost
preferIpAddress: true
client:
registerWithEureka: false
fetchRegistry: false
serviceUrl:
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka
2番目のサービスのbootstrap.yml
spring:
application:
name: secondservice
eureka:
instance:
hostname: ${spring.application.name}
preferIpAddress: true
instanceId: ${spring.application.name}:${spring.application.instance_id:${random.value}}
statusPageUrlPath: ${server.servlet.context-path}/actuator/info
healthCheckUrlPath: ${server.servlet.context-path}/actuator/health
leaseRenewalIntervalInSeconds: 15
leaseExpirationDurationInSeconds: 45
metadata-map:
server.servlet.context-path: ${server.servlet.context-path}
client:
enabled: true
serviceUrl:
defaultZone: http://localhost:8761/eureka
私のtest/templateサービスのbootstrap.yml
spring:
application:
name: templateservice
eureka:
instance:
hostname: ${spring.application.name}
preferIpAddress: true
instanceId: ${spring.application.name}:${spring.application.instance_id:${random.value}}
statusPageUrlPath: ${server.servlet.context-path}/actuator/info
healthCheckUrlPath: ${server.servlet.context-path}/actuator/health
leaseRenewalIntervalInSeconds: 15
leaseExpirationDurationInSeconds: 45
metadata-map:
server.servlet.context-path: ${server.servlet.context-path}
client:
enabled: true
serviceUrl:
defaultZone: http://localhost:8761/eureka
logging:
level:
com...MessageServiceClient: DEBUG
私の偽のクライアント
@FeignClient(name = "secondservice", configuration = FeignConfig.class)
public interface MessageServiceClient {
@RequestMapping(method = RequestMethod.GET, value = "/dummy")
public String getMessage();
}
私のサービスクラス:
@Autowired MessageServiceClient messageServiceClient;
@Autowired private LoadBalancerClient loadBalancer;
public String getDummyMessage() {
ServiceInstance instance = loadBalancer.choose("secondservice");
URI secondServiceUri = URI.create(String.format("http://%s:%s", instance.getHost(), instance.getPort()));
System.out.println(secondServiceUri); // logs http://192.168.0.205:8090, check log below
return messageServiceClient.getMessage(); // throws 404??
}
FeignConfigでは、ログレベルをFULLに設定するだけです。ログは次のようになります。
2018-10-08 11:14:59.511 INFO [templateservice,,,] 16801 --- [onPool-worker-2] s.c.a.AnnotationConfigApplicationContext : Refreshing SpringClientFactory-secondservice: startup date [Mon Oct 08 11:14:59 IST 2018]; parent: org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext@451f35ad
2018-10-08 11:14:59.683 INFO [templateservice,,,] 16801 --- [onPool-worker-2] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring
2018-10-08 11:15:00.042 INFO [templateservice,,,] 16801 --- [onPool-worker-2] c.netflix.config.ChainedDynamicProperty : Flipping property: secondservice.ribbon.ActiveConnectionsLimit to use NEXT property: niws.loadbalancer.availabilityFilteringRule.activeConnectionsLimit = 2147483647
2018-10-08 11:15:00.095 INFO [templateservice,,,] 16801 --- [onPool-worker-2] c.n.u.concurrent.ShutdownEnabledTimer : Shutdown hook installed for: NFLoadBalancer-PingTimer-secondservice
2018-10-08 11:15:00.146 INFO [templateservice,,,] 16801 --- [onPool-worker-2] c.netflix.loadbalancer.BaseLoadBalancer : Client: secondservice instantiated a LoadBalancer: DynamicServerListLoadBalancer:{NFLoadBalancer:name=secondservice,current list of Servers=[],Load balancer stats=Zone stats: {},Server stats: []}ServerList:null
2018-10-08 11:15:00.189 INFO [templateservice,,,] 16801 --- [onPool-worker-2] c.n.l.DynamicServerListLoadBalancer : Using serverListUpdater PollingServerListUpdater
2018-10-08 11:15:00.287 INFO [templateservice,,,] 16801 --- [onPool-worker-2] c.netflix.config.ChainedDynamicProperty : Flipping property: secondservice.ribbon.ActiveConnectionsLimit to use NEXT property: niws.loadbalancer.availabilityFilteringRule.activeConnectionsLimit = 2147483647
2018-10-08 11:15:00.291 INFO [templateservice,,,] 16801 --- [onPool-worker-2] c.n.l.DynamicServerListLoadBalancer : DynamicServerListLoadBalancer for client secondservice initialized: DynamicServerListLoadBalancer:{NFLoadBalancer:name=secondservice,current list of Servers=[192.168.0.205:8090, 192.168.0.205:8090],Load balancer stats=Zone stats: {defaultzone=[Zone:defaultzone; Instance count:2; Active connections count: 0; Circuit breaker tripped count: 0; Active connections per server: 0.0;]
},Server stats: [[Server:192.168.0.205:8090; Zone:defaultZone; Total Requests:0; Successive connection failure:0; Total blackout seconds:0; Last connection made:Thu Jan 01 05:30:00 IST 1970; First connection made: Thu Jan 01 05:30:00 IST 1970; Active Connections:0; total failure count in last (1000) msecs:0; average resp time:0.0; 90 percentile resp time:0.0; 95 percentile resp time:0.0; min resp time:0.0; max resp time:0.0; stddev resp time:0.0]
]}ServerList:org.springframework.cloud.netflix.ribbon.eureka.DomainExtractingServerList@3625959e
http://192.168.0.205:8090
2018-10-08 11:15:01.215 INFO [templateservice,,,] 16801 --- [erListUpdater-0] c.netflix.config.ChainedDynamicProperty : Flipping property: secondservice.ribbon.ActiveConnectionsLimit to use NEXT property: niws.loadbalancer.availabilityFilteringRule.activeConnectionsLimit = 2147483647
2018-10-08 11:15:07.951 DEBUG [templateservice,,,] 16801 --- [onPool-worker-2] c.e.m.t.clients.MessageServiceClient : [MessageServiceClient#getMessage] ---> GET http://secondservice/dummy HTTP/1.1
2018-10-08 11:15:12.527 DEBUG [templateservice,,,] 16801 --- [onPool-worker-2] c.e.m.t.clients.MessageServiceClient : [MessageServiceClient#getMessage] <--- HTTP/1.1 404 (4575ms)
2018-10-08 11:15:12.559 ERROR [templateservice,7004692c56b2e643,7004692c56b2e643,false] 16801 --- [nio-8080-exec-4] o.s.c.s.i.web.ExceptionLoggingFilter : Uncaught exception thrown
問題は、これが404をスローすることです。もちろん、ヒットしようとしているURLがhttp://secondservice/dummy
であり、そのようなことはありません。 FeignClientでurl
を設定すると機能することに注意してください。しかし、Eurekaのポイントは何ですか?また、これが機能する場合、fiegnクライアントは自動的にコンテキストパスを使用しますか?または、クライアントのすべてのURLで指定する必要がありますか?
UPDATE 1:応答: http:// localhost:8761/eureka/apps/secondservice
それを見つけた!それは発見や一般的な設定とは何の関係もありません、それはfeignがコンテキストパスをサポートしていないからです!
「ダム」ダウンする試みで、私はサービスを維持するためにすべての構成を最小限に削除し続けました。 2番目のサービスのコンテキストパスを削除すると、突然機能しました。他のサービスによって設定された場合、Feign + Ribbonはカスタムコンテキストパスをサポートしません。これは 古いバグ ですが、まだ修正されていません。
2つの可能な解決策があります:
//以下のフォーマットを正しくするには、これがここにある必要があります
_@FeignClient(name = "secondservice/secondservice", configuration = FeignConfig.class)
public interface MessageServiceClient {
@RequestMapping(method = RequestMethod.GET, value = "/dummy")
public String getMessage();
}
_
私は個人的にどちらの解決策も好きではありません。私はコンテキストパスを持っているのが好きです、まあ、URLにコンテキストを与えるために、それはコンテキストで自明になります。ただし、これは他のサービス(secondservice)のプロパティであり、そのサービスによって選択/変更する必要があります。したがって、依存するサービスにハードコーディングしないでください。サポートされていればよかったのですが、その間、次のことを行います。
_@FeignClient(name = "${dependencies.secondservice.url}")
public interface MessageServiceClient {....}
_
そして、application.properties:_dependencies.secondservice.url=secondservice/secondservice
_。これにより、プロパティがこのサービスではなく依存関係によって所有されていることが明確になります。
その他の注意事項:1。リクエストを_SynchronousMethodHandler#executeAndDecode
_、response = client.execute(request, options);
まで追跡できます。ここまで、URLはメモで解決されます。 2.ログに記録されるURL:_GET http://secondservice/secondservice/dummy
_は実際には正しいURLであり、最初のsecondservice
文字列はlogステートメントの後にIPに置き換えられます。これをサポートするドキュメントは次のとおりです。 https://cloud.spring.io/spring-cloud-static/Finchley.SR1/single/spring-cloud.html#_using_ribbon 。 restTemplateに渡されたURLに注意してください。これが、別の原因の検索のきっかけとなりました。
両方のサービスプロパティファイルからeureka.client.serviceUrl.defaultZone
の値を変更します。次に、localhost
をIPアドレスに置き換えたところ、うまくいきました。
それが役に立てば幸い?