Spring Cloud_8_SpringCloud与Ribbon
SpringCloud与RibbonSpringCloud中使用Ribbon在SpringCloud_7_Ribbon负载均衡器中,主要讲解Ribbon负载均衡机制SpringCloud集成了Ribbon,结合Eureka,可实现客户端的负载均衡在SpingCloud_4_Eureka集群中所使用RestTemplate(被@LoadBalancer修饰),都已经拥有负载均衡功能本小...
·
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/
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/
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中@RibbonClient
server:
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/
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
}
更多推荐
已为社区贡献8条内容
所有评论(0)