第四章:客户端负载均衡:Spring Cloud Ribbon(Spring cloud微服务实战)

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

本章主要介绍如何使用Ribbon实现客户端的负载均衡并且通过源码分析了解Ribbon实现客户端负载均衡的原理。

客户端负载均衡

    负载均衡是对系统的高可用、网络压力的缓解和处理扩容的重要手段之一。我们通常说的负载均衡指的都是服务端负载均衡,其中分为硬件负载均衡和软件负载均衡。硬件负载均衡主要通过在服务器节点之间安装专门用于负载均衡的设备,比如F5等;而软件负载均衡则是通过在服务器上安装一些具有均衡负载功能或者模块的软件完成请求分发工作,比如Nginx等。

    硬件负载均衡的设备或者是软件负载均衡的软件模块都会维护一个下挂可用的服务端清单,通过心跳检测来剔除故障的服务端节点以保证清单中都是可以正常访问的服务端节点。当客户端发送请求到负载均衡设备的时候,该设备按某种算法(比如线性轮询、按权重负载、按流量负载等)从维护的可用服务端清单中取出一台服务端的地址,然后进行转发。

    客户端负载均衡和服务端负载均衡最大的不同在于服务清单所存储的位置。在客户端负载均衡中,所有客户端节点都维护着自己要访问的服务端清单,而这些服务端的清单来自于服务注册中心。

    Spring Cloud Ribbon使用客户端负载均衡只需要两步:

    1.服务提供者只需要启动多个服务实例并注册到一个注册中心或是多个相关联的服务注册中心。

    2.服务消费者直接通过调用被@LoadBalanced注解修饰过的RestTemplate来实现面向服务的接口调用。


RestTemplate详解

    Get请求:对Get请求可以通过两种方式进行调用实现

    1.getForEntity函数。该方法返回ResponseEntity,该对象是Spring对HTTP请求响应的封装,其中主要存储了HTTP的几个重要元素,比如HTTP请求状态码的枚举对象HttpStatus、在它的父类HttpEntity中还存储着HTTP请求的头信息对象HttpHeaders以及泛型类型的请求体对象。

    在服务端增加一个接口:

@RestController
public class BookController {
	
	@RequestMapping(value="/getbookbyname",method=RequestMethod.GET)
	public Book getBookByName(String name){
		Book book = new Book();
		book.setName(name);
		return book;
	}

}

    在客户端增加一个接口调用服务端接口:

	@RequestMapping(value="/getbookbyname",method=RequestMethod.GET)
	public Book bookConsumer(){
		//三种方式:
		//第一种:参数绑定
		//return restTemplate.getForEntity("http://HELLO-SERVICE/getbookbyname?name={1}", Book.class, "didi").getBody();
		//第二种:Map
		/*Map<String, String> params = new HashMap<>();
		params.put("name", "didi");
		return restTemplate.getForEntity("http://HELLO-SERVICE/getbookbyname?name={name}", Book.class, params).getBody();*/
		//第三种:URI
		/*UriComponents uriComponents = UriComponentsBuilder.fromUriString("http://HELLO-SERVICE/getbookbyname?name={name}")
		.build().expand("didi").encode();
		URI uri = uriComponents.toUri();*/
		/*return restTemplate.getForObject(uri, Book.class);*/
		
		//return restTemplate.getForObject(uri, Book.class);
		
		return restTemplate.getForObject("http://HELLO-SERVICE/getbookbyname?name={1}", Book.class, "didi");
	}

启动服务注册中心、服务端、客户端,且访问http://localhost:9000/getbookbyname,可以看到返回了book信息:


    2.getForObject函数。该方法可以理解为对getForEntity的进一步封装,通过HttpMessageConverterExtrator对HTTP的请求响应体body内容进行对象转换,实现请求直接返回包装好的对象内容。

return restTemplate.getForObject("http://HELLO-SERVICE/getbookbyname?name={1}", Book.class, "didi");

    POST请求,有三种方法进行调用实现。

    1.postForEntity函数。同get类似,多了一个入参:请求字段

    2.postForObject函数。同get类似

    3.postForLocation

    服务器增加接口:

	/**
	 * post请求
	 * @param name
	 * @return
	 */
	@RequestMapping(value="/postbookbyname",method=RequestMethod.POST)
	public Book postBookByName(@RequestBody String name){
		Book book = new Book();
		book.setName(name);
		return book;
	}

    客户端调用服务端接口:

	@RequestMapping(value="/postbookbyname",method=RequestMethod.GET)
	public Book getBookByPost(){
		//第一种
		//return restTemplate.postForEntity("http://HELLO-SERVICE/postbookbyname","didi",Book.class).getBody();
		return restTemplate.postForObject("http://HELLO-SERVICE/postbookbyname","didi",Book.class);
	 	//URI responseURI = restTemplate.postForLocation("http://HELLO-SERVICE/postbookbyname","didi");
	}


PUT请求:put函数没有返回内容,入参与其他函数类似。

DELETE请求,由于通常将delete请求的唯一标识拼接在url中,所以delete请求不需要request的body信息。


源码解析:先省略,后续补充


配置详解:

引入Spring Cloud Ribbon的依赖之后,就能过自动化构建下面这些接口的实现:

1. IClientConfig:Ribbon的客户端配置,默认采用com.netflix.client.config.DefaultClientConfigImpl实现。

2.TRule:Ribbon的负载均衡策略,默认采用com.netflix.loadbalancer.ZoneAvoidanceRule实现,该策略能够在多区域环境下选出最佳区域的实例进行访问。

3.IPing:Ribbon的实例检查策略,默认采用com.netflix.loadbalancer.NoOpPing实现,该检查策略使一个特殊的实现,实际上它并不会检查实例是否可用,而是始终返回true。默认所有服务实例都是可用的。

4.ServerList<Server>:服务实例请饭的维护机制,默认采用com.netflix.loadbalancer.ConfigurationBasedServerList实现。

5.ServerListFilter<Server>:服务实例清单过滤机制,默认采用org.springframework.cloud.netflix.ribbon.ZonePreferenceServerListFilter实现,该策略能够有限过滤出与请求调用方处于同区域的服务实例。

6.ILoadBalancer:负载均衡器,默认采用com.netflix.loadbalancer.ZoneAwareLoadBalancer实现,它具备了区域感知的能力。


对Ribbon的参数配置通常有两种方式:全局配置以及指定客户端配置。

 全局配置,使用ribbon.<key>=<value>格式进行配置,比如创建连接的超时时间:ribbon.ConnectTimeout=250

指定客户端的配置方式采用<client>.ribbon.<key>=<value>的格式进行配置。


重试机制

Spring Clous整合了Spring Retry增强了RestTemplate的重试能力。

##开启重试机制
spring.cloud.loadbalancer.retry.enabled=true
##断路器的超时时间需要大于Ribbon的超时时间,不然不会触发重试
hystrix.command.default.execution.isolation.thread.timeoutInMIlliseconds=10000
##请求连接的超时时间
hello-service.ribbon.ConnectionTimeout=250
##请求处理的超时时间
hello-service.ribbon.ReadTimeout=1000
##对所有请求都进行重试
hello-service.ribbon.OkToRetryOnAllOpeations=true
##切换实例的重试次数
hello-service.ribbon.MaxAutoRetriesNextServer=2
##对当前实例的重试次数
hello-service.ribbon.MaxAutoRetries=1

猜你喜欢

转载自blog.csdn.net/dxh0823/article/details/80022487