eureka+zuul
3.yml配置4.0.0 springcloud1 cn.tedu 1.0-SNAPSHOT cn.tedu sp06-zuul 0.0.1-SNAPSHOT sp06-zuul Demo project for Spring Boot 1.8 org.springframework.cloud spring-cloud-starter-netflix-eureka-client org.springframework.boot spring-boot-starter-test test org.springframework.cloud spring-cloud-starter-netflix-zuul cn.tedu sp01-commons 1.0-SNAPSHOT org.springframework.boot spring-boot-maven-plugin
spring:
application:
name: zuul
# eureka2001 3001 3001 4001 5001 6001
server:
port: 3001
eureka:
client:
service-url:
defaultZone: http://eureka1:2001/eureka,http://eureka2:2002/eureka
zuul:
routes:
# **包含深层子路径
# *只包含一层路径
# service-id 作为访问子路径,是默认设置
# 根据注册表中的注册信息,zuul可以自动配置,防止注册表不全
# 最好自己手动配置
item-service: /item-service/**
user-service: /user-service/**
order-service: /order-service/**
4.启动类注解
@EnableZuulProxy
package cn.tedu.sp06;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
@SpringBootApplication
@EnableZuulProxy
public class Sp06ZuulApplication {
public static void main(String[] args) {
SpringApplication.run(Sp06ZuulApplication.class, args);
}
}
5. rest.http测试
### 获取订单的商品列表
GET http://localhost:8001/ty4g33t3
### 减少商品库存
POST http://localhost:8001/decreaseNumber
Accept: application/json
Content-Type: application/json
[{"id":1, "name":"abc", "number":23},{"id":2, "name":"def", "number":11}]
### 获取用户
GET http://localhost:8101/7
###
GET http://localhost:8101/8
###
GET http://localhost:8101/9
###
GET http://localhost:8101/10
### 增加积分
GET http://localhost:8101/8/score?score=1000
### 获取订单
GET http://localhost:8201/iujhygf435tg
### 添加订单
GET http://localhost:8201/add
# ---------------------------------------------------------------------------------
### 获取订单的商品列表
GET http://localhost:3001/item-service/ty4g33t3
### 减少商品库存
POST http://localhost:3001/item-service/decreaseNumber
Accept: application/json
Content-Type: application/json
[{"id":1, "name":"abc", "number":23},{"id":2, "name":"def", "number":11}]
### 获取用户
GET http://localhost:3001/user-service/7
###
GET http://localhost:3001/user-service/8
###
GET http://localhost:3001/user-service/9
###
GET http://localhost:3001/user-service/10
### 增加积分
GET http://localhost:3001/user-service/8/score?score=1000
### 获取订单
GET http://localhost:3001/order-service/iujhygf435tg
### 添加订单
GET http://localhost:3001/order-service/add
统一权限校验
- zuul的过滤器XZuulProxy,可以过滤客户端请求,在过滤器中可以检查访问权限
前置、路由、后置、错误过滤器
测试:http://localhost:3001/item-service/jsihfhj 没有登录不允许访问
http://localhost:3001/item-service/jsihfhj?token=ndhfjdhsjfdjs bfjhdskj 有令牌,则一登陆允许访问 (真正项目token应放在协议头,很测试没有登录系统)
- AccessFilter 按照Zull的规则实现 继承ZuulFilter
- 设置过滤器的类型
- 设置过滤器添加的顺序号
- 针对当前请求判断是否要执行下面的过滤代码
- 过滤代码
- @Component 自动扫描自动创建实例
实现代码
package cn.tedu.sp06.filter;
import cn.tedu.web.util.JsonResult;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import org.apache.commons.lang.StringUtils;
import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
@Component
public class AccessFilter extends ZuulFilter {
@Override
public String filterType() {
// return "pre";
return FilterConstants.PRE_TYPE;
}
@Override
public int filterOrder() {
return 6;
}
@Override
public boolean shouldFilter() {
//1.获得一个请求上下文对象
RequestContext ctx=RequestContext.getCurrentContext();
//2.从上下文对象获得调用后台服务的 serviceid 类型要转成字符串类型
String serviceId = (String)ctx.get(FilterConstants.SERVICE_ID_KEY);//"serviceId"
//3.如果调用了item-service 返回true
return "item-service".equals(serviceId);
}
@Override
public Object run() throws ZuulException {
//1.获得上下文对象
RequestContext ctx=RequestContext.getCurrentContext();
//2.获得Request对象
HttpServletRequest request = ctx.getRequest();
//3.接收token参数
String token = request.getParameter("token");
//4.如果token不存在: ①null ②"" ③" "
if(StringUtils.isBlank(token)){ //区别idEmpty()
//5.阻止继续调用
ctx.setSendZuulResponse(false);//发送zuul响应关闭
//6.直接返回响应 提示未登录
//JsonResult--{code:400,msg:未登录,data:null}
String json=JsonResult.build().code(400).msg("not log in").toString();
//响应协议头
ctx.addZuulResponseHeader("Content-Type", "application/json;charset=UTF-8");
//响应协议体
ctx.setResponseBody(json);
}
return null;//zuul当前版本这个返回值不起任何作用
}
}
设置过滤器的类型
实现效果
- 为什么顺序号为6???
- 前置过滤器中有五个默认过滤器PreDecorationFilter 自定义过滤器放在末尾 位置为6
在第五个过滤器放入了serviceid
- 负载均衡默认启用
- 重试默认禁用
- 在最前面重试会造成后台服务器大面积出现故障
也可以启用重试,一般不会启用
设置: - 添加spring-retry依赖
org.springframework.retry spring-retry
- yml配置启用重试
spring:
application:
name: zuul
# eureka2001 3001 3001 4001 5001 6001
server:
port: 3001
eureka:
client:
service-url:
defaultZone: http://eureka1:2001/eureka,http://eureka2:2002/eureka
zuul:
routes:
# **包含深层子路径
# *只包含一层路径
# service-id 作为访问子路径,是默认设置
# 根据注册表中的注册信息,zuul可以自动配置,防止注册表不全
# 最好自己手动配置
item-service: /item-service/**
user-service: /user-service/**
order-service: /order-service/**
retryable: true
# 对所有服务都有效的通用配置
ribbon:
MaxAutoRetries: 1
# 对某一个单独配置
item-service:
ribbon:
MaxAutoRetries: 0
Zuul集成Hystrix
- Hystrix是容错和限流工具(与sentinel相似)
- Hystrix容错:通过降级处理
- Hystrix限流:熔断
- Zuul默认已经启用Hystrix,任何基础配置都不用做
- 调用后台服务失败,执行前面模块中的降级代码,返回降级结果
①给出错误提示
②返回缓存数据
③根据业务逻辑返回任何结果都可以
package cn.tedu.sp06.fb;
import cn.tedu.web.util.JsonResult;
import org.springframework.cloud.netflix.zuul.filters.route.FallbackProvider;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.stereotype.Component;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
@Component
public class itemFB implements FallbackProvider {
@Override
public String getRoute() {
return "item-service";
}
@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 msg data}
String json = JsonResult.build().code(500).msg("后台服务出错请稍后重试").toString();
return new ByteArrayInputStream(json.getBytes("UTF-8"));
}
@Override
public HttpHeaders getHeaders() {
HttpHeaders h = new HttpHeaders();
h.add("Content-Type", "application/json;charset=UTF-8");
return h;
}
};
}
}
2.新建降级类 ItemFB 实现FallbackProvider接口
package cn.tedu.sp06.fb;
import cn.tedu.web.util.JsonResult;
import org.springframework.cloud.netflix.zuul.filters.route.FallbackProvider;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.stereotype.Component;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
@Component
public class orderFB implements FallbackProvider {
@Override
public String getRoute() {
return "order-service";
}
@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 msg data}
String json = JsonResult.build().code(500).msg("后台服务出错请稍后重试").toString();
return new ByteArrayInputStream(json.getBytes("UTF-8"));
}
@Override
public HttpHeaders getHeaders() {
HttpHeaders h = new HttpHeaders();
h.add("Content-Type", "application/json;charset=UTF-8");
return h;
}
};
}
}
实现效果
- 当流量 过大,后台服务出现故障,可以断开链路,限制后台故障服务
- 在06添加断路器,断开连接后,直接执行06的降级代码(不会进行远程调用),返回降级结果(短路请求),执行效率很高
断路器打开条件:
①20次/10s 请求,必须首先满足
②50%请求出错,执行了降级代码
if(20){if(50%){}} - 断路器打开之后,会进入半开状态
在半开状态下,会向服务器尝试发送一次客户端调用
调用成功,自动关闭断路器恢复正常;
调用失败,继续保持打开状态。再进入半开状态
打开 半开 打开 半开…循环
- 对降流和熔断的情况进行监控,可以通过监控快速定位故障模块
- 调用02.03.04在06产生监控日志 使用Actuator工具
- Actuator是spring提供的监控指标工具,可以暴露项目的各种监控指标
①健康状态
②spring容器中的所有对象
③spring mvc 映射的所有路径
④环境变量
⑤堆内存镜像(java虚拟机使用的堆内存)
org.springframework.cloud >spring-cloud-starter-netflix-zuul
actuator依赖于zuul
2. 06yml配置m.e.w.e.i="*" # *:暴露所有监控指标
m.e.w.e.i=health,beans,mappings # *:暴露指定监控指标
m.e.w.e.i=hystrix.stream
***********************************************************
#暴露actuator的监控指标
management:
endpoints:
web:
exposure:
include: "*" #暴露所有监控
3.访问
http://localhost:3001/actuator
### actuator GET http://localhost:3001/actuator ### GET http://localhost:3001/actuator/health ### GET http://localhost:3001/actuator/info ### GET http://localhost:3001/actuator/beans ### GET http://localhost:3001/actuator/mappings ### GET http://localhost:3001/actuator/heapdump ### GET http://localhost:3001/actuator/hystrix.stream # 监控数据路径搭建Hystrix-dashboard(仪表盘) 1. 新建spring模块: sp07-hystrix-dashboard 2. 调整pom.xml 添加hystrix dashboard依赖
3. 配置yml4.0.0 springcloud1 cn.tedu 1.0-SNAPSHOT cn.tedu sp07-hystrix-dashboard 0.0.1-SNAPSHOT sp07-hystrix-dashboard Demo project for Spring Boot 1.8 UTF-8 UTF-8 org.springframework.cloud spring-cloud-starter-netflix-hystrix-dashboard org.springframework.boot spring-boot-starter-test test org.apache.maven.plugins maven-compiler-plugin 3.8.1 1.8 1.8 UTF-8 org.springframework.boot spring-boot-maven-plugin 2.4.1 cn.tedu.sp07.Sp07HystrixDashboardApplication repackage repackage
server:
port: 4001
#允许抓取日志的服务器列表
hystrix:
dashboard:
proxy-stream-allow-list: localhost
4. 启动类添加注解
@EnableHystrixDashboard
package cn.tedu.sp07;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard;
@SpringBootApplication
@EnableHystrixDashboard
public class Sp07HystrixDashboardApplication {
public static void main(String[] args) {
SpringApplication.run(Sp07HystrixDashboardApplication.class, args);
}
}
5. 启动访问
http://localhost:4001/hystrix http://localhost:3001/actuator/hystrix.stream
首先需要调用远端服务
ab -n 20000 -c 50 http://localhost:3001/item-service/u56y4?token=u5y4f3 ab -n 20000 -c 50 http://localhost:3001/user-service/3
Apache24服务器里自带ab压力测试工具
1.zuul是什么??
2.使用zuul网关的准备工作??
创建zuul工程→添加eureka+zuul依赖→配置eureka、zuul.routes→启动类上添加@EnableZuulProxy注解→测试
3.zuul的作用???
统一的入口
统一的权限校验 使用ZuulFilter类(过滤器)
集成Ribbon
集成hystrix
4.Zuul的过滤器分类??
前置、后置、路由、错误过滤器
5.如何配置ZuulFilter过滤器??
设置过滤器的类型
设置过滤器添加的顺序号
针对当前请求判断是否要执行下面的过滤代码
过滤代码
6.StringUtils.isBlank()与isEmpty()区别??
isBlank():字符串为null “” “ ” 返回true
isEmpty():字符串为 null “” 返回true
7.设置过滤器添加的顺序号为6???
前置过滤器中有五个默认过滤器PreDecorationFilter 自定义过滤器放在末尾 位置为6
在第五个过滤器放入了serviceid
8.Ribbon作用??
负载均衡+重试
9.zuul集成ribbon默认开启吗??
是默认关闭的 可以手动开启(在yml文件中配置)
10.hystrix作用???
Hystrix是容错和限流工具(与sentinel相似)
Hystrix容错:通过降级处理
Hystrix限流:熔断
11.Zuul默认开启hystrix,那么如何进行容错处理??降级 具体步骤??
首先创建FallbackProvider接口的实现类
调用后台服务失败,执行前面模块中的降级代码,返回降级结果
设置针对哪个后台服务进行降级
设置向客户端返回的响应数据
12.Zuul集成hystrix如何实现限流??
断路器
断路器开启的条件??
①20次/10s 请求,必须首先满足
②50%请求出错,执行了降级代码
13.Actuator是什么??
Actuator是spring提供的监控指标工具,可以暴露项目的各种监控指标
①健康状态
②spring容器中的所有对象
③spring mvc 映射的所有路径
④环境变量
⑤堆内存镜像(java虚拟机使用的堆内存)
14.Hystrix 的dashboard作用???
对降流和熔断的情况进行监控,可以通过监控快速定位故障模块



