随行付微服务之基于Zuul自研服务网关

2024-01-12 01:18

本文主要是介绍随行付微服务之基于Zuul自研服务网关,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

随行付微服务之服务网关

微服务是时下最流行的架构之一,作为微服务不可或缺的一部分,API网关的作用至关重要。本文将对随行付微服务的API网关实践进行介绍。

API网关的作用

我们知道,在一个微服务系统中,整个系统被划分为许多小模块,客户端想要调用服务,可能需要维护很多ip+port信息,管理十分复杂。API网关作为整个系统的统一入口,所有请求由网关接收并路由转发给内部的微服务。对于客户端而言,系统相当于一个黑箱,客户端不需要关心其内部结构。

随着业务的发展,服务端可能需要对微服务进行重新划分等操作,由于网关将客户端和具体服务隔离,因此可以在尽量不改动客户端的情况下进行。网关可以完成权限验证、限流、安全、监控、缓存、服务路由、协议转换、服务编排、灰度发布等功能剥离出来,讲这些非业务功能统一解决、统一机制处理。

Zuul原理简介

随行付微服务API网关基于Netflix的Zuul实现。Netflix是实践微服务最成功的公司之一,他们创建并开源了一系列微服务相关的框架,Zuul便是用来实现网关功能的框架。Zuul的整体架构图如下:

Zuul基于Servlet开发,ZuulServlet是整个框架的入口。Zuul的核心组件是Filter,Filter分为四类,分别是pre、route、post、error。pre-filter用来实现前置逻辑,route-filter用来实现对目标服务的调用逻辑,post-filter用来实现收尾逻辑,error-filter则在任意位置发生异常时做异常处理(此处应该注意,如果pre或route发生异常,执行error后,仍然会执行post),其示意图如下:

在Filter中可以定义某些条件下是否执行过滤器逻辑,以及同种类Filter的优先级。Filter的各个方法中并不存在入参,其参数传递是通过一个基于ThreadLocal实现的RequestContext,虽然RequestContext中定义了很多参数的读写方法,但初始的可用参数仅有req和res,对应HttpSerlvetRequest和HttpServletResponse。Filter代码范例如下:

public class TestFilter extends ZuulFilter {@Override /** 是否拦截 */public boolean shouldFilter() {return false;}@Override /** filter逻辑 */public Object run() throws ZuulException {RequestContext context = RequestContext.getCurrentContext();// 获取当前线程的HttpServletRequest req = context.getRequest();// 获取请求信息return null; // 从源码来看,这个返回值没什么用}@Override /** filter类型 */public String filterType() {return "pre";// pre/route/post/error}@Override /** filter优先级,仅在同类型filter中生效 */public int filterOrder() {return 0;}
}

Filter通常使用groovy编写,以便于动态加载。当我们编写好一个Filter类后,将其放在指定的磁盘路径下,FilterFileManager会启动一个守护线程去定期读取并加载。通过动态加载,我们可以在不停机的情况下添加、修改功能模块。FilterFileManager源码摘要如下:

public class FilterFileManager {.../*** Initialized the GroovyFileManager.** @throws Exception*/@PostConstructpublic void init() throws Exception{long startTime = System.currentTimeMillis();filterLoader.putFiltersForClasses(config.getClassNames());manageFiles();startPoller();LOG.warn("Finished loading all zuul filters. Duration = " + (System.currentTimeMillis() - startTime) + " ms.");}.../** 启动线程定时读取文件 */void startPoller() {poller = new Thread("GroovyFilterFileManagerPoller") {public void run() {while (bRunning) {try {sleep(config.getPollingIntervalSeconds() * 1000);manageFiles();}catch (Exception e) {LOG.error("Error checking and/or loading filter files from Poller thread.", e);}}}};poller.start();}.../** 读取文件并加载 */void manageFiles(){try {List<File> aFiles = getFiles();processGroovyFiles(aFiles);}catch (Exception e) {String msg = "Error updating groovy filters from disk!";LOG.error(msg, e);throw new RuntimeException(msg, e);}}
}

SpringCloud-Zuul

Spring Cloud通过集成Zuul来实现API网关模块,我们来简单介绍一下它的整合原理。

SpringCloud-Zuul的核心配置类是ZuulServerAutoConfiguration以及ZuulProxyAutoConfiguration。Spring首先使用ZuulController来封装ZuulServlet,然后定义一个ZuulHandlerMapping,使得除一些特殊请求以外(如/error)的大部分请求被转发到ZuulController进行处理。源码摘要如下:

    @Configuration@EnableConfigurationProperties({ ZuulProperties.class })@ConditionalOnClass(ZuulServlet.class)@ConditionalOnBean(ZuulServerMarkerConfiguration.Marker.class)// Make sure to get the ServerProperties from the same place as a normal web app would@Import(ServerPropertiesAutoConfiguration.class)public class ZuulServerAutoConfiguration {...@Beanpublic ZuulController zuulController() {return new ZuulController();}@Beanpublic ZuulHandlerMapping zuulHandlerMapping(RouteLocator routes) {ZuulHandlerMapping mapping = new ZuulHandlerMapping(routes, zuulController());mapping.setErrorController(this.errorController);return mapping;}}public class ZuulController extends ServletWrappingController {public ZuulController() {setServletClass(ZuulServlet.class);setServletName("zuul");setSupportedMethods((String[]) null); // Allow all}...}public class ZuulHandlerMapping extends AbstractUrlHandlerMapping {...private final ZuulController zuul;...@Overrideprotected Object lookupHandler(String urlPath, HttpServletRequest request) throws Exception {if (this.errorController != null && urlPath.equals(this.errorController.getErrorPath())) {return null;}if (isIgnoredPath(urlPath, this.routeLocator.getIgnoredPaths())) return null;RequestContext ctx = RequestContext.getCurrentContext();if (ctx.containsKey("forward.to")) {return null;}if (this.dirty) {synchronized (this) {if (this.dirty) {registerHandlers();this.dirty = false;}}}return super.lookupHandler(urlPath, request);}...private void registerHandlers() {Collection<Route> routes = this.routeLocator.getRoutes();if (routes.isEmpty()) {this.logger.warn("No routes found from RouteLocator");}else {for (Route route : routes) {registerHandler(route.getFullPath(), this.zuul);}}}}

SpringCloud默认定义了一些Filter来实现网关逻辑,其中最核心的Filter——RibbonRoutingFilter是负责实际转发操作的,在它的过滤逻辑里又集成了hystrix、ribbon等其他重要框架。源码摘要如下:

public class RibbonRoutingFilter extends ZuulFilter {@Overridepublic Object run() {RequestContext context = RequestContext.getCurrentContext();this.helper.addIgnoredHeaders();try {RibbonCommandContext commandContext = buildCommandContext(context);//构建请求数据ClientHttpResponse response = forward(commandContext);//执行请求setResponse(response);//设置应答信息return response;}catch (ZuulException ex) {throw new ZuulRuntimeException(ex);}catch (Exception ex) {throw new ZuulRuntimeException(ex);}}
}

加载Filter的方式通过ZuulFilterInitializer扩展为可以从ApplicationContext中获取。源码摘要:

/** 代码出自ZuulServerAutoConfiguration */
@Configuration
protected static class ZuulFilterConfiguration {@Autowiredprivate Map<String, ZuulFilter> filters;//从spring上下文中获取Filter bean@Beanpublic ZuulFilterInitializer zuulFilterInitializer(CounterFactory counterFactory, TracerFactory tracerFactory) {FilterLoader filterLoader = FilterLoader.getInstance();FilterRegistry filterRegistry = FilterRegistry.instance();return new ZuulFilterInitializer(this.filters, counterFactory, tracerFactory, filterLoader, filterRegistry);}
}public class ZuulFilterInitializer {private final Map<String, ZuulFilter> filters;...@PostConstructpublic void contextInitialized() {...// 设置filterfor (Map.Entry<String, ZuulFilter> entry : this.filters.entrySet()) {filterRegistry.put(entry.getKey(), entry.getValue());}}
}

Zuul2

随着业务的不断发展,Zuul对于Netflix来说性能已经不太够用,于是Netflix又开发了Zuul2。Zuul2最大的变革是基于Netty实现了框架的异步化,从而提升其性能。根据官方的数据,Zuul2的性能比Zuul1约有20%的提升。Zuul2架构图如下:

由于框架改为了异步的模式,Zuul2在提升性能的同时,也带来了调试、运维的困难。在实际的使用当中,对于绝大多数公司来说,并发量远远没有Netflix那样庞大,选择开发调试更简单、且性能够用的Zuul1是更合适的选择。

这篇关于随行付微服务之基于Zuul自研服务网关的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/596329

相关文章

【区块链 + 人才服务】可信教育区块链治理系统 | FISCO BCOS应用案例

伴随着区块链技术的不断完善,其在教育信息化中的应用也在持续发展。利用区块链数据共识、不可篡改的特性, 将与教育相关的数据要素在区块链上进行存证确权,在确保数据可信的前提下,促进教育的公平、透明、开放,为教育教学质量提升赋能,实现教育数据的安全共享、高等教育体系的智慧治理。 可信教育区块链治理系统的顶层治理架构由教育部、高校、企业、学生等多方角色共同参与建设、维护,支撑教育资源共享、教学质量评估、

【区块链 + 人才服务】区块链集成开发平台 | FISCO BCOS应用案例

随着区块链技术的快速发展,越来越多的企业开始将其应用于实际业务中。然而,区块链技术的专业性使得其集成开发成为一项挑战。针对此,广东中创智慧科技有限公司基于国产开源联盟链 FISCO BCOS 推出了区块链集成开发平台。该平台基于区块链技术,提供一套全面的区块链开发工具和开发环境,支持开发者快速开发和部署区块链应用。此外,该平台还可以提供一套全面的区块链开发教程和文档,帮助开发者快速上手区块链开发。

基于SpringBoot的宠物服务系统+uniapp小程序+LW参考示例

系列文章目录 1.基于SSM的洗衣房管理系统+原生微信小程序+LW参考示例 2.基于SpringBoot的宠物摄影网站管理系统+LW参考示例 3.基于SpringBoot+Vue的企业人事管理系统+LW参考示例 4.基于SSM的高校实验室管理系统+LW参考示例 5.基于SpringBoot的二手数码回收系统+原生微信小程序+LW参考示例 6.基于SSM的民宿预订管理系统+LW参考示例 7.基于

计算机网络基础概念 交换机、路由器、网关、TBOX

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、VLAN是什么?二 、交换机三、路由器四、网关五、TBOXTelematics BOX,简称车载T-BOX,车联网系统包含四部分,主机、车载T-BOX、手机APP及后台系统。主机主要用于车内的影音娱乐,以及车辆信息显示;车载T-BOX主要用于和后台系统/手机APP通信,实现手机APP的车辆信息显示与控

Golang支持平滑升级的HTTP服务

前段时间用Golang在做一个HTTP的接口,因编译型语言的特性,修改了代码需要重新编译可执行文件,关闭正在运行的老程序,并启动新程序。对于访问量较大的面向用户的产品,关闭、重启的过程中势必会出现无法访问的情况,从而影响用户体验。 使用Golang的系统包开发HTTP服务,是无法支持平滑升级(优雅重启)的,本文将探讨如何解决该问题。 一、平滑升级(优雅重启)的一般思路 一般情况下,要实现平滑

Golang服务平滑重启

与重载配置相同的是我们也需要通过信号来通知server重启,但关键在于平滑重启,如果只是简单的重启,只需要kill掉,然后再拉起即可。平滑重启意味着server升级的时候可以不用停止业务。 我们先来看下Github上有没有相应的库解决这个问题,然后找到了如下三个库: facebookgo/grace - Graceful restart & zero downtime deploy for G

Java后端微服务架构下的API限流策略:Guava RateLimiter

Java后端微服务架构下的API限流策略:Guava RateLimiter 大家好,我是微赚淘客返利系统3.0的小编,是个冬天不穿秋裤,天冷也要风度的程序猿! 在微服务架构中,API限流是保护服务不受过度使用和拒绝服务攻击的重要手段。Guava RateLimiter是Google开源的Java库中的一个组件,提供了简单易用的限流功能。 API限流概述 API限流通过控制请求的速率来防止

【微服务】Ribbon(负载均衡,服务调用)+ OpenFeign(服务发现,远程调用)【详解】

文章目录 1.Ribbon(负载均衡,服务调用)1.1问题引出1.2 Ribbon负载均衡1.3 RestTemplate整合Ribbon1.4 指定Ribbon负载均衡策略1.4.1 配置文件1.4.2 配置类1.4.3 定义Ribbon客户端配置1.4.4 自定义负载均衡策略 2.OpenFeign面向接口的服务调用(服务发现,远程调用)2.1 OpenFeign的使用2.1 .1创建

java后端服务监控与告警:Prometheus与Grafana集成

Java后端服务监控与告警:Prometheus与Grafana集成 大家好,我是微赚淘客返利系统3.0的小编,是个冬天不穿秋裤,天冷也要风度的程序猿! 在现代的微服务架构中,监控和告警是确保服务稳定性的关键组成部分。Prometheus和Grafana是两个强大的工具,它们可以集成在一起,为Java后端服务提供实时监控和可视化告警。 服务监控的重要性 服务监控可以帮助我们实时了解服务的健

OpenStack离线Train版安装系列—3控制节点-Keystone认证服务组件

本系列文章包含从OpenStack离线源制作到完成OpenStack安装的全部过程。 在本系列教程中使用的OpenStack的安装版本为第20个版本Train(简称T版本),2020年5月13日,OpenStack社区发布了第21个版本Ussuri(简称U版本)。 OpenStack部署系列文章 OpenStack Victoria版 安装部署系列教程 OpenStack Ussuri版