[TOC]
1、配置高可用的注册中心:集群
- 步骤一:修改核心yml文件,application.yml,只配置服务名(共享内容)
#服务名
spring:
application:
name: eureka_demo3
- 步骤二:创建application-10086.yml,配置10086端口和注册路径(10087)
#端口号
server:
port: 10086
#注册地址
eureka:
client:
service-url:
defaultZone: http://localhost:10087/eureka
register-with-eureka: true #是否注册自己到注册中心,默认值true(可省略)
fetch-registry: true #是否从注册中心拉取服务列表,默认值true(可省略)
- 步骤三:创建application-10087.yml,配置10087端口和注册路径(10086)
#端口号
server:
port: 10087
#注册地址
eureka:
client:
service-url:
defaultZone: http://localhost:10086/eureka
register-with-eureka: true #是否注册自己到注册中心
fetch-registry: true #是否从注册中心拉取服务列表
- 步骤四:修改核心yml文件,激活10086配置,并启动程序
#服务名
spring:
application:
name: eureka_demo3
profiles:
active: 10086
- 步骤五:修改核心yml文件,激活10087配置,并启动程序
#服务名
spring:
application:
name: eureka_demo3
profiles:
active: 10087
- 步骤六:测试结果
2、IDEA中配置多启动
3、eureka配置详情(了解原理)
服务提供者要向EurekaServer注册服务,并且完成服务续约等工作
-
服务注册
服务提供者在启动时,会检测配置属性中的:eureka.client.register-with-erueka=true参数是否正确,事实上默认就是true。如果值确实为true,则会向EurekaServer发起一个Rest请求,并携带自己的元数据信息,完成注册操作。
-
服务续约
在注册服务完成以后,服务提供者会提供一个心跳,定时向EurekaServer发送Rest请求,告诉EurekaServer:“我还活着”,称为服务续约(renew)
eureka:
instance:
lease-expiration-duration-in-seconds: 90
lease-renewal-interval-in-seconds: 30
• lease-renewal-interval-in-seconds:服务续约(renew)的间隔,默认为30秒
• lease-expiration-duration-in-seconds:服务失效时间,默认值90秒
默认:每30s,服务会向注册中心发送一次心跳,证明自己还活着,超过90秒没有发送心跳,EurekaServer会认为"你"挂了,就会从服务列表移除
3.1.1客户端的配置
#注册路径
eureka:
client:
service-url:
defaultZone: http://localhost:10086/eureka
registry-fetch-interval-seconds: 5 #从注册中心获取服务列表间隔时间
instance:
lease-expiration-duration-in-seconds: 10 #服务失效时间(10秒即过期)
lease-renewal-interval-in-seconds: 5 #服务续约时间(5秒一次心跳)
3.1.2服务端的配置
#服务名
spring:
application:
name: eureka_demo
#服务端配置
eureka:
server:
eviction-interval-timer-in-ms: 4000 #剔除失效服务间隔时间
enable-self-preservation: false #关闭自我保护
4、Ribbon负载均衡
4.1、Provider(服务提供者--集群)
- 同一个名称的服务,只要提供多个实例,注册到eureka中,就可以自动形成集群。
具体操作:
-
步骤一:创建application-8081.yml文件,并配置端口号8081
server: port: 8081
-
步骤二:创建application-8082.yml文件,并配置端口号8082
server: port: 8082
-
步骤三:为两个yml文件,分别配置启动项
- 步骤四:启动,测试
4.2、Consumer(服务调用方--消费者)
-
pon文件
<dependencies> <!--web起步依赖--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- Eureka客户端 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> <!--spring boot监控--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> </dependencies>
-
yml文件
server: port: 9090 spring: application: name: client eureka: client: service-url: defaultZone: http://localhost:10086/eureka
-
-
启动类
package com.czxy; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.EnableEurekaClient; @SpringBootApplication @EnableEurekaClient public class ClientApplication { public static void main(String[] args) { SpringApplication.run(ClientApplication.class,args); } }
-
编写配置类,配置RestTemplate实例
package com.czxy.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
@Configuration
public class HttpConfig {
@Bean
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
- 编写dao,请求提供方/test
package com.czxy.dao;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
import javax.annotation.Resource;
@Component
public class DataDao {
@Resource
private RestTemplate restTemplate;
public ResponseEntity<String> data(){
String url = "http://localhost:8081/test";
return restTemplate.getForEntity(url,String.class);
}
}
- 编写controller,显示数据,对外提供接口/data
package com.czxy.controller;
import com.czxy.dao.DataDao;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
@RestController
@RequestMapping("/data")
public class DataController {
@Resource
private DataDao dataDao;
@GetMapping
public ResponseEntity<String> data(){
return dataDao.data();
}
}
4.3、负载均衡
- eureka内置ribbon,也就是说自动集成负载均衡器。
- 负载均衡器,就是在集群环境下,选择续约的服务。
-
步骤一:修改配置类,让RestTemplate支持"服务名"访问机制
- 添加注解@LoadBalanced
package com.czxy.config; import org.springframework.cloud.client.loadbalancer.LoadBalanced; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.client.RestTemplate; @Configuration public class HttpConfig { @Bean @LoadBalanced //让RestTemplate支持负载均衡,也就是说支持“服务名”访问 public RestTemplate restTemplate(){ return new RestTemplate(); } }
-
步骤二:修改dao,使用RestTemplate进行远程调用时,使用"服务名"进行调用即可。
package com.czxy.dao; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Component; import org.springframework.web.client.RestTemplate; import javax.annotation.Resource; @Component public class DataDao { @Resource private RestTemplate restTemplate; public ResponseEntity<String> data(){ //String url = "http://localhost:8081/test"; String url = "http://service/test"; return restTemplate.getForEntity(url,String.class); } }
4、负载均衡策略
4.1.1负载均衡策略初体验
pom,添加test依赖
<!--测试-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
测试类
package com.czxy;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.netflix.ribbon.RibbonLoadBalancerClient;
import org.springframework.test.context.junit4.SpringRunner;
import javax.annotation.Resource;
/**
* @author 庭前云落
* @Date 2019/12/10 16:53
* @description
*/
@SpringBootTest(classes=ClientApplication.class) //Junit和Springboot整合,将所有实例加载到spring容器
@RunWith(SpringRunner.class) //Junit和Spring整合,将spring容器中的数据注入当前类
public class TestRibbon {
@Resource
private RibbonLoadBalancerClient client;
@Test
public void testDemo(){
//通过"服务名" 获得对应服务实例
for (int i = 0; i < 10; i++) {
ServiceInstance instance = client.choose("service");
System.out.println(instance.getHost()+":"+instance.getPort());
}
}
}
Provoider(提供方)yml,支持显示IP地址,并重启8081和8082
#服务名
spring:
application:
name: service
#注册地址
eureka:
client:
service-url:
defaultZone: http://localhost:10086/eureka
instance:
prefer-ip-address: true #显示IP地址
4.1.2修改策略
-
给指定的"服务"设置策略
服务名.ribbon.NFLoadBalancerRuleClassName=策略实现类
service4: ribbon: NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule #随机 #NFLoadBalancerRuleClassName : com.netflix.loadbalancer.BestAvailableRule #并发最少 #NFLoadBalancerRuleClassName : com.netflix.loadbalancer.WeightedResponseTimeRule #请求时间权重
Ribbon 中提供了 七种
负载均衡策略
策略类 | 命名 | 描述 |
---|---|---|
RandomRule | 随机策略 | 随机选择 Server |
RoundRobinRule | 轮询策略 | 按照顺序循环选择 Server |
RetryRule | 重试策略 | 在一个配置时间段内,当选择的 Server 不成功,则一直尝试选择一个可用的 Server |
BestAvailableRule | 最低并发策略 | 逐个考察 Server,如果 Server 的断路器被打开,则忽略,在不被忽略的 Server 中选择并发连接最低的 Server |
AvailabilityFilteringRule | 可用过滤测试 | 过滤掉一直连接失败,并被标记未 circuit tripped(即不可用) 的 Server,过滤掉高并发的 Server |
ResponseTimeWeightedRule | 响应时间加权策略 | 根据 Server 的响应时间分配权重,响应时间越长,权重越低,被选择到的几率就越低 |
ZoneAvoidanceRule | 区域权衡策略 | 综合判断 Server 所在区域的性能和 Server 的可用性轮询选择 Server,并判定一个 AWS Zone 的运行性能是否可用,剔除不可用的 Zone 中的所有 Server |
Ribbon 默认的负载均衡策略是 轮询策略
。
5、重试机制
- 重试机制:服务B访问集群环境下的服务A,某一个服务A遇到故障无法访问,服务B将尝试访问其他可以使用的服务A。
- 9090访问8081和8082
- 如果8082宕机了
- 9090将尝试访问8081
当访问到故障请求的时候,它会再尝试访问一次当前实例(次数由MaxAutoRetrires这个配置决定),如果不行,就换一实例进行访问,如果还是不行,再换一次实例访问(更换次数是由MaxAutoRetriesNextServer配置),如果依然不行,再返回失败信息。
如果你现在有A,B,C 3个服务,如果把A,B都停掉MaxAutoRetriesNextServer=2,则C可能没有被轮询查询的机会,如果你把MaxAutoRetriesNextServer=3,则没问题。
当用eureka做注册中心,当服务撕掉或者因为网络故障导致服务不可用时,eureka不会马上剔除这个服务,而是将它保留等待修复
pom,添加重试retry依赖
<!--重试机制-->
<dependency>
<groupId>org.springframework.retry</groupId>
<artifactId>spring-retry</artifactId>
</dependency>
yml,开启cloud重试机制
spring:
cloud:
loadbalancer:
retry:
enabled: true #开启重试机制
配置当前服务的重试参数
service4:
ribbon:
ConnectTimeout: 250 # Ribbon的连接超时时间
ReadTimeout: 1000 # Ribbon的数据读取超时时间
OkToRetryOnAllOperations: true # 是否对所有操作都进行重试
MaxAutoRetriesNextServer: 1 # 切换实例的重试次数
MaxAutoRetries: 1 # 对当前实例的重试次数