2

下面的指南页面很棒,可以作为 Spring Boot 应用程序中功能区的基本案例。

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]
4

2 回答 2

2

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

于 2016-08-15T08:59:43.130 回答
0

我也在使用这个示例应用程序来开始使用功能区,这很棒。

为了清楚起见,我想在设计上多说几句:

  1. “/complete/user”文件夹下的用户应用程序是“客户端”应用程序,我们可以通过“ curl http://{host}:8888 ”访问它;而“/complete/say-hello”文件夹下的say-hello应用程序是“服务提供者”。按照示例的说明,我们应该通过 {host}:8090{host}:9092{host}:9999启动 3 个实例——我们可以查看 /complete/user/src/main/resources/application.yml看一下;
  2. Ribbon,嵌入在“客户端”用户应用程序中,将通过默认的 Ping 策略维护一系列负载均衡服务实例(如果我们如上所述启动实例,这里将是 3 个),它会通过调用特定的周期性 ping 服务实例网址。默认情况下是“/”,因为我们可以在这里看到代码(同样,也可以通过指定 URI 来配置): @Bean public IPing ribbonPing(IClientConfig config) { return new PingUrl(); } 现在,让我们回到您的问题。

SayHelloApplication.java通过显式添加更改 URI 映射后@RequestMapping(value = "/welcome"),“/”的映射

@RequestMapping(value = "/")
public String home() {
  log.info("Access /");
  return "Hi!";
}

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

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

于 2016-11-10T09:52:45.970 回答