本章节回顾下前段时间负责搭建网关所涉及的内容:由于网关特殊性,功能简单但要求并不低;功能方面不复杂只要:流量转发,鉴权,熔断,监控;运维方面:,高并发,高可用,简化配置,不能过多要求配置增加运维成本,因此综合考虑值得用一篇文章坐下记录,便于后期有bug或回溯能快速拾起来。
zuul实践
一:路由:初始化配置,规则加载,路由缓存,请求拦截并寻址
1:路由规则:初始化读取配置
1。初始化对url路径的预处理
2。处事初始化zuulFilter拦截器(非本次重点)init提一下是有这个内容
3。初始化httpclinet 这里后面服务通信再讲,init提一下是有这个内容
2:规则加载
3:路由缓存
4:请求拦截并寻址
二:负载均衡:默认集成ribbon负载均衡和其七种算法策略,
三:服务通信:服务通信及调用原理
1:DiscoverClient源码:
2: DiscoveryClientRouteLocator属性和拥有几个重要的能力
四:熔断机制:hystix熔断回滚配置
2:补充:
Zuul网关过滤器生命周期
系统功能:
1:配置中心采用CC,公司架构组结合开源增强自研,类似nacos配置中心,disconf的功能,实现nacos自动刷新功能(不是本文重点,这里不做详解;有意可以去nacos官网学习)
2:esg服务注册与发现与nacos注册中心两者皆兼容实现(in 和 out);这里esg类似开源ESB企业服务总线在SOA架构中实现服务间智能化集成与管理的中介(不是本文重点,这里不做详解;有意可以去这github;另外这老哥总结也不错link)
3:网关zuul功能实现(重点,下面逐条)
- 路由:初始化配置,规则加载,路由缓存,请求拦截并寻址
- 负载均衡:默认集成ribbon负载均衡和其七种算法策略,
- 服务通信:服务通信及调用原理
- 熔断机制:hystix熔断回滚配置
前提概述
zuul作为Servlet的实现,对于一般情况,ZuulServet被嵌入到Spring Dispatch机制中,由DispatcherServlet分派处理,这样Spring MVC可以控制路由,并且Zuul缓冲请求。请求转发由 SimpleHostRoutingFilter、RibbonRoutingFilter 完成,前者通过Apache HttpClient来转发请求,后者与Ribbon、Hystrix一起,完成客户端负载均衡及应用守护工作。
如果需要绕过multipart处理,在不缓冲请求的情况下通过Zuul(例如,对于大文件上传),ZuulServlet也可以装载在Spring Dispatcher之外,让请求绕过DispatcherServlet。默认情况下,ZuulServlet的mapping地址是/zuul。此路径可以使用zuul.servletPath更改。
一:路由:初始化配置,规则加载,路由缓存,请求拦截并寻址
1:路由规则:初始化读取配置
1。初始化对url路径的预处理
2。处事初始化zuulFilter拦截器(非本次重点)init提一下是有这个内容
请求转发由 SimpleHostRoutingFilter、RibbonRoutingFilter 完成,前者通过Apache HttpClient来转发请求,后者与Ribbon、Hystrix一起,完成客户端负载均衡及应用守护工作。
3。初始化httpclinet 这里后面服务通信再讲,init提一下是有这个内容
2:规则加载
3:路由缓存
4:请求拦截并寻址
二:负载均衡:默认集成ribbon负载均衡和其七种算法策略,
RandomRule:随机算法实现 RoundRobinRule:轮询负载均衡策略,依次轮询所有可用服务器列表,遇到第一个可用的即返回 RetryRule :先按照RoundRobinRule策略获取服务,如果获取服务失败会在指定时间内重试 AvaliabilityFilteringRule: 过滤掉那些因为一直连接失败的被标记为circuit tripped的后端server,并过滤掉那些高并发的的后端server(active connections 超过配置的阈值) BestAvailableRule :会先过滤掉由于多次访问故障二处于断路器跳闸状态的服务,然后选择一个并发量最小的服务 WeightedResponseTimeRule: 根据响应时间分配一个weight,响应时间越长,weight越小,被选中的可能性越低 ZoneAvoidanceRule: 复合判断server所在区域的性能和server的可用性选择server
三:服务通信:服务通信及调用原理
1:DiscoverClient源码:
2: DiscoveryClientRouteLocator属性和拥有几个重要的能力
在将路由属性存入RequestContext后,上面我们提到url路径统一为requestURI属性,但是转发的目标分为3种属性,在filterType为route类型的zuulfilter对其实现最终的转发。
1.serviceId对应RibbonRoutingFilter类,order为10,委托RibbonCommand的execute方法进行转发。
2.routeHost对应SimpleHostRoutingFilter类,order为100,委托CloseableHttpClient的execute进行转发。
3.forward.to对应SendForwardFilter类,order为500,委托RequestDispatcher的forward方法进行转发。
DiscoveryClientRouteLocator它基于DiscoveryClinet路由数据来自properties静态配置和从注册中心获取的数据
- 动态添加Route
- 刷新路由
- 从DiscoveryClient获取路由信息,但用途不大
四:熔断机制:hystix熔断回滚配置
在spring cloud中,Zuul启动器中包含了Hystrix相关依赖,在Zuul网关工程中,默认是提供了Hystrix Dashboard服务监控数据的(hystrix.stream),但是不会提供监控面板的界面展示。可以说,在spring cloud中,zuul和Hystrix是无缝结合的。
/**
* 如果需要在Zuul网关服务中增加容错处理fallback,需要实现接口ZuulFallbackProvider
* spring-cloud框架,在Edgware版本(包括)之后,声明接口ZuulFallbackProvider过期失效,
* 提供了新的ZuulFallbackProvider的子接口 - FallbackProvider
* 在老版本中提供的ZuulFallbackProvider中,定义了两个方法。
* - String getRoute()
* 当前的fallback容错处理逻辑处理的是哪一个服务。可以使用通配符‘*’代表为全部的服务提供容错处理。
* 如果只为某一个服务提供容错,返回对应服务的spring.application.name值。
* - ClientHttpResponse fallbackResponse()
* 当服务发生错误的时候,如何容错。
* 新版本中提供的FallbackProvider提供了新的方法。
* - ClientHttpResponse fallbackResponse(Throwable cause)
* 如果使用新版本中定义的接口来做容错处理,容错处理逻辑,只运行子接口中定义的新方法。也就是有参方法。
* 是为远程服务发生异常的时候,通过异常的类型来运行不同的容错逻辑。
*/
@Component
public class TestFallBbackProvider implements FallbackProvider {
/**
* return - 返回fallback处理哪一个服务。返回的是服务的名称
* 推荐 - 为指定的服务定义特性化的fallback逻辑。
* 推荐 - 提供一个处理所有服务的fallback逻辑。
* 好处 - 服务某个服务发生超时,那么指定的fallback逻辑执行。如果有新服务上线,未提供fallback逻辑,有一个通用的。
*/
@Override
public String getRoute() {
return "eureka-application-service";
}
/**
* fallback逻辑。在早期版本中使用。
* Edgware版本之后,ZuulFallbackProvider接口过期,提供了新的子接口FallbackProvider
* 子接口中提供了方法ClientHttpResponse fallbackResponse(Throwable cause)。
* 优先调用子接口新定义的fallback处理逻辑。
*/
@Override
public ClientHttpResponse fallbackResponse() {
System.out.println("ClientHttpResponse fallbackResponse()");
List<Map<String, Object>> result = new ArrayList<>();
Map<String, Object> data = new HashMap<>();
data.put("message", "服务正忙,请稍后重试");
result.add(data);
ObjectMapper mapper = new ObjectMapper();
String msg = "";
try {
msg = mapper.writeValueAsString(result);
} catch (JsonProcessingException e) {
msg = "";
}
return this.executeFallback(HttpStatus.OK, msg,
"application", "json", "utf-8");
}
/**
* fallback逻辑。优先调用。可以根据异常类型动态决定处理方式。
*/
@Override
public ClientHttpResponse fallbackResponse(Throwable cause) {
System.out.println("ClientHttpResponse fallbackResponse(Throwable cause)");
if(cause instanceof NullPointerException){
List<Map<String, Object>> result = new ArrayList<>();
Map<String, Object> data = new HashMap<>();
data.put("message", "网关超时,请稍后重试");
result.add(data);
ObjectMapper mapper = new ObjectMapper();
String msg = "";
try {
msg = mapper.writeValueAsString(result);
} catch (JsonProcessingException e) {
msg = "";
}
return this.executeFallback(HttpStatus.GATEWAY_TIMEOUT,
msg, "application", "json", "utf-8");
}else{
return this.fallbackResponse();
}
}
/**
* 具体处理过程。
* @param status 容错处理后的返回状态,如200正常GET请求结果,201正常POST请求结果,404资源找不到错误等。
* 使用spring提供的枚举类型对象实现。HttpStatus
* @param contentMsg 自定义的响应内容。就是反馈给客户端的数据。
* @param mediaType 响应类型,是响应的主类型, 如:application、text、media。
* @param subMediaType 响应类型,是响应的子类型, 如:json、stream、html、plain、jpeg、png等。
* @param charsetName 响应结果的字符集。这里只传递字符集名称,如:utf-8、gbk、big5等。
* @return ClientHttpResponse 就是响应的具体内容。
* 相当于一个HttpServletResponse。
*/
private final ClientHttpResponse executeFallback(final HttpStatus status,
String contentMsg, String mediaType, String subMediaType, String charsetName) {
return new ClientHttpResponse() {
/**
* 设置响应的头信息
*/
@Override
public HttpHeaders getHeaders() {
HttpHeaders header = new HttpHeaders();
MediaType mt = new MediaType(mediaType, subMediaType, Charset.forName(charsetName));
header.setContentType(mt);
return header;
}
/**
* 设置响应体
* zuul会将本方法返回的输入流数据读取,并通过HttpServletResponse的输出流输出到客户端。
*/
@Override
public InputStream getBody() throws IOException {
String content = contentMsg;
return new ByteArrayInputStream(content.getBytes());
}
/**
* ClientHttpResponse的fallback的状态码 返回String
*/
@Override
public String getStatusText() throws IOException {
return this.getStatusCode().getReasonPhrase();
}
/**
* ClientHttpResponse的fallback的状态码 返回HttpStatus
*/
@Override
public HttpStatus getStatusCode() throws IOException {
return status;
}
/**
* ClientHttpResponse的fallback的状态码 返回int
*/
@Override
public int getRawStatusCode() throws IOException {
return this.getStatusCode().value();
}
/**
* 回收资源方法
* 用于回收当前fallback逻辑开启的资源对象的。
* 不要关闭getBody方法返回的那个输入流对象。
*/
@Override
public void close() {
}
};
}
}
2:补充:
Zuul网关过滤器生命周期
做一个
说话有趣,稳着冷静,见识高明,眼神清澈的人