Ribbon
注册中心的高可用(ribbon)
注册中心
多个注册中心开启注册和抓取的功能,
注册中心互为客户端相,相互注册注册中心的服务,
同时抓取的逻辑开启,30秒抓取一次更新的内存map数据,同步到本地合并
服务提供者
但是一旦8888宕机,这个服务不会再有后续管理,所以高可用结构中,客户端服务提供者需要同时提供多个注册中心地址,只会使用其中一个,一旦宕机将会自动下沿,使用第二个
搭建步骤
准备2个以上的
eureka-server
修改和配置的application.properties
注册中心的服务名称:
eurekaserver
端口不能一样 8888 8889
注册中心相互通信开启
preferIpAddress
eureka.instance.preferIpAddress=true
客户端角色既要进行注册,也要抓取同步
eureka.client.registerWithEureka=true
eureka.client.fetchRegistry=true
两个注册中心之间相互注册,提供
serviceUrl.defaultZone
的值8888
http://localhost:8889/eureka
8889
http://localhost:8888/eureka
eureka-server01
src/main/resourses
application.properties
注册端口
defaultZone
为eureka-server01
的地址
server.port=8888 #Eureka eureka.instance.hostname=localhost eureka.instance.preferIpAddress=true eureka.client.registerWithEureka=true eureka.client.fetchRegistry=true eureka.client.serviceUrl.defaultZone=http://localhost:8889/eureka eureka.server.enable-self-preservation=false
eureka-server02
src/main/resourses
application.properties
server.port=8889 #Eureka eureka.instance.hostname=localhost eureka.instance.preferIpAddress=true eureka.client.registerWithEureka=true eureka.client.fetchRegistry=true eureka.client.serviceUrl.defaultZone=http://localhost:8888/eureka eureka.server.enable-self-preservation=false
备注
两个服务端同时启动,会出现找不到已知服务器的错误提示
Connection refused: connect
提示无法连接
Cannot execute request on any known server
发送注册请求没有任何服务响应
客户端提供注册地址多个,防止其中一个宕机导致服务续约失败
客户端提供注册地址多个,防止其中一个宕机导致服务续约失败
eureka.client.serviceUrl.defaultZone=http://localhost:8888/eureka,http://localhost:8889/eureka
ribbon组件的使用
服务器内部调用实现负载均衡
能够实现微服务集群中的服务调服务的功能
ribbon客户端搭建
eureka-client01
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.wiscom</groupId> <artifactId>eureka-server01</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.9.RELEASE</version> </parent> <name>eureka-server01</name> <url>http://maven.apache.org</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka</artifactId> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <scope>test</scope> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Edgware.RELEASE</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> </project>
src/main/resourses
application.properties
server.port=9001
# service name
spring.application.name=service-hi
#Eureka client
eureka.instance.ipAddressPrefer=true
eureka.client.registerWithEureka=true
eureka.client.fetchRegistry=false
eureka.client.serviceUrl.defaultZone=http://localhost:8888/eureka,http://localhost:8889/eureka
src/main/java
com.wiscom
StarterEurekaClient01.java
package com.wiscom; @SpringBootApplication //启动eureka注册中心的进程 @EnableEurekaClient public class StarterEurekaClient01 { public static void main(String[] args) { SpringApplication.run(StarterEurekaClient01.class, args); } }
com.wiscom.controller
HelloController.java
package com.wiscom.controller; @RestController public class HelloController { //通过属性,读取server.port @Value("${server.port}") private String port; @RequestMapping("hello") public String sayHi(String name){ return "hello "+name+",i am from "+port; } }
eureka-client02
配置与eureka-client01相同
server.port=9002
ribbont-client
pom.xml
parent继承springboot
导入springcloud的依赖dependencies
eureka-client依赖
ribbon依赖
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.wiscom</groupId> <artifactId>ribbont-client</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.9.RELEASE</version> </parent> <name>ribbont-client</name> <url>http://maven.apache.org</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <scope>test</scope> </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> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Edgware.RELEASE</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> </project>
src/main/resourses
application.properties
开启注册能力,和抓取服务的能力
eureka.client.registerWithEureka=true
eureka.client.fetchRegistry=true
向8888节点的eureka注册中心抓取服务
eureka.client.serviceUrl.defaultZone=http://localhost:8888/eureka
server.port=9004
# service name
spring.application.name=service-ribbon
#Eureka client
eureka.instance.ipAddressPrefer=true
eureka.client.registerWithEureka=true
eureka.client.fetchRegistry=true
# 可写多个服务中心
eureka.client.serviceUrl.defaultZone=http://localhost:8888/eureka
src/main/java
com.wiscom
StarterRibbon.java
ROUNDROBINRULE
轮询逻辑
RANDOMRULE
随机
WeightedResponseTimeRule
根 据响应时间设置权重值,响应时间越慢,权重值越低,反之亦然
package com.wiscom; @SpringBootApplication @EnableEurekaClient public class StarterRibbon { public static void main(String[] args) { SpringApplication.run(StarterRibbon.class, args); } //准备一个负载均衡访问的客户端对象 //RestTemplate @Bean注解实现一个对象由框架维护 @Bean @LoadBalanced //ribbon客户端扫描的负载均衡注解 public RestTemplate initRestTemplate(){ return new RestTemplate(); } @Bean public IRule initIrule(){ return new RandomRule(); } }
com.wiscom.controller
HelloController.java
package com.wiscom.controller; @RestController public class HelloController { //注入service实现底层访问服务的方法 @Autowired private HelloService helloService; @RequestMapping("sayHi") public String sayHi(String name){ return "RIBBON:"+helloService.sayHi(name); } }
com.wiscom.service
HelloService.java
package com.wiscom.service; @Service public class HelloService { //注入RestTemplate @Autowired private RestTemplate client; public String sayHi(String name) { //访问service-hi的服务提供者集群,实现负载均衡 //直接在代码中由于ribbon客户端进程的存在,由于创建 //RestTemplate使用了LoadBalanced注解,直接访问服务名称 String result = client.getForObject( "http://service-hi/hello?name=" +name, String.class); //9001/9002 hello name i am from 9001/9002 return result; } }
测试结果:
客户端访问9004的ribbon工程
实际内部做了负载均衡
服务器内部访问后端服务service-hi的提供者9001/9002
负载均衡逻辑
ROUNDROBINRULE
轮询逻辑
RANDOMRULE
随机、
WeightedResponseTimeRule
根据响应时间设置权重值,响应时间越慢,权重值越低,反之亦然
@Bean public IRule initIrule(){ return new RandomRule(); }
RIBBON的拦截逻辑
ribbon内嵌拦截器(
LoadBalancerInterceptor
)获取原有url
解析服务名称
获取服务名称对应的mapper数据
根据负载均衡从服务实例列表中选取一个
拼接地址