SpringCloud之Ribbon:负载均衡

Spring Cloud集成了Ribbon,结合Eureka,可实现客户端的负载均衡。

下面实现一个例子,结构下图所示。

一、服务器端

1、创建项目

开发工具:IntelliJ IDEA 2019.2.3
IDEA中创建一个新的SpringBoot项目,名称为“cloud-server”,SpringBoot版本选择2.1.10,在选择Dependencies(依赖)的界面勾选Spring Cloud Discovery ->
Eureka Server,创建完成后的pom.xml配置文件自动添加SpringCloud最新稳定版本依赖,当前为Greenwich.SR3。
pom.xml完整内容如下:

1<?xml version="1.0" encoding="UTF-8"?> 2<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 3 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> 4 <modelVersion>4.0.0</modelVersion> 5 <parent> 6 <groupId>org.springframework.boot</groupId> 7 <artifactId>spring-boot-starter-parent</artifactId> 8 <version>2.1.10.RELEASE</version> 9 <relativePath/> <!-- lookup parent from repository --> 10 </parent> 11 <groupId>com.example</groupId> 12 <artifactId>cloud-server</artifactId> 13 <version>0.0.1-SNAPSHOT</version> 14 <name>cloud-server</name> 15 <description>Demo project for Spring Boot</description> 16 17 <properties> 18 <java.version>1.8</java.version> 19 <spring-cloud.version>Greenwich.SR3</spring-cloud.version> 20 </properties> 21 22 <dependencies> 23 <dependency> 24 <groupId>org.springframework.cloud</groupId> 25 <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId> 26 </dependency> 27 28 <dependency> 29 <groupId>org.springframework.boot</groupId> 30 <artifactId>spring-boot-starter-test</artifactId> 31 <scope>test</scope> 32 </dependency> 33 </dependencies> 34 35 <dependencyManagement> 36 <dependencies> 37 <dependency> 38 <groupId>org.springframework.cloud</groupId> 39 <artifactId>spring-cloud-dependencies</artifactId> 40 <version>${spring-cloud.version}</version> 41 <type>pom</type> 42 <scope>import</scope> 43 </dependency> 44 </dependencies> 45 </dependencyManagement> 46 47 <build> 48 <plugins> 49 <plugin> 50 <groupId>org.springframework.boot</groupId> 51 <artifactId>spring-boot-maven-plugin</artifactId> 52 </plugin> 53 </plugins> 54 </build> 55 56</project>

View Code

2、修改配置application.yml

1server: 2 port: 8761 3eureka: 4 client: 5 register-with-eureka: false 6 fetch-registry: false

3、修改启动类代码CloudServerApplication.java

增加注解@EnableEurekaServer

1package com.example.cloudserver; 2 3import org.springframework.boot.SpringApplication; 4import org.springframework.boot.autoconfigure.SpringBootApplication; 5import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer; 6 7@SpringBootApplication 8@EnableEurekaServer 9public class CloudServerApplication { 10 11 public static void main(String[] args) { 12 SpringApplication.run(CloudServerApplication.class, args); 13 } 14 15}

二、服务提供者

1、创建项目

IDEA中创建一个新的SpringBoot项目,除了名称为“cloud-provider”,其它步骤和上面创建服务器端一样。

2、修改配置application.yml

1spring: 2 application: 3 name: cloud-provider 4eureka: 5 instance: 6 hostname: localhost 7 client: 8 serviceUrl: 9 defaultZone: http://localhost:8761/eureka/

3、修改启动类代码CloudProviderApplication.java

增加注解@EnableEurekaClient;
让类在启动时读取控制台输入,决定使用哪个端口启动服务器;
增加一个测试用的控制器方法。

1package com.example.cloudprovider; 2 3//import org.springframework.boot.SpringApplication; 4import org.springframework.boot.autoconfigure.SpringBootApplication; 5import org.springframework.boot.builder.SpringApplicationBuilder; 6import org.springframework.cloud.netflix.eureka.EnableEurekaClient; 7import org.springframework.web.bind.annotation.RequestMapping; 8import org.springframework.web.bind.annotation.RestController; 9 10import javax.servlet.http.HttpServletRequest; 11import java.util.Scanner; 12 13@SpringBootApplication 14@EnableEurekaClient 15@RestController 16public class CloudProviderApplication { 17 18 public static void main(String[] args) { 19 //SpringApplication.run(CloudProviderApplication.class, args); 20 Scanner scan = new Scanner(System.in); 21 String port = scan.nextLine(); 22 new SpringApplicationBuilder(CloudProviderApplication.class).properties("server.port=" + port).run(args); 23 } 24 25 @RequestMapping("/") 26 public String index(HttpServletRequest request) { 27 return request.getRequestURL().toString(); 28 } 29}

三、服务调用者

1、创建项目
IDEA中创建一个新的SpringBoot项目,除了名称为“cloud-invoker”,其它步骤和上面创建服务器端一样。

2、修改配置application.yml

1server: 2 port: 9000 3spring: 4 application: 5 name: cloud-invoker 6eureka: 7 instance: 8 hostname: localhost 9 client: 10 serviceUrl: 11 defaultZone: http://localhost:8761/eureka/

3、修改启动类代码CloudInvokerApplication.java

增加注解@EnableDiscoveryClient。

1package com.example.cloudinvoker; 2 3import org.springframework.boot.SpringApplication; 4import org.springframework.boot.autoconfigure.SpringBootApplication; 5import org.springframework.cloud.client.discovery.EnableDiscoveryClient; 6 7@SpringBootApplication 8@EnableDiscoveryClient 9public class CloudInvokerApplication { 10 11 public static void main(String[] args) { 12 SpringApplication.run(CloudInvokerApplication.class, args); 13 } 14 15}

4、配置Ribbon有2种方式:使用代码、使用配置文件

方式一:使用代码
(1)新建一个自定义负载规则类MyRule.java
Ribbon的负载均衡器接口定义了服务器的操作,主要是用于进行服务器选择。
调用ILoadBalancer的getAllServers方法可以返回全部服务器,这里只返回第一个服务器。

1package com.example.cloudinvoker; 2 3import com.netflix.loadbalancer.ILoadBalancer; 4import com.netflix.loadbalancer.IRule; 5import com.netflix.loadbalancer.Server; 6 7import java.util.List; 8 9public class MyRule implements IRule { 10 11 private ILoadBalancer iLoadBalancer; 12 13 @Override 14 public Server choose(Object o) { 15 List<Server> servers = iLoadBalancer.getAllServers(); 16 System.out.println("自定义服务器规则类,输出服务器信息:"); 17 for(Server s: servers){ 18 System.out.println(" " + s.getHostPort()); 19 } 20 return servers.get(0); 21 } 22 23 @Override 24 public void setLoadBalancer(ILoadBalancer iLoadBalancer) { 25 this.iLoadBalancer = iLoadBalancer; 26 } 27 28 @Override 29 public ILoadBalancer getLoadBalancer() { 30 return this.iLoadBalancer; 31 } 32}

(2)新建一个Ping类MyPing.java

负载均衡器中提供了Ping机制,每隔一段时间去Ping服务器,判断服务器是否存活。
该工作由IPing接口的实现类负责。

1package com.example.cloudinvoker; 2 3import com.netflix.loadbalancer.IPing; 4import com.netflix.loadbalancer.Server; 5 6public class MyPing implements IPing { 7 8 @Override 9 public boolean isAlive(Server server) { 10 System.out.println("自定义Ping类,服务器信息:" + server.getHostPort() + ",状态:" + server.isAlive()); 11 return true; 12 } 13}

(3)新建配置类MyConfig.java

1package com.example.cloudinvoker.config; 2 3import com.example.cloudinvoker.MyPing; 4import com.example.cloudinvoker.MyRule; 5import com.netflix.loadbalancer.IPing; 6import com.netflix.loadbalancer.IRule; 7import org.springframework.context.annotation.Bean; 8 9public class MyConfig { 10 @Bean 11 public IRule getRule(){ 12 return new MyRule(); 13 } 14 @Bean 15 public IPing getPing(){ 16 return new MyPing(); 17 } 18}

(4)新建配置类CloudProviderConfig.java

1package com.example.cloudinvoker.config; 2 3import org.springframework.cloud.netflix.ribbon.RibbonClient; 4 5@RibbonClient(name = "cloud-provider", configuration = MyConfig.class) 6public class CloudProviderConfig { 7}

方式二:使用配置文件

把方式一的两个配置类注释掉,在application.yml的最后面添加下面配置

1cloud-provider: 2 ribbon: 3 NFLoadBalancerRuleClassName: com.example.cloudinvoker.MyRule 4 NFLoadBalancerPingClassName: com.example.cloudinvoker.MyPing 5 listOfServers: http://localhost:8080/,http://localhost:8081/

5、添加控制器 InvokerController.java

1package com.example.cloudinvoker; 2 3import org.springframework.cloud.client.loadbalancer.LoadBalanced; 4import org.springframework.context.annotation.Bean; 5import org.springframework.context.annotation.Configuration; 6import org.springframework.http.MediaType; 7import org.springframework.web.bind.annotation.RequestMapping; 8import org.springframework.web.bind.annotation.RequestMethod; 9import org.springframework.web.bind.annotation.RestController; 10import org.springframework.web.client.RestTemplate; 11 12@RestController 13@Configuration 14public class InvokerController { 15 16 @LoadBalanced 17 @Bean 18 public RestTemplate getRestTemplate(){ 19 return new RestTemplate(); 20 } 21 22 @RequestMapping(value="/router", method = RequestMethod.GET,produces = MediaType.APPLICATION_JSON_VALUE) 23 public String router(){ 24 RestTemplate restTemplate = getRestTemplate(); 25 //根据名称调用服务 26 String json = restTemplate.getForObject("http://cloud-provider/", String.class); 27 return json; 28 } 29}

四、测试

1、启动服务器端。
2、启动两个服务提供者,在控制台中分别输入8080和8081启动。
3、启动服务调用者。
4、浏览器访问http://localhost:9000/router,多次刷新页面,结果都是:

http://localhost:8081/

服务调用者项目IDEA控制台定时输出:

1自定义服务器规则类,输出服务器信息: 2 localhost:8081 3 localhost:8080 4自定义Ping类,服务器信息:localhost:8081,状态:true 5自定义Ping类,服务器信息:localhost:8080,状态:true
点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

MySQL部分从库上面因为大量的临时表tmp_table造成慢查询

背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_

皕杰报表之UUID

​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

2020年前端实用代码段,为你的工作保驾护航

有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )