《Ribbon 负载均衡,重试》

Ribbon 服务

Ribbon 提供了负载均衡和重试功能, 它底层是使用 RestTemplate 进行 Rest api 调用


RestTemplate

RestTemplate 是SpringBoot提供的一个Rest远程调用工具

它的常用方法:

  • getForObject() - 执行get请求

  • postForObject() - 执行post请求

之前的系统结构是浏览器直接访问后台服务

在这里插入图片描述

后面我们通过一个Demo项目演示 Spring Cloud 远程调用

在这里插入图片描述

使用RestTemplate后服务器的负载明显降低,springCloud 的 ribbon 优化RestTemplate后 效果提升了好几倍

接下来使用Ribbon来远程调用和负载均衡


ribbon 负载均衡和重试

在这里插入图片描述

Ribbon的底层包含RestTemplate远程调用工具


Ribbon 负载均衡

步骤 :

  • 新建 ribbon 项目
  • pom.xml 添加依赖
  • application.yml 添加配置
  • 主程序
  • controller
  • 启动,并访问测试

1 - 创建项目

创建项目是有两个依赖,如果使用eureka的话 加入eureka的依赖

在这里插入图片描述


2 - pom.xml

  • 如果有公共模块的话引入 比如 common

  • eureka 依赖中已经包含了 ribbon

添加 ribbon 起步依赖(可选)
<dependency>
	<groupId>org.springframework.cloud</groupId>
	<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>

3 - application.yml

在这里插入图片描述

spring:
  application:
    name: ribbon
    
server:
  port: 3001
  
eureka:
  client:
    service-url:
      defaultZone: http://eureka1:2001/eureka, http://eureka2:2002/eureka

在这里插入图片描述


4 - 主程序

创建 RestTemplate 实例

RestTemplate 是用来调用其他微服务的工具类,封装了远程调用代码,提供了一组用于远程调用的模板方法,例如:getForObject()、postForObject() 等
@EnableDiscoveryClient
@SpringBootApplication
public class Sp06RibbonApplication {
    
    

    public static void main(String[] args) {
    
    
        SpringApplication.run(Sp06RibbonApplication.class, args);
    }
    
    @LoadBalanced //负载均衡注解
    @Bean
    public RestTemplate restTemplate(){
    
    
        return new RestTemplate();
    }
}

RestTemplate 设置 @LoadBalanced

@LoadBalanced 负载均衡注解,会对 RestTemplate 实例进行封装,创建动态代理对象,并切入(AOP)负载均衡代码,把请求分发到集群中的服务器

在这里插入图片描述


5 - RibbonController

访问路径设置为服务id

@RestController
public class RibbonController {
    
    
	@Autowired
	private RestTemplate rt;
	
	@GetMapping("/item-service/{orderId}")
	public JsonResult<List<Item>> getItems(@PathVariable String orderId) {
    
    
	    //这里服务器路径用 service-id 代替,ribbon 会向服务的多台集群服务器分发请求
		return rt.getForObject("http://item-service/{1}", JsonResult.class, orderId);
	}

	@PostMapping("/item-service/decreaseNumber")
	public JsonResult decreaseNumber(@RequestBody List<Item> items) {
    
    
		return rt.postForObject("http://item-service/decreaseNumber", items, JsonResult.class);
	}

在这里插入图片描述
在这里插入图片描述


6 - 访问测试

启动ribbon服务器
在这里插入图片描述

访问测试,ribbon 会把请求分发到 8001 和 8002 两个服务端口上

在这里插入图片描述
在这里插入图片描述

Ribbon 重试

什么是重试?

重试是一种错机制,如果请求后台服务出错,或者 服务器故障,可以向另一台服务器重试访问

依赖 :

<dependency>
	<groupId>org.springframework.retry</groupId>
	<artifactId>spring-retry</artifactId>
</dependency>

application.yml 配置 ribbon 重试 :

在这里插入图片描述

spring:
  application:
    name: ribbon

server:
  port: 3001

eureka:
  client:
    service-url:
      defaultZone: http://eureka1:2001/eureka,http://eureka2:2002/eureka

ribbon:
  MaxAutoRetriesNextServer: 2
  MaxAutoRetries: 1
  OkToRetryOnAllOperations: true
MaxAutoRetriesNextServer —— 更换实例的次数 (2次就够了)
MaxAutoRetries —— 当前实例重试次数,尝试失败会更换下一个实例 (1次就够了)
OkToRetryOnAllOperations=true —— 默认只对GET请求重试, 当设置为true时, 对POST等所有类型请求都重试在这里插入图片描述

主程序设置 RestTemplate 的请求工厂的超时

@SpringBootApplication
@EnableDiscoveryClient
public class Sp06RibbonApplication {
    
    

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

    @LoadBalanced //负载均衡注解
    @Bean
    public RestTemplate restTemplate(){
    
    
        SimpleClientHttpRequestFactory f = new SimpleClientHttpRequestFactory();
        f.setConnectTimeout(1000);
        f.setReadTimeout(1000);
        return new RestTemplate();
    }

}

在这里插入图片描述

利用SimpleClientHttpRequestFactory API来设定超时时间

setConnectTimeout(1000) —— 链接超时1000毫秒

setReadTimeout(1000) —— 暂停时间1000毫秒


访问,测试 ribbon 重试机制

为了测试我们在tem-service 的 ItemController 添加延迟代码,以便测试 ribbon 的重试机制(测试好了后删掉)

@Slf4j
@RestController
public class ItemController {
    
    
	@Autowired
	private ItemService itemService;
	
	@Value("${server.port}")
	private int port;
	
	@GetMapping("/{orderId}")
	public JsonResult<List<Item>> getItems(@PathVariable String orderId) throws Exception {
    
    
		log.info("server.port="+port+", orderId="+orderId);

        ///--设置随机延迟
		if(Math.random()<0.6) {
    
     
			long t = new Random().nextInt(5000);
			log.info("item-service-"+port+" - 暂停 "+t);
			Thread.sleep(t);
		}
		///~~
		
		List<Item> items = itemService.getItems(orderId);
		return JsonResult.ok(items).msg("port="+port);
	}

在这里插入图片描述

ribbon的重试机制,在 feign 和 zuul 中进一步进行了封装,后续可以使用feign或zuul的重试机制

猜你喜欢

转载自blog.csdn.net/weixin_45103228/article/details/114043046
今日推荐