Spring Cloud 微服务架构全链路实践

阅读目录:
- 1. 网关请求流程
- 2. Eureka 服务治理
- 3. Config 配置中心
- 4. Hystrix 监控
- 5. 服务调用链路
- 6. ELK 日志链路
- 7. 统一格式返回
Java 微服务框架选型(Dubbo 和 Spring Cloud?)
目前公司使用的 Spring Cloud 整个技术组件,基本包含了上面图中所包含的,不得不说,Spring Cloud 整个生态真的很强大,使用起来也很方便有效。
后面有时间再针对每个组件进行使用解读,这篇文章主要说下 Spring Cloud 架构的链路图,顺便把自己的思路整理下来,以备查阅。
1. 网关请求流程

在 Spring Cloud 整个组件库中,Spring Cloud Zuul 是最容易被忽视,但也是最重要的,Spring Cloud Zuul 可以和 Eureka 注册中心集成,我们目前使用 Spring Cloud Zuul 的功能如下:
- Filter 过滤器
- Router 路由
- Ribbon 负载均衡
- Hystrix 熔断
- Retry 重试
有些功能是 Spring Cloud Zuul 自带的,比如 Filter 和 Router,有些是结合 Spring Cloud 其他组件,比如 Ribbon 和 Hystrix。
这里重点介绍下 Filter 过滤器,分为四个过滤类型:
- pre:Zuul 转发请求之前执行,我们目前的实现是
AccessTokenFilter,用于 oAuth2.0 JWT 的授权验证。 - route:Zuul 路由时执行,目前项目没用到。
- post:Zuul 路由转发后执行,也就是已经请求成功了后端服务,我们目前的实现是
CustomResponseFilter,用于统一请求格式的封装,比如 code/msg/data 等。 - error:以上过滤器发生错误时执行,我们目前的实现是
CustomErrorFilter,用于拦截过滤器执行的出现的错误,然后统一格式封装返回,另外,error 过滤器好像并不能捕获后端服务执行出现的错误。
另外,关于 oAuth2.0 JWT 的授权验证,实现的方式有两种:
- 授权的配置在后端服务中(每个服务都需要当作 Resource Server 进行配置,需要配置公钥,接口的授权具体配置在注解中),Zuul 只做转发,并不进行授权的验证。
- 授权的配置在 Zuul 中,也就是把 Zuul 当作 Resource Server,后端服务不需要进行任何处理,Zuul 中具体的实现就是
AccessTokenFilter,里面的逻辑是手动解析 JWT,然后判断是否正确,以及解析出用户信息/Scope/Role,然后根据当前的请求 API,对授权 Map 中的配置进行匹配,如果匹配错误,直接抛出 401 授权错误。
我们目前采用的是第二种方式,这两种方式都有利有弊,关键在于自己的取舍,为什么采用第二种方式?目的就是发挥 Zuul 的作用,对外网关进行统一授权验证。
关于授权 Map,里面存储了所有服务接口的配置,示例配置:
private static final Map ROUTE_MAPS;
static
{
ROUTE_MAPS = new HashMap<String, String>();
ROUTE_MAPS.put("eureka-client/home", "read:ROLE_ADMIN");
ROUTE_MAPS.put("eureka-client/user", "read:ROLE_ADMIN");
ROUTE_MAPS.put("eureka-client/error", "read:ROLE_ADMIN");
}
这是我们目前的配置,是一个静态的 Map,后面会存储在 Spring Cloud Config 配置中心,Zuul 启动时进行加载,利用 Spring Cloud Bus 动态刷新。
关于 Zuul 网关,其实还有很多需要说的,后面有机会再进行针对说明。
2. Eureka 服务治理

Eureka 遵循的是 AP 原则(服务可用性和分区容错性),是服务治理最理想的遵循 CAP 分布式原则。
Eureka 集群中的节点是彼此平级,不像 Consul 有 master/worker 之分,集群中的 Eureka 节点彼此两两注册,所以,Eureka 集群最好部署三个节点,这也是我们目前的部署方式。
另外,Eureka 的自我保护机制,可以参考这篇文章。
服务之间的相互调用,负载有两种使用方式:
- Feign:基于声明式,顾名思义,就是需要定义接口,就像我们平常使用对象调用一样。
- Ribbon:软负载,通过往 RestTemplate 中注入负载 Handler,然后通过负载算法选取调用(通过 Eureka 获取服务注册信息)。
我们目前打算使用 Ribbon 负载方式,为什么?看下面代码就知道了:
restTemplate.getForObject("http://eureka-client/hello", String.class);
3. Config 配置中心

我们目前配置中心使用的是 Spring Cloud Config,当然你也可以使用功能更强大的 Polly(携程开源),但 Config 目前也能满足我们的需求,存储仓库我们现在使用的是 Git。
Config 配置中心提供了数据加密功能,你可以使用 RSA 的加密方式,这样存储在 Git 中的配置都是密文形式,Config Client 获取加密配置的时候,Config Server 会自动进行解密返回。
配置中心的使用场景,我们目前主要是两个地方:
- 项目启动的配置信息,比如数据库的连接字符串等。
- 业务服务的配置信息,也就是业务相关的配置。
另外,需要说明的是,默认情况下,如果 Git 中的配置更新了,Config Client 不会进行更新配置,我们目前的解决方式是,使用 Spring Cloud Bus 进行动态刷新配置(Config Server 中配置),具体的流程:
- Git 中添加 WebHooks 脚本,比如
curl -X POST http://manager1:8180/bus/refresh,当 Git 仓库中的配置更新后,自动执行。 - Config Server 中配置 Spring Cloud Bus,接受 Git 的配置刷新请求,然后利用 RabbitMQ 广播通知所有的 Config Client 订阅方,刷新配置信息。
4. Hystrix 监控

Hystrix 主要是用于服务熔断/降级/隔离处理,Hystrix 配置在调用方,当被调用方服务不可用时,触发 Hystrix 熔断,会执行指定的 Fallback 方法,进行特殊处理。
我之前以为,Hystrix 熔断的触发条件是服务不可用,也就是服务请求超时(比如服务挂掉了),但我自己测试了下,服务出现 500 错误,也会触发 Hystrix 熔断,而且会自动忽略 Hystrix 的超时时间设置。
我们目前使用 Hystrix,主要有两个地方:
- 内部服务调用:可以对某个 API 接口进行熔断处理。
- Zuul 网关使用:就是当 Zuul 路由转发调用时,但有个局限性,就是只能对服务进行熔断,并不能针对某个 API 接口熔断。
上面图中,主要画的是 Hystrix 的监控流程,我们目前主要使用 RabbitMQ 进行采集传输,turbine-server 进行数据流的聚合,hystrix-dashboard 进行图形化的展示。
5. 服务调用链路

服务调用链路的概念,就是当服务请求发起时,记录整个请求链路的数据,以备查询。
目前市面上,几乎所有服务调用链路的实现,理论基础都是基于 Google Dapper 的那篇论文,其中最重要的概念就是 traceId 和 spanId。
- traceId 记录整个服务链路的 ID,由首次请求方创建,服务链路中唯一。
- spanId 记录当前服务块的 ID,由当前服务方创建。
- parentId 记录上一个请求服务的 spanId。
下面我描述下,我们目前的服务调用链路过程:
- H5 发起请求,到 Zuul 网关,Zuul 创建全局的 traceId 和自己的 spanId,然后携带这些数据到业务服务 A,并利用 Spring Cloud Sluth 传输到 RabbitMQ。
- 业务服务 A,接收到 Zuul 传输的 traceId 和 spanId,然后把 Zuul 的 spanId 设置成 parentId,并生成自己的 spanId,然后携带这些数据到业务服务 B,并利用 Spring Cloud Sluth 传输到 RabbitMQ。
- ....
上面图中,详细说明了整个服务调用链路的过程,这边再说下使用的技术栈:
- Spring Cloud Sluth:和 SkyWalking 的探针概念比较类似,每个服务都进行配置,收集当然服务的请求数据(traceId 和 spanId),然后利用
stream-sluth和binder-rabbit组件,将请求数据传输到 RabbitMQ。 - Spring Cloud Zipkin:主要用于请求链路的 UI 展示,Zipkin 会从 RabbitMQ 读取请求数据,然后存储到 ElasticSearch 中,然后下次显示直接从 ElasticSearch 中读取。
- Kibana:Kibana 也可以显示 ElasticSearch 中的请求数据,只不过不是图形化的,需要索引配置创建。
6. ELK 日志链路

ELK 可以参考下之前的几篇文章:
- ELK 架构之 Elasticsearch 和 Kibana 安装配置
- ELK 架构之 Logstash 和 Filebeat 安装配置
- ELK 架构之 Logstash 和 Filebeat 配置使用(采集过滤)
- ELK 架构之 Elasticsearch、Kibana、Logstash 和 Filebeat 安装配置汇总(6.2.4 版本)
上面图中已经很详细介绍了下 ELK 的流程,ELK 默认技术栈里是没有 Filebeat 的,Logstash 用作日志收集的时候,CPU 和内存会占用资源比较大,所以我们使用轻量化的 Filebeat 进行日志的收集,Filebeat 部署在每个业务服务所在的服务器,然后将收集到的日志数据传输到 Logstash,Logstash 可以部署两到三台服务器上,用作日志的过滤和分析工作,然后再将处理后的日志数据,传输到 ElasticSearch 存储。
7. 统一格式返回

关于统一格式返回,图中已经详细的说明了,如果你有更好的方案,欢迎探讨。
Spring Cloud 微服务架构全链路实践的更多相关文章
- 全链路实践Spring Cloud 微服务架构
Spring Cloud 微服务架构全链路实践Spring Cloud 微服务架构全链路实践 阅读目录: 网关请求流程 Eureka 服务治理 Config 配置中心 Hystrix 监控 服务调用链 ...
- 一张图了解Spring Cloud微服务架构
Spring Cloud作为当下主流的微服务框架,可以让我们更简单快捷地实现微服务架构.Spring Cloud并没有重复制造轮子,它只是将目前各家公司开发的比较成熟.经得起实际考验的服务框架组合起来 ...
- Dubbo和Spring Cloud微服务架构比较
Dubbo 出生于阿里系,是阿里巴巴服务化治理的核心框架,并被广泛应用于中国各互联网公司:只需要通过 Spring 配置的方式即可完成服务化,对于应用无入侵,设计的目的还是服务于自身的业务为主. 微服 ...
- Dubbo 和 Spring Cloud微服务架构 比较及相关差异
你真的了解微服务架构吗?听听八年阿里架构师怎样讲述Dubbo和Spring Cloud微服务架构. 微服务架构是互联网很热门的话题,是互联网技术发展的必然结果.它提倡将单一应用程序划分成一组小的服务, ...
- Spring Cloud 微服务架构解决方案
1 理解微服务 1.1 软件架构演进 软件架构的发展经历了从单体结构.垂直架构.SOA架构到微服务架构的过程. 1.1.1 单体架构 特点: 1.所有的功能集成在一个项目工程中. 2.所有的功能打一个 ...
- 放弃Dubbo,选择最流行的Spring Cloud微服务架构实践与经验总结
http://developer.51cto.com/art/201710/554633.htm Spring Cloud 在国内中小型公司能用起来吗?从 2016 年初一直到现在,我们在这条路上已经 ...
- Spring Cloud 微服务架构学习笔记与示例
本文示例基于Spring Boot 1.5.x实现,如对Spring Boot不熟悉,可以先学习我的这一篇:<Spring Boot 1.5.x 基础学习示例>.关于微服务基本概念不了解的 ...
- Spring Cloud 微服务架构的五脏六腑,统统晒一晒!
Spring Cloud 是一个基于 Spring Boot 实现的微服务框架,它包含了实现微服务架构所需的各种组件. 注:Spring Boot 简单理解就是简化 Spring 项目的搭建.配置.组 ...
- Spring Cloud微服务架构升级总结
↵ [编者的话]微服务的概念源于 2014 年 3 月 Martin Fowler 所写的一篇文章“Microservices”.文中内容提到:微服务架构是一种架构模式,它提倡将单一应用程序划分成一组 ...
随机推荐
- Django-视图层(view)
视图层(view) 视图函数,简称视图,本质上是一个简单的Python函数,它接受Web请求并且返回Web响应.响应的内容可以是HTML网页,重定向,404错误,图片等任何东西,但本质是返回响应对 ...
- E - Coin Change UVA - 674 &&(一些记录路径的方法)
这一道题并不难,我们只需要将dp数组先清空,再给dp[0]=1,之后就按照完全背包的模板写 主要是我们要证明着一种方法不会出现把(1+3+4)(1+4+3)当作两种方法,这一点如果自己写过背包的那个表 ...
- Ubuntu如何安装vncserver
Ubuntu上安装和配置vncserver,然后通过客户端进行连接,就能够使用图像界面的方式来运行上面的软件了. 1.使用apt-cache search vncserver命令搜索可以用来安装vnc ...
- 详解MariaDB数据库的索引
1.什么是索引 索引是一种特殊的文件(InnoDB数据表上的索引是表空间的一个组成部分),它们包含着对数据表里所有记录的引用指针. 更通俗的说,数据库索引好比是一本书前面的目录,在查找内容之前可以先在 ...
- 拦截请求并记录相应信息-springboot
方式: 1.FIlter过滤器 2.interceptor拦截器 3.Aspect切片 一.Filter过滤器形式 只能处理request中的数据 不能确定请求要走的是哪个controller信息 ...
- JS中函数常见的表现形式以及立即执行函数
函数常见的几种表现形式: 1.一般形式(函数声明): 会进行函数的预解释,函数会进行声明和定义,在函数体前面或则后面都可以进行调用. 2.函数表达式(匿名函数): 会进行函数的预解析,函数会进行声明但 ...
- SQLAlchemy使用介绍
SQLAlchemy is the Python SQL toolkit and Object Relational Mapper that gives application developers ...
- swagger出现no response from server错误的解决办法
解决办法:1.启用80端口2.如果不是使用的80端口,是用的nginx做了映射的其他端口的话可以用Springfox swagger-ui 覆盖默认request host,加上这个在spring的应 ...
- 【Idea】idea code style配置eclipse code formatter
在eclipse中有自动配置code style的功能 ,但是idea上却没有,这个时候需要自己手工配置 1. 在idea中找到Preference->Plugins->Browse re ...
- 【Linux】在Win10上搭建WSL(适用于Linux的Windows子系统)
1.打开WSL ,控制面板 -- 程序 -- 程序和功能 -- 打开或关闭Windows功能 - 选中[适用于Linux的Windows子系统] 2.开启后重启电脑 3.在Win10自带的Micro ...