微服务 云原生

生产就绪(Production Ready)

架构的可运维性主要和配置,监控,部署这些环节相关。其中监控包括日志监控,调用链监控。

经典软件工程阶段

可运维架构设计和实践 - 图1

互联网软件交付阶段

可运维架构设计和实践 - 图2

什么是生产就绪

可运维架构设计和实践 - 图3

SpringBoot如何实现分环境配置

Staffjoy环境

可运维架构设计和实践 - 图4

配置中心选项比较

动态配置更新

可运维架构设计和实践 - 图5

Apollo vs SpringCloud Config vs K8s ConfigMap


Apollo SpringCloud K8s ConfigMap
配置界面 统一界面管理,不同环境和集群配置 无,通过Git操作 Cli或Dashboard
配置存储 DB Git Etcd
配置生效时间 实时推送+应用配合 近实时+应用配合 近实时+应用配置
动态配置 支持,实时推送 复杂+MQ 支持发布更新
版本管理 UI支持发布历史和回滚 无,通过Git操作 无,需自己管理
灰度发布 支持 不支持 支持灰度发布
授权/审计/审核 UI操作,修改和发布权限分离 需要通过Git仓库设置 K8s平台部分支持
实例配置监控 可见哪些客户端配置生效 不支持 可查询容器环境变量
客户端支持 原生Java/.Net,提供API,支持Spring标注 Spring应用+标注支持 语言无关

参考样例

Apollo动态配置

https://github.com/ctripcorp/apollo-use-cases

SpringCloud集中配置

https://github.com/sqshq/piggymetrics

服务监控工具对比

监控平台的演进历史

可运维架构设计和实践 - 图6

CAT vs Zipkin vs Skywalking


CAT Zipkin Apache Skywalking
调用链可视化
聚合报表 非常丰富 较丰富
服务依赖图 简单 简单
埋点方式 侵入 侵入 非侵入,运行期字节码增强
VM指标监控
告警支持
多语言支持 Java/.Net 丰富 Java/.Net/NodeJS/PHP自动,Go手动
存储机制 MySQL(报表),本地文件/HDFS(调用链) 可选in memory,MySQL,ES(生产),Cassandra(生产) H2,ES(生产)
社区支持 主要在国内,点评/美团 文档丰富,国外主流 Apache支持,国内社区好
国内案例 点评,携程,陆金所,拍拍贷 京东,阿里定制不开源 华为,小米,当当,微众银行
APM Yes No Yes
祖先源头 eBay CAL Google Dapper Google Dapper
同类产品 暂无 Uber Jaeger,SpringCloud Sleuth Naver Pinpoint
亮点 企业级生产,报表丰富 社区生态好 非侵入,Apache背书
不足 用户体验一般,社区一般 APM报表能力弱 时间不长,文档一般,仅限中文社区

Skywalking

https://skywalking.apache.org/
image.png

Skywalking Java Agent支持库

https://skywalking.apache.org/docs/#JavaAgent
image.png

Zipkin

https://zipkin.io/
image.png

Jaeger

https://www.jaegertracing.io/
image.png

Staffjoy依赖监控图

image.png

日志监控

结构化日志和审计日志

https://github.com/jacek99/structlog4j
可运维架构设计和实践 - 图12

  1. import com.github.structlog4j.IToLog;
  2. import lombok.Builder;
  3. import lombok.Data;
  4. @Data
  5. @Builder
  6. public class LogEntry implements IToLog {
  7. private String currentUserId;
  8. private String companyId;
  9. private String teamId;
  10. private String authorization;
  11. private String targetType;
  12. private String targetId;
  13. private String originalContents;
  14. private String updatedContents;
  15. @Override
  16. public Object[] toLog() {
  17. return new Object[] {
  18. "auditlog", "true",
  19. "currentUserId", currentUserId,
  20. "companyId", companyId,
  21. "teamId", teamId,
  22. "authorization", authorization,
  23. "targetType", targetType,
  24. "targetId", targetId,
  25. "originalContents", originalContents,
  26. "updatedContents", updatedContents
  27. };
  28. }
  29. }
  1. import com.github.structlog4j.ILogger;
  2. import com.github.structlog4j.SLoggerFactory;
  3. static ILogger logger = SLoggerFactory.getLogger(AccountService.class);
  4. LogEntry auditLog = LogEntry.builder()
  5. .authorization(AuthContext.getAuthz())
  6. .currentUserId(AuthContext.getUserId())
  7. .targetType("account")
  8. .targetId(account.getId())
  9. .updatedContents(account.toString())
  10. .build();
  11. logger.info("created account", auditLog);

集中异常监控和Sentry

官网:https://sentry.io
开源仓库:https://github.com/getsentry/sentry

Sentry云服务的使用

客户端配置

  1. @Bean
  2. public SentryClient sentryClient() {
  3. SentryClient sentryClient = Sentry.init(staffjoyProps.getSentryDsn());
  4. sentryClient.setEnvironment(activeProfile);
  5. sentryClient.setRelease(staffjoyProps.getDeployEnv());
  6. sentryClient.addTag("service", appName);
  7. return sentryClient;
  8. }

发送异常监控日志

  1. public void handleError(ILogger log, String errMsg) {
  2. log.error(errMsg);
  3. if (!envConfig.isDebug()) {
  4. sentryClient.sendMessage(errMsg);
  5. }
  6. }

EFK & Prometheus & Skywalking + Kubernetes集成架构

EFK + K8s

可运维架构设计和实践 - 图13

Prometheus + K8s

可运维架构设计和实践 - 图14

Skywalking + K8s

可运维架构设计和实践 - 图15