前一篇文章介绍了Spring Cloud Eureka的简单实践,本篇文章介绍Ribbon的实践。
What is Ribbon
Spring Cloud Ribbon是一个基于HTTP和TCP的客户端负载均衡工具,这里的客户端是站在服务器的角度来看的,它基于Netflix Ribbon实现。
通过Spring Cloud的封装,可以轻松的将面向服务的Rest模板请求自动转化成客户端负载均衡的服务调用。当然这属于软件的负载均衡。
例子
下面通过一个简单例子来用用Ribbon,基于上篇文章代码来进行。
- 首先,新建一个项目service-consumer,作为暴露对外的url调用,该项目pom文件如下:
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-ribbon</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
</dependencies>
- 写一个main类
@SpringBootApplication
@EnableEurekaClient
public class RibbonConsumerApplication {
public static void main(String[] args){
SpringApplication.run(RibbonConsumerApplication.class,args);
}
}
- 配置一个RestTemplate的bean:
@Bean
@LoadBalanced
public RestTemplate restTemplate(){
return new RestTemplate();
}
- 定一个公开的controller,用于从另一个服务端获取数据:
@Autowired
private RestTemplate restTemplate;
@GetMapping(value = "/ribbon/{name}")
public String findInfoById(@PathVariable String name){
//注意以下命名是以eureka的服务名称来获取的
ResponseEntity<String> responseEntity = restTemplate.getForEntity("http://hello-service/user?name={1}",String.class,name+":test anla");
String body = responseEntity.getBody();
return body;
}
- 此时,hello-service,就做为服务提供者,实际中可能有多个hello-service实例,它们在eureka注册的名称需要一致,端口不同,在
hello-service中可以定义众多restful方法供调用:
@RequestMapping(value = "/user",method = RequestMethod.GET)
public String index(@RequestParam String name){
ServiceInstance config = client.getLocalServiceInstance();
String serviceId = config.getServiceId();
String result = "hello: I am "+serviceId+", hello-service"+name+"my port is"+config.getPort();
logger.info(result);
return result;
}
- 分别启动eureka-server,hello-service,service-consumer,然后改变hello-service的server.port,换一个端口再进行注册,此时eureka中实例如下:
此时在浏览器中输入:http://localhost:8081/ribbon/123
回车两次,可以分别看到不同端口输出(默认是轮询方法负载均衡)
一个简单例子就完成了,可以去我git上直接clone代码,check out到v2分支:
https://github.com/anLA7856/hello-springcloud.git
小窥
在上述示例代码中,我使用了RestTemplate来进行对服务端的restful调用,当然,在Restful API规范中,对应有不同的操作,而在
RestTemplate中也有对应:
- GET
public <T> ResponseEntity<T> getForEntity(String url, Class<T> responseType, Object... uriVariables)
public <T> ResponseEntity<T> getForEntity(String url, Class<T> responseType, Map<String, ?> uriVariables)
public <T> ResponseEntity<T> getForEntity(URI url, Class<T> responseType)
public <T> T getForObject(String url, Class<T> responseType, Object... uriVariables)
public <T> T getForObject(String url, Class<T> responseType, Map<String, ?> uriVariables)
- …
- POST
public <T> ResponseEntity<T> postForEntity(String url, Object request, Class<T> responseType, Object... uriVariables)
- …
public <T> T postForObject(String url, Object request, Class<T> responseType, Object... uriVariables)
- …
- PUT
public void put(String url, Object request, Object... uriVariables)
- …
- DELTE
public void delete(String url, Object... uriVariables)
- …
上述中列举了四种请求的对应的方法,其中重载则并未列出了。
负载均衡策略
对于Ribbon,负载均衡策略主要有以下几种:
- RandomRule:随机
- RoundRobinRule:线性轮询一次选择每个服务器实例
- RetryRule:具备重试机制的实例选择功能
- WeightedResponseTimeRule:对RoundRobinRule的扩展,增加了对实例运行情况来计算权重,并根据权重来挑选实例