工作中使用了微服务架构,接下来的一段时间里,我会写一系列的文章来介绍微服务架构,同时我也会在github上写一个microservices的应用框架(地址会在后续文章给出)。
这篇文章主要讲述了微服务架构的应用普遍需要关注的点。
翻译和整理自:
- http://microservices.io/patterns/microservice-chassis.html
- http://microservices.io/patterns/externalized-configuration.html
- http://microservices.io/patterns/observability/application-logging.html
- http://microservices.io/patterns/observability/application-metrics.html
- http://microservices.io/patterns/observability/distributed-tracing.html
- http://microservices.io/patterns/observability/health-check-api.html
一、微服务的框架
1.上下文
当你开始开发一个应用的时候,你经常会花很多时间去处理横切关注点/普适性问题。比如说:
- 暴露给外部的配置- 包括凭证、外部服务(比如数据库、消息中间件)的网络地址
- 日志- 配置一个像log4j或者logback这样的日志框架
- 健康检查- 一个可以“ping”的用来监控一个service是否健康的url
- 指标- 提供一个指标,可以知道这个应用现在在做什么,做的怎么样
- 分布式追踪- 给每个请求一个唯一的标识码,这个标识码会在services之间被传递
除了这些通用的横切关注点,还有一些这个应用使用的技术的具体的关注点。 使用数据库或者消息中间件这样的基础架构服务的应用需要一些模板化的配置。比如说,使用关系型数据库的应用必须配置一个连接池,处理HTTP请求的应用也需要一些模板化的配置。
花一两天甚至更长的时间去建立起这么一套机制是很常见的。如果你要花几个月或者几年的时间去开发一个单一架构应用,那么这些前期的对于横切关注点的投入是微不足道的。但是如果你是要开发一个微服务架构的应用,情况就有所不同了。可能会有几十个或者几百个服务,你会频繁地创建新的service,这些service每个都需要几天或者几周去开发。你不可能每个服务都花一两天时间去配置这些横切关注点。在微服务架构中,除了上述这些横切关注点,你还要去解决服务注册、服务发现以及为了可靠地处理部分故障的断路器。
2.强制条件
- 创建一个新的微服务应该是快速和简单的
- 当创建一个微服务时,你必须处理像暴露给外部的配置、日志、健康检查、指标监控、服务注册和发现、断路器等等横切关注点。还有一些你这个微服务用到的具体的技术的横切关注点。
3.解决方案
使用一个微服务的底盘框架,它处理了这些横切关注点。
示例:
二、暴露给外部的配置
1. 问题
如何让一个service可以不用修改,就跑在多个环境下?
2. 强制条件
- 一个服务必须被提供配置信息,说明它应该链接哪个外部的/第三方的服务。比如说,数据库地址和验证信息。
- 一个服务必须在多种环境下运行而不需要修改和重新编译:开发,测试,产品。
- 不同的环境有不同的第三方服务实例。比如说QA的数据库和产品环境的数据库不一样。
3.解决方案
把应用的配置暴露给外部。在启动时,服务从外部环境读到这些配置信息,比如说,环境变量。
示例
docker-compose.yml 文件支持把环境变量作为它的值。
web:
image: sb_web
ports:
- "8080:8080"
links:
- eureka
environment:
USER_REGISTRATION_URL: http://REGISTRATION-SERVICE/user
REGISTRATION-SERVICE是一个服务的逻辑名。它使用客户端服务发现来处理。
三、日志聚合
我们可以建立一个集中化的log service, 它把每个service实例产生的日志聚合在一起,用户可以搜索和分析这些日志。他们可以配置一些alerts, 比如说某个具体的消息出现时就会被触发。
示例:
AWS Cloud Watch
(译者注: 在我们的项目中,所有的service的log本质上都是以stdout的方式打出的,当运行在container中时,这些输出文件都在宿主机的某一个文件目录下,我们可以额外配置一些别的软件,来把这些文件统一聚集到某一个地方去做分析,比如Splunk!)
四、健康检查API
每个service都应该有一个健康检查的API, 比如说 HTTP /health, 来返回这个service的健康状况。这个API endpoint应该执行一系列的检查,比如:
- 这个service实例所连接的基础设施服务的状态(比如数据库等)
- 主机的状态,比如磁盘空间
- 应用特有的逻辑
健康检查的client-一个监控服务、服务注册或者负载均衡器,周期性调用这个api来检查这个service实例的健康状态。
五、Metrics
让一个service可以把单个的操作的统计信息集成起来。我们可以建立一个集中化的metrics service, 它产生一些报表和警告。有两种模型可以用来聚合metrics信息:
- push - 服务把metrics消息推送到metrics service
- pull - metrics service从服务实例上抓取
示例:
- 生成metrics的 libraries:
- Coda Hale/Yammer Java Metrics Library
- Prometheus client libraries
- Metrics 聚合服务:
结果
优点:
- 对应用的行为提供了一个深度的Insight
缺点:
- Metrics的代码和业务逻辑混合在一起,使它更复杂
问题:
- 聚集 metrics可能需要很大的基础设施
六、分布式追踪
一个请求可能会覆盖到多个service,那么怎么去追踪这单个的请求呢?
我们可以在service中加入这样的代码:
- 给每个单个的请求一个唯一的request id
- 把这个request id传递给别的与处理这个请求相关的service
- 把这个request id加入到所有的log信息中
- 把请求的信息(比如开始时间,结束时间)和在处理这个请求时的行为记录下来