【问题标题】:spring boot 2 + feign + eureka client wont resolve service-name to URLspring boot 2 + feign + eureka 客户端不会将服务名称解析为 URL
【发布时间】:2019-03-12 18:31:32
【问题描述】:

我正在尝试使用 spring-cloud (Finchley.SR1) 的 spring-boot (2.0.5) 并尝试使用 Eureka 作为发现服务器和 Feign/Ribbon 作为客户端来设置两个服务之间的通信。设置非常简单(尽管我尝试过的各种事情和其他答案有点混乱):

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

第二个服务的 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

我的测试/模板服务的 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

我的 Feign 客户

@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 中指定它?

更新 1:回复:http://localhost:8761/eureka/apps/secondservice

【问题讨论】:

  • 点击时输出是什么:localhost:8761/eureka/apps/secondservice
  • @hideburn 用回复的截图更新了问题。
  • 好的,请检查以下内容: 1. 您的模板服务主类使用@EnableFeignClients 注释。 2.你的templateservice依赖有:feign-ribbon、feign-core、feign-slf4j、ribbon-loadbalancer
  • 谢谢。我检查了:注释存在,feign-core,feign-slf4j,ribbon-loadbalancer。我可以在路径上找到 openfeign 和ribbon jars,但没有名为 feign-ribbon 的 jar/包,如果这就是你的意思的话。 Ribbon-core、ribbon、ribbon-httpclient 等都在那里,并作为 feign 的依赖项被拉取。

标签: spring spring-boot netflix-eureka spring-cloud-feign netflix-ribbon


【解决方案1】:

找到了!它与发现无关,或一般配置,这是因为 feign 不支持上下文路径!

为了让服务变得“笨拙”,我继续将每个配置都删除到最低限度,以保持服务正常运行。当我删除第二个服务的上下文路径时,它突然起作用了。如果由其他服务设置,Feign+Ribbon 不支持自定义上下文路径。这是old bug,仍未修复。

有两种可能的解决方案:

  1. 删除上下文路径。
  2. 在您的 Feign 客户端中添加上下文路径。所以基本上你的 Feign 客户变成了:

// 这需要在这里才能使下面的格式正确

@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#executeAndDecoderesponse = 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。这就是触发寻找替代原因的原因。

【讨论】:

    【解决方案2】:

    我从两个服务属性文件中更改了eureka.client.serviceUrl.defaultZone 的值。然后我用 IP 地址替换了localhost,它对我有用。

    希望有帮助吗?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-08-31
      • 2015-04-11
      • 2016-06-21
      • 1970-01-01
      • 2020-07-20
      • 2020-05-16
      • 2020-05-22
      相关资源
      最近更新 更多