您的位置:首页 > 编程语言 > Java开发

[置顶] 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中@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/[/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

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: