一、Zuul简介
Zuul相当于是第三方调用和服务提供方之间的防护门 , 其中最大的亮点就是可动态发布过滤器
二、Zuul可以为我们提供什么
1、权限控制
2、预警和监控
3、红绿部署、(粘性)金丝雀部署 , 流量调度支持
4、流量复制转发 , 方便分支测试、埋点测试、压力测试
5、跨区域高可用 , 异常感知
6、防爬防攻击
7、负载均衡、健康检查和屏蔽坏节点
8、静态资源处理
9、重试容错服务
三、Zuul网关架构
文章插图
可以看到其架构主要分为发布模块、控制管理加载模块、运行时模块、线程安全的请求上下文模块 。在Spring Cloud中 , Zuul每个后端都称为一个Route,为了避免资源抢占 , 整合了Hystrix进行隔离和限流 , 基于线程的隔离机制 , 另外一种机制是信号量 , 后面文章会提到 。Zuul默认使用ThreadLocal
protected static final ThreadLocal<? extends RequestContext> threadLocal = new ThreadLocal<RequestContext>() { @Override protected RequestContext initialValue() { try { return contextClass.newInstance(); } catch (Throwable e) { e.printStackTrace(); throw new RuntimeException(e); } }};
文章插图
请求处理生命周期 , ”pre” filters(认证、路由、请求日记)->”routing filters”(将请求发送到后端)->”post” filters(增加HTTP头、收集统计和度量、客户端响应)
四、过滤器
一些概念
1、类型Type,定义被运行的阶段 , 也就是preroutingposterror阶段
2、顺序Execution Order,定义同类型链执行中顺序
3、条件Criteria,定义过滤器执行的前提条件
4、动作Action , 定义过滤器执行的业务
下面是一个DEMO
class DebugFilter extends ZuulFilter { static final DynamicBooleanProperty routingDebug = DynamicPropertyFactory.getInstance().getBooleanProperty(ZuulConstants.ZUUL_DEBUG_REQUEST, true) static final DynamicStringProperty debugParameter = DynamicPropertyFactory.getInstance().getStringProperty(ZuulConstants.ZUUL_DEBUG_PARAMETER, "d") @Override String filterType() { return 'pre' } @Override int filterOrder() { return 1 } boolean shouldFilter() { if ("true".equals(RequestContext.getCurrentContext().getRequest().getParameter(debugParameter.get()))) { return true } return routingDebug.get(); } Object run() { RequestContext ctx = RequestContext.getCurrentContext() ctx.setDebugRouting(true) ctx.setDebugRequest(true) ctx.setChunkedRequestBody() return null; }五、代码剖析
在Servlet API 中有一个ServletContextListener接口 , 它能够监听 ServletContext 对象的生命周期 , 实际上就是监听 Web 应用的生命周期 。接口中定义了两个方法
/** * 当Servlet 容器启动Web 应用时调用该方法 。在调用完该方法之后 , 容器再对Filter 初始化 , * 并且对那些在Web 应用启动时就需要被初始化的Servlet 进行初始化 。*/contextInitialized(ServletContextEvent sce) /** * 当Servlet 容器终止Web 应用时调用该方法 。在调用该方法之前 , 容器会先销毁所有的Servlet 和Filter 过滤器 。*/contextDestroyed(ServletContextEvent sce)在Zuul网关中
public class InitializeServletListener implements ServletContextListener {@Overridepublic void contextInitialized(ServletContextEvent arg0) { try { //实例化 initZuul();} catch (Exception e) { LOGGER.error("Error while initializing zuul gateway.", e); throw new RuntimeException(e); }}private void initZuul() throws Exception { //文件管理 FilterFileManager.init(5, preFiltersPath, postFiltersPath, routeFiltersPath, errorFiltersPath); //从DB中加载Filter startZuulFilterPoller(); }}在initZuul中 , FilterFileManager主要是做文件管理 , 起一个poll Thread , 定期把FilterDirectory中file放到FilterLoader中 , 在FilterLoad中会进行编译再放到filterRegistry中 。而startZuulFilterPoller主要是判断DB中有是否变化或者新增的Filer,然后写到FilterDirectory中
public boolean putFilter(File file) throws Exception { Class clazz = COMPILER.compile(file); if (!Modifier.isAbstract(clazz.getModifiers())) { //通过反射创建对象 , 可以对此类一无所知 filter = (ZuulFilter) FILTER_FACTORY.newInstance(clazz); filterRegistry.put(file.getAbsolutePath() + file.getName(), filter); filterClassLastModified.put(sName, file.lastModified()); //二次hash检查 List<ZuulFilter> list = hashFiltersByType.get(filter.filterType()); if (list != null) { hashFiltersByType.remove(filter.filterType()); //rebuild this list } } }
推荐阅读
- 消防工程师报考条件是什么?
- 怎么开发直播APP?资深技术划重点了
- 系统架构师、算法工程师、人工智能工程师需要学多少数学?
- 我的六年软件测试工程师感悟
- 京东网上购物有哪些流程
- 前端工程师如何判断一个对象是否有某个属性?
- 京东开源PyTorch人脸识别工具包FaceX-Zoo:覆盖最强模型,支持训练跑分
- 求职|中级工程师来啦
- 安溪茶歌传播两岸,安溪铁观音京东秋茶节获关注
- 每个软件架构师和软件工程师都必须知道的10种设计模式