通过 Ribbon 查询 Nacos 服务实例(上)

本文涉及的产品
传统型负载均衡 CLB,每月750个小时 15LCU
网络型负载均衡 NLB,每月750个小时 15LCU
EMR Serverless StarRocks,5000CU*H 48000GB*H
简介: Nacos  提供了开放 API 可通过 /nacos/v1/ns/instance/list 获取服务列表。如果我们采用 spring-cloud 方式去获取服务,最终会通过 Nacos Client + loadbalancer 的方式进行客户端负载均衡。

Nacos 服务列表管理


Nacos  提供了开放 API 可通过 /nacos/v1/ns/instance/list 获取服务列表。如果我们采用 spring-cloud 方式去获取服务,最终会通过 Nacos Client + loadbalancer 的方式进行客户端负载均衡。


环境介绍:


  • Jdk 1.8
  • nacos-server-1.4.2
  • spring-boot-2.3.5.RELEASE
  • spring-cloud-Hoxton.SR8
  • spring-cloiud-alibab-2.2.5.RELEASE


Ribbon 源码解析


Ribbon 简介


Spring Cloud Ribbon 是  Netflix Ribbon 实现的一套客户端负载均衡工具 简单的说,Ribbon 是 Netflix 发布的开源项目,主要功能是提供客户端的复杂的算法和服务调用。 Ribbon 客户端组件提供一系列完善的配置项如超时、重试等。简单的说,就是配置文件中列出 load Balancer (简称 LB)后面所有的机器,Ribbon 会自动的帮助你基于某种规则(如简单轮询,随机链接等)去链接这些机器。我们很容易使用 Ribbon 自定义的负载均衡算法。


Ribbon 使用


  1. 首先需要定义 RestTemplate 使用 Ribbon 策略;


@Configuration
public class RestTemplateConfig {
    @LoadBalanced
    @Bean
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
}


  1. 本地使用 RestTemplate 调用远程接口;


@Autowired
private RestTemplate restTemplate;
@RequestMapping(value = "/echo/{id}", method = RequestMethod.GET)
public String echo(@PathVariable Long id) {
    return restTemplate.getForObject("http://member-service/member/get/" + id, String.class);
}


Ribbon 源码分析


  1. RestTemplate 继承 InterceptingHttpAccessor 通过 interceptors 字段接受 HttpRequestInterceptor 请求拦截器。


  1. 对于 Ribbion 初始化类是 RibbonAutoConfiguration 中的, 它在 spring-cloud-netflix-ribbon 中定义。


  1. 但是它在初始化之前,又需要加载 RibbonAutoConfiguration 配置,它是在 spring-cloud-common 中。具体的代码如下:


@Configuration(proxyBeanMethods = false)
// 工程中一定存在 RestTemplate 类
@ConditionalOnClass(RestTemplate.class)
// 容器中一定存在 LoadBalancerClient 类 Bean 实例
@ConditionalOnBean(LoadBalancerClient.class)
@EnableConfigurationProperties(LoadBalancerRetryProperties.class)
public class LoadBalancerAutoConfiguration {
   // 获取 Spring 容器中所有的 RestTemplate 实例
   @LoadBalanced
   @Autowired(required = false)
   private List<RestTemplate> restTemplates = Collections.emptyList();
   // 获取 Spring 容器中 LoadBalancerRequestTransformer 实例
   @Autowired(required = false)
   private List<LoadBalancerRequestTransformer> transformers = Collections.emptyList();
   // 在 Bean 初始化完成后会调用 afterSingletonsInstantiated 方法
   // 这里是一个 lambda 表达式方式的实现, 主要是为 restTemplate 实例设置 RestTemplateCustomizer
   @Bean
   public SmartInitializingSingleton loadBalancedRestTemplateInitializerDeprecated(
         final ObjectProvider<List<RestTemplateCustomizer>> restTemplateCustomizers) {
      return () -> restTemplateCustomizers.ifAvailable(customizers -> {
         for (RestTemplate restTemplate : LoadBalancerAutoConfiguration.this.restTemplates) {
            for (RestTemplateCustomizer customizer : customizers) {
               customizer.customize(restTemplate);
            }
         }
      });
   }
   // LoadBalancerRequestFactory 工厂类
   // 主要是用来提供 LoadBalancerClient 实例和 LoadBalancerRequestTransformer
   @Bean
   @ConditionalOnMissingBean
   public LoadBalancerRequestFactory loadBalancerRequestFactory(
         LoadBalancerClient loadBalancerClient) {
      return new LoadBalancerRequestFactory(loadBalancerClient, this.transformers);
   }
   // LoadBalancerInterceptor 拦截器 
   @Configuration(proxyBeanMethods = false)
   @ConditionalOnMissingClass("org.springframework.retry.support.RetryTemplate")
   static class LoadBalancerInterceptorConfig {
      // 创建默认的拦截器 LoadBalancerInterceptor 的实例
      @Bean
      public LoadBalancerInterceptor ribbonInterceptor(
            LoadBalancerClient loadBalancerClient,
            LoadBalancerRequestFactory requestFactory) {
         return new LoadBalancerInterceptor(loadBalancerClient, requestFactory);
      }
      // 如果没有 RestTemplateCustomizer 实例才会创建
      // 这里就就会为咱们所有的  restTemplate 实例添加 loadBalancerInterceptor 拦截器
      @Bean
      @ConditionalOnMissingBean
      public RestTemplateCustomizer restTemplateCustomizer(
            final LoadBalancerInterceptor loadBalancerInterceptor) {
         return restTemplate -> {
            List<ClientHttpRequestInterceptor> list = new ArrayList<>(
                  restTemplate.getInterceptors());
            list.add(loadBalancerInterceptor);
            restTemplate.setInterceptors(list);
         };
      }
   }
  // ...
}


针对下面的代码我们可以总结一下:


  • 如果需要使用负载均衡,工程下面必须要有 RestTemplate 类, 然后Spring 容器中要有 LoadBalancerClient 的实例。


  • LoadBalancerClientspring-cloud-netflix-ribbon 中只有一个实现类: RibbonLoadBalancerClient


  • 利用 Spring 的 SmartInitializingSingleton 拓展点,在 restTemplateCustomizer() 中为所有的 RestTemplate 添加 LoadBalancerInterceptor 拦截器


  • 其实 LoadBalancer 的本质就是通过拦截器。利用 RestTemplate 的拓展点来实现请求服务的负载均衡


LoadBalancerInterceptor


LoadBalancerInterceptor 拦截器会将请求交给 LoadBalancerClient 去处理,首先会选择一个 ILoadBalancer  的实现来处理获取和选择服务,然后通过 serviceName 和负载均衡算法去选择 Server 对象。最后执行请求。


public class LoadBalancerInterceptor implements ClientHttpRequestInterceptor {
   // 负载均衡
   private LoadBalancerClient loadBalancer;
   // 构建请求 
   private LoadBalancerRequestFactory requestFactory;
   // ...
   @Override
   public ClientHttpResponse intercept(final HttpRequest request, final byte[] body,
         final ClientHttpRequestExecution execution) throws IOException {
      final URI originalUri = request.getURI();
      String serviceName = originalUri.getHost(); 
      return this.loadBalancer.execute(serviceName,
            this.requestFactory.createRequest(request, body, execution));
   }
}


RibbonLoadBalancerClient


我们通过跟踪 this.loadBalancer.execute 代码发现。最终所有的请求都交由 RibbonLoadBalancerClient 去处理。它实现了。LoadBalancerClient 接口, 代码如下:


public interface ServiceInstanceChooser {
  // 通过 serviceId 选择具体的服务实例
  ServiceInstance choose(String serviceId);
}
public interface LoadBalancerClient extends ServiceInstanceChooser {
  <T> T execute(String serviceId, LoadBalancerRequest<T> request) throws IOException;
  <T> T execute(String serviceId, ServiceInstance serviceInstance,
         LoadBalancerRequest<T> request) throws IOException;
  // 将服务实例信息替换还具体的 IP 信息 
  URI reconstructURI(ServiceInstance instance, URI original);
}


相关实践学习
SLB负载均衡实践
本场景通过使用阿里云负载均衡 SLB 以及对负载均衡 SLB 后端服务器 ECS 的权重进行修改,快速解决服务器响应速度慢的问题
负载均衡入门与产品使用指南
负载均衡(Server Load Balancer)是对多台云服务器进行流量分发的负载均衡服务,可以通过流量分发扩展应用系统对外的服务能力,通过消除单点故障提升应用系统的可用性。 本课程主要介绍负载均衡的相关技术以及阿里云负载均衡产品的使用方法。
相关文章
|
5月前
|
存储 Nacos 数据安全/隐私保护
【SpringCloud】Nacos的安装、Nacos注册、Nacos服务多级存储模型
【SpringCloud】Nacos的安装、Nacos注册、Nacos服务多级存储模型
73 1
|
27天前
|
负载均衡 Java Nacos
SpringCloud基础1——远程调用、Eureka,Nacos注册中心、Ribbon负载均衡
微服务介绍、SpringCloud、服务拆分和远程调用、Eureka注册中心、Ribbon负载均衡、Nacos注册中心
SpringCloud基础1——远程调用、Eureka,Nacos注册中心、Ribbon负载均衡
|
2月前
|
存储 设计模式 缓存
OpenFeign集成Ribbon负载均衡-过滤和选择服务核心实现
该文章主要介绍了如何在OpenFeign中集成Ribbon以实现负载均衡,并详细分析了Ribbon中服务选择和服务过滤的核心实现过程。文章还涉及了Ribbon中负载均衡器(ILoadBalancer)和负载均衡策略(IRule)的初始化方式。
OpenFeign集成Ribbon负载均衡-过滤和选择服务核心实现
|
2月前
|
负载均衡 监控 Java
SpringCloud常见面试题(一):SpringCloud 5大组件,服务注册和发现,nacos与eureka区别,服务雪崩、服务熔断、服务降级,微服务监控
SpringCloud常见面试题(一):SpringCloud 5大组件,服务注册和发现,nacos与eureka区别,服务雪崩、服务熔断、服务降级,微服务监控
SpringCloud常见面试题(一):SpringCloud 5大组件,服务注册和发现,nacos与eureka区别,服务雪崩、服务熔断、服务降级,微服务监控
|
3月前
|
监控 安全 网络安全
inishConnect(..) failed: Connection refused,服务本地正常服务器网关报400,nacos服务实例不能下线
总之,这种问题需要通过多方面的检查和校验来定位和解决,并可能需要结合实际环境的具体情况来进行相应的调整。在处理分布式系统中这类问题时,耐心和细致的调试是必不可少的。
73 13
|
2月前
|
Kubernetes Nacos 微服务
【技术难题破解】Nacos v2.2.3 + K8s 微服务注册:强制删除 Pod 却不消失?!7步排查法+实战代码,手把手教你解决Nacos Pod僵死问题,让服务瞬间满血复活!
【8月更文挑战第15天】Nacos作为微服务注册与配置中心受到欢迎,但有时会遇到“v2.2.3 k8s 微服务注册nacos强制删除 pod不消失”的问题。本文介绍此现象及其解决方法,帮助开发者确保服务稳定运行。首先需检查Pod状态与事件、配置文件及Nacos配置,确认无误后可调整Pod生命周期管理,并检查Kubernetes版本兼容性。若问题持续,考虑使用Finalizers、审查Nacos日志或借助Kubernetes诊断工具。必要时,可尝试手动强制删除Pod。通过系统排查,通常能有效解决此问题。
50 0
|
2月前
|
Java Nacos 开发工具
【Nacos】心跳断了怎么办?!8步排查法+实战代码,手把手教你解决Nacos客户端不发送心跳检测问题,让服务瞬间恢复活力!
【8月更文挑战第15天】Nacos是一款广受好评的微服务注册与配置中心。然而,“客户端不发送心跳检测”的问题时有发生,可能导致服务实例被视为离线。本文介绍如何排查此类问题:确认Nacos服务器地址配置正确;检查网络连通性;查看客户端日志;确保Nacos SDK版本兼容;调整心跳检测策略;验证服务实例注册状态;必要时重启应用;检查影响行为的环境变量。通过这些步骤,通常可定位并解决问题,保障服务稳定运行。
115 0
|
2月前
|
网络安全 Nacos 开发者
【Nacos】神操作!节点提示暂时不可用?别急!7步排查法+实战代码,手把手教你解决Nacos服务实例状态异常,让服务瞬间满血复活!
【8月更文挑战第15天】Nacos作为微服务注册与配置中心,虽广受好评,但仍可能遇到“节点提示暂时不可用”的问题。本文解析此现象及其解决之道。首先需理解该提示意味着服务实例未能正常响应。解决步骤包括:检查服务状态与网络、审查Nacos配置、调整健康检查策略、重启服务及分析日志。通过系统化排查,可有效保障服务稳定运行。
55 0
|
4月前
|
Java Nacos 数据格式
Spring Cloud Nacos 详解:服务注册与发现及配置管理平台
Spring Cloud Nacos 详解:服务注册与发现及配置管理平台
155 3
|
3月前
|
负载均衡 Java Linux
黑马头条01,环境搭建,今日头条的介绍,今日头条的功能架构图,技术栈的说明,服务层,nacos(奶靠丝)安装,安装在Linux服务器上环境准备,
黑马头条01,环境搭建,今日头条的介绍,今日头条的功能架构图,技术栈的说明,服务层,nacos(奶靠丝)安装,安装在Linux服务器上环境准备,