【微服务】2、网关
Spring Cloud微服务网关技术先容[*]单体项目拆分微服务后的题目
[*]服务地点题目:单体项目端口固定(如黑马商城为8080),拆分微服务后端口各异(如购物车808、商品8081、支付8086等)且可能变革,前端难以确定哀求的服务地点及应对变革。
[*]登录校验题目:单体项目登录校验后全部功能可获取用户信息,拆分后若各微服务都做登录校验,代码重复度高,且分发密钥风险大。
https://i-blog.csdnimg.cn/direct/3e5433dd041f4ca8b9f96e1466708e59.png
[*]网关办理方案及作用
[*]网关功能概述:网关负责哀求路由转发和身份校验,雷同小区看门大爷,住户类比微服务。前端只需知网关地点(设为8080),全部哀求发往网关后,网关根据哀求路由至相应微服务(如查商品路由到商品微服务,查用户路由到用户微服务),并在路由前校验用户身份,登录则解析获取用户信息并向后通报,制止微服务重复校验,同时掩护微服务,使前端开发体验与单体架构划一,成为微服务开发必备组件。
[*]路由转发与微服务地点获取:网关通过注册中心获取微服务地点,微服务启动时注册信息到注册中心,网关启动后拉取,地点变更时注册中心推送。微服务多实例部署时,网关利用负载平衡算法挑选实例转发哀求。
[*]Spring Cloud网关组件
https://i-blog.csdnimg.cn/direct/bf7a11baa3e746329a4259f107409dbb.png
[*]网关路由转发功能先容与入门案例规划
[*]焦点功能论述:网关重要有两个焦点功能,一是对前端哀求举行路由转发,二是对用户身份举行校验,本节课重要学习路由转发功能。
[*]路由转发流程分析:由于微服务拆分,前端难以知晓哀求对象,网关作为微服务群入口,可从注册中心获取服务地点,前端哀求网关后,网关判断应由哪个微服务处理(路由),再从注册中心拉取实例列表并负载平衡挑选实例发送哀求(转发)。
[*]入门案例步调规划:创建网关服务实现路由转发分为四步,重点是路由规则配置,包括创建新项目模块、引入网关相关依靠、编写启动类、配置路由规则,其中前三步是创建网关微服务,依靠坐标可复制,本节课重点学习路由规则配置。
https://i-blog.csdnimg.cn/direct/e0ea1e789236446bb58f7deb82fc7c99.png
https://i-blog.csdnimg.cn/direct/494ab961d6ab4a80a4eea56d21e02b2e.png
Spring Cloud网关路由特殊配置
https://i-blog.csdnimg.cn/direct/d74fa0f44a1045999ed3a6331e2a1a02.png
网关路由特殊配置引入
[*]背景:上节课学习了网关路由规则基本配置,能满足多数开发需求,但特殊复杂需求需特殊路由配置。
[*]路由配置类:网关路由配置由RouteDefinition类读写,常见四个属性,ID是路由唯一标识,URI是目的服务地点,配置方式与上节课基本划一;重点关注路由断言predicates和路由过滤器filters属性。
路由断言
[*]作用:判断哀求是否符合规则,符合则路由到对应目的地点。
[*]断言方式
[*]Spring内部提供12种,如按哀求路径匹配的Path、按时间判断的After和Before(与After相反)、按哀求头、cookie、哀求方式等匹配。
[*]语法与上节课雷同,路径规则中{}为占位符,一般按/开头后接*的方式配置。
[*]配置方式:可参考官网spring cloud gateway中的Route Predicate Factory部分,路由断言由工厂类处理,工厂名以RoutePredicateFactory为后缀,以路由规则名字为前缀,官网有详细示例。
https://i-blog.csdnimg.cn/direct/47b1c8ed07aa488e801004f966d30bea.png
路由过滤器
[*]作用:对进入网关的前端哀求和微服务相应效果举行加工处理。
[*]过滤器种类及示例
[*]Spring提供30多种,如AddRequestHeader(添加哀求头)、RemoveRequestHeader(移除哀求头)、AddResponseHeader(添加相应头)、RemoveResponseHeader(移除相应头)、RewritePath(重写哀求路径)、StripPrefix(去除哀求路径中的N段前缀)等。
[*]以StripPrefix为例,可办理前端哀求路径与微服务路径不划一题目,如前端哀求路径含/API前缀,微服务路径无此前缀,可通过StripPrefix去除前缀使路由准确。
[*]配置语法:与路由断言雷同,如AddRequestHeader过滤器,等号左边为过滤器名字,右边为以逗号隔开的键值形式参数(哀求头的key和value)。
[*]演示示例:以添加哀求头过滤器AddRequestHeader为例,在idea中操作,在商品微服务路由下添加filters,具体配置可参考源码或直接复制粘贴,如添加名为truth的哀求头,值为anyone Long press like button will be rich;在商品微服务controller中利用@RequestHeader注解获取哀求头并打印(设置required = false),测试时先重启网关和商品服务,访问网关后检察idea中是否成功打印出添加的哀求头内容,以此验证过滤器见效。
默认过滤器配置
[*]配置方法:若盼望过滤器对全部路由见效,可配置在defaultFilter下,与路由同级,无需在每个路由中单独配置。
[*]验证测试:测试时仅需重启网关,再次访问网关检察是否能获取到哀求头,以此验证默认过滤器对全部路由见效。
[*]网关实现登录校验功能的分析与思路
[*]登录授权功能部署:采用JWT登录,登录授权功能置于user service(用户微服务),登录后颁发JWT token,可从token解析用户信息。
[*]多微服务对用户信息的需求及校验题目:多个微服务(如购物车服务、生意业务服务)需知晓登录用户信息,若在各微服务分别举行JWT校验,会导致代码重复且增加密钥泄露风险,因此考虑在网关举行校验并向后通报用户信息。
[*]校验机遇的重要性:JWT校验必须在网关将哀求转发到微服务之前完成,否则校验失去意义。
https://i-blog.csdnimg.cn/direct/c7cd0bb99eaf4b5a836d2db58fb020b4.png
[*] 网关底层处理流程分析
[*]路由规则判断:网关底层基于路由规则判断前端哀求应由哪个微服务处理,此过程由handler mapping接口(默认实现为root predicted handler mapping)基于路由断言完成路由规则匹配,找到符合哀求的路由后存入上下文并转交给web handler接口。
[*]过滤器链的形成与作用:web handler接口(默认实现为filtering web handler)找到当前哀求对应路由见效的过滤器,排序形成过滤器链,依次调用。过滤器链中的netty routine filter默认对全部路由见效且在末了执行,负责将哀求转发到微服务,微服务执行完返回效果后它举行封装并存入上下文,再依次返回给其他过滤器和用户。
[*]过滤器的PRE和POST逻辑:过滤器内部有PRE和POST两部分逻辑,哀求进入先执行PRE逻辑,若失败则结束,成功才继续调用下一个过滤器的PRE逻辑;执行到netty routine filter的PRE逻辑时将哀求转发到微服务,微服务执行完进入POST阶段,效果经netty routine filter封装存入上下文后依次返回给上一个过滤器,PRE阶段按次序执行,POST阶段倒序执行。
[*] 网关转发前校验方案及用户信息通报题目
https://i-blog.csdnimg.cn/direct/b15d83f2d9e6490ebb6320a69178d3f3.png
[*]自界说过滤器实现校验:需在网关内自界说过滤器,保证其执行次序在netty routine filter之前,在PRE逻辑里实现JWT校验,从而确保转发前完成校验。
[*]网关与微服务间用户信息通报方式:网关校验得到用户信息后,将用户信息放入哀求头通报给微服务。
[*]微服务之间用户信息通报题目及差别:复杂业务中微服务间相互调用(如生意业务服务调用购物车服务)时也需通报用户信息,虽同样基于HTTP哀求,但实现方式与网关到微服务通报有所不同,因为微服务间的HTTP哀求基于open feign发起,而网关到微服务是网关内置的哀求方式。
https://i-blog.csdnimg.cn/direct/cfec3733625049d98a79c51e2800a881.png
网关过滤器自界说及登录校验逻辑实现
网关过滤器种类
[*]gateway filter
[*]之前在学习网关路由时见过,在路由配置属性中有filters,其可指定过滤器及参数。
[*]过滤器约30多种,默认不见效,可配置到特定路由或default filter下,针对指定路由或全部路由见效,机动性高,能恣意指定作用范围。
[*]global filter(全局过滤器)
[*]作用范围是全部路由,进入网关的哀求都会被处理,无需指定或选择,声明后自动见效,利用更简朴。
[*]两种过滤器的filter方法在返回值、方法名和方法参数上完全一样,该方法是编写过滤逻辑的焦点,编写登录校验逻辑时方法差别不大,以global filter为例解读方法信息。
过滤器方法参数及返回值(以global filter为例)
https://i-blog.csdnimg.cn/direct/0d879f2122004934b21d9431f6ef1e3a.png
[*]方法参数
[*]server web exchange:网关内部上下文对象,用于保存网关内部共享数据,如request、response、session等,过滤器链中全部过滤器可从中读取和存入数据。
[*]gateway filter chain:过滤器链,自界说过滤器业务逻辑处理完后,调用它来调用下一个过滤器,使整个链条串联。
[*]返回值
[*]返回值为mono,网关过滤器内部分为PRE和post两部分逻辑,实现filter方法后写的业务属于PRE部分。PRE执行完调用chain调用下一个过滤器,全部过滤器PRE执行完后将哀求转发到微服务,微服务返回效果才执行post部分。
https://i-blog.csdnimg.cn/direct/807c5728273b48018ceea0950f36e1a7.png
界说global filter示例
[*]界说一个类实现global filter接口,加上component注解注册为spring bean,实现filter方法编写PRE逻辑(如模仿登录校验逻辑,先获取哀求头,这里仅打印哀求头,实际登录校验时再从哀求头获取登录凭证)。
[*]校验逻辑完成后利用chain放行(调用filter方法并传入exchange,使下一个过滤器可利用上下文)。
控制过滤器执行次序
[*]过滤器界说后要保证在netty routing filter之前执行,因为其作用是做转发,盼望在转发前做登录校验,所以优先级要更高。
[*]通过检察nt routing filter源码发现它实现了order接口来排序,order接口要求实现get order方法返回int值,值越小优先级越高,netty routing filter默认优先级为integer最大值(最低优先级)。
[*]自界说过滤器实现order接口并设置较小优先级值(如0)即可在其之前执行
总结
[*]自界说global filter方式:写类实现接口,实现filter方法利用ServerWebExchange exchange获取哀求信息做登录校验,校验完成利用过滤器链放行。
[*]控制过滤器执行次序靠order接口,实现get order方法返回int值,值越小优先级越高,NTROUTFILTER默认优先级最低,自界说过滤器值比其小即可。掌握这些后,登录校验可行。
自界说gateway filter概述
https://i-blog.csdnimg.cn/direct/d11f165a23604506a96e5e509465211b.png
[*]gateway filter特点:利用时可自由指定作用范围,能配置自界说参数,比global filter更机动,但自界说较贫苦,一样平常开发多选用global filter,做登录校验功能时也常用global filter。
- 自界说方式:需继承abstract gateway filter factory,其作用是读取配置创建定制化过滤器对象,采用工厂模式,界说的是过滤器工厂。过滤器工厂内有apply方法,基于配置创建过滤器对象,采用匿名内部类实现filter方法编写逻辑。
- 过滤器工厂命名要求:名字必须以gateway filter factory为后缀,类名前缀将作为过滤器名字在配置文件中利用。
[*]无参gateway filter的界说与实现
[*]界说无参过滤器工厂类:如print any gateway filter工厂类,继承Abstract gateway filter factory,泛型为object,实现apply方法。
[*]注册工厂类:给工厂类加@Component注解注册为bean。
[*]构造过滤器:在apply方法中用匿名内部类构造gateway filter,实现filter方法,可编写PRE或post逻辑,此处仅打印执行信息。
[*]过滤器执行次序题目:全局过滤器和自界说过滤器执行次序需控制,匿名内部类无法实现order接口指定次序,办理办法一是单独写类实现gateway filter和order接口,二是利用装饰模式。
[*]装饰模式实现:界说OrderGatewayFilter类,接受gateway filter和order参数,实现GTFILTER和order接口,构造函数记录参数,filter方法调用委托对象的filter方法,返回记录的order,利用该装饰模式为自界说过滤器添加次序。
[*]配置见效与测试:在yml文件中配置过滤器,可界说在某一路由下或default下(作用于全部),配置print any过滤器。重启服务,清空日志,欣赏器访问后检察日志,验证global filter先执行(次序为1),print any gateway filter后执行(次序为0,值越大优先级越低)。
[*]带参gateway filter的界说方式
[*]界说属性类:自界说带参gateway filter更复杂,需界说专门属性类匹配参数,一般界说在过滤器工厂内部为内部类,变量数目与参数数目对应。
https://i-blog.csdnimg.cn/direct/04c465871efc4756b23043a8802934bf.png
网关登录校验功能实现
[*]预备工作及工具先容
[*]网关过滤器类型:网关过滤器有gateway filter和global filter两种,一样平常开发多用global filter,本节课用它实现登录校验功能。
[*]黑马商城登录方式:基于JWT实现,相关密钥和工具类在单体架构项目hm service中,需拷贝到网关项目。包括保存JWT密钥的加密文件hmall.jks、加载属性的JwtProperties类、生成密钥并注册到spring容器的SecurityConfig类、配置不需要登录校验路径的exclude paths、读取路径属性AuthProperties类,以及生成息争析token的工具类JwtTool。
https://i-blog.csdnimg.cn/direct/b8d8fedc7a01419aaf28a9e8ffc5661c.png
[*]工具拷贝与配置
[*]拷贝属性类:将jw properties、OLI等属性类拷贝到网关项目新建的CONFIG包中,标记为component使其见效。
[*]拷贝工具类:拷贝工具类GDP t two到网关项目,办理报错题目。
[*]拷贝密钥文件和配置文件:将密钥文件HMGK和相关配置文件拷贝到网关项目。
[*]界说全局过滤器:界说名为OsGlobalFilter的全局过滤器,实现global filter和order接口,设置order值为0,在filter方法中编写登录校验逻辑,包括获取request对象,判断哀求路径是否在放行路径中,若在则放行,不在则获取token并校验解析,校验失败用401状态码拦截,校验通过则通报用户信息(本节课先打印用户id,后续再实现通报)。
[*]校验token与拦截逻辑
[*]获取token:从request获取header,通过指定哀求头名字authorization获取token,判断header不为空且不为null时取出token。
[*]校验token:利用拷贝过来的工具类jp t two校验解析token,校验失败时try catch捕捉非常,用401状态码拦截并设置response状态码为Unauthorized,停止哀求。
[*]通报用户信息:校验通过则通报用户信息(本节课先打印用户id)。
[*]路径校验与整体回顾
[*]路径校验方法:界说判断哀求路径是否需要被拦截的方法,通过注入all properties类获取放行路径,利用spring提供的ant pass match匹配器判断哀求路径与放行路径是否匹配,循环遍历全部放行路径,若匹配则返回true,否则返回false。
[*]测试与回顾:完成过滤器逻辑后,配置购物车服务路由路径cars,重启网关服务举行测试。未登录访问购物车路径返回401,登录后可成功查询,说明登录拦截见效。回顾网关登录校验逻辑,重要包括获取哀求和token、校验token、根据校验效果拦截或放行,拦截时通过response设置状态码401并结束哀求,路径判断通过ant pass match匹配器判断配置路径与当前路径是否匹配。掌握这些API可实现整套登录拦截逻辑。
https://i-blog.csdnimg.cn/direct/56c0716c52434dba951f4fe2c767d242.png
从网关到微服务的用户通报实现方法
[*]实现思路
[*]哀求流程与用户信息通报方式:哀求先到网关,网关过滤器中已实现登录校验并获取用户信息。网关到微服务是新的哀求,将用户信息保存到哀求头是通报信息的最佳方案,微服务可从哀求头获取用户信息。
[*]微服务获取用户信息的优化:微服务业务接口基于Spring MVC,为制止在每个业务接口获取登录用户信息,可在全部业务接口执行前,通过Spring MVC拦截器获取哀求头中的用户信息并保存到ThreadLocal,后续业务可随时取用。
[*]网关过滤器保存用户信息到哀求头
[*]利用API修改哀求头:网关提供了ServerWebExchange上下文对象,其mutate方法可对下游哀求举行改变和处理,通过该方法返回的RequestBuilder可修改哀求头信息。
[*]约定哀求头名称与设置值:哀求头名称可自界说,但需与微服务开发者约定好,本案例约定为user info,其值为用户ID(long型转字符串)。
[*]完成哀求头修改与通报:修改完哀求头后,需调用build方法构建新的ServerWebExchange,并将其通报到下一个过滤器,以确保修改见效。
[*]测试用户信息通报:在购物车服务的Controller中获取并打印哀求头中的user info,重启网关后,通过查询购物车操作测试用户信息是否通报成功。
[*]微服务编写拦截器获取用户信息
[*]拦截器编写与功能实现
[*]创建拦截器类:在common模块的interceptor包下新建UserInfoInterceptor拦截器,实现HandlerInterceptor接口,只需实现preHandle和afterCompletion方法。
[*]获取并保存用户信息:在preHandle方法中,从Spring MVC的request对象获取哀求头中的用户信息(与网关约定的user info划一),利用工具类判断不为空后,通过common中的UserContext将用户信息(字符串转long型)存入ThreadLocal。
[*]清算用户信息:在afterCompletion方法中,调用UserContext的removeUser清算用户信息。
[*]拦截器配置与见效题目办理
[*]配置拦截器:界说Spring MVC配置类MvcConfig,实现WebMvcConfigure接口并加Configuration注解,在addInterceptor方法中将UserInfoInterceptor添加到拦截器注册器,默认拦截全部路径。
[*]办理配置类扫描题目:由于配置类所在包与微服务包不同,需在resource目录下的meta - info下的spring.factories文件中记录配置类名字,使配置类见效。
[*]制止网关引用报错:因网关引用了common且无Spring MVC,会导致配置类在网关报错。通过给配置类加@ConditionalOnClass注解,以判断是否存在Spring MVC的焦点API DispatcherServlet为条件,使配置类仅在微服务见效。
[*]测试拦截器见效:重启网关和微服务(如购物车服务),测试拦截器是否见效,如查询购物车时,日志显示能从ThreadLocal获取到准确的用户ID,而非写死的值。
[*]总结回顾
[*]网关通报用户信息:网关通过过滤器获取用户信息,利用exchange的API修改哀求头,将用户信息添加到哀求头中通报给微服务。
[*]微服务获取用户信息:微服务通过在common模块界说拦截器,在全部业务接口执行前获取哀求头中的用户信息并保存到ThreadLocal,方便后续业务利用。
[*]题目办理与技术应用:办理了拦截器配置见效题目,包括配置类扫描和网关引用报错题目,运用了Spring Boot自动装配原理。通过在spring.factories文件中记录配置类名字实现自动装配,利用@ConditionalOnClass注解根据项目中是否存在Spring MVC的焦点API来控制配置类见效范围。这表明Spring Boot自动装配原理在实际开发中可办理诸多题目,如本案例中的拦截器配置题目,同时也为后续在微服务之间通报登录用户信息等操作奠定了底子。
https://i-blog.csdnimg.cn/direct/6c8bc841760247b4b675d1c298aa7899.png
[*]微服务间用户信息通报题目引出
[*]背景:实现从网关到微服务的用户信息通报后,复杂业务场景中微服务间相互调用时的用户信息通报面临挑战。
[*]场景示例:以用户下单场景为例,涉及生意业务服务、商品服务和购物车服务。前端哀求先辈入生意业务服务,生意业务服务保存订单时需向商品服务扣减库存、向购物车服务清算购物车。
[*]用户信息通报流程及题目分析
[*]正常流程
[*]前端带JWT token哀求到网关,网关过滤器校验token,有效则解析用户信息存于哀求头并转发给微服务。
[*]微服务通过通用拦截器从哀求头获取用户信息,如生意业务服务可拿到登录用户信息创建订单。
[*]现有题目
[*]生意业务服务调用购物车服务时未传用户id,仅传商品id。
[*]购物车服务从user context获取用户id,但因哀求头无用户信息导致获取失败。
[*]缘故原由是生意业务服务调用购物车服务未处理哀求头,而购物车服务获取用户方式依靠user context,其前提是拦截器能从哀求头取用户信息并存入user context,当宿世意业务服务调用购物车服务时哀求头无用户信息。
[*]OpenFeign拦截器办理方案
[*]拦截器原理与作用:OpenFeign的request interceptor接口,其apply方法在每次哀求时调用,可利用request template修改哀求头,如添加哀求头信息。
[*]拦截器界说与配置
[*]界说位置:因全部微服务调用其他服务时都需通报用户信息,故界说在公共的HM-api模块最符合,这样引用该模块的微服务在发起远程调用时拦截器自动见效。
[*]界说方式:采用匿名内部类声明,实现apply方法,在方法内从user context获取用户信息(需添加common依靠以利用user context),判断用户id不为空后添加到哀求头。
[*]见效条件:配置类需加在Feign启动类上。
[*]测试效果:重启生意业务服务后下单测试,检察购物车服务日志,发现其执行业务时成功拿到user context中的用户信息,购物车成功删除,证明用户信息通报成功。
https://i-blog.csdnimg.cn/direct/3dcfd1e5d5814dadb9e49acd2e0590f4.png
[*]总结回顾微服务用户信息通报方案
[*]过滤器和拦截器总结
[*]网关的global filter过滤器:举行JWT登录校验,获取用户信息后保存到哀求头转发给微服务。
[*]微服务的handler interceptor拦截器:从哀求头获取用户信息后保存到thread local,方便微服务内部业务利用。
[*]OpenFeign的request interceptor拦截器:在微服务间基于OpenFeign调用时,将用户信息保存到哀求头,确保下游微服务能获取用户信息。
[*]方案代价:此方案是办理微服务体系登录功能的整体思路,公司实现思路与之雷同,对实际开发具有重要参考代价。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页:
[1]