当前位置: 首页 > news >正文

SpringCloud之服务远程调用--ribbon的服务调用和负载均衡

(一)ribbon概述

Spring Cloud Ribbon是一个基于HTTP和TCP的客户端负载均衡工具,它基于Netflix Ribbon实现。通过Spring Cloud的封装,可以让我们轻松地将面向服务的REST模版请求自动转换成客户端负载均衡的服务调用。

ribbon的主要作用是服务调用负载均衡

(二)ribbon服务调用

服务调用:eureka内部继承了ribbon

1.在创建RestTemplate时,声明@LoadBalanced

2.使用restTemplate调用远程微服务,用服务的名称代替ip地址

还是回到之前的项目,这个项目可以看SpringCloud专题的前两篇博客,修改admin微服务中的启动类,在restTemplate中加上LoadBalanced注解:

@SpringBootApplication
@EntityScan("com.sdxb.admin.entity")
@EnableEurekaClient
public class AdminApplication {
    //增加ribbon注解
    @LoadBalanced
    @Bean
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }

    public static void main(String[] args) {
        SpringApplication.run(AdminApplication.class,args);
    }
}

在adminController中使用服务名称代替ip地址

@RestController
@RequestMapping("/admin")
public class adminController {
    @Autowired
    private RestTemplate restTemplate;
    @RequestMapping(value = "/{id}",method = RequestMethod.GET)
    public User getuser(@PathVariable int id){
        //使用服务名称代替IP地址
        User user= restTemplate.getForObject("http://userservice/user/1",User.class);
        return user;
    }
}

注意一个可能发生的小错误,服务名称我们是在application.properties中定义的,服务名称不能出现下划线,否则会显示找不到该url

(三)ribbon负载均衡

ribbon最主要的功能不是远程调用,而是负载均衡,所谓负载均衡就是将请求分摊到各个微服务中,缓解服务器的压力。举个例子有相同的三个微服务ABC,都能实现同样的功能,此时一个请求发过来的时候,就需要客户端或服务器通过一定算法决定该给哪个微服务。

常见的服务器端负载均衡:nginx

常见的客户端负载均衡:ribbon

服务器端负载均衡是指服务器接收到请求后选择发给哪个服务,客户端负载均衡是指客户端决定了发给哪个服务从而实现负载均衡。

负载均衡实战:

首先对原来的userservice做个小小的修改,让它的数据中带有该微服务的ip地址和端口号:

@RestController
@RequestMapping("/user")
public class UserController {
    @Autowired
    private UserMapper userMapper;
    @Value("${server.port}")
    private String port;//使用注解获取端口号
    @Value("${spring.cloud.client.ip-address}")
    private String ip;//使用注解获取ip地址

    @GetMapping("/{id}")
    public User user(@PathVariable("id") int id){
        User user = userMapper.selectbyid(id);
        user.setUsername(ip+":"+port);
        return user;
    }
}

通过@Value注解获取到端口号和ip地址,写到user的name中

启动eureka注册中心和UserApplication,将user微服务注册到eureka注册中心中,在Run DashBoard中copy一份UserApplication,命名为UserApplication2

 修改UserService的端口号为9010,启动UserApplication2

在浏览器中输入http://localhost:9000/,可以看到两个端口都注册到eureka注册中心了

 启动adminApplication,在浏览器中输入http://localhost:9002/admin/1

 

 

通过刷新浏览器可以看到负载均衡的效果。

负载均衡算法:

ribbon提供了许多负载均衡算法:

com.netflix.loadbalancer.RoundRobinRule    轮询的方式负载均衡(默认)

com.netflix.loadbalancer.RandomRule    随机

com.netflix.loadbalancer.RetryRule    重试

com.netflix.loadbalancer.WeightedResponseTimeRule   权重策略

com.netflix.loadbalancer.BestAvailableRule    最佳策略

com.netflix.loadbalancer.AvailabilityFilteringRule    过滤策略

用得比较多的轮询和权重策略,当所用的服务器配置有高有低时,推荐权重策略,它会计算每个服务器的权重。

修改负载均衡算法的方式也很简单,在你想修改负载均衡的客户端微服务的配置文件application.properties下,增加下面的语句:

微服务名称.ribbon.NFLoadBalancerRuleClassName=所采用的方式的全限定类名(上面红色字体),我将策略修改为随机,重启服务后刷新浏览器,发现所调用的服务不再是轮询了。

#修改ribbon负载均衡策略
userservice.ribbon.NFLoadBalancerRuleClassName=com.netflix.loadbalancer.RandomRule

(三)ribbon重试机制

ribbon属于客户端负载均衡,即客户端会选择要访问哪个微服务,如果这个时候微服务断掉了,就无法返回数据。因此需要引入重试机制。

重试机制的引入有两个步骤:

1.导入依赖:

在客户端的pom.xml导入依赖

<!--引入重试依赖-->
<dependency>
    <groupId>org.springframework.retry</groupId>
    <artifactId>spring-retry</artifactId>
</dependency>

 2.填写相关配置

配置的解释全部放在注解中了

#重试机制
#ribbon连接超时时间
userservice.ribbon.ConnectTimeout=250
#ribbon读取数据超时时间
userservice.ribbon.ReadTimeout=1000
#是否对所有操作都重试
userservice.ribbon.OkToRetryOnAllOperations=true
#切换实例的重试次数
userservice.ribbon.MaxAutoRetriesNextServer=1
#对当前实例的重拾次数
userservice.ribbon.MaxAutoRetries=1

此时如果出现一个端口断掉的情况依然可以保证服务不崩溃。

代码放在github中,与这篇博客对应的代码放在version3.0分支上:github

 

 

 

 

相关文章:

  • SpringCloud之模板化Http客户端--Feign的入门和高级使用
  • Linux 添加开机启动项的两种方法
  • SpringCloud之容错框架--Hystrix的入门和高级使用
  • IOS指纹识别调用
  • SpringCloud之微服务网关的入门与进阶(请求过滤、网关限流)
  • redis入门到精通系列(一):入门redis看这一篇就够了
  • 常用的第三方库
  • redis入门到精通系列(二):redis操作的两个实践案例
  • 给所有的td单元格绑定一个click事件
  • redis入门到精通系列(三):key的通用操作和redis内部db的通用操作
  • 正则表达式与grep详解
  • redis入门到精通系列(四):Jedis--使用java操作redis详解
  • C语言 原码--反码--补码
  • redis入门到精通系列(五):redis的持久化操作(RDB、AOF)
  • 我的学习进度条
  • “Material Design”设计规范在 ComponentOne For WinForm 的全新尝试!
  • docker容器内的网络抓包
  • Java面向对象及其三大特征
  • Mac 鼠须管 Rime 输入法 安装五笔输入法 教程
  • nginx 配置多 域名 + 多 https
  • PHP 小技巧
  • SpringBoot几种定时任务的实现方式
  • vue从创建到完整的饿了么(11)组件的使用(svg图标及watch的简单使用)
  • 代理模式
  • 构建工具 - 收藏集 - 掘金
  • 基于Android乐音识别(2)
  • 简析gRPC client 连接管理
  • 爬虫进阶 -- 神级程序员:让你的爬虫就像人类的用户行为!
  • 排序(1):冒泡排序
  • 批量截取pdf文件
  • 前嗅ForeSpider中数据浏览界面介绍
  • 策略 : 一文教你成为人工智能(AI)领域专家
  • (01)ORB-SLAM2源码无死角解析-(56) 闭环线程→计算Sim3:理论推导(1)求解s,t
  • (C语言)输入一个序列,判断是否为奇偶交叉数
  • (Note)C++中的继承方式
  • (ZT)一个美国文科博士的YardLife
  • (附源码)ssm学生管理系统 毕业设计 141543
  • (九)信息融合方式简介
  • (十三)Flask之特殊装饰器详解
  • (一)appium-desktop定位元素原理
  • (已解决)什么是vue导航守卫
  • (原)记一次CentOS7 磁盘空间大小异常的解决过程
  • .gitignore文件—git忽略文件
  • .NET Core SkiaSharp 替代 System.Drawing.Common 的一些用法
  • .net core 控制台应用程序读取配置文件app.config
  • .net core 微服务_.NET Core 3.0中用 Code-First 方式创建 gRPC 服务与客户端
  • .NET Framework 服务实现监控可观测性最佳实践
  • .Net MVC4 上传大文件,并保存表单
  • .NET 的静态构造函数是否线程安全?答案是肯定的!
  • .NET 反射 Reflect
  • .net 前台table如何加一列下拉框_如何用Word编辑参考文献
  • .NET/C# 的字符串暂存池
  • [ vulhub漏洞复现篇 ] Django SQL注入漏洞复现 CVE-2021-35042
  • [ 数据结构 - C++] AVL树原理及实现
  • [100天算法】-每个元音包含偶数次的最长子字符串(day 53)