8.微服务核心组件API Gateway
8.1.API Gateway应用场景
(1)什么是网关
API Gateway,是系统的唯一对外的入口,介于客户端和服务端之间的中间层,处理非业务功能,提供路由请求、鉴权、监控、缓存、限流等功能
2)统一接入
- 智能路由
- AB测试、灰度测试
- 负载均衡、容灾处理
- 日志埋点(类似nginx日志)
(3)流量控制
- 限流处理
- 服务降级
(4)安全防护
- 鉴权处理
- 监控
- 机器网络隔离
(5)主流的网关
- zuul:是Netflix开源的微服务网关,和Eureka、Ribbon、Hystrix等组件配合使用,依赖组件比较多,性能较差。
- kong:由Mashape公司开源的,基于Nginx的API gateway
- nginx+lua:高性能的HTTP反向代理服务器,lua是脚本语言,让Nginx执行脚本,并且高并发、非阻塞的处理各种请求。
- SpringCloud Gateway:Spring公司专门开发的网关,替代zuul,基于Spring5+Reactor技术开发,在spring2.x中可以直接jar包方式运行
8.2.API Gateway配置实战
(1)先添加网关的依赖
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway</artifactId> </dependency>
(2)配置启动类
@SpringBootApplication public class GatewayApplication { public static void main(String[] args){ SpringApplication.run(GatewayApplication.class); } }
(3)配置yml文件
server: port: 8888 spring: application: name: gateway-service cloud: gateway: routes: - id: video-service #唯一标识 uri: http://127.0.0.1:9001 #转发服务的地址端口 order: 1 #优先级,1表示最大 predicates: #断言,配置那个路径才转发 - Path=/video-server/** filters: #过滤器,请求在传递过程中通过过滤器修改 - StripPrefix=1 #1表示过滤掉第一层前缀
(4)效果演示
8.3.API Gateway整合Nacos
(1)添加nacos依赖
<!--添加nacos客户端--> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency>
(2)启动类开启支持
@EnableDiscoveryClient
(3)修改配置文件
server: port: 8888 spring: application: name: gateway-service cloud: gateway: routes: - id: video-service uri: lb://video-service #注意这块要写nacos中注册的服务名,lb://服务名 order: 1 predicates: - Path=/video-server/** filters: - StripPrefix=1 discovery: locator: enabled: true #开启网关拉取nacos服务 nacos: discovery: server-addr: 192.168.10.88:8848 #配置nacos地址
(4)效果演示
8.4.API Gateway交互流程
- 客户端向SpringCloud Gateway发出请求
- 如果网关处理程序映射确定请求与路由匹配
- 则将其发送到网关web处理程序
- 通过特定过滤器链运行,前置处理-后置处理
- 过滤器生命周期
- PRE:这种过滤器在请求被路由之间调用,一般用于鉴权,限流等。
- POST:这种过滤器在路由到微服务以后执行,一般用于修改响应结果,比如增加header信息,打点日志等
- 网关过滤分类
- 局部过滤器GatewayFilter:应用在某个路由上,每个过滤器工厂都对应一个实现类,并且这些类的名称必须以 GatewayFilterFactory 结尾
- 全局过滤器:作用全部路由上
8.5.Gateway内置的路由断言
(1)什么是Gateway路由断言
- Predicate来源于java8,接受输入参数,返回一个布尔值结果
- SpringCloud Gateway中Spring利用Predicate的特性实现了各种路由匹配规则
- 转发判断条件,Spring Cloud Gateway支持多种方式,常见如:Path、Query、Method、Header等
- 支持多个Predicate,但是必须全部Predicate满足才可以进行路由转发
- 参数编写规则XXXRoutePredicateFactory,使用XXX作为参数配置
predicates: - Host= - Path= - Method= - Header= - Query= - Cookie=
8.6.Gateway配置定时下线接口
#需求:接口需要在指定时间进行下线,过后不可以在被访问 #使用Before,只有当时时间小于设定时间,路由才会匹配请求 #格式: predicates: - Before=2020-09-09T01:01:01.000+08:00
8.7.Gateway配置必传参数
- Query=source
8.8.自定义全局过滤器实现鉴权
(1)代码编写
@Component public class UserGlobalFilter implements GlobalFilter, Ordered { @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { //写业务逻辑 String token = exchange.getRequest().getHeaders().getFirst("token"); if(StringUtils.isBlank(token)){ exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED); return exchange.getResponse().setComplete(); } //否则就继续往下执行 return chain.filter(exchange); } @Override public int getOrder() { return 0; } }
(2)测试
- 注意:网关不要加太多的业务逻辑,否则会影响性能。
9.微服务链路追踪系统
9.1.微服务链路追踪系统的作用
(1)微服务中常见的问题
- 微服务中链路调用时间过长怎么定位
- 微服务中链路调用出现异常怎么排查
(2)链路追踪系统
- 分布式应用架构虽然满足了应用横向扩展的需求,但是运维和诊断的过程变得越来越复杂,例如会遇到接口诊断困难、应用性能诊断复杂、架构分析复杂等难题,传统的监控工具并无法满足,分布式链路系统由此诞生
- 核心:将一次请求分布式调用,使用GPS定位穿起来,记录每个调用的耗时、性能等日志,并通过可视化工具展示出来。
- 注意:AlibabaCloud全家桶还没对应的链路追踪系统,我们使用Sleuth和zipkin(内部使用的鹰眼)
9.2.整合链路追踪组件Sleuth
(1)什么是Sleuth
- 一个组件,专门记录链路数据的开源组件
(2)微服务项目添加依赖
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-sleuth</artifactId> </dependency>
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-sleuth</artifactId> </dependency>
(3)日志各个字段含义
#示例:[order-service,96f95a0dd81fe3ab,852ef4cfcdecabf3,false] 第一个:服务名称,spring.application.name 第二个:trace id,整个服务调用链路只用这一个trace id 第三个:span id,标记每个微服务的唯一标识,基本工作单元 第四个:是否要将该信息输出到zipkin服务中收集和展示
9.3.整合链路追踪可视化Zipkin
(1)什么是zipkin
大规模分布式系统的APM工具(Application Performance Management),基于Google Dapper的基础实现,和sleuth结合可以提供可视化web界面分析调用链路耗时情况
(2)同类产品
- 鹰眼(EagleEye)
- CAT
- twitter开源zipkin,结合sleuth
- Pinpoint,运用JavaAgent字节码增强技术
- StackDriver Trace (Google)
(3)zipkin启动
- zipkin启动非常容易,直接启动jar即可
java -jar zipkin-server-2.12.9-exec.jar
- 默认端口9411
(4)zipkin组成:Collector、Storage、Restful API、Web UI组成
9.4.链路追踪Zipkin+Sleuth整合
(1)微服务项目添加依赖
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-zipkin</artifactId> </dependency>
(2)配置zikpin地址和采样百分比配置
spring: application: name: api-gateway zipkin: base-url: http://127.0.0.1:9411/ #zipkin地址 discovery-client-enabled: false #不用开启服务发现 sleuth: sampler: probability: 1.0 #采样百分比
默认为0.1,即10%,这里配置1,是记录全部的sleuth信息,是为了收集到更多的数据(仅供测试用)。 在分布式系统中,过于频繁的采样会影响系统性能,所以这里配置需要采用一个合适的值。
9.5.链路追踪日志持久化
(1)存在的问题
- 服务重启会导致链路追踪系统的数据丢失
(2)配置mysql持久化
- 官方提供了mysql的脚本
nohup java -jar zipkin-server-2.12.9-exec.jar --STORAGE_TYPE=mysql --MYSQL_HOST=127.0.0.1 --MYSQL_TCP_PORT=3306 --MYSQL_DB=zipkin_log --MYSQL_USER=root --MYSQL_PASS=xdclass.net &
10.微服务分布式配置中心
10.1.微服务下的分布式配置中心
(1)现在微服务存在的问题
- 配置文件增多,不好维护
- 修改配置文件需要重新发布
(2)什么是配置中心
- 统一管理配置,快速切换各个环境的配置
- 相关产品
- 百度的disconf 地址:https://github.com/knightliao/disconf
- 阿⾥的diamand 地址:https://github.com/takeseem/diamond
- springcloud的configs-server: 地址:http://cloud.spring.io/spring-cloud-config/
- 阿⾥的Nacos:既可以当服务治理,⼜可以当配置中⼼,Nacos = Eureka + Config
10.2.微服务整合Nacos配置中心
(1)添加项目依赖
<dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId></dependency>
(2)配置bootstrap.yml配置文件
- 配置文件优先级讲解
- 不能使用原先的application.yml,需要使用bootstrap.yml作为配置文件
- 配置读取优先级bootstrap.yml > application.yml
- 配置实操
- 订单服务迁移配置
- 增加bootstrap.yml
spring: application: name: order-service cloud: nacos: config: server-addr: 192.168.10.88:8848 #Nacos配置中心地址 file-extension: yaml #文件扩展格式 profiles: active: dev
(3)nacos控制台配置
(4)Data Id组成结构
${prefix}-${spring.profiles.active}.${file-extension} prefix:默认为spring.application.name的值 spring.profiles.active:即为当前环境对应的profile如果当前的spring.profiles.active为空时,对应的连接符-也将不存在,dataId的拼接格式变为${prefix}.${file-extension} file-exetension:配置内容的数据格式,可以通过配置项 spring.cloud.nacos.config.file-extension 来配置。⽬前只⽀持 properties 和 yaml 类型。
(5)测试配置是否生效
- 启动微服务
10.3.配置中心Nacos动态配置下发
(1)什么是动态刷新配置
- 修改了配置文件,程序不能自动更新
- 动态刷新就可以解决这个问题
(2)添加属性值url
(3)controller增加@RefreshScope
- 注意:这块一定要加在controller上,不要加在启动类上
10.4.Nacos配置中心持久化
(1)进入到nacos安装目录下的conf将脚本在mysql中执行
(2)配置nacos的配置文件
(3)重启nacos
/usr/local/nacos/bin/startup.sh
(4)测试效果
10.5.搭建Nacos服务集群
(1)准备三台机器,分别部署nacos
192.168.10.90:8848 192.168.10.91:8848 192.168.10.92:8848
- 安装步骤这里省略
(2)编写cluster.conf配置文件
#编写内容,三台机器分别编写 192.168.10.90:8848 192.168.10.91:8848 192.168.10.92:8848
(3)配置mysql持久化
#三天机器分别配置 ### If use MySQL as datasource: spring.datasource.platform=mysql ### Count of DB: db.num=1 ### Connect URL of DB: db.url.0=jdbc:mysql://192.168.10.88:3306/nacos?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useUnicode=true&useSSL=false&serverTimezone=UTC db.user=root db.password=123456
(4)访问nacos可以三台集群节点
11.微服务容器化部署
11.1.前期依赖准备
(1)父工程确定版本
<properties> <java.version>1.8</java.version> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> <spring.boot.version>2.3.3.RELEASE</spring.boot.version> </properties>
(2)每个项目添加镜像打包前缀
<docker.image.prefix>docker-cloud</docker.image.prefix> <!--镜像打包前缀-->
(3)每个项目添加打包配置
<build> <finalName>alibaba-cloud-gateway</finalName> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <fork>true</fork> <addResources>true</addResources> </configuration> </plugin> <plugin> <groupId>com.spotify</groupId> <artifactId>dockerfile-maven-plugin</artifactId> <version>1.4.10</version> <configuration> <repository>${docker.image.prefix}/${project.artifactId}</repository> <buildArgs> <JAR_FILE>target/${project.build.finalName}.jar</JAR_FILE> </buildArgs> </configuration> </plugin> </plugins> </build>
11.2.DockerFile打包微服务镜像
(1)编写DockerFile文件,注意一定要命名成dockerfile
FROM adoptopenjdk/openjdk11:jre11u-nightly COPY target/打包后的jar名 打包后的jar名 ENTRYPOINT ["java","-jar","/打包后的jar名"]
(2)执行打包命令
mvn install -Dmaven.test.skip=true dockerfile:build
(3)启动容器
docker run 镜像ID -p 指定端口
(4)查看容器日志
docker logs -f 容器ID