阅读目录:

  • 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-sluthbinder-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 微服务架构全链路实践相关推荐

  1. 《Spring Cloud 微服务架构进阶》读书笔记

    前页 随着 DevOps 和以 Docker 为主的容器技术的发展,云原生应用架构和微服 务变得流行起来. 云原生包含的内容很多,如 DevOps.持续交付.微服务.敏捷等 第一章,微服务架构介绍 架 ...

  2. 《Spring Cloud微服务架构实战派》PDF样章

    内容摘要: 本书针对Spring Cloud Greenwich.SR2版本+Spring Boot的2.1.x.RELEASE版本.在编写过程中,不仅考虑到在企业任职所需的技能,还考虑到求职面试时可 ...

  3. 疯狂Spring Cloud微服务架构实战

    网站 更多书籍点击进入>> CiCi岛 下载 电子版仅供预览及学习交流使用,下载后请24小时内删除,支持正版,喜欢的请购买正版书籍 电子书下载(皮皮云盘-点击"普通下载" ...

  4. Dubbo和Spring Cloud微服务架构对比

    一.为什么要使用微服务? 微服务提倡将单一应用程序划分成一组小的服务,服务之间互相协调.互相配合. 今天我们来了解下业内主要的微服务框架:Dubbo 和 Spring Cloud 微服务主要的优势 降 ...

  5. 放弃Dubbo,选择最流行的Spring Cloud微服务架构实践与经验总结

    Spring Cloud 在国内中小型公司能用起来吗?从 2016 年初一直到现在,我们在这条路上已经走了一年多. 在使用 Spring Cloud 之前,我们对微服务实践是没有太多的体会和经验的.从 ...

  6. 驾驭云端之风1——Spring Cloud微服务架构实践指南

    本博客纯属个人总结,非原创. 喜欢技术交流的,可关注博主,武汉有后端开发群,可支持内推,了解武汉行情等. 前沿 优惠卷平台项目的整体功能和模块,以及每个功能点的技术选型和背后的依据. 搭建一个简化版的 ...

  7. Spring Cloud 微服务架构

    一.分布式服务框架的发展 1.1 第一代服务框架 代表:Dubbo(Java).Orleans(.Net)等 特点:和语言绑定紧密 1.2 第二代服务框架 代表:Spring Cloud等 现状:适合 ...

  8. Spring Cloud 微服务架构的五脏六腑!

    来源:webfe.kujiale.com/spring-could-heart/ 整理:Java技术栈(公众号ID:javastack) Spring Cloud 是一个基于 Spring Boot ...

  9. 绍一下Spring Cloud微服务架构

    2019独角兽企业重金招聘Python工程师标准>>> Spring Cloud解决的第一个问题就是:服务与服务之间的解耦.很多公司在业务高速发展的时候,服务组件也会相应的不断增加. ...

最新文章

  1. 再学 GDI+[91]: TGPImage(11) - 转灰度图像
  2. .NET Core 中使用 Humanizer 显示友好时间格式
  3. 转 C#对多个集合和数组的操作(合并,去重,判断)
  4. Openstack入门篇(十一)之neutron服务(控制节点)的部署与测试
  5. python如何安装pdfminer_|请教在python3中安装pdfminer.six的方法
  6. 命令行导出和导入数据库 How to export and import MySQL database using command line Interface...
  7. MongoDB 快速入门实战教程最新版
  8. VS 编译选项如何设置以及对性能的影响1
  9. oracle varchar2(n) 与 postgresql varchar(n) 的区别
  10. android - studio版本控制文件颜色代表意思
  11. 【sketchup 2021】草图大师图像输出与渲染之Enscape渲染(优秀的实时渲染软件)的高级使用【灯光的添加、代理模型的添加、材质编辑器、视频编辑器、全景导出并编辑】
  12. matlab for局部变量赋值,Matlab中的persistent变量
  13. 建模实训报告总结_模型实训心得体会
  14. 如何删除github上的文件夹(抖机灵方法)
  15. 基于物联网的无线温度系统在钢铁行业的应用
  16. 三颗种子开发系统源码
  17. 关于“档案大数据”的非主流看法
  18. B树的原理及代码实现、B+树和B*树介绍及应用
  19. 进阶实验4-3.5 哈夫曼编码 (30 分)
  20. 提高个税起征点可增加工薪层可支配收入

热门文章

  1. typescript断言
  2. nodeJS 事件绑定
  3. java解析动态AIS原始数据
  4. 人工机器:作为归纳系统的深度学习
  5. GrepWin:Win7下的文本替换工具
  6. java util包类_java.util包下的类及常用方法
  7. 使用 yield 减少内存消耗
  8. 数据之路 Day5 - Python基础5
  9. LNMP架构介绍、MySQL安装、PHP安装、Nginx介绍
  10. 优雅地在Mac+Valet环境下本地部署phphub