当服务压力突然变大时,我们需要通过对服务进行弹性伸缩和动态的扩容,让服务展示更强的并发能力和容错能力

1.修改服务提供者的数据接口

修改服务提供者的接口,可以让我们很清晰的看到,我们当前调用的是那一台服务提供者。让我们来修改 provider 里面 EchoController 这个类

 

代码如下:

@RestController
public class EchoController {

	@Value("${server.port}")
	private Integer port ;

	@GetMapping("/echo/{message}")
	public ResponseEntity<String> echo(@PathVariable("message") String message){
   
     
		return ResponseEntity.ok(String.format("hello,%s,我是服务提供者:%s",message,port)) ;
	}
}

  • 因为我们在同一台机器上启动多个服务提供者,那服务提供者的端口肯定不相同,我们在此使用 port 作为服务提供者的唯一标示。
  • @Value : 从 env 里面注入这个值

2.启动多个服务的提供者

先停止所有的服务:

 

在启动一个服务的提 供者:

 

启动成功后:

 

启动其他 1 个:

 

进入编辑页面:

 

2 个操作:

  • Name:不能重复,这里我修改为 ProviderApplication-2
  • Program arguments:–server.port=8081 这句话的意思是,在启动该服务时,添加一个变量: server.port=8081 ,类似我们使用这样的命令启动:
    java -jar xxx.jar --server.port=8081
  • –server.port 该值将会被添加到 spring 的 env 里面,并且该方式的优先级高于 application.yml 里面的配置值。所以,系统会使用该 port 来启动服务。
  • 修改完毕后,点击 ok
  • 现在启动我们的复制的 ProviderApplicaton-2:

 

观察 Nacos 里面的数据:

 

服务:provider-service 已经有 2 个实例了,点击详情:

 

可以手动的下线该服务。

3.测试负载均衡

修改 consumer 里面的 ConsumerApplication ,在里面的末尾添加如下的代码:

@Autowired
private LoadBalancerClient loadBalancerClient ;

@GetMapping("/choose/{serviceName}")
public ResponseEntity<String> choose(@PathVariable("serviceName") String serviceName){
   
     
	ServiceInstance instance = loadBalancerClient.choose(serviceName);
	System.out.println(String.format("本次选择的实例为:%s:%s",instance.getHost(),instance.getPort()));
	return ResponseEntity.ok(instance.getHost()+":"+instance.getPort()) ;
}

其中:

  • LoadBalancerClient :Ribbon 提供给我们最外层的接口,使用它我们可以很轻易的实现负载均衡
  • LoadBalancerClient.choose(serviceName):通过给定的服务名称,Ribbon 底层通过负载均衡的算法得到一个可以进行远程的实例。
  • 现在,启动 Consumer 进行测试:
  • 在浏览器里面输入:
    http://localhost:8090/choose/provider-service

得到:

 

刷新页面:

 

并且后台输出:

 

发现负载均衡已经完成

4.更简单的远程调用测试

在之前,我们在 consumer 使用 RestTemplate 调用 provider 时,手动实现了负载均衡,url 的拼接:

 

  • 代码相当的冗余。现在,我们使用 Ribbon 的方式来实现:
  • 在注入 RestTemplate 的方法上添加注解:

 

远程调用的代码变为:

@GetMapping("/rpc/ribbon/{message}")
public ResponseEntity<String> rpcByRibbon(@PathVariable("message") String message){
   
     
	ResponseEntity<String> responseEntity = restTemplate.getForEntity("http://provider-service/echo/" + message,String.class);
	if(responseEntity.getStatusCode()==HttpStatus.OK){
   
     
		return ResponseEntity.ok("调用成功,provider-service 相应给我们的数据为:"+responseEntity.getBody()) ;
	}
	return ResponseEntity.badRequest().body("调用失败,provider-service 的相应码为:"+responseEntity.getStatusCode()) ;
}

  • 重启 consumer 测试:
  • 在浏览器里面输入:

http://localhost:8090/rpc/ribbon/{message}

 

刷新测试:

 

负载均衡已经完成了