[置顶] Spring Cloud_8_SpringCloud与Ribbon
2018-03-03 16:11
507 查看
SpringCloud与Ribbon
SpringCloud中使用Ribbon在SpringCloud_7_Ribbon负载均衡器中,主要讲解Ribbon负载均衡机制
SpringCloud集成了Ribbon,结合Eureka,可实现客户端的负载均衡
在SpingCloud_4_Eureka集群中所使用RestTemplate(被@LoadBalancer修饰),都已经拥有负载均衡功能
本小节以RestTemplate为基础,讲述及测试Eureka中Ribbon配置
使用Spring自动配置
在配置文件中配置
1、准备工作
新建Eureka服务器项目:atm_eureka_ribbon_server,端口为8761新建Eureka服务提供者项目:atm_eureka_ribbon_provider,主要工作
在控制器里面,发布一个REST服务,地址为“/person/{personId}”,请求后返回Person实例,其中Pereson的message为Http请求的URL
服务提供者需要启动两次,所以在控制台中需要输入启动端口
新建Eureka服务调用者项目:atm_eureka_ribbon_invoker,对外端口9000
下面是项目结构图
1.1、新建atm_eureka_ribbon_server
1.1.1、引入依赖
<!-- Spring Cloud --> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Dalston.SR3</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka-server</artifactId> </dependency>
1.1.2、配置文件
server: port: 8761 eureka: client: registerWithEureka: false fetchRegistry: false
1.1.3、启动类
package com.atm.cloud; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer; @SpringBootApplication @EnableEurekaServer public class MyEurekaRibbonServer { public static void main(String[] args) { SpringApplication.run(MyEurekaRibbonServer.class, args); } }
1.2、新建atm_eureka_ribbon_provider
1.2.1、引入依赖
<!-- Spring Cloud --> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Dalston.SR3</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <!-- 服务提供者 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-config</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka</artifactId> </dependency> <!-- 服务提供者 -->
1.2.2、配置文件
spring: application: name: atm-eureka-ribbon-provider eureka: client: serviceUrl: defaultZone: http://localhost:8761/eureka/[/code]1.2.3、启动类
package com.atm.cloud; import java.util.Scanner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.cloud.netflix.eureka.EnableEurekaClient; @SpringBootApplication @EnableEurekaClient public class MyEurekaRibbonProvider { public static void main(String[] args) { // 读取控制台输入,避免端口冲突 Scanner scanner = new Scanner(System.in); String port = scanner.nextLine(); new SpringApplicationBuilder(MyEurekaRibbonProvider.class).properties( "server.port=" + port).run(args); } }1.2.4、控制器
package com.atm.cloud; import javax.servlet.http.HttpServletRequest; import org.springframework.http.MediaType; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; @RestController public class MyController { @RequestMapping(value = "/person/{personId}", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) public Person findPerson(@PathVariable("personId")Integer personId,HttpServletRequest request){ Person person=new Person(); person.setId(personId); person.setAge(18); person.setName(request.getRequestURL().toString()); return person; } }1.3、新建atm_erueka_ribbon_invoker
1.3.1、引入依赖
<!-- Spring Cloud --> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Dalston.SR3</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <!-- 服务调用者 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-config</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka</artifactId> </dependency> <dependency><!-- 负载均衡框架 --> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-ribbon</artifactId> </dependency> <!-- 服务调用者 -->1.3.2、配置文件
server: port: 9000 spring: application: name: atm-eurake-ribbon-invoker eureka: client: serviceUrl: defaultZone: http://localhost:8761/eureka/[/code]1.3.3、启动类
package com.atm.cloud; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; @SpringBootApplication @EnableDiscoveryClient public class MyEurekaRibbonInvoker { public static void main(String[] args) { SpringApplication.run(MyEurekaRibbonInvoker.class, args); } }1.3.4、控制器
package com.atm.cloud; import org.springframework.cloud.client.loadbalancer.LoadBalanced; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.MediaType; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.client.RestTemplate; @RestController @Configuration public class MyInvokerController { @Bean @LoadBalanced public RestTemplate getRestTemplate() { return new RestTemplate(); } @RequestMapping(value="/router",method=RequestMethod.GET, produces=MediaType.APPLICATION_JSON_VALUE) public String router() { RestTemplate restTemplate = getRestTemplate(); // 根据应用名称调用服务 String json = restTemplate.getForObject( "http://atm-eureka-ribbon-provider/person/1", String.class); return json; } }1.4、回顾
启动atm_eureka_ribbon_server
分别以8080、8081端口启动atm_eureka_ribbon_provider
启动atm_eureka_ribbon_invoker
浏览器访问http://localhost:9000/router
端口轮询调用2、调用者配置Ribbon
之前已经讲述了负载规则以及Ping,在SpringCloud中,可将自定义的负载规则以及Ping类,发到服务器调用者中2.1、自定义IRule(编写自定义规则类)
package com.atm.cloud; import java.util.ArrayList; import java.util.List; import java.util.Random; import com.netflix.loadbalancer.ILoadBalancer; import com.netflix.loadbalancer.IRule; import com.netflix.loadbalancer.Server; /** * 编写自定义规则 * * @author aitemi * */ public class MyRule implements IRule { ILoadBalancer iLoadBalancer; public Server choose(Object key) { // 获取所有的服务器 List<Server> servers = iLoadBalancer.getAllServers(); // 使用自定义规则,随机数大于7,访问8080端口,否则使用8081端口 Random random = new Random(); int ranNum = random.nextInt(10); System.out.println("-- 这是自定义规则类, 输出服务器信息 ,随机数为:" + ranNum + " --->>>"); if (ranNum > 7) { return getServerByPort(servers, 8080); } return getServerByPort(servers, 8081); } public Server getServerByPort(List<Server> servers, int port) { for (Server server : servers) { if (server.getPort() == port) { System.out.println(" " + server.getHostPort()); return server; } } return null; } public ILoadBalancer getLoadBalancer() { return this.iLoadBalancer; } public void setLoadBalancer(ILoadBalancer ibBalancer) { this.iLoadBalancer = ibBalancer; } }2.2、配置自定义规则
package com.atm.cloud; import org.springframework.context.annotation.Bean; import com.netflix.loadbalancer.IRule; /** * 配置自定义规则 * @author aitemi * */ public class MyConfig { @Bean public IRule getRule(){ return new MyRule(); } /** * 问题:如何让Spring容器知道,有这么一个配置类存在呢? */ }2.3、Spring中自动配置
package com.atm.cloud; import org.springframework.cloud.netflix.ribbon.RibbonClient; /** * 1.使Spring容器得知我们自定义的配置类 * 2.name="atm-eureka-ribbon-provider",建议调用那个服务就配置那个服务 * 3.当调用"atm-eureka-ribbon-provider",这个服务的时候,将使用这个配置 * * @author aitemi * */ @RibbonClient(name = "atm-eureka-ribbon-provider", configuration = MyConfig.class) public class MyInvokerConfig { }
启动atm_eureka_ribbon_server服务器
启动atm_eureka_ribbon_provide客户端,分别以8080、8081端口启动
启动atm_eureka_ribbon_invoker客户端
浏览器访问http://localhost:9000/router
@RibbonClient(name = “atm-eureka-ribbon-provider”, configuration = MyConfig.class),这个时候访问atm-eureka-ribbon-provider,自定义规则生效2.4、配置文件中配置
测试时,记得先注释MyInvokerConfig中@RibbonClientserver: port: 9000 spring: application: name: atm-eurake-ribbon-invoker atm-eureka-ribbon-provider: ribbon: NFLoadBalancerRuleClassName: com.atm.cloud.MyRule eureka: client: serviceUrl: defaultZone: http://localhost:8761/eureka/[/code]3、使用Spring封装的Ribbon
SpringCloud对Ribbon进行了封装(负载客户端、负载均衡器等,可以直接使用Spring的LoadBalancerClient来处理请求以及服务选择)3.1、LoadBalancerClient
3.1.1、修改MyInvokerController
package com.atm.cloud; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cloud.client.ServiceInstance; import org.springframework.cloud.client.loadbalancer.LoadBalanced; import org.springframework.cloud.client.loadbalancer.LoadBalancerClient; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.client.RestTemplate; @RestController @Configuration public class MyInvokerController { @LoadBalanced @Bean public RestTemplate getRestTemplate() { return new RestTemplate(); } @GetMapping("/router") @ResponseBody public String router() { RestTemplate restTemplate = getRestTemplate(); // 根据应用名称调用服务 String json = restTemplate.getForObject( "http://atm-eureka-ribbon-provider/person/1", String.class); return json; } // 使用SpringCloud集成Ribbon -- start @Autowired private LoadBalancerClient loadBalancerClient; @GetMapping("/lb") @ResponseBody public ServiceInstance lb() { // 让SpringCloud集成的Ribbon帮助我们选择服务实例 ServiceInstance serviceInstance = loadBalancerClient .choose("atm-eureka-ribbon-provider"); return serviceInstance; } // 使用SpringCloud集成Ribbon -- end }
同样使用了自定义规则3.2、SpringCloud中Ribbon的默认配置
查看SpringCloud中Ribbon的默认配置package com.atm.cloud; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cloud.client.ServiceInstance; import org.springframework.cloud.client.loadbalancer.LoadBalanced; import org.springframework.cloud.client.loadbalancer.LoadBalancerClient; import org.springframework.cloud.netflix.ribbon.SpringClientFactory; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.client.RestTemplate; import com.netflix.loadbalancer.ZoneAwareLoadBalancer; @RestController @Configuration public class MyInvokerController { @LoadBalanced @Bean public RestTemplate getRestTemplate() { return new RestTemplate(); } @GetMapping("/router") @ResponseBody public String router() { RestTemplate restTemplate = getRestTemplate(); // 根据应用名称调用服务 String json = restTemplate.getForObject( "http://atm-eureka-ribbon-provider/person/1", String.class); return json; } // 使用SpringCloud集成Ribbon -- start @Autowired private LoadBalancerClient loadBalancerClient; @GetMapping("/lb") @ResponseBody public ServiceInstance lb() { // 让SpringCloud集成的Ribbon帮助我们选择服务实例 ServiceInstance serviceInstance = loadBalancerClient .choose("atm-eureka-ribbon-provider"); return serviceInstance; } // 使用SpringCloud集成Ribbon -- end // 查看SpringCloud中的Ribbon配置 -- start @Autowired private SpringClientFactory springClientFactory; @GetMapping("/fa") public String factory() { System.out.println("---- >>> 查看默认配置 <<< ----\n"); ZoneAwareLoadBalancer zoneAwareLoadBalancer = (ZoneAwareLoadBalancer) springClientFactory .getLoadBalancer("default"); System.out.println("ICientConfig\t" + springClientFactory.getLoadBalancer("default").getClass() .getName() + "\n"); System.out.println("IRule\t" + zoneAwareLoadBalancer.getRule().getClass().getName() + "\n"); System.out.println("ServerList\t" + zoneAwareLoadBalancer.getServerListImpl().getClass() .getName() + "\n"); System.out .println("ServerListFilter\t" + zoneAwareLoadBalancer.getFilter().getClass() .getName() + "\n"); System.out.println("ILoadBalancer\t" + zoneAwareLoadBalancer.getClass().getName() + "\n"); System.out.println("PingInterval\t" + zoneAwareLoadBalancer.getPingInterval() + "\n\n"); System.out .println("---- >>> atm-eureka-ribbon-privoder配置 <<< ----\n"); ZoneAwareLoadBalancer zoneAwareLoadBalancer2 = (ZoneAwareLoadBalancer) springClientFactory .getLoadBalancer("atm-eureka-ribbon-privoder"); System.out.println(" IClientConfig\t" + springClientFactory .getLoadBalancer("atm-eureka-ribbon-privoder-provider") .getClass().getName() + "\n"); System.out.println(" IRule\t" + zoneAwareLoadBalancer2.getRule().getClass().getName() + "\n"); System.out.println(" IPing\t" + zoneAwareLoadBalancer2.getPing().getClass().getName() + "\n"); System.out.println(" ServerLis\t" + zoneAwareLoadBalancer2.getServerListImpl().getClass() .getName() + "\n"); System.out.println(" ServerListFilter\t" + zoneAwareLoadBalancer2.getFilter().getClass().getName() + "\n"); System.out.println(" ILoadBalancer\t" + zoneAwareLoadBalancer2.getClass().getName() + "\n"); System.out.println(" PingInterval\t" + zoneAwareLoadBalancer2.getPingInterval()); return ""; } // 查看SpringCloud中的Ribbon配置 -- end }
浏览器访问http://localhost:9000/fa
相关文章推荐
- 疯狂Spring Cloud连载(8)——Spring Cloud与Ribbon
- [置顶] Spring cloud系列一 包含所有基本要素的完整Spring Cloud demo
- Spring Cloud学习:02服务消费者(Ribbon&Feign)
- 如何用springcloud找妹纸之5--- 一个寻找"妹纸"的路人甲(rest+ribbon)
- Spring Cloud搭建手册(6)——Spring Cloud Zuul
- Spring Cloud 客户端负载均衡之Ribbon(三)
- springcloud使用ribbon实现客户端负载均衡
- Spring Cloud 之 Spring Cloud Zuul(七)
- spring-cloud-ribbon负载均衡(一)
- Spring Cloud应用进行服务追踪分析(Zipkin和spring cloud Sleuth)
- 【Spring Cloud】Ribbon负载均衡
- 【Spring Cloud】Ribbon负载均衡
- springboot-cloud-8-ribbon-source
- SpringCloud Ribbon的分析
- spring cloud概述,为何使用spring cloud
- Spring Cloud Eureka+Ribbon+Hystrix
- Spring Cloud(十一)高可用的分布式配置中心 Spring Cloud Bus 消息总线集成(RabbitMQ)
- Spring Cloud Ribbon
- Spring Cloud+Eureka+Ribbon实现客户端负载均衡
- Spring Cloud Ribbon