本文共 6710 字,大约阅读时间需要 22 分钟。
Ribbon是Netflix体系中的基于客户端的负载均衡器,可以通过从eureka拉取服务提供方的地址列表中,按照某种负载均衡算法请求对应的服务方。
本文演示内容,部分基于前一篇 。
1、新建一个membership服务。
现在要比之前多依赖一个jar包,spring-cloud-starter-netflix-ribbon,但是这个包默认在spring-cloud-starter-netflix-eureka-client中已经包含了,所以我们也不需要额外的引入。
4.0.0 org.springframework.boot spring-boot-starter-parent 2.3.5.RELEASE com.wyl.springcloud membership 0.0.1-SNAPSHOT membership Demo project for Spring Boot 1.8 Hoxton.SR9 org.springframework.boot spring-boot-starter-web org.springframework.cloud spring-cloud-starter-netflix-eureka-client org.springframework.boot spring-boot-starter-test test org.junit.vintage junit-vintage-engine org.springframework.cloud spring-cloud-dependencies ${spring-cloud.version} pom import org.springframework.boot spring-boot-maven-plugin
2、注入RestTemplate
为了方便,我们会使用restTemplate方式来进行远程调用。
@EnableEurekaClient@SpringBootApplicationpublic class MembershipApplication { public static void main(String[] args) { SpringApplication.run(MembershipApplication.class, args); } @Bean //@LoadBalanced,这个注解我们可以先不加,先使用编码的方式实现负载均衡 public RestTemplate restTemplate() { return new RestTemplate(); }}
LoadBalancerClient是一个接口,RibbonLoadBalancerClient实现了它。
@RestController@RequestMapping("/user")public class UserController { @Autowired private RestTemplate restTemplate; @Autowired LoadBalancerClient lb; @PostMapping("/queryOrder") public String queryOrder() { ServiceInstance choose = lb.choose("order"); String str = restTemplate.getForObject("http://" + choose.getHost() + ":" + choose.getPort() + "/userOrder/queryOrderList", String.class); //String str = restTemplate.getForObject("http://order/userOrder/queryOrderList", String.class); System.out.println(str); return str; }}
Ribbon和RestTemplate内部已经整合好了,加上注解就可以直接使用,这就使得调用时变得简单了,直接通过服务名调用即可。
@EnableEurekaClient@SpringBootApplicationpublic class MembershipApplication { public static void main(String[] args) { SpringApplication.run(MembershipApplication.class, args); } @Bean @LoadBalanced public RestTemplate restTemplate() { return new RestTemplate(); }}
import org.springframework.beans.factory.annotation.Autowired;import org.springframework.cloud.client.ServiceInstance;import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;import org.springframework.web.bind.annotation.PostMapping;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;import org.springframework.web.client.RestTemplate;@RestController@RequestMapping("/user")public class UserController { @Autowired private RestTemplate restTemplate; //@Autowired //LoadBalancerClient lb; @PostMapping("/queryOrder") public String queryOrder() { //ServiceInstance choose = lb.choose("order"); //String str = restTemplate.getForObject("http://" + choose.getHost() + ":" + choose.getPort() + "/userOrder/queryOrderList", String.class); String str = restTemplate.getForObject("http://order/userOrder/queryOrderList", String.class); System.out.println(str); return str; }}
原有的order服务,新增一个接口,供membership服务调用。
import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;@RestController@RequestMapping("/userOrder")public class UserOrderController { @GetMapping("/queryOrderList") public String queryOrderList(){ //我会启动两个order服务,一个服务端口号19200,再启另外一个服务时把端口号改成19201,这样可以在调用时看到负载均衡的效果。 //return "queryOrderList,我的端口号:19201"; return "queryOrderList,我的端口号:19200"; }}
可以看到,默认是以轮询的方式调用。
1、注解方式
@EnableEurekaClient@SpringBootApplicationpublic class MembershipApplication { public static void main(String[] args) { SpringApplication.run(MembershipApplication.class, args); } @Bean @LoadBalanced public RestTemplate restTemplate() { return new RestTemplate(); } // @Bean public IRule myRule() { //return new RoundRobinRule(); //return new RandomRule(); return new RandomRule(); }}
随机调用。
IRule是ribbon-loadbalancer包下的一个接口
2、配置文件
可以更细粒度的针对具体的服务指定负载均衡策略。
order是服务提供方的服务名。
#配置ribbon负载均衡策略,优先级低于编码的方式order.ribbon.NFLoadBalancerRuleClassName=com.netflix.loadbalancer.RandomRule
这些参数都非常容易理解,本文也就不就演示了,建议大家自己的尝试一下,非常有意思。
#连接超时时间(单位秒)ribbon.ConnectTimeout=1000#连接后等待返回超时时间(单位秒)ribbon.ReadTimeout=2000#是否对所有操作都开启重试功能ribbon.OkToRetryOnAllOperations=true#切换实例重试次数ribbon.MaxAutoRetriesNextServer=2#当前实例重试次数ribbon.MaxAutoRetries=1#开启ribbon超时管理(注意如果不开启,以上配置将无效。)ribbon.http.client.enabled=true
默认是懒加载,在第一次请求时会加载服务列表,所以第一次访问会比较慢,开启饥饿加载后会改善第一次请求较慢的现象。
#开启饥饿加载ribbon.eager-load.enabled=true#指定加载的服务名ribbon.eager-load.clients=order
未开启饥饿加载时,服务启动后控制台未输出相关内容,但是在第一次调用时会输出加载到的服务列表。
开启饥饿加载,服务启动后控制台输出了服务列表。
PS
如果你仔细观察,每次服务启动后都会看到如下告警项:
WARN 8016 --- [ main] ockingLoadBalancerClientRibbonWarnLogger : You already have RibbonLoadBalancerClient on your classpath. It will be used by default. As Spring Cloud Ribbon is in maintenance mode. We recommend switching to BlockingLoadBalancerClient instead. In order to use it, set the value of `spring.cloud.loadbalancer.ribbon.enabled` to `false` or remove spring-cloud-starter-netflix-ribbon from your project.
表达的含义就是spring cloud ribbon现在已经是维护模式了,官方建议我们使用spring-cloud-loadbalancer中的BlockingLoadBalancerClient。
Spring官方是想用自家的spring-cloud-loadbalancer替代netflix的ribbon,所以提供了BlockingLoadBalancerClient,但是目前只有一种负载均衡策略:RoundRobinLoadBalancer,并且也没有相关的超时措施等,和ribbon比起来还是有一点差距,所以尽管告警吧,目前貌似没人搭理。。。
转载地址:http://fllrb.baihongyu.com/