@LoadBalanced RestTemplate用于调用嵌套的上下文端点

时间:2016-08-14 19:32:22

标签: spring spring-cloud spring-cloud-netflix netflix-ribbon

以下指南很棒,可作为弹簧启动应用程序中功能区的基本案例。

https://spring.io/guides/gs/client-side-load-balancing/

示例在端点映射嵌套后立即停止工作 - 例如添加

  

@RequestMapping(value =" / welcome")

在班级

@RestController
@SpringBootApplication
@RequestMapping(value = "/welcome") //<------------- ADDED --->
public class SayHelloApplication {

  private static Logger log = LoggerFactory.getLogger(SayHelloApplication.class);

  @RequestMapping(value = "/greeting")
  public String greet() {

然后从

更改客户端中的@LoadBalanced RestTemplate调用
String greeting = this.restTemplate.getForObject("http://say-hello/greeting", String.class);

String greeting = this.restTemplate.getForObject("http://say-hello/welcome/greeting", String.class);

使用附加的堆栈跟踪调用失败,而直接访问http://localhost:8090/welcome/greeting仍然可以正常工作。配置功能区以将请求加载到长和嵌套URL端点(如domain.com/x/y/z/p/q)的适当方法是什么?

堆栈跟踪:

java.lang.IllegalStateException: No instances available for say-hello
    at org.springframework.cloud.netflix.ribbon.RibbonLoadBalancerClient.execute(RibbonLoadBalancerClient.java:79) ~[spring-cloud-netflix-core-1.1.4.RELEASE.jar:1.1.4.RELEASE]
    at org.springframework.cloud.client.loadbalancer.LoadBalancerInterceptor.intercept(LoadBalancerInterceptor.java:46) ~[spring-cloud-commons-1.1.1.RELEASE.jar:1.1.1.RELEASE]
    at org.springframework.http.client.InterceptingClientHttpRequest$InterceptingRequestExecution.execute(InterceptingClientHttpRequest.java:85) ~[spring-web-4.2.6.RELEASE.jar:4.2.6.RELEASE]
    at org.springframework.http.client.InterceptingClientHttpRequest.executeInternal(InterceptingClientHttpRequest.java:69) ~[spring-web-4.2.6.RELEASE.jar:4.2.6.RELEASE]
    at org.springframework.http.client.AbstractBufferingClientHttpRequest.executeInternal(AbstractBufferingClientHttpRequest.java:48) ~[spring-web-4.2.6.RELEASE.jar:4.2.6.RELEASE]
    at org.springframework.http.client.AbstractClientHttpRequest.execute(AbstractClientHttpRequest.java:53) ~[spring-web-4.2.6.RELEASE.jar:4.2.6.RELEASE]
    at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:596) ~[spring-web-4.2.6.RELEASE.jar:4.2.6.RELEASE]
    at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:557) ~[spring-web-4.2.6.RELEASE.jar:4.2.6.RELEASE]
    at org.springframework.web.client.RestTemplate.getForObject(RestTemplate.java:264) ~[spring-web-4.2.6.RELEASE.jar:4.2.6.RELEASE]
    at hello.UserApplication.hi(UserApplication.java:31) ~[classes/:na]
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_45]
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_45]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_45]
    at java.lang.reflect.Method.invoke(Method.java:497) ~[na:1.8.0_45]

2 个答案:

答案 0 :(得分:2)

问题是在类中添加了@RequestMapping,您还更改了/处理程序,以便从根目录移动到/welcome/。为了使负载均衡器能够继续工作,您必须更新用户应用的PingUrl内使用的SayHelloConfiguration。设为new PingUrl(false, "/welcome/")

答案 1 :(得分:0)

我也在使用这个示例应用程序开始使用Ribbon,这很棒。

为了说清楚,我想在设计上多说一些话:

  1. 用户应用程序位于“/ complete / user”文件夹下 “客户端”应用程序,我们可以通过“ curl”访问它 http:// {host}:8888 “;而 say-hello 应用程序, “/ complete / say-hello”文件夹是“服务提供商”。如 在示例的指导下,我们应该通过实现3个实例 {host}:8090 {host}:9092 {host}: 9999 - 我们可以退房 /complete/user/src/main/resources/application.yml 来看看;
  2. 功能区,嵌入在“客户端”用户应用程序中,将通过默认的Ping策略维护一系列负载平衡服务实例(如果我们按上述方式启动实例,这将是3)将通过调用特定的URL定期ping服务实例。默认情况下是“/”,因为我们可以在这里看到代码(同样,也可以通过指定URI来配置): @Bean public IPing ribbonPing(IClientConfig config) { return new PingUrl(); } 现在,让我们回到你的问题。
  3. 通过明确添加SayHelloApplication.java更改@RequestMapping(value = "/welcome")中的URI映射后,

    中的“/”映射
    @RequestMapping(value = "/")
    public String home() {
      log.info("Access /");
      return "Hi!";
    }
    

    将表示“/ welcome”下的根路径,即“/ welcome /”,而不是say-hello应用程序的“/”。

    然后我们没有任何真实的“/”映射,例如'http:// {host}:8090 /'。在这种情况下,Ping将逐个失败,最终Ribbon会将所有服务实例标记为不健康,因此您最终会得到“没有可用于说明问候的实例”。