微服务是一种软件架构风格,它是以专注于单一职责的很多小型项目为基础,组合出复杂的大型应用。
微服务是一种架构。
微服务是一种架构。
微服务是一种架构。
以前自己做项目最常用的架构是单体架构。单体项目不适合开发大型项目。
学习微服务技术来解决服务拆分碰到的问题。
使用微服务技术(工具)把单体项目拆成微服务项目。
上图是一些微服务技术,解决相应问题。
什么是单体架构
将业务的所有功能集中在一个项目中开发,打成一个包部署。
优点:架构简单、部署成本低。
缺点:团队协作成本高、系统发布效率低、系统可用性差。
总结:单体架构适合开发功能相对简单,规模较小的项目。
微服务架构
微服务架构,是服务化思想指导下的一套最佳实践架构方案。服务化,就是把单体架构中的功能模块拆分为多个独立项目。
SpringCloud
SpringCloud是目前国内使用最广泛的微服务框架。SpringCloud集成了各种微服务功能组件,并基于SpringBoot实现了这些组件的自动装配,从而提供了良好的开箱即用体验。(但对于Springboot的版本也有要求)
(题外话:Springboot最擅长自动装配和依赖管理)
拆分原则
目标:高内聚、低耦合
拆分方式:横向拆分(抽取公共服务,提高复用性)、纵向拆分(按照业务模块拆分)
拆分服务
工程结构有两种:独立project、Maven聚合
远程调用
一旦微服务进行了拆分,数据产生了隔离,服务也产生了隔离,没法像以前一样调用了,如果想要像以前一样查询,查别人的数据,就必须通过网络调用。
注册中心
为什么要有注册中心?8081不能写死,8082和8083服务也要访问。
1.服务调用者不知道服务提供者的地址,因为写代码的那一刻项目还没启动。
2.就算知道了地址,要访问哪个。
3.写好了代码却挂了,怎么知道新的服务的地址。
这就是服务远程调用时可能出现的问题,可以用注册中心来解决这个问题。设一个中介。
Nacos——注册中心的技术
Nacos是目前国内企业中占比最多的注册中心组件。它是阿里巴巴的产品,目前已经加入SpringCloudAlibaba中。
服务注册
拆好的服务去实现服务的注册,引入依赖,配ip和端口,注册后可以通过Nacos看到注册好的服务。
服务发现
服务调用者去Nacos里拉取服务的信息。也要引入依赖,获取ip和端口才行,提供好了这个API。
最简单的负载均衡,随机负载均衡,Ramdom。
OpenFeign
OpenFeign是一个声明式的http客户端,用来发送http请求的。让刚刚的代码也就是下图的代码变得简单。
简化后(OpenFeign已经被SpringCloud自动装配)
连接池
日志
总结
服务拆分尝试(以支付微服务为例)
首先去支付部分的controller, 看里面的各种接口进到serviceImpl里,然后看是否用到其他微服务,用到了就把此接口拆出来,放到新的client里,加上FeignClient注解,由api统一向所有的发请求(包括拆出来的client),然后回到servicelmpl里修改那些调用的主体。把那些不变的复制粘贴过来。
网关
就是网络的关口,负责请求的路由,转发,身份验证。
在SpringCloud中网关的实现包括两种:Spring Cloud Gateway、Netfilx Zuul
网关路由
1.创建新模块
2.引入网关依赖:起步依赖(网关依赖、负载均衡依赖、Nacos依赖)
3.编写启动器:xxxApplication.java(记得带SpringbootApplication注解)
4.配置路由规则
【GeekHour】30分钟Nginx入门教程_哔哩哔哩_bilibili
路由属性
网关路由对应的java类型是RouteDefinition,其中常见的属性:
id:路由唯一标识
url:路由目标地址
predicates:路由断言,判断请求是否符合当前路由(不仅可以指定路径,还能设置在某时之前之后的条件)
filters:路由过滤器,对请求或响应做特殊处理(可添加修改请求头、响应头、路径重写、去路径n段前缀)
网关登录校验
网关就像小区的开门大爷,是整个微服务的入口。
我们就不必在每个微服务里都校验一次,在网关里这个入口jwt校验一次就可以了。
这个校验一定要放在网关转发之前去做,就像看门大爷在找人前必须校验外来人员。
基于路由断言RoutePredicateHandMapping去做路由匹配,然后到过滤器形成过滤器链...
综上,如何在网关转发之前做登录校验?在网关自定义一个过滤器,保证这个过滤器执行的顺序在NettyRoutingFilter之前,并且在它的pre逻辑去实现jwt的校验。(pre是转发之前,post是之后)
网关如何传递用户信息给微服务?不同的微服务tomcat都不一样,所以肯定没法用threadlocal(threadlocal在tomcat内部,线程之间去共享)。可以保存用户到请求头。
如何在微服务之间传递用户信息?也是保存用户要请求头。
自定义过滤器
网关过滤器由两种:GatewayFilter、GlobalFilter
GatewayFilter:路由过滤器,可以任意指定路由范围
GlobalFilter:全局过滤器,作用范围是所有路由
自定义过滤器仿写:微服务02-05.网关登录校验-自定义GlobalFilter_哔哩哔哩_bilibili
方法1.自定义过滤器GlobalFilter类直接实现GlobalFilter接口就行了,如果向控制自定义过滤器的执行顺序,加个order就可以了:利用exchang参数获取请求信息,然后写过滤器业务逻辑,然后放行(调用过滤器链chain的下一个过滤器)
方法2.利用gateway自定义过滤器,回头再写吧。
登录校验
自定义过滤器写好了,准备工作就完毕了,可以写登录校验了。(黑马商城是JWT实现的登录校验)
hmall.jks文件打开乱码,是保存jwt密钥的文件,所以看起来乱码。配置在hm的jwt里(yaml),有个类(jwtProperties.java)去加载配置里的属性,真正去读取文件生成密钥的在securityConfig.java里。还有一个jwtTool。
excludePaths不用登录校验的,放行的路径。也要有一个属性类去读取(回头再看吧)
如果不用登录拦截就直接放行chain链调用下一个,否则获取token再校验并解析token,可以的话就传递用户信息后放行。
网关传递用户
拦截器
步骤:
1.在网关的登录校验过滤器中,把获取到的用户写入请求头。(有API)
2.在hm-common中编写SpringMVC拦截器,获取登录用户。(因为每个微服务都有登录用户的需求)
OpenFeign传递用户
微服务之间也要传递用户。
openFeign中提供了一个拦截接口,所有由OpenFeign发起的请求都会先调用拦截器处理请求,其中的RequestTemplate类中提供了一些方法可以让我们修改请求头。
拦截器每个微服务都会用,公共的,所以放在hm-api里。
总结:
1.登录校验问题:
网关部分定义了一个过滤器,过滤器主要做两件事:请求来了之后先去做JWT登录校验,从而获取token中的用户信息,把用户信息保存到请求头,转发这个请求的时候自然就传到微服务了。这里用到的过滤器是GlobalFilter。
当请求到达微服务部分,我们需要在微服务里获取用户信息。该微服务里有好多业务都要去获取用户信息,不可能在每个微服务的每个业务里都写这个逻辑,为了简化这个操作,我们就在微服务里定义了一个拦截器,拦截器可以帮助我们把网关传过来的请求头中的用户信息给取出来,取完之后为了方便使用,保存信息到threadlocal里(因为这是微服务内部,可以线程来回调,就可以用threadlocal)。这样的拦截器是SpringMVC的拦截器,叫做HandlerInterceptor。
微服务之间的相互调用:有一些业务比较复杂,可能会出现微服务之间的相互调用,往往这些可以通过OpenFeign去实现,而这些微服务要怎么拿到用户信息呢(从微服务,而不是网关)?也保存到请求头,后续的微服务才能拿到用户信息。用到OpenFeign的拦截器,requestInterceptor。
配置管理
微服务太多,重复配置太多,如mysql
优点:配置共享;避免配置更新后的重启,实现配置热更新。
而之前我们用到提供注册中心服务的nacos,也可以提供配置管理服务。
配置共享
步骤:
1.添加共享配置到Nacos中,包括jdbc、MybatisPlus、日志、Swagger、OpenFeign等。
2.拉取共享配置:基于NacosConfig拉取共享配置代替微服务的本地配置。
引入依赖->新建bootstrap.yaml
配置热更新
当我们修改配置文件中的配置中时,微服务无需重启即可使配置生效。
配置前提:
1.nacos中要有一个与微服务名有关的配置文件。
2.微服务中要以特定方式读取需要热更新的配置属性。