为了使服务做好部署到生产环境中的准备,需要确保满足三个关键的质量属性:安全性、可配置性和可观测性。
开发安全的服务
四个方面:
身份验证
访问授权
审计
安全的进程间通信
传统的单体应用程序的安全性
应用程序的客户首先登陆获取会话令牌,该令牌通常是cookie。客户在向应用发出的每个后续请求中都会包含会话令牌。
安全架构的关键部分是会话(存储主体的ID和角色)、安全上下文(存储有关发出当前请求的用户的信息)
缺点:使用内存中会话,必须把特定会话的所有请求路由到同一个应用程序实例。这使负载均衡和操作变得复杂。
避免方法:将会话存储在数据库,或者不保存服务器端会话,而在每个请求中提供其凭据,或者将会话状态存储在会话令牌中。
在微服务架构中实现安全性
单体安全架构的一些方面对微服务架构来说是不可用的。
内存中的安全上下文
服务无法共享内存
集中会话
多个服务可以访问基于数据库的会话,但这违反了松耦合原则。
由API Gateway处理身份验证
让每个服务分别对用户进行身份验证,出现安全漏洞的风险、概率比较大。且服务需要处理不同的身份验证机制。
可以让API Gateway在请求转发给服务前对其进行身份验证。
客户端事件序列:
客户端发出包含凭据的请求給API Gateway
API Gateway对凭据进行身份验证,创建安全令牌,并将其传递给服务。
基于登陆的客户端事件序列:
客户端发出包含凭据的登陆请求。
API Gateway 返回安全令牌
客户端在调用操作的请求中包含安全令牌
API Gateway验证安全令牌并将其转发给服务
处理访问授权
验证客户端凭据不够,还要实现访问授权机制。
在API Gateway中集中实现访问授权可降低安全漏洞的风险,可使用Spring Security等安全框架实现访问授权,但会产生API Gateway与服务的耦合,且只能实现对URL路径的基于角色的访问。需要详细了解服务的领域逻辑。
另一个实现访问授权的位置是服务,它可以实现基于角色和基于ACL的访问授权机制。
使用JWT传递用户身份和角色
两种令牌可供选择
一种是不透明的令牌,无可读性,通常是一串UUID,缺点是降低性能和可用性,增加延迟。
另一种是使用包含用户信息的透明令牌。其流行标准是JWT。它使用仅为JWT创建者所知的签名,确保恶意第三方不能伪造、篡改JWT。但没有切实可行方法撤销落入恶意第三方的JWT令牌。解决方案是发布具有较短到期时间的JWT,可以限制恶意第三方。
在微服务架构中使用OAuth2.0
OAuth2.0是一种访问授权协议,最初旨在使公共云服务的用户能够授予第三方应用程序访问其信息的服务,而不必向第三方应用透露他们的密码。但你也可以将其用于应用程序中的身份验证和访问授权。
如何验证API客户端: 客户端发出请求,使用凭据,API Gateway通过向OAuth2.0身份验证服务器发出请求来验证API客户端。身份验证服务器返回访问令牌,API Gateway将其传递给服务。服务验证令牌的签名,并提取有关用户的信息,包括其身份和角色。
支持基于登陆的客户端: 客户端通过其凭据发送到API Gateway来登录。API Gateway使用OAuth2.0身份验证服务器对其凭据进行身份验证,并将其访问令牌和刷新令牌作为cookie返回。客户端在其对API Gateway的请求中包含这些令牌(访问令牌、刷新令牌)。
微服务架构中实现安全性的关键思想:
API Gateway负责验证客户端身份。
API Gateway和服务使用透明令牌来传递有关主体的信息。
服务使用令牌获取主体的身份和角色
设计可配置的服务
将特定环境的配置属性硬写入可部署服务的代码是没有意义的,这些环境是动态创建的,使用Spring配置文件机制在运行时选择也没有意义,这样会引入安全漏洞,且限制可部署的位置。
外部化配置机制在运行时向服务实例提供配置属性值,分为推送和拉取两种模型。
使用基于推送的外部化配置
推送模型依赖于部署环境和服务的协作,当部署基础设施创建服务实例时,它会设置包含外部化配置的环境变量。服务读取这些环境变量。
若使用Spring boot创建服务,它具有极其灵活的外部化配置机制,可使用明确的定义的优先级规则从各种来源检索配置属性。
命令行参数
SPRING_APPLICATION_JSON
JVM系统属性
操作系统环境变量
当前目录中的配置文件
来自此列表的靠前的来源的特定属性值将覆盖此列表稍后的来源中的相同属性。
Spring Boot使这些属性可以通过ApplicationContext访问,如通过@Value注解获取属性的值。
推送模式有效、使用广泛,但要重新配置正在运行的服务很难,且配置属性值存在分散在众多服务定义中的风险。
使用基于拉取的外部化配置
启动时,服务实例从配置服务器检索其配置属性。部署基础设施提供用于访问配置服务器的配置属性。
多种方法可以实现配置服务器:
Git
数据库
专用配置服务器,如Spring Cloud Config Server。
使用配置服务器好处:
集中配置,易于管理
敏感数据的透明加密
动态重新配置
缺点是需要额外的人力进行设置和运维。
设计可观测的服务
可观测性模式使开发人员和运维人员能够理解应用程序的行为并解决问题。开发人员有责任确保他们的服务是可观测的,运维人员负责收集服务公开信息的基础设施。
使用健康检查API模式
服务实例需要能够告诉部署基础设施它是否能够处理请求。一个好的解决方案是服务实现健康检查接口。部署基础设施定期调用该端点确定服务实例的健康状况。
Health Check Request Handler通常测试服务实例与外部服务的连接。
实现健康检查接口
Spring Boot Actuator是健康检查库的一个很好的例子,它实现了/actuator/health接口,实现此接口的代码负责返回健康状况检查结果。基于部署基础设施实现了一组合理的健康检查,验证服务实例是否可以访问其外部基础设施服务。
调用健康检查接口
部署服务时,必须配置部署基础设施以调用接口。
使用日志聚合模式
集中式日志聚合基础设施将每个服务实例的日志发送给集中式日记记录服务器。用户可以查看和搜索日志。他们还可以设置告警,当日志内容与特定条件匹配时触发告警。
服务如何生成日志
确定使用的日志库,如Logback、log4j、JUL、SLF4J。
还需要确定记录的位置,你可以日志输出到stdout,然后,部署基础设施将决定如何处理服务的输出。
日志聚合的基础设施
负责聚合日志、存储日志以及用户能够搜索日志。一种流行的方式是ELK套件。
使用分布式追踪模式
深入了解应用程序正在执行的操作的一种好方法是使用分布式追踪。为每个外部请求分配一个唯一的ID,并在提供可视化和分析的集中式服务器中记录它如何从一个服务流向下一个服务。可以看到处理外部交互花费的时间,查找特定请求相关的所有日志。
使用追踪工具类库
追踪工具类库构建跨度树,并将它们发送到分布式追踪服务器。Spring Cloud Sleuth是基于AOP技术的一个优秀框架。
关于分布式追踪服务器
分布式追踪服务器将跨度拼接在一起以形成完整的追踪并将它们存储在数据库,如Open Zipkin。
使用应用程序指标模式
收集技术栈中每个级别的指标,并将其存储在指标服务中,该服务可以提供可视化和告警功能。
收集服务层面的指标
基于Spring Boot的服务可以使用Micrometer Metrics库作为依赖项来收集(并公布)基本指标,还可以使用其API收集特定应用的指标,如订单数量。
把指标发送给指标服务
分为推送模式(服务实例通过调用API将指标发送给指标服务,如AWS Cloudwatch),和拉取模式(Metrics Service或本地运行的代理调用服务的API,从服务实例检索指标信息,如Prometheus)
使用异常追踪模式
服务把产生的异常报告给中央服务,该服务对异常进行重复数据删除、生成警报并管理异常的解决方案。服务可直接调用异常追踪服务的API,或使用客户端库(如HoneyBadger、Sentry)
使用审计日志模式
记录数据库中的用户操作,以帮助客户支持、确保合规性,并检测可疑行为。
向业务逻辑添加审计日志代码
与业务代码交织,降低可维护性;可能出错
使用面向切面编程
自动记录每个服务方法调用,缺点是只能记录调用的方法名称和它的参数,而确定正在执行的业务对象,并生成面向业务的审计日志具有挑战性。
使用事件溯源
自动为创建和更新操作提供审计日志,但它不记录查询。
使用微服务基底模式开发服务
微服务基底
异常追踪、日志记录、健康检查、外部化配置和分布式追踪是微服务架构需要解决的共性问题,我们需要在能够处理这些共性问题的框架或框架集合上构建服务。
如Spring Boot,Spring Cloud,Go Kit都是微服务基底。
从微服务基底到服务网格
微服务基底框架需要和使用的编程语言相关。
避免此问题的替代方案是服务网格。把所有进出服务的网络流量通过一个网络层进行路由。这个网络层负责解决包括断路器、分布式追踪、服务发现等具有共性的需求。服务网格可以通过在服务之间使用基于TLS的机制来保护进程间通信。
实现:Istio、Linkerd、Conduit
java达人
ID:drjava
(长按或扫码识别)