前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >springcloud 服务间通讯方式 Ribbon

springcloud 服务间通讯方式 Ribbon

作者头像
DencyCheng
发布2019-01-02 16:14:11
1.1K0
发布2019-01-02 16:14:11
举报
文章被收录于专栏:SpringBootSpringBoot

版权声明:本文为博主原创文章,未经博主允许不得转载。

1.Eureka服务发现

product 启动了两个实例

2.RestTemplate

RestTemplate

参考:https://blog.csdn.net/madmk/article/details/76431486

代码语言:javascript
复制
        RestTemplate restTemplate = new RestTemplate();
        String response =   restTemplate.getForObject("http://localhost:9001/msg",String.class);
        log.info("response={}",response);

这种方式,调用很简单,但是访问地址写死,不方便,所以这种方式很少用。

并且,当服务启动多个时,很难做到调用多个服务实例。

3.LoadBalancerClient + RestTemplate

代码语言:javascript
复制
我们通过loadBalancerClient根据应用名获取url 
代码语言:javascript
复制
    @Autowired
    LoadBalancerClient loadBalancerClient;

    /**
     * LoadBalancerClient + RestTemplate方式
     *
     * @return
     */
    @GetMapping("/msg2")
    public String helloMsg2() {
        RestTemplate restTemplate = new RestTemplate();

        ServiceInstance instance = loadBalancerClient.choose("product");
        String storesUri = String.format("http://%s:%s", instance.getHost(), instance.getPort());

        String response = restTemplate.getForObject(storesUri + "/msg", String.class);
        log.info("response={}", response);

        return response;
    }

4.@LoadBalanced注解 

添加RestTemplateConfig 配置文件,重点在方式上添加@LoadBalanced注解

代码语言:javascript
复制
@Configuration
public class RestTemplateConfig {

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

使用

代码语言:javascript
复制
    @Autowired
    private RestTemplate restTemplate;

    /**
     * LoadBalancerClient + RestTemplate方式
     *
     * @return
     */
    @GetMapping("/msg3")
    public String helloMsg3() {

        //通过应用名+访问地址
        String response = restTemplate.getForObject("http://product/msg", String.class);
        log.info("response={}", response);

        return response;
    }

5.Ribbon实现客户端负载均衡原理

5.1主要概念

  • 服务发现 :根据服务名字,把该服务下所以实力查询出来
  • 服务选择规则:根据服务选择规则,选择出一条有效服务
  • 服务监听:检测失效的服务,高效剔除

5.2主要组件

  • ServerList
  • IRule
  • ServerListFilter

流程:通过ServerList获取可用服务列表,然后通过ServerListFilter过滤掉一部分服务,最后通过IRule选择出一个最终目标结果。

5.3源码分析

5.3.1类间关系

5.3.2 获取可用服务列表

代码语言:javascript
复制
  ServiceInstance instance = loadBalancerClient.choose("product");

我们按住CTRL跟进到choose方法里面

代码语言:javascript
复制
    public ServiceInstance choose(String serviceId) {
        return this.choose(serviceId, (Object)null);
    }

    public ServiceInstance choose(String serviceId, Object hint) {
        Server server = this.getServer(this.getLoadBalancer(serviceId), hint);
        return server == null ? null : new RibbonLoadBalancerClient.RibbonServer(serviceId, server, this.isSecure(server, serviceId), this.serverIntrospector(serviceId).getMetadata(server));
    }

然后跟进CTRL this.getLoadBalancer(serviceId) 跟进得到的方法是

代码语言:javascript
复制
    protected ILoadBalancer getLoadBalancer(String serviceId) {
        return this.clientFactory.getLoadBalancer(serviceId);
    }
代码语言:javascript
复制
我们现在查看ILoadBalancer
代码语言:javascript
复制
public interface ILoadBalancer {
    void addServers(List<Server> var1);

    Server chooseServer(Object var1);

    void markServerDown(Server var1);

    /** @deprecated */
    @Deprecated
    List<Server> getServerList(boolean var1);

    List<Server> getReachableServers();

    List<Server> getAllServers();
}
代码语言:javascript
复制
我们猜测gelAllServers是获取所有可用服务列表的集合,现在我们查看一下其实现方法BaseLoadBalancer打一个断点查看一下
代码语言:javascript
复制
    public List<Server> getAllServers() {
        return Collections.unmodifiableList(this.allServerList);
    }
代码语言:javascript
复制
结果

这个刚好就是我们选择的PRODUCT的两个服务,就此我们可以判断,gelAllServers是根据服务名称获取服务列表的方法。

现在我们获取到服务列表了,下一步就应该根据规则选择一个服务进行返回。

5.3.3选择一个服务

现在跟进 this.getServer方法

代码语言:javascript
复制
    protected Server getServer(ILoadBalancer loadBalancer, Object hint) {
        return loadBalancer == null ? null : loadBalancer.chooseServer(hint != null ? hint : "default");
    }

然后跟进chooseServer方法

代码语言:javascript
复制
    public Server chooseServer(Object key) {
        if (this.counter == null) {
            this.counter = this.createCounter();
        }

        this.counter.increment();
        if (this.rule == null) {
            return null;
        } else {
            try {
                return this.rule.choose(key);
            } catch (Exception var3) {
                logger.warn("LoadBalancer [{}]:  Error choosing server for key {}", new Object[]{this.name, key, var3});
                return null;
            }
        }
    }
代码语言:javascript
复制
我们可以看见Server svr = this.rule.choose(key); 这个方法,这个就是根据规则选择一个服务
代码语言:javascript
复制
我们查看一下规则rule
代码语言:javascript
复制
  protected IRule rule;

构造函数

代码语言:javascript
复制
 this.rule = DEFAULT_RULE;
代码语言:javascript
复制
  private static final IRule DEFAULT_RULE = new RoundRobinRule();

通过名字我们可以看出来,负责均衡的方法规则是轮询的方式。

查看测试结果

第一次

第二次

第三次

我们跟进choose方法

代码语言:javascript
复制
   public Server choose(Object key) {
        ILoadBalancer lb = this.getLoadBalancer();
        Optional<Server> server = this.getPredicate().chooseRoundRobinAfterFiltering(lb.getAllServers(), key);
        return server.isPresent() ? (Server)server.get() : null;
    }

debug看到

lb变量里面的

我们可以看见所有服务列表,跟校验规则

然后根据

代码语言:javascript
复制
  Optional<Server> server = this.getPredicate().chooseRoundRobinAfterFiltering(lb.getAllServers(), key);

返回一个服务对象

5.4 修改规则

需要在application.yml

代码语言:javascript
复制
product: #访问服务名称
  ribbon:
    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule

规则在IRule的实现类里面可以选择,也可以自定义

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018年11月16日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1.Eureka服务发现
  • 2.RestTemplate
    • 3.LoadBalancerClient + RestTemplate
    • 4.@LoadBalanced注解 
    • 5.Ribbon实现客户端负载均衡原理
      • 5.1主要概念
        • 5.2主要组件
          • 5.3源码分析
            • 5.4 修改规则
            相关产品与服务
            负载均衡
            负载均衡(Cloud Load Balancer,CLB)提供安全快捷的流量分发服务,访问流量经由 CLB 可以自动分配到云中的多台后端服务器上,扩展系统的服务能力并消除单点故障。负载均衡支持亿级连接和千万级并发,可轻松应对大流量访问,满足业务需求。
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档