Dawn's Blogs

分享技术 记录成长

0%

微服务架构设计模式 (9) 安全性 可配置性 可观测性

安全性

在安全性中,主要讨论用户身份认证的问题。目前有两种方法实现身份认证,Session 和 JWT。

Session 的缺陷

在单体应用程序中,可以使用 Cookie+Session 来进行身份认证,Session 信息是由服务器维护的。但是在微服务架构中,由于会水平扩展所以由服务本地维护 Session 信息是不现实的,有两种解决方法:

  • 将 Session 信息放在数据库中,这样 Session 信息在多个实例中就是共享的。
  • 使用特定的负载均衡算法,如对客户端地址进行哈希,使得同一个客户端发出的请求到达同一个实例。

JWT

如果由服务器端来维护用户身份信息会带来种种设计上的问题,那么可以由客户端自己维护用户身份信息。JWT 就是这样一种思想,JWT 包含一个 Json 对象,其中有用户信息以及其他元信息(如到期时间)。JWT 包含的 Json 对象是被加密过的(token),并且签名可以保证第三方无法伪造。

因为 JWT 是客户端自包含的,所以请求不论被路由到哪一个服务实例上,服务实例都可以根据 JWT 去验证用户信息。

JWT 的缺点在于无法验证被恶意第三方偷取的 JWT token,只要恶意第三方获取到了 token 就等于获取了这个用户的登录信息。一种缓解的方法是使用较短的到期时间,但是随之而来的问题就是客户端需要频繁的请求 JWT 认证重新获取 token。

可配置性

在微服务架构中,最常使用的是外部化配置,即从服务外部而不是源代码中获取配置信息。

在源代码中直接定义配置文件有两个缺点

  • 密码等敏感信息是直接存在于源代码中的,这可能会造成一些安全性问题。
  • 不够灵活,如果需要修改配置信息就必须修改源代码文件。

外部化配置主要有两种方式实现,推送模型和拉取模型。

推送模型

推送依赖于部署基础设施(如 docker、k8s 等),使用配置环境变量或者挂载存储卷的方式将配置信息传递给服务实例。

推送模型非常的简单有效,在服务实例看来就是从本地去读取配置文件信息。

但是他的一个限制就是重新配置正在运行的服务很难,因为部署基础设施可能不允许你在不重新启动服务的情况下变更外部化配置信息。另一个限制就是配置信息分散在各个服务中,不集中管理

拉取模型

在拉取模型中,服务实例从配置服务器主动的拉取配置信息。使用配置服务器的优点:

  • 可以集中化的管理配置信息。
  • 敏感数据的透明解密,存储在配置服务器上的敏感信息是加密的,发送到具体服务实例上的敏感信息是已经解密了的。
  • 动态重新配置,服务可能通过轮询等方式检查更新的配置值,用于更新自身配置。

image-20230525135920199

可观测性

可观测性总的来说包括三个方面:日志、追踪和指标。

  • 日志:记录服务处理的过程、请求和响应详情、详细的错误信息等。
  • 追踪:请求在系统中的调用链路,以及调用时间。
  • 指标:CPU 使用率、内存使用率等。

日志聚合

在微服务架构中,服务多实例部署在不同的物理机上,各个微服务的日志也被分散储存在不同的物理机。集群足够大的话,使用上述传统的方式查阅日志就变得非常不合适。因此需要集中化管理分布式系统中的日志。日志聚合就是将分散在各个服务上的日志都写入集中式的日志记录服务器中,该服务器提供搜索和告警功能。

image-20230525141323392

ELK

一种流行的日志记录基础设施是 ELK(ElasticSearch、Logstash、Kibana)

  • ElasticSearch:文本数据库,用作日志记录的服务器。它是 NoSQL 文档数据库,可以存储和搜索整个文档。
  • Logstash:数据分析软件,主要用于分析 Log 日志。数据源首先将数据传给 Logstash,它主要包括 Input 数据输入、Filter 数据源过滤和 Output 数据输出三部分。Logstash 可以对数据进行处理,包括数据的过滤和格式化,之后发送到 Elasticsearch 存储,并在 Elasticsearch 中建立相应的索引。

image-20230525143758999

  • Kibana:ElasticSearch 的可视化工具。Kibana 利用 Elasticsearch 的 REST 接口来检索数据,调用 Elasticsearch 存储的数据,将其可视化。

在实际使用中,Logstash 对应的功能(过滤日志、格式化)是可以自己实现的。而各个服务可以通过消息队列将日志发往日志服务器。

分布式追踪

分布式追踪(链路追踪)可以了解服务之间的调用关系,并且记录调用信息(如开始时间和结束时间)。具体来说,就是为每一个外部请求分配唯一的 ID,并在集中式的服务器中记录它是如何从一个服务流向下一个服务的

在链路追踪中,有两个核心概念需要了解,trace 和 span:

  • trace:就是一个完整的请求从开始到结束,都属于一个 trace,一个 trace 有一个唯一的 Trace ID。
  • span:每进行一次 RPC 调用,都视为一个 span,一个 span 内部有唯一的 Span ID。

OpenTelemetry + Jaeger

OpenTelemetry 只涉及到遥感数据(链路追踪信息、日志、指标)的采集和传输,为遥感数据的采集和传输提供一套统一的标准。

Jaeger 是分布式链路追踪工具,用于管理和监控链路追踪数据。

链路追踪可以涉及两个步骤:

  • 采集链路请求数据。
  • 存储、管理和可视化收集的数据以采取快速行动。

OpenTelemetry 解决了第一步,而 Jaeger 旨在解决后者。使用 OpenTelemetry,可以生成链路信息、日志、指标,而 Jaeger 只负责链路追踪分析。

下图为 OpenTelemetry 加 Jaeger 的架构图,可以看到中间为 OpenTelemetry 负责数据的收集、处理、传输,下方为链路追踪应用 Jaeger,用于管理由 OpenTelemetry 采集而来的数据。

image-20230525152552462

监控指标

在微服务架构中,同样也需要监控和告警。监控系统从各个服务实例中收集指标信息(CPU、内存、磁盘占用率等),然后指标服务用于提供存储、告警的功能。

指标定期采样,每一个指标样本都具有三个熟悉:名称、值、时间戳。在一些监控系统中,样本还会带上标签(tag),标签是一组键值对。

典型的监控系统就是 Prometheus + Grafana。

服务网格

如果在每一种服务中都需要配置熔断器、服务发现、链路追踪、负载均衡等共性的需求,这无疑将耗费巨大的时间,并且这样的工作都是相同重复的。所以可以引出服务网格,服务网格是一种网络基础设施,它负责上述的这些共性需求,所以不需要在服务中关注这些问题了。

image-20230525160802743

如 Istio 就是一种服务网格,它将服务发现等都集成在服务网格内部,服务本身不用关心:

image-20230525160710238