1、注册中心
1.1 Eureka运行机制
- 注册:客户端向服务器注册时,会一次次返回的注册,直到注册成功为止
- 拉取:客户端每30秒拉取一次注册表。更新本地的缓存的注册表
- 心跳:客户端每30秒发送一次心跳数据,服务器连续3次收不到服务的心跳,就会删除该服务。
- 自我保护模式:
1、在网络中断时,15分钟之内,==85%==的服务器出现心跳异常(一次心跳丢失),
2、自动进入保护模式,保留注册信息不删除。
3、网络恢复后,可以自动退出保护模式
4、开发调试期间,禁用保护模式,避免影响测试。
1.2 Eureka 服务端
- 创建eureka项目
- 配置依赖 pom.xml
- 配置 application.yml
- 主程序启用 eureka 服务器
- 启动,访问测试
1.3 Eureka 客户端
- 添加eureka client依赖
- yml配置eureka地址
- 修改hosts,添加eureka1和eureka
添加eureka的IP映射
172.0.0.1 eureka1
172.0.0.1 eureka2
1.3 Eureka与服务提供者 高可用
1.3.1 服务提供者高可用
1、启动参数 --server.port 可以覆盖yml中的端口配置
–server.port=8001
相同的服务以不同的端口开启多个,模拟高可用。
当加入了eureka客户端依赖之后,就会自动向eureka注册中心注册。
1.3.2 Eureka高可用
1、添加两个服务的profile配置文件
application-eureka1.yml
eureka:
instance:
hostname: eureka1
client:
register-with-eureka: true #profile的配置会覆盖公用配置
fetch-registry: true #profile的配置会覆盖公用配置
service-url:
defaultZone: http://eureka2:2002/eureka #eureka1启动时向eureka2注册
application-eureka2.yml
eureka:
instance:
hostname: eureka2
client:
register-with-eureka: true #profile的配置会覆盖公用配置
fetch-registry: true #profile的配置会覆盖公用配置
service-url:
defaultZone: http://eureka1:2001/eureka #eureka2启动时向eureka1注册
2、配置启动参数 --spring.profiles.active 和 --server.port
- eureka1 启动参数:
–spring.profiles.active=eureka1 --server.port=2001 - eureka2 启动参数:
–spring.profiles.active=eureka2 --server.port=2002 - 如果在命令行:
java -jar xxx.jar --spring.profiles.active=eureka1 --server.port=2001
访问eureka服务器
2 Ribbon
2.1 Ribbon 负载均衡
Feign集成了Ribbon,默认启动负载均衡
2.2 Riboon 重试
- 调用后台服务时,如果失败由Ribbon重试调用服务。
- Feign集成了Ribbon,默认启动重试。
- 重试参数:
1、ribbon.MaxAutoRetries:单台服务器的重试次数 0
2、ribbon.MaxAutoRetresNextServer:更换服务器次数 1
3 Zuul API网关
背景:在微服务项目中,服务多,需要一个统一的API网关入口。网关面向用户,网关转发客户端请求,访问后台服务。
功能:
3.1 统一入口
配置步骤:
3.1.1新建spring模块
新建一个模块作为网关模块
3.1.2 添加依赖
spring-cloud-starter-netflix-eureka-client 注册发现
spring-cloud-starter-netflix-zuul zuul网关
3.1.3yml配置转发规则
# 应用名称
spring:
application:
name: zuul
server:
port: 3001
eureka:
client:
service-url:
defaultZone: http://eureka1:2001/eureka,http://eureka2:2002/eureka
zuul:
routes:
item-service: /item-service/**
user_service: /user-service/**
order_service: /order-service/**
3.1.4 启动类注解
@EnableZuulProxy 启动类注解
3.2 统一权限校验
zuul的过滤器zuulProxy,可以过滤客户端的请求,在过滤器中可以检查访问权限
1、新建过滤器类,AccessFilter按照Zuul规则实现
2、将该类交给spring管理
3、zuul的自动配置,会在spring容器中发现过滤器实,完成自动配置。
配置zuul过滤器
public class Fitller extends ZuulFilter {
@Override
public String filterType() {
return FilterConstants.PRE_TYPE;
}
@Override
public int filterOrder() {
//定义过滤器的执行顺序,第六个过滤器。
//第五个过滤器中,才向里面加入了serverId
return 6;
}
@Override
public boolean shouldFilter() {
/**调用商品需要权限
* 调用用户或订单不检查权限*/
//1、获取上下文对象
RequestContext ctx = RequestContext.getCurrentContext();
//2、从上下文中获取调用的服务
String serverId = (String) ctx.get(FilterConstants.SERVICE_ID_KEY);
return serverId.equals("item-service");
}
@Override
public Object run() throws ZuulException {
//获取token参数,从请求路径中获取
//获取上下文对象
RequestContext ctx = RequestContext.getCurrentContext();
//获得request对象
HttpServletRequest request = ctx.getRequest();
//接收token参数
String token = request.getParameter("token");
//如果token不存在
if (StringUtils.isBlank(token)){
//阻止继续调用
ctx.setSendZuulResponse(false);
String json = JsonResult.build().code(400).msg("未登录").toString();
ctx.addZuulResponseHeader("Context-Type",
"application/json;charset=UTF-8");
ctx.setResponseBody(json);
}
return null;//zuul当前版本不起任何作用
}
}
3.3 集成Ribbon
负载均衡方式:轮询,hash,权重,随机等算法。
1、负载均衡默认启用,
2、重试默认禁用(减少后台服务器访问压力)
在最前面重试,能造成服务器大面积压力倍增,大面积出现故障。
3、启动重试
1)添加spring-retry依赖
2)yml配置启动重试:zuul.retryable=true
3) 如果需要可以配置重试参数
重试两种配置方法:
#对所有服务有效
ribbon:
MaxAutoRetries: 1
#对单个服务有效
item-service:
Ribon:
MaxAutoRetries: 0
3.4集成Hystrix
Hystrix是一个容错限流工具
Hystrix 容错:重试机制,与降级处理。
Hystrix 是一个延迟和容错库,旨在隔离远程系统,服务和第三方库的访问点,当出现故障是不可避免的故障时,停止级联故障
Hystrix 限流:熔断
3.4.1 Zuul网关使用Hystrix进行容错降级处理
Zuul默认以及启动Hystrix,任何基础配置不用做。
调用后台服务失败,执行签名模块中的降级代码,向客户端返回降级结果
降级结果:1、错误提示 2、返回缓存数据 3、根据业务逻辑,返回任何结果。
降级处理步骤:
1、新建降级类,ItemFB,实现FallbackProvider接口
2、添加@component注解,交给sping处理
3、Zuul的自动配置,可以自动发现降级类的实例,完成自动配置
@Component
public class ItemFB implements FallbackProvider {
/**设置针对哪个后台服务进行降级处理
* Item-service:只针对商品服务进行降级
* *:针对所有的服务都应用当前降级类
* null :对所有的服务都引用当前的降级类*/
@Override
public String getRoute() {
return "item-sevice";
}
/**向客户端返回的响应数据*/
@Override
public ClientHttpResponse fallbackResponse(String route, Throwable cause) {
//该对象是一个接口,返回的是匿名内部类
return new ClientHttpResponse() {
@Override
public HttpStatus getStatusCode() throws IOException {
//内部服务器出错-状态码
return HttpStatus.INTERNAL_SERVER_ERROR;
//可以在这里返回缓存的结构
}
//原始状态码
@Override
public int getRawStatusCode() throws IOException {
return HttpStatus.INTERNAL_SERVER_ERROR.value();
}
//返回文本字符串
@Override
public String getStatusText() throws IOException {
return HttpStatus.INTERNAL_SERVER_ERROR.getReasonPhrase();
}
@Override
public void close() {
//用来关闭下面的流,BAIS不占用底层系统资源,所以不需要关闭。
}
//设置协议体
@Override
public InputStream getBody() throws IOException {
//JsonResult - {code:500,msg:xxx,data:null}
String json = JsonResult
.build()
.code(500)
.msg("后台服务器出错请稍后重试")
.toString();
//将字符串封装到byte[]数组中返回。
return new ByteArrayInputStream(json.getBytes("UTF-8"));
}
//设置协议头
@Override
public HttpHeaders getHeaders() {
//告诉客户端我发送数据的格式
HttpHeaders headers = new HttpHeaders();
headers.add("Content-type","application/json;charset=UTF-8");
return headers;
}
};
}
}
3.4.2 Zuul集成Hystrix实现限流,熔断
当流量过大后台服务出现故障,可以断开链路,限制后台故障服务的流量,等待它从故障中恢复
实现:通过断路器实现
当短路器打开,前端请求过来直接执行降级逻辑,返回前端。不会调用远端服务,直接返回短路返回。效率高。
- 断路器打开的条件:
1)10秒20次请求(必须首先满足条件)
2)50%请求出错,执行了降级代码 - 断路器打开后,会进入半开状态
在半开状态下,会向后端服务器尝试发送一次客服端调用
3.4.2Hystrix dashboard(监控工具)
对Hystrix降级和熔断的情况进行监控,可以通过监控快速定位故障模块。
在Zuul网关模块抓取日志,然后分析,生成图表。
Hystrix使用Actuator暴露自己监控的日志
Actuator是springBoot提供的项目监控指标工具,可以暴露项目的多种监控指标
- 健康状态
- springcontext容器中所有的对象
- spring mvc 映射的所有路径
- 环境变量
- 堆内存镜像
3.4.3暴露Actuator监控指标
1、添加Actuator依赖
2、yml
m.e.w.e.i="*" #暴露全部
m.e.w.e.i=health,beans,hystryix.stream
m.e.w.e.i=hystryix.stream
3、访问(暴露的监控指标)
http://localhost:3001/actuator
MAT分析工具。分析堆内存占用情况。
3.4.3 搭建Hystrix-dashboard仪表盘
1.新建spring模块
2.添加Hystrix-dashbard依赖
3.yml配置 允许抓取日志的服务区列表
4.启动类注解 @EnableHystrixDashboard
5.访问
http://localhost:/hystrix
输入框填入:http://localhost:3001/actuator/hystrix