可运维架构设计和实践

Posted by WZhong on Tuesday, January 21, 2020

TOC

架构的可运维性主要和配置、监控(日志,调用链,metrics,告警)、部署相关

何谓生产就绪 Production Ready

  1. 经典软件工程阶段

    • 需求分析 -> 架构设计 -> 实现测试 -> 部署运维
  2. 互联网软件交付阶段

    • 编码完成 -> 生产就绪 -> 价值交付
  3. 何谓生产就绪

    • 功能测试OK
    • 性能测试OK
    • 配置管理
    • 日志监控
    • Metrics监控:调用树,调用延迟,出错树
    • 健康检查
    • 调用链监控
    • 安全性考量
    • 高可用考量
    • 扩展升级考量

Spring Boot如何实现分环境配置

  1. Staffjoy环境

    • Dev:IntelliJ IDEA
    • TEST:Docker Compose
    • UAT/PROD:K8s
  2. 示例:accountService

    • resources下有5个yml配置文件,利用spring profile机制实现
      • 公共配置文件:application.yml
      • 分环境配置文件:application-dev.yml,application-test.yml,application-uat.yml,application-prod.yml

配置管理:Apollo vs. Spring Cloud Config vs. K8s ConfigMap

  1. 何谓动态配置更新

    • 配置中心 + 应用监听新配置并刷新
  2. Apollo vs. Spring Cloud Config vs. K8s ConfigMap

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

    • Apollo动态配置
    • SpringCloud集中配置

调用链(Tracy)监控:CAT vs. Zipkin vs. Skywalking

  1. 演进历史

    2002 eBay CAL:Centralized Application Logging
    2010 Google Dapper论文(是除CAL/CAT外所有产品的基础)
    2011 点评 CAT(CAL基础上发展演化的)
    2012 Twitter Zipkin
    2012 Naver Pinpoint
    2015 Apache Skywalking
    2016 Uber Jaeger
  2. 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
    祖先源头 CAL Dapper Dapper
    同类产品 暂无 Jaeger、Spring Cloud Sleuth Naver Pinpoint
    github star 9.6k 11.2k 9.2k
    亮点 企业生产级,报表丰富 社区生态好 非侵入,Apache背书
    不足 用户体验一般,社区一般 APM报表能力弱 时间不长,文档一般,仅限中文社区
  3. 选型推荐

    • 对于微服务监控,除了调用链监控,APM报表能力很重要,可以分析定位出很多系统性能问题,所有不推荐zipkin
    • 对于大多数企业级微服务应用,CAT仍然是首选
    • Skywalking使用门槛较高,推荐关注和试点使用
  4. Skywalking Java Agent支持库

  5. Staffjoy依赖监控图

结构化日志和审计日志

  1. 说明

    • 结构化日志一般出现在Go、C#,Java社区结构化日志不够热
    • Java的结构化日志库:structlog4j
    • Json结构的日志,后续方便处理,如通过ELK存储分析
  2. structlog4j

    • structlog4j
    • 在slf4j的基础上做了封装
    • 使用方式与slf4j类似
    • 审计日志:- 对一些重要的业务操作,希望能把操作者、操作内容、操作数据记录日志
    @Service
    @RequiredArgsConstructor
    public class AccountService {
    
        static ILogger logger = SLoggerFactory.getLogger(AccountService.class);
    
        ...
    
        public AccountDto create(String name, String email, String phoneNumber) {
            ...
    
            LogEntry auditLog = LogEntry.builder()
                    .authorization(AuthContext.getAuthz())
                    .currentUserId(AuthContext.getUserId())
                    .targetType("account")
                    .targetId(account.getId())
                    .updatedContents(account.toString())
                    .build();
    
            logger.info("created account", auditLog);
    
            AccountDto accountDto = this.convertToDto(account);
            return accountDto;
        }
    
        public AccountDto update(AccountDto newAccountDto) {
            ...
    
            LogEntry auditLog = LogEntry.builder()
                    .authorization(AuthContext.getAuthz())
                    .currentUserId(AuthContext.getUserId())
                    .targetType("account")
                    .targetId(newAccount.getId())
                    .originalContents(existingAccount.toString())
                    .updatedContents(newAccount.toString())
                    .build();
    
            logger.info("updated account", auditLog);
    
            ...
    
            return accountDto;
        }
    
        ...
    }
    

集中异常监控和Sentry

  1. 日志

    • 日志收集存储展示用ELK
    • 集中异常监控用Sentry,云服务量小免费
  2. Sentry粒度细,方便对接告警产品,各种统计、日志监控、异常监控功能丰富

        try {
            accountRepo.save(newAccount);
        } catch (Exception ex) {
            String errMsg = "Could not update the user account";
            serviceHelper.handleException(logger, ex, errMsg);
            throw new ServiceException(errMsg, ex);
        }
    public void handleException(ILogger log, Exception ex, String errMsg) {
        log.error(errMsg, ex);
        if (!envConfig.isDebug()) {
            sentryClient.sendException(ex);
        }
    }
    @Around("execution(* io.sentry.SentryClient.send*(..))")
    public void around(ProceedingJoinPoint joinPoint) throws Throwable {
        // no sentry logging in debug mode
        if (envConfig.isDebug()) {
            log.debug("no sentry logging in debug mode");
            return;
        }
        joinPoint.proceed();
    }

日志、metrics、调用链如何跟K8s环境进行集成

  1. 日志集成K8s环境:EFK + K8s

    • DeamonSet:fluentd专区docker生成的日志
    • 日志发送到kafka队列:做缓冲,减小对ELK的压力;缓存日志,对ELK升级有好处
    • 开发Log Parser,或用LogStash对日志做解析和过滤垃圾日志
  2. metrics监控和告警的标准配置:Prometheus + K8s

    • Prometheus通过K8s Discovery发现K8s的服务,抓取相应metrics
    • Spring Boot开启Micrometer + Actuator
  3. 调用链监控:SkyWalking + K8s

    • Java启动时带上SkyWalking Agent
    • agent通过trace发送到SkyWalking Collector
    • collector将调用链信息存储到elasticsearch

「真诚赞赏,手留余香」

WZhong

真诚赞赏,手留余香

使用微信扫描二维码完成支付