源代码获取点击[这里](https://github.com/fymod/easy-spring-cloud) # 概念 Ribbon是负载均衡器,默认提供了多种负载均衡算法,例如轮询、随机等等。在Spring Cloud中,一般将Ribbon和服务注册发现(如Eureka)结合使用,比如启用多个相同的Eureka Client(一般在不同的服务器上),然后另外一个客户端来调用多个相同的client,是逐个调用,还是随机调用,还是根据自己配置好的策略来调用等。 # 项目概况 - 新建一个Eureka Server,和之前的一致 - 新建两个Eureka Client,spring.application.name要相同,这样在注册到server的时候就是相同的两个了 - 新建一个调用层(如web),也是Eureka Client,来调用相同name的两个client # Eureka Server 新建一个普通的Eureka Server,分别配置application.yml、pom.xml和添加注解@EnableEurekaServer ~~~ <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId> </dependency> ~~~ ~~~ server: port: 9020 eureka: client: register-with-eureka: false fetch-registry: false service-url: defaultZone: http://localhost:9020/eureka/ ~~~ 以上步骤完成后,直接启动即可,然后浏览器地址栏输入http://localhost:9020/eureka查看界面。 # Eureka Client 新建两个相同的Eureka Client,只是端口不一致。 添加的依赖至少要有: ~~~ <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> ~~~ application.yml文件中配置除了端口号外,其他一致(特别是spring.application.name必须一样): ~~~ server: port: 9021 spring: application: name: ribbon-client eureka: client: service-url: defaultZone: http://localhost:9020/eureka/ instance: prefer-ip-address: true ~~~ 在启动类中添加注解@EnableDiscoveryClient,声明这是一个Eureka Client。注解也可以使用@EnableEurekaClient,不同的是@EnableDiscoveryClient同时还可以作为Zookeeper、Consul中发现注解,作用范围更广一些。 为了可以让后续的项目来调用,两个client都新建一个Controller,代码为: ~~~ import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RestController; @RestController public class TestController { @GetMapping("/{id}") public String getMessage(@PathVariable Long id) { return "the request1 id is " + id; } } ~~~ 两个client不同的是需要将返回内容简单修改下,以便清除确认是谁返回的,比如讲上面的request1改成request2就是第二个controller中的返回内容了。 启动完成后查看server的web管理端,可以看到有ribbon-client了,地址端口为配置好的两个。 # Web Web项目也是一个Eureka Client,pom.xml引入和上面的一致。 ~~~ <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> ~~~ 本篇要介绍ribbon,但是上面的引入并没有ribbon相关,这是因为eureka-client已经包含了ribbon,如果不是和eureka-client集成,需要添加以下依赖: ~~~ <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-ribbon</artifactId> </dependency> ~~~ 在项目入口类中,添加注解@EnableDiscoveryClient,同时添加Bean的引入 ~~~ @Bean @LoadBalanced RestTemplate restTemplate() { return new RestTemplate(); } ~~~ 这里的@LoadBalanced注解可以为RestTemplate整合Ribbon时期具有负载均衡的能力。 application.yml文件和前述的大体一致: ~~~ server: port: 9023 spring: application: name: ribbon-web eureka: client: service-url: defaultZone: http://localhost:9020/eureka/ instance: prefer-ip-address: true ~~~ 接下来是核心的调用Controller,先上代码 ~~~ 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.GetMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.client.RestTemplate; @RestController public class WebController { @Autowired private RestTemplate restTemplate; @Autowired private LoadBalancerClient loadBalancerClient; @GetMapping("/test") public String test() { String result = restTemplate.getForObject("http://ribbon-client/123",String.class); System.out.println(result); return result; } @GetMapping("/test2") public String test2() { ServiceInstance serviceInstance = loadBalancerClient.choose("ribbon-client"); String result = serviceInstance.getServiceId() + ":" + serviceInstance.getHost() + ":" + serviceInstance.getPort(); System.out.println(result); return result; } } ~~~ 其中,/test调用是测试调用client中的方法,可以多调用几次,分别查看网页端内容或者控制台打印的内容。/test2是用来展示如何使用LoadBalancerClient获取正在调用的服务信息,多调用几次,分别查看网页端微服务信息或者查看控制台打印。 两个测试地址分别为:http://localhost:9023/test http://localhost:9023/test2 会发现对两个client的调用时轮询的,逐个调用。 # 修改策略 可以查看com.netflix.loadbalancer包中的类,对应多种不同Rule,比如随机调用的RandomRule等,本篇将上述的web调用策略修改为随机调用。 查看application.yml文件,添加以下内容: ~~~ ribbon-client: ribbon: NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule ~~~ 调用策略修改完成,测试两个地址,查看打印内容是否变成了随机。 上面的格式为"微服务名称.ribbon.策略对应完整路径类",ribbon-client是我定义调用微服务的名称,com.netflix.loadbalancer.RandomRule是对应的完整策略类,之所以要写全称,也就是为了方便可以使用自定义的策略,这时只需要将路径类修改成自己定义的就行了。 源代码获取点击<https://github.com/fymod/easy-spring-cloud>