当前位置:   article > 正文

spring-cloud-commons之LoadBalancer_bean 'org.springframework.cloud.client.loadbalance

bean 'org.springframework.cloud.client.loadbalancer.reactive.loadbalancerbea

spring-cloud-commons的结构如下:

spring-cloud-commons 包括了整个 SpringCloud 对各种微服务化组件的抽象,比如:

  1. actuator:

  2. circuitbreaker:断路器功能

  3. doscovery:服务发现功能,比较经典的实现如 spring-cloud-netflix-eureka-client,依赖三方组件 netflix-eureka,也是 SpringCloud 2020 版本后唯一支持的 netflix 组件
  4. loadbalancer:客户端负载均衡功能,spring-cloud-commons 同时提供了一方实现 spring-cloud-loadbalancer,用来代替已经被废弃的 spring-cloud-netflix-ribbon
  5. serviceregistry:服务注册功能,同上,spring-cloud-commons 针对 netflix-eureka 的 server 部分也提供了二方实现 spring-cloud-netflix-eureka-server

LoadBalancer组件

在spring.factories中与LoadBalancer有关的自动化配置类有如下

  1. org.springframework.cloud.client.loadbalancer.AsyncLoadBalancerAutoConfiguration,\
  2. org.springframework.cloud.client.loadbalancer.LoadBalancerAutoConfiguration,\
  3. org.springframework.cloud.client.loadbalancer.reactive.LoadBalancerBeanPostProcessorAutoConfiguration,\
  4. org.springframework.cloud.client.loadbalancer.reactive.ReactorLoadBalancerClientAutoConfiguration,\
  5. org.springframework.cloud.client.loadbalancer.reactive.ReactiveLoadBalancerAutoConfiguration,\

@LoadBalanced客户端负载均衡注解

load balancer会收集标记@LoadBalanced注解的RestTemplate进行定制化,实现客户端负载均衡

  1. @Target({ ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD })
  2. @Retention(RetentionPolicy.RUNTIME)
  3. @Documented
  4. @Inherited
  5. @Qualifier
  6. public @interface LoadBalanced {
  7. }

ServiceInstanceChooser接口

服务实例选择器,使用load balancer根据serviceId获取具体的实例

  1. public interface ServiceInstanceChooser {
  2. // 根据服务id获取具体的服务实例
  3. ServiceInstance choose(String serviceId);
  4. }

LoadBalancerClient接口

负载均衡客户端,继承ServiceInstanceChooser,对外提供API以供第三方实现自己的负载均衡客户端

  1. public interface LoadBalancerClient extends ServiceInstanceChooser {
  2. // 根据serviceId使用ServiceInstance执行请求
  3. <T> T execute(String serviceId, LoadBalancerRequest<T> request) throws IOException;
  4. // 重载方法。同上
  5. <T> T execute(String serviceId, ServiceInstance serviceInstance, LoadBalancerRequest<T> request) throws IOException;
  6. // 基于服务实例和URI重新构造一个新的带有host和port信息的URI。比如http://myservice/path/to/service.这个地址 myservice 这个服务名将会替换成比如 192.168.1.122:8080
  7. URI reconstructURI(ServiceInstance instance, URI original);
  8. }

那么该LoadBalancerClient接口就有了三个功能:

  • execute:执行服务请求,根据serviceId,选择ServiceInstance,重新构造URI,并进行服务请求
  • choose:根据serviceId选择服务实例ServiceInstance
  • reconstruct URI:根据负载得到的ServiceInstance,重新构造新的真实的带有host和port的URI

ServiceRequestWrapper对HttpRequestWarpper的封装

  1. public class ServiceRequestWrapper extends HttpRequestWrapper {
  2. private final ServiceInstance instance;
  3. private final LoadBalancerClient loadBalancer;
  4. public ServiceRequestWrapper(HttpRequest request, ServiceInstance instance, LoadBalancerClient loadBalancer) {
  5. super(request);
  6. this.instance = instance;
  7. this.loadBalancer = loadBalancer;
  8. }
  9. //重写了HttpRequestWrapper的getURI方法,通过调用LoadBalancer重写的reconstructURI方法重构URI
  10. public URI getURI() {
  11. URI uri = this.loadBalancer.reconstructURI(this.instance, this.getRequest().getURI());
  12. return uri;
  13. }
  14. }

LoadBalancerAutoConfiguration自动配置类

  1. @Configuration(proxyBeanMethods = false)
  2. @ConditionalOnClass(RestTemplate.class)
  3. @ConditionalOnBean(LoadBalancerClient.class)
  4. @EnableConfigurationProperties(LoadBalancerProperties.class)
  5. public class LoadBalancerAutoConfiguration {
  6. //收集所有标注 @LoadBalanced 的 RestTemplate
  7. @LoadBalanced
  8. @Autowired(required = false)
  9. private List<RestTemplate> restTemplates = Collections.emptyList();
  10. // 使用RestTemplateCustomizer定制化这些被@LoadBalanced注解修饰的RestTemplate
  11. @Bean
  12. public SmartInitializingSingleton loadBalancedRestTemplateInitializerDeprecated(
  13. final ObjectProvider<List<RestTemplateCustomizer>> restTemplateCustomizers) {
  14. return () -> restTemplateCustomizers.ifAvailable(customizers -> {
  15. for (RestTemplate restTemplate : LoadBalancerAutoConfiguration.this.restTemplates) {
  16. for (RestTemplateCustomizer customizer : customizers) {
  17. customizer.customize(restTemplate);
  18. }
  19. }
  20. });
  21. }
  22. //请求工厂,生成LoadBalancerRequest,并使用ServiceRequestWrapper封装request
  23. @Bean
  24. @ConditionalOnMissingBean
  25. public LoadBalancerRequestFactory loadBalancerRequestFactory(LoadBalancerClient loadBalancerClient) {
  26. return new LoadBalancerRequestFactory(loadBalancerClient, this.transformers);
  27. }
  28. /** 非 retry相关的配置,SpringCloud也提供了retryTemplate,增加了重试机制*/
  29. // 如果没有依赖spring-retry模块。如果依赖spring-retry模块的话会构造另外一个配置类RetryInterceptorAutoConfiguration。内部也会1个拦截器和1个定制化器,分别是RetryLoadBalancerInterceptor和RetryLoadBalancerInterceptor。原理类似
  30. @Configuration(proxyBeanMethods = false)
  31. @Conditional(RetryMissingOrDisabledCondition.class)
  32. static class LoadBalancerInterceptorConfig {
  33. //new 负载均衡器的拦截器
  34. @Bean
  35. public LoadBalancerInterceptor loadBalancerInterceptor(LoadBalancerClient loadBalancerClient,
  36. LoadBalancerRequestFactory requestFactory) {
  37. return new LoadBalancerInterceptor(loadBalancerClient, requestFactory);
  38. }
  39. // 构造定制化器RestTemplateCustomizer,为这些RestTemplate添加拦截器LoadBalancerInterceptor
  40. // 使用了java8的函数式接口
  41. @Bean
  42. @ConditionalOnMissingBean
  43. public RestTemplateCustomizer restTemplateCustomizer(final LoadBalancerInterceptor loadBalancerInterceptor) {
  44. return restTemplate -> {
  45. List<ClientHttpRequestInterceptor> list = new ArrayList<>(restTemplate.getInterceptors());
  46. list.add(loadBalancerInterceptor);
  47. restTemplate.setInterceptors(list);
  48. };
  49. }
  50. }
  51. ...
  52. }

     上述列出部分代码,核心自动装配类,该类由 spring-cloud-commons 提供(而非 spring-cloud-loadbalancer),因此提供了最 基本 的配置:

  1. 正如之前所说,此处收集容器中所有标注了 @LoadBalanced 注解的 RestTemplate(@Qualifer 限定符的妙用)
  2. 对于上述 RestTemplate,使用(容器中)所有的 RestTemplateCustomizer 进行定制化处理
  3. 同时,针对 retry 、非 retry 配置注册了一个 RestTemplateCustomizer,代码中 非 retry 配置下的 RestTemplateCustomizer 是给所有 RestTemplate 插入了一个拦截器 LoadBalancerInterceptor
  4. 同时,也注册了一个 LoadBalancerInterceptor,不难理解,RestTemplate 负载均衡的能力由 LoadBalancerInterceptor 提供

LoadBalancerInterceptor对request请求进行拦截

        LoadBalancerInterceptor拦截器拦截住RestTemplate的request请求,通过请求的URI得到负载均衡的serviceId,负载均衡器根据serviceId得到ServiceInstance,通过重构得到最终的URI,然后通过LoadBalancer的execute方法进行真实的服务请求

  1. public class LoadBalancerInterceptor implements ClientHttpRequestInterceptor {
  2. private LoadBalancerClient loadBalancer;
  3. private LoadBalancerRequestFactory requestFactory;
  4. public LoadBalancerInterceptor(LoadBalancerClient loadBalancer, LoadBalancerRequestFactory requestFactory) {
  5. this.loadBalancer = loadBalancer;
  6. this.requestFactory = requestFactory;
  7. }
  8. public LoadBalancerInterceptor(LoadBalancerClient loadBalancer) {
  9. this(loadBalancer, new LoadBalancerRequestFactory(loadBalancer));
  10. }
  11. //对Request请求进行拦截
  12. public ClientHttpResponse intercept(final HttpRequest request, final byte[] body, final ClientHttpRequestExecution execution) throws IOException {
  13. //这里获取到原来的请求URI,该URI里请求的host是负载均衡服务端的serviceId
  14. URI originalUri = request.getURI();
  15. String serviceName = originalUri.getHost();
  16. Assert.state(serviceName != null, "Request URI does not contain a valid hostname: " + originalUri);
  17. //调用LoadBalancer的execute进行真实的请求
  18. //通过LoadBalancerRequestFactory创造LoadBalancerRequest
  19. return (ClientHttpResponse)this.loadBalancer.execute(serviceName, this.requestFactory.createRequest(request, body, execution));
  20. }
  21. }

LoadBalancerInterceptor拦截器内部会对request请求进行拦截。

拦截器内部使用LoadBalancerClient完成请求的调用,这里调用的时候需要的LoadBalancerRequestLoadBalancerRequestFactory构造,LoadBalancerRequestFactory内部使用LoadBalancerRequestTransformer对request进行转换。

ReactiveLoadBalancer负载均衡器接口

  1. public interface ReactiveLoadBalancer<T> {
  2. Request<DefaultRequestContext> REQUEST = new DefaultRequest();
  3. Publisher<Response<T>> choose(Request request);
  4. default Publisher<Response<T>> choose() {
  5. return this.choose(REQUEST);
  6. }
  7. @FunctionalInterface
  8. public interface Factory<T> {
  9. ReactiveLoadBalancer<T> getInstance(String serviceId);
  10. }
  11. }

目前在spring-cloud-loadbalancer中,只提供了RoundRobinLoadBalancer一种负载均衡策略 

LoadBalancerRequestFactory创建ServiceRequestWrapper

  1. public class LoadBalancerRequestFactory {
  2. private LoadBalancerClient loadBalancer;
  3. private List<LoadBalancerRequestTransformer> transformers;
  4. public LoadBalancerRequestFactory(LoadBalancerClient loadBalancer, List<LoadBalancerRequestTransformer> transformers) {
  5. this.loadBalancer = loadBalancer;
  6. this.transformers = transformers;
  7. }
  8. public LoadBalancerRequestFactory(LoadBalancerClient loadBalancer) {
  9. this.loadBalancer = loadBalancer;
  10. }
  11. //创建LoadBalancerRequest,函数式编程,实现了apply(ServiceInstance instance)方法
  12. //ClientHttpRequestExecution接口的实现类是InterceptingClientHttpRequest
  13. public LoadBalancerRequest<ClientHttpResponse> createRequest(final HttpRequest request, final byte[] body, final ClientHttpRequestExecution execution) {
  14. return (instance) -> {
  15. //在LoadBalancerClient的execute方法中会回调这个apply方法
  16. HttpRequest serviceRequest = new ServiceRequestWrapper(request, instance, this.loadBalancer);
  17. LoadBalancerRequestTransformer transformer;
  18. if (this.transformers != null) {
  19. for(Iterator var6 = this.transformers.iterator(); var6.hasNext(); serviceRequest = transformer.transformRequest((HttpRequest)serviceRequest, instance)) {
  20. transformer = (LoadBalancerRequestTransformer)var6.next();
  21. }
  22. }
  23. //执行远程请求
  24. return execution.execute((HttpRequest)serviceRequest, body);
  25. };
  26. }
  27. }

LoadBalancerRequest接口

  1. public interface LoadBalancerRequest<T> {
  2. T apply(ServiceInstance instance) throws Exception;
  3. }

RestTemplate继承了InterceptingHttpAccessor,里面有拦截器

        客户端负载均衡是通过对RestTemplate添加拦截器实现的。
        RestTemplate提供了一个方法setInterceptors,用于设置拦截器,拦截器需要实现ClientHttpRequestInterceptor接口即可,在实际远程去请求服务端接口之前会先调用拦截器的intercept方法逻辑。

在下面的代码中ClientHttpRequest的实现类是InterceptingClientHttpRequest

  1. public class RestTemplate extends InterceptingHttpAccessor implements RestOperations {
  2. ......省略......
  3. //执行远程请求
  4. protected <T> T doExecute(URI url, @Nullable HttpMethod method, @Nullable RequestCallback requestCallback, @Nullable ResponseExtractor<T> responseExtractor) throws RestClientException {
  5. Assert.notNull(url, "URI is required");
  6. Assert.notNull(method, "HttpMethod is required");
  7. ClientHttpResponse response = null;
  8. Object var14;
  9. try {
  10. //ClientHttpRequest的实现类是InterceptingClientHttpRequest
  11. ClientHttpRequest request = this.createRequest(url, method);
  12. if (requestCallback != null) {
  13. requestCallback.doWithRequest(request);
  14. }
  15. response = request.execute();
  16. this.handleResponse(url, method, response);
  17. var14 = responseExtractor != null ? responseExtractor.extractData(response) : null;
  18. } catch (IOException var12) {
  19. String resource = url.toString();
  20. String query = url.getRawQuery();
  21. resource = query != null ? resource.substring(0, resource.indexOf(63)) : resource;
  22. throw new ResourceAccessException("I/O error on " + method.name() + " request for \"" + resource + "\": " + var12.getMessage(), var12);
  23. } finally {
  24. if (response != null) {
  25. response.close();
  26. }
  27. }
  28. return var14;
  29. }
  30. ......省略......
  31. }

InterceptingClientHttpRequest执行最终真实的请求

在InterceptingClientHttpRequest类中有一个内部类InterceptingRequestExecution,执行拦截器里的方法并进行最终的远程请求

  1. class InterceptingClientHttpRequest extends AbstractBufferingClientHttpRequest {
  2. private final ClientHttpRequestFactory requestFactory;
  3. private final List<ClientHttpRequestInterceptor> interceptors;
  4. private HttpMethod method;
  5. private URI uri;
  6. protected InterceptingClientHttpRequest(ClientHttpRequestFactory requestFactory, List<ClientHttpRequestInterceptor> interceptors, URI uri, HttpMethod method) {
  7. this.requestFactory = requestFactory;
  8. this.interceptors = interceptors;
  9. this.method = method;
  10. this.uri = uri;
  11. }
  12. public HttpMethod getMethod() {
  13. return this.method;
  14. }
  15. public String getMethodValue() {
  16. return this.method.name();
  17. }
  18. public URI getURI() {
  19. return this.uri;
  20. }
  21. protected final ClientHttpResponse executeInternal(HttpHeaders headers, byte[] bufferedOutput) throws IOException {
  22. InterceptingClientHttpRequest.InterceptingRequestExecution requestExecution = new InterceptingClientHttpRequest.InterceptingRequestExecution();
  23. return requestExecution.execute(this, bufferedOutput);
  24. }
  25. //InterceptingRequestExecution是Spring中对ClientHttpRequestExecution接口的实现,执行拦截器里的方法,并进行最终的远程请求
  26. private class InterceptingRequestExecution implements ClientHttpRequestExecution {
  27. private final Iterator<ClientHttpRequestInterceptor> iterator;
  28. public InterceptingRequestExecution() {
  29. this.iterator = InterceptingClientHttpRequest.this.interceptors.iterator();
  30. }
  31. public ClientHttpResponse execute(HttpRequest request, byte[] body) throws IOException {
  32. //如果拦截器不为空,则执行拦截器里的拦截方法
  33. if (this.iterator.hasNext()) {
  34. ClientHttpRequestInterceptor nextInterceptor = (ClientHttpRequestInterceptor)this.iterator.next();
  35. return nextInterceptor.intercept(request, body, this);
  36. } else {
  37. //进行最终的远程请求
  38. HttpMethod method = request.getMethod();
  39. Assert.state(method != null, "No standard HTTP method");
  40. ClientHttpRequest delegate = InterceptingClientHttpRequest.this.requestFactory.createRequest(request.getURI(), method);
  41. request.getHeaders().forEach((key, value) -> {
  42. delegate.getHeaders().addAll(key, value);
  43. });
  44. if (body.length > 0) {
  45. if (delegate instanceof StreamingHttpOutputMessage) {
  46. StreamingHttpOutputMessage streamingOutputMessage = (StreamingHttpOutputMessage)delegate;
  47. streamingOutputMessage.setBody((outputStream) -> {
  48. StreamUtils.copy(body, outputStream);
  49. });
  50. } else {
  51. StreamUtils.copy(body, delegate.getBody());
  52. }
  53. }
  54. return delegate.execute();
  55. }
  56. }
  57. }
  58. }

LoadBalancerProperties 

  1. @ConfigurationProperties("spring.cloud.loadbalancer")
  2. public class LoadBalancerProperties {
  3. private LoadBalancerProperties.HealthCheck healthCheck = new LoadBalancerProperties.HealthCheck();
  4. ...省略...
  5. public static class HealthCheck {
  6. private int initialDelay = 0;
  7. private Duration interval = Duration.ofSeconds(25L);
  8. private Map<String, String> path = new LinkedCaseInsensitiveMap();
  9. ...省略...
  10. }
  11. }

LoadBalancer工作流程图如下

总结:

spring-cloud-commons 定义好了整个 loadbalance 的基调及相关接口,实现方需要实现响应的接口即可,同时 spring-cloud-commons 也给出了自己的 一方 实现: spring-cloud-loadbalancer 

spring-cloud-loadbalancer对loadbalancer的实现

BlockingLoadBalancerClient 

  1. public class BlockingLoadBalancerClient implements LoadBalancerClient {
  2. private final LoadBalancerClientFactory loadBalancerClientFactory;
  3. public BlockingLoadBalancerClient(LoadBalancerClientFactory loadBalancerClientFactory) {
  4. this.loadBalancerClientFactory = loadBalancerClientFactory;
  5. }
  6. public <T> T execute(String serviceId, LoadBalancerRequest<T> request) throws IOException {
  7. //根据servicerId选择服务后端服务节点
  8. ServiceInstance serviceInstance = this.choose(serviceId);
  9. if (serviceInstance == null) {
  10. throw new IllegalStateException("No instances available for " + serviceId);
  11. } else {
  12. return this.execute(serviceId, serviceInstance, request);
  13. }
  14. }
  15. public <T> T execute(String serviceId, ServiceInstance serviceInstance, LoadBalancerRequest<T> request) throws IOException {
  16. try {
  17. return request.apply(serviceInstance);
  18. } catch (IOException var5) {
  19. throw var5;
  20. } catch (Exception var6) {
  21. ReflectionUtils.rethrowRuntimeException(var6);
  22. return null;
  23. }
  24. }
  25. //重构URI
  26. public URI reconstructURI(ServiceInstance serviceInstance, URI original) {
  27. return LoadBalancerUriTools.reconstructURI(serviceInstance, original);
  28. }
  29. //根据serviceId选择后端服务节点
  30. public ServiceInstance choose(String serviceId) {
  31. ReactiveLoadBalancer<ServiceInstance> loadBalancer = this.loadBalancerClientFactory.getInstance(serviceId);
  32. if (loadBalancer == null) {
  33. return null;
  34. } else {
  35. Response<ServiceInstance> loadBalancerResponse = (Response)Mono.from(loadBalancer.choose()).block();
  36. return loadBalancerResponse == null ? null : (ServiceInstance)loadBalancerResponse.getServer();
  37. }
  38. }
  39. }

附录:Ribbon负载均衡的实现

RibbonLoadBalancerClient实现类

  1. public class RibbonLoadBalancerClient implements LoadBalancerClient {
  2. private SpringClientFactory clientFactory;
  3. public RibbonLoadBalancerClient(SpringClientFactory clientFactory) {
  4. this.clientFactory = clientFactory;
  5. }
  6. public URI reconstructURI(ServiceInstance instance, URI original) {
  7. Assert.notNull(instance, "instance can not be null");
  8. String serviceId = instance.getServiceId();
  9. RibbonLoadBalancerContext context = this.clientFactory.getLoadBalancerContext(serviceId);
  10. URI uri;
  11. Server server;
  12. if (instance instanceof RibbonLoadBalancerClient.RibbonServer) {
  13. RibbonLoadBalancerClient.RibbonServer ribbonServer = (RibbonLoadBalancerClient.RibbonServer)instance;
  14. server = ribbonServer.getServer();
  15. uri = RibbonUtils.updateToSecureConnectionIfNeeded(original, ribbonServer);
  16. } else {
  17. server = new Server(instance.getScheme(), instance.getHost(), instance.getPort());
  18. IClientConfig clientConfig = this.clientFactory.getClientConfig(serviceId);
  19. ServerIntrospector serverIntrospector = this.serverIntrospector(serviceId);
  20. uri = RibbonUtils.updateToSecureConnectionIfNeeded(original, clientConfig, serverIntrospector, server);
  21. }
  22. return context.reconstructURIWithServer(server, uri);
  23. }
  24. public ServiceInstance choose(String serviceId) {
  25. return this.choose(serviceId, (Object)null);
  26. }
  27. public ServiceInstance choose(String serviceId, Object hint) {
  28. Server server = this.getServer(this.getLoadBalancer(serviceId), hint);
  29. return server == null ? null : new RibbonLoadBalancerClient.RibbonServer(serviceId, server, this.isSecure(server, serviceId), this.serverIntrospector(serviceId).getMetadata(server));
  30. }
  31. public <T> T execute(String serviceId, LoadBalancerRequest<T> request) throws IOException {
  32. return this.execute(serviceId, (LoadBalancerRequest)request, (Object)null);
  33. }
  34. public <T> T execute(String serviceId, LoadBalancerRequest<T> request, Object hint) throws IOException {
  35. ILoadBalancer loadBalancer = this.getLoadBalancer(serviceId);
  36. Server server = this.getServer(loadBalancer, hint);
  37. if (server == null) {
  38. throw new IllegalStateException("No instances available for " + serviceId);
  39. } else {
  40. RibbonLoadBalancerClient.RibbonServer ribbonServer = new RibbonLoadBalancerClient.RibbonServer(serviceId, server, this.isSecure(server, serviceId), this.serverIntrospector(serviceId).getMetadata(server));
  41. return this.execute(serviceId, (ServiceInstance)ribbonServer, (LoadBalancerRequest)request);
  42. }
  43. }
  44. public <T> T execute(String serviceId, ServiceInstance serviceInstance, LoadBalancerRequest<T> request) throws IOException {
  45. Server server = null;
  46. if (serviceInstance instanceof RibbonLoadBalancerClient.RibbonServer) {
  47. server = ((RibbonLoadBalancerClient.RibbonServer)serviceInstance).getServer();
  48. }
  49. if (server == null) {
  50. throw new IllegalStateException("No instances available for " + serviceId);
  51. } else {
  52. RibbonLoadBalancerContext context = this.clientFactory.getLoadBalancerContext(serviceId);
  53. RibbonStatsRecorder statsRecorder = new RibbonStatsRecorder(context, server);
  54. try {
  55. //调用LoadBalancerRequest的apply方法
  56. T returnVal = request.apply(serviceInstance);
  57. statsRecorder.recordStats(returnVal);
  58. return returnVal;
  59. } catch (IOException var8) {
  60. statsRecorder.recordStats(var8);
  61. throw var8;
  62. } catch (Exception var9) {
  63. statsRecorder.recordStats(var9);
  64. ReflectionUtils.rethrowRuntimeException(var9);
  65. return null;
  66. }
  67. }
  68. }
  69. protected Server getServer(String serviceId) {
  70. return this.getServer(this.getLoadBalancer(serviceId), (Object)null);
  71. }
  72. protected Server getServer(ILoadBalancer loadBalancer) {
  73. return this.getServer(loadBalancer, (Object)null);
  74. }
  75. protected Server getServer(ILoadBalancer loadBalancer, Object hint) {
  76. return loadBalancer == null ? null : loadBalancer.chooseServer(hint != null ? hint : "default");
  77. }
  78. protected ILoadBalancer getLoadBalancer(String serviceId) {
  79. return this.clientFactory.getLoadBalancer(serviceId);
  80. }
  81. public static class RibbonServer implements ServiceInstance {
  82. private final String serviceId;
  83. private final Server server;
  84. private final boolean secure;
  85. private Map<String, String> metadata;
  86. public RibbonServer(String serviceId, Server server) {
  87. this(serviceId, server, false, Collections.emptyMap());
  88. }
  89. public RibbonServer(String serviceId, Server server, boolean secure, Map<String, String> metadata) {
  90. this.serviceId = serviceId;
  91. this.server = server;
  92. this.secure = secure;
  93. this.metadata = metadata;
  94. }
  95. ......省略......
  96. }
  97. }

参考

https://blog.csdn.net/weixin_42189048/article/details/117781378

http://fangjian0423.github.io/2018/10/02/spring-cloud-commons-analysis/

https://blog.csdn.net/weixin_50518271/article/details/111449560

声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号