├── .DS_Store ├── .gitattributes ├── .gitignore ├── .nojekyll ├── 00~DevOps 文化 └── 99~参考资料 │ ├── 2021-万字长文带你彻底搞懂什么是 DevOps.md │ └── 2023-必致(BizDevOps).md ├── 01~持续集成与交付 ├── .DS_Store ├── CI │ └── CI.md ├── README.md ├── 交付规范 │ ├── README.md │ └── 交付系统要求.md ├── 变更与发布 │ ├── 多策略部署.md │ └── 风险评估.md └── 平台工具 │ ├── Jenkins │ └── README.md │ ├── Spinnaker │ ├── README.md │ └── 部署配置.md │ └── Tekton │ └── README.md ├── 02~自动化运维 ├── .DS_Store ├── AIOps │ └── README.md ├── README.md ├── 设施即代码 │ ├── Pulumi.md │ ├── README.md │ └── Terraform.md ├── 设计理念 │ ├── 体系设计.md │ ├── 场景分析.md │ └── 流水线即代码.md ├── 运维脚本 │ ├── README.md │ └── 数据库.md └── 运行成本 │ └── README.md ├── 03~监控告警 ├── .DS_Store ├── APM │ └── README.md ├── README.md ├── 全链路监控 │ └── README.md ├── 开源监控系统 │ └── SkyWalking │ │ └── README.md ├── 监控指标 │ ├── README.md │ ├── 实践案例 │ │ └── README.md │ ├── 程序指标 │ │ ├── README.md │ │ ├── 响应时延.md │ │ ├── 应用.md │ │ └── 服务吞吐量.md │ ├── 系统指标 │ │ ├── CPU │ │ │ ├── CPU.md │ │ │ ├── perf 与火焰图 │ │ │ │ ├── README.md │ │ │ │ └── 火焰图解析.md │ │ │ ├── sar.md │ │ │ ├── stat.md │ │ │ ├── top.md │ │ │ └── 中间件.md │ │ ├── README.md │ │ ├── 内存 │ │ │ └── 内存.md │ │ ├── 磁盘 │ │ │ ├── README.md │ │ │ └── fio.md │ │ └── 网络 │ │ │ └── 网络.md │ ├── 统计与告警策略 │ │ ├── 异常检测.md │ │ └── 统计与告警策略.md │ └── 黄金指标 │ │ └── README.md └── 监控系统设计 │ ├── README.md │ ├── 存储设计.md │ ├── 监控系统对比.md │ └── 采集设计.md ├── 04~日志聚合 ├── .DS_Store ├── ELK │ └── README.md ├── Flume │ ├── README.md │ ├── 安装与配置.md │ └── 组件类型.md ├── README.md └── 系统设计 │ ├── 多租户隔离.md │ └── 采集与调度.md ├── 05~SRE ├── 99~参考资料 │ └── 2020~《站点可靠性工作手册》 │ │ └── README.md ├── API 安全 │ └── README.md ├── Linux 安全加固 │ ├── 99~参考资料 │ │ ├── 2022-Linux Hardening Guide.md │ │ └── 2023-How To Secure A Linux Server.md │ └── Linux 安全加固.md ├── README.md ├── 备份 │ ├── README.md │ └── 文件备份.md └── 零信任 │ └── README.md ├── 99~参考资料 └── 2020~Devops Basics │ └── README.md ├── INTRODUCTION.md ├── LICENSE ├── README.md ├── _sidebar.md └── index.html /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wx-chevalier/DevOps-Notes/d7b6420975e9914f5512ae398dd926d6fc08796f/.DS_Store -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | *.xmind filter=lfs diff=lfs merge=lfs -text 2 | *.pdf filter=lfs diff=lfs merge=lfs -text 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Ignore all 2 | * 3 | 4 | # Unignore all with extensions 5 | !*.* 6 | 7 | # Unignore all dirs 8 | !*/ 9 | 10 | .DS_Store 11 | 12 | # Logs 13 | logs 14 | *.log 15 | npm-debug.log* 16 | yarn-debug.log* 17 | yarn-error.log* 18 | 19 | # Runtime data 20 | pids 21 | *.pid 22 | *.seed 23 | *.pid.lock 24 | 25 | # Directory for instrumented libs generated by jscoverage/JSCover 26 | lib-cov 27 | 28 | # Coverage directory used by tools like istanbul 29 | coverage 30 | 31 | # nyc test coverage 32 | .nyc_output 33 | 34 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 35 | .grunt 36 | 37 | # Bower dependency directory (https://bower.io/) 38 | bower_components 39 | 40 | # node-waf configuration 41 | .lock-wscript 42 | 43 | # Compiled binary addons (https://nodejs.org/api/addons.html) 44 | build/Release 45 | 46 | # Dependency directories 47 | node_modules/ 48 | jspm_packages/ 49 | 50 | # TypeScript v1 declaration files 51 | typings/ 52 | 53 | # Optional npm cache directory 54 | .npm 55 | 56 | # Optional eslint cache 57 | .eslintcache 58 | 59 | # Optional REPL history 60 | .node_repl_history 61 | 62 | # Output of 'npm pack' 63 | *.tgz 64 | 65 | # Yarn Integrity file 66 | .yarn-integrity 67 | 68 | # dotenv environment variables file 69 | .env 70 | 71 | # next.js build output 72 | .next 73 | -------------------------------------------------------------------------------- /.nojekyll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wx-chevalier/DevOps-Notes/d7b6420975e9914f5512ae398dd926d6fc08796f/.nojekyll -------------------------------------------------------------------------------- /00~DevOps 文化/99~参考资料/2021-万字长文带你彻底搞懂什么是 DevOps.md: -------------------------------------------------------------------------------- 1 | > [原文地址](https://juejin.cn/post/6965860856311578637) 2 | 3 | # 万字长文带你彻底搞懂什么是 DevOps 4 | -------------------------------------------------------------------------------- /00~DevOps 文化/99~参考资料/2023-必致(BizDevOps).md: -------------------------------------------------------------------------------- 1 | # 必致(BizDevOps) 2 | 3 | ![BizDevOps 概念图](https://assets.ng-tech.icu/item/%E4%BC%81%E4%B8%9A%E5%BE%AE%E4%BF%A1%E6%88%AA%E5%9B%BE_25172c54-c849-43ec-89e4-9aa0e2ddeeb5.png) 4 | -------------------------------------------------------------------------------- /01~持续集成与交付/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wx-chevalier/DevOps-Notes/d7b6420975e9914f5512ae398dd926d6fc08796f/01~持续集成与交付/.DS_Store -------------------------------------------------------------------------------- /01~持续集成与交付/CI/CI.md: -------------------------------------------------------------------------------- 1 | # 持续集成 2 | 3 | Here’s an excerpt from [Thoughtworks](https://www.thoughtworks.com/continuous-integration) on what a typical continuous integration flow looks like: 4 | 5 | - Developers check out code into their private workspaces 6 | - When done, commit the changes to the repository 7 | - The CI server monitors the repository and checks out changes when they occur 8 | - The CI server builds the system and runs unit and integration tests 9 | - The CI server releases deployable artifacts for testing 10 | - The CI server assigns a build label to the version of the code it just built 11 | - The CI server informs the team of the successful or failed build 12 | 13 | ![](https://semaphoreci.com/blog/assets/images/2017-07-27/cicd-flow-dde970bb.jpg) 14 | 15 | - **Continuous Integration (CI)**: short-lived feature branches, team is merging to master branch multiple times per day, fully automated build and test process which gives feedback within 10 minutes; deployment is manual. 16 | - **Continuous Delivery (CD)**: CI + the entire software release process is automated, it may be composed of multiple stages, and deployment to production is manual. 17 | - **Continuous Deployment**: CI + CD + fully automated deployment to production. 18 | -------------------------------------------------------------------------------- /01~持续集成与交付/README.md: -------------------------------------------------------------------------------- 1 | # 持续集成 2 | 3 | # Links 4 | 5 | - https://www.ibm.com/developerworks/cn/rational/continuous-integration-agile-development/ 6 | -------------------------------------------------------------------------------- /01~持续集成与交付/交付规范/README.md: -------------------------------------------------------------------------------- 1 | # 交付规范 2 | -------------------------------------------------------------------------------- /01~持续集成与交付/交付规范/交付系统要求.md: -------------------------------------------------------------------------------- 1 | # 交付系统要求 2 | 3 | - 部署流程图,是整个解决方案中最重要的环节,没有之一。类似于工程施工图,将整体工程从无到有的所有过程、环节、工艺标准、施工要求、依赖和注意事项,进行完整的说明。部署流程图决不能止步于模块部署的内容,而是要涵盖从网络的实施、硬件的上架、操作系统的安装到部署服务的所有环节,这样才能保证一键部署的成功率。找一个完全空白的环境,不断的从零重建,相信大家都可以梳理出完善的部署流程图。在这里再次提醒大家,要覆盖所有环节,尤其是那些你从未接触的部分,以我为例,在交换机参数配置上就吃过好几次亏。 4 | 5 | - 功能验证,以客户的定制化需求为例说明,研发开发完毕自测通过,测试也通过了,运维验证通过后打包发版,交付发现功能上有缺陷,这时候,研发可能就愤怒了,有问题,怎么不早说!因此,功能验证是需要整合产品、研发、测试、运维、安全、法务、合规、交付和客户各种角色对功能验收的要求,便于及早发现问题,减少返工的成本。具体来说,在每个原子操作执行完毕后,对涉及到的功能、接口、页面进行充分的验证,在每个阶段完成后,也要对该阶段的组合功能进行验证。同时,对于相关模块的实例数量,实例规格,依赖,健康状态,配置正确性,错误日志以及性能指标等进行检查,以及相关的配置是否真正生效。多管齐下,确保能够准确判断每个原子操作执行的正确性以及在异常情况下尽可能给出异常原因。 6 | 7 | - 一致性维护,通过 Puppet 等配置管理工具来确保服务器配置的一致性,如 NTP、DNS、YUM、信任关系、日志统一收集、工具列表和版本以及系统参数,避免手工维护缺失和遗漏导致的质量缺陷问题。例如在部署阶段,NTP 时钟不同步导致的趋势图无法展示实时数据,进而耗费了非常大的人力来进行问题定位。 8 | 9 | - 检查清单,主要是对标准规范、统一配置、最佳实践,易错问题且会导致严重后果的问题再次确认,避免后期的大规模返工或者故障。例如,配置变更后需要重启服务器才能真正生效的策略,不仅要检查其配置是否生效,还需要在相关步骤执行完毕后,确保检查服务器的运行时间;通过 Systemd 拉起的服务,要检查其设置了开机自动启动;系统安装后,要确保所有磁盘均为 XFS 格式且全部写入系统配置中;所有用户定制化内容,全部需要再次检查是否生效,如不同用户要求的超卖比。 10 | 11 | - 虚拟化和启动自检,将模块实现虚拟化部署,从而能够和硬件、组网协议、IP 地址等用户资源解耦,实现镜像在多套环境下的固化,从而大幅提升模块部署的成功率。短时间内无法实现虚拟化部署的模块,则必须实现启动自检功能,在物理机或者虚拟机环境下启动前,需要检查环境是否满足自己的要求,例如 Java 是否可用,版本是否符合要求,Swap 是否关闭等。 12 | 13 | - 全局标准化,以服务启停方式为例,全部收敛为 Systemd 方式拉起服务,用户仅需要知道进程名就可以实现任意服务的启停操作,日志切分则全部由程序自行实现,不通过外部的 crontab 来进行,这样既降低了复杂度,也大幅提升了可运维性。 14 | 15 | - 插件化,对于专有云产品的定制化功能,尽量由系统通过插件的形式来支持,避免直接修改相关代码导致后期的不可维护。以登录功能为例,目前所有的主流公有云,都支持多种登录方式,这样,在专有云模式下,多增加一种登录方式,其对系统整体的影响就非常小了。 16 | 17 | - 操作平台,将日常运维工作中的各类场景(包括但不限于日常巡检,故障处理,版本升级、预案执行、问题定位、配置变更、补丁升级),进行标准化的文档改造并录入到操作平台,然后按照使用频率和重要性逐步将各类场景进行自动化和智能化的升级,减少运维人员需要介入的频次。 18 | 19 | - 可视化,运维人员的主要工作从执行变为监督,因此可视化会变为主要的使用工具。通过各类大屏,将系统的运行状态、健康度、核心指标、容量数据等关键信息进行实时展示,便于运维人员了解情况。 20 | -------------------------------------------------------------------------------- /01~持续集成与交付/变更与发布/多策略部署.md: -------------------------------------------------------------------------------- 1 | # 多策略部署 2 | -------------------------------------------------------------------------------- /01~持续集成与交付/变更与发布/风险评估.md: -------------------------------------------------------------------------------- 1 | # 发布风险评估 2 | 3 | # 系统变更分析 4 | 5 | - 从系统层面描述此次变更的改动点如:系统提供服务的变更(如:服务删除、参数变更、错误码变更等),与外围系统、DB 交互的方式的变更(如:调用量、调用方式、频率等的变化等),系统自身实现的重点变化(如:定时任务,大数据量查询,主要业务逻辑,批量处理,消息,缓存等) 6 | 7 | # 依赖变更分析 8 | -------------------------------------------------------------------------------- /01~持续集成与交付/平台工具/Jenkins/README.md: -------------------------------------------------------------------------------- 1 | # Jenkins 2 | -------------------------------------------------------------------------------- /01~持续集成与交付/平台工具/Spinnaker/README.md: -------------------------------------------------------------------------------- 1 | ![Spinnaker 题图](https://s2.ax1x.com/2019/10/30/K4GzrD.md.png) 2 | 3 | # Spinnaker 4 | 5 | Spinnaker 是 Netflix 的开源项目,是一个持续交付平台,它定位于将产品快速且持续的部署到多种云平台上。Spinnaker 通过将发布和各个云平台解耦,来将部署流程流水线化,从而降低平台迁移或多云品台部署应用的复杂度,它本身内部支持 Google、AWS EC2、Microsoft Azure、Kubernetes 和 OpenStack 等云平台,并且它可以无缝集成其他持续集成(CI)流程,如 git、Jenkins、Travis CI、Docker registry、cron 调度器等。简而言之,Spinnaker 是致力于提供在多种平台上实现开箱即用的集群管理和部署功能的平台。 6 | 7 | # 功能特性 8 | 9 | Spinnaker 主要包含两大块内容,集群管理和部署管理。 10 | 11 | ## 集群管理 12 | 13 | ![Spinnaker 集群管理](https://assets.ng-tech.icu/item/20230420110750.png) 14 | 15 | 集群管理主要用于管理云上的资源,它分为以下几个块: 16 | 17 | - Server Group:服务组,是资源管理单位,识别可部署组件和基础配置设置,它并且关联了一个负载均衡器和安全组,当部署完毕后,服务组就相当于一组运行中的软件实例集合,如(VM 实例,Kubernetes pods)。 18 | 19 | - Cluster:集群,由用户定义的,对服务组的逻辑分组。 20 | 21 | - Applications:应用,是对集群的逻辑分组。 22 | 23 | - Load Balancer:负载均衡,用于将外部网络流量重定向到服务组中的机器实例,还可以指定一系列规则,用来对服务组中的机器实例做健康监测。 24 | 25 | - Security Group:安全组,定义了网络访问权限,由 IP、端口和通信协议组成的防火墙规则。 26 | 27 | ## 部署管理 28 | 29 | 部署管理功能用于创建一个持续交付流程,它可分为管道和阶段两大部分: 30 | 31 | - 管道:部署管理的核心是管道,在 Spinnaker 的定义中,管道由一系列的阶段(stages)组成。管道可以人工触发,也可以配置为自动触发,比如由 Jenkins Job 完成时、Docker Images 上传到仓库时,CRON 定时器、其他管道中的某一阶段。同时,管道可以配置参数和通知,可以在管道一些阶段上执行时发送邮件消息。Spinnaker 已经内置了一些阶段,如执行自定义脚本、触发 Jenkins 任务等。 32 | 33 | ![部署管道](https://assets.ng-tech.icu/item/20230420110813.png) 34 | 35 | - 阶段:阶段在 Spinnaker 中,可以作为管道的一个自动构建模块的功能组成。我们可以随意在管道中定义各个阶段执行顺序。Spinnaker 提供了很多阶段供我们选择使用,比如执行发布(Deploy)、执行自定义脚本 (script)、触发 Jenkins 任务 (jenkins)等,功能很强大。 36 | 37 | - 部署策略:Spinnaker 支持精细的部署策略,比如 红/黑(蓝/绿)部署,多阶段环境部署,滚动红/黑策略,canary 发布等。用户可以为每个环境使用不同部署策略,比如,测试环境可以使用红/黑策略,生产环境使用滚动红/黑策略,它封装好了必须的步骤,用户不需要复杂操作,就可以实现企业级上线。 38 | 39 | ![部署策略](https://assets.ng-tech.icu/item/20230420110847.png) 40 | 41 | # Spinnaker 架构组件 42 | 43 | ![组件与角色](https://assets.ng-tech.icu/item/20230420132800.png) 44 | 45 | - **Deck**:面向用户 UI 界面组件,提供直观简介的操作界面,可视化操作发布部署流程。 46 | - **API**:面向调用 API 组件,我们可以不使用提供的 UI,直接调用 API 操作,由它后台帮我们执行发布等任务。 47 | - **Gate**:是 API 的网关组件,可以理解为代理,所有请求由其代理转发。 48 | - **Rosco**:是构建 beta 镜像的组件,需要配置 Packer 组件使用。 49 | - **Orca**:是核心流程引擎组件,用来管理流程。 50 | - **Igor**:是用来集成其他 CI 系统组件,如 Jenkins 等一个组件。 51 | - **Echo**:是通知系统组件,发送邮件等信息。 52 | - **Front50**:是存储管理组件,需要配置 Redis、Cassandra 等组件使用。 53 | - **Cloud driver** 是它用来适配不同的云平台的组件,比如 Kubernetes,Google、AWS EC2、Microsoft Azure 等。 54 | - **Fiat** 是鉴权的组件,配置权限管理,支持 OAuth、SAML、LDAP、GitHub teams、Azure groups、Google Groups 等。 55 | 56 | ![组件间数据交互](https://assets.ng-tech.icu/item/20230420132821.png) 57 | 58 | 以上组件除了核心组件外,一些组价可选择配置是否启动,比如不做权限管理的话,Fiat 就可以不启动,不集成其他 CI 的话,那就可以不启动 Igor 组件等。这些都可以在配置文件中配置,下边会说到。Development 版本,各个组件独立服务运行,有各自的服务端口,且各个组件都有自己的独立的项目 GitHub 地址。 59 | -------------------------------------------------------------------------------- /01~持续集成与交付/平台工具/Spinnaker/部署配置.md: -------------------------------------------------------------------------------- 1 | # Spinnaker 部署与配置 2 | -------------------------------------------------------------------------------- /01~持续集成与交付/平台工具/Tekton/README.md: -------------------------------------------------------------------------------- 1 | # Tekton 2 | 3 | Tekton 是一款 Kubernetes 原生的应用发布框架,主要用来构建 CI/CD 系统。它原本是 Knative 项目里面一个叫做 build-pipeline 的子项目,用来作为 knative-build 的下一代引擎。然而,随着 Kubernetes 社区里各种各样的需求涌入,这个子项目慢慢成长为一个通用的框架,能够提供灵活强大的能力去做基于 Kubernetes 的构建发布。 4 | 5 | - Kubernetes 原生:流程和概念,尤其是面向用户的部分,需要融入到 Kubernetes 体系中。此外,最好能跟生态里的其他工具互相连通,成为生态的一环。 6 | 7 | 举个例子:Spinnaker 这个项目是很强大的,但它的设计初衷,是面向公有云进行应用交付用的(以虚拟机为运行时),Kubernetes 只是它所支持的一种 Provider,并且 Provider 还得用 Groovy 写集成插件。这就使得它跟 Kubernetes 的协作是比较别扭的。 8 | 9 | - 灵活扩展:基本上所有工具都不能够满足我们复杂多变的业务需求。这些工具架构本身需要提供足够灵活的扩展性,来快速定制实现所需功能。 10 | 11 | 举个例子:Argo Rollout 本身的应用发布,是跟 Kubernetes 的 Workload(比如 Deployment)耦合在一起的。这就不是一个很具备扩展性的做法。最简单的例子:对于复杂有状态应用来说,大多都是用 Operator 或者 OpenKruise 管理的,这时候 Argo Rollout 该怎么办呢? 12 | 13 | - 轻量级:工具本身不能做得“太重”,即不能有太多的组件或太多的概念。小而轻的项目初期易上手、中期易交付、后期易维护。 14 | 15 | 举个例子:Spinnaker 虽然功能强大,但是这也就意味着它把所有的事情都帮你做了。而我们团队要发布的应用是复杂有状态的中间件应用,是需要我们写自己的 Rollout Controller 来控制发布流程的。这个要基于 Spinnaker 来做,还得大量做二次开发了,于是原有的众多功能和组件反而成了负担。 16 | 17 | - 白盒化:运行中的管道、步骤等需要“白盒化”,即对外暴露状态。这样才能跟前端工具联通,给用户展示实时状态信息。 18 | 19 | 举个例子:Tekton 其实只提供 Pipeline 这个一个功能,Pipeline 会被直接映射成 Kubernetes Pod 等 API 资源。而比如应用发布过程的控制,灰度和上线策略,都是我们自己编写 Kubernetes Controller 来实现的,这个可控度其实是我们比较喜欢的。另外,这种设计,也就意味着 Tekton 不会在 Kubernetes 上盖一个“大帽子”,比如我们想看发布状态、日志,就等是直接通过 Kubernetes 查看这个 Pipeline 对应的 Pod 的状态和日志,不需要再面对另外一个 API。 20 | -------------------------------------------------------------------------------- /02~自动化运维/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wx-chevalier/DevOps-Notes/d7b6420975e9914f5512ae398dd926d6fc08796f/02~自动化运维/.DS_Store -------------------------------------------------------------------------------- /02~自动化运维/AIOps/README.md: -------------------------------------------------------------------------------- 1 | # AIOps 2 | 3 | 在数据采集阶段,保留了 Open-Faclon、CAT、客户端 SDK、Logstash 等入口,通过 Kafka 进行汇聚,引入大数据实时计算平台 Flink,提炼 metric 指标,并最终入库。 4 | 5 | ![](https://ww1.sinaimg.cn/large/007rAy9hgy1g0f3i634lsj30u00jwabs.jpg) 6 | 7 | 在告警方面,开发了 Alert Manager 组件,对接多种告警渠道:钉钉、短信、微信等,并且自动创建 Jira,告警闭环。 8 | -------------------------------------------------------------------------------- /02~自动化运维/README.md: -------------------------------------------------------------------------------- 1 | # 自动化运维 2 | 3 | 近几年随着大数据技术的爆发、系统规模和复杂度的提升以及行业开始对 ServiceMesh、FaaS 等云原生技术体系的探索,自动化运维与管控在业界及公司内的重要性越发凸显。直观来看,服务器的数量迅速地从几十台、上百台增加到成千上万台。企业内部服务器数量的大幅增长,使得服务器出现故障的频次也大幅增加,手工运维时代的瓶颈随之到来。运维工程师越来越难以远程登录每一台服务器去搭建环境、部署应用、清理磁盘、查看服务器状态以及排查系统错误,此时急需自动化运维体系与开发技术体系配合。 4 | 5 | ![](https://assets.ng-tech.icu/item/20230417211744.png) 6 | 7 | 从工具的角度来看,自动化运维工具主要包括两大类:监控自动化工具以及流程自动化工具: 8 | 9 | - 监控自动化工具可以对服务器的 CPU、内存、磁盘 IO、网络 IO 等重要配置进行主动探测监控,一旦指标超过或接近阈值则自动通过邮件、短信等方式通知相关责任人。使用 Nagios、Zabbix 等系统监控工具可以有效实现这一点。 10 | 11 | - 流程自动化工具主要对服务器进行维护,同时实现应用上线部署等日常操作的自动化和标准化。Puppet、Chef、Ansible、SaltStack 等自动化运维管理工具的出现,快速地将运维工作推向自动化,让一名运维工程师可以很容易地维护成千上万台服务器。 12 | 13 | 从解决问题的角度来看,自动化运维又可以分为三个发展阶段: 14 | 15 | - 操作自动化:采用集成的脚本或 Web 类工具来解决同一类问题。 16 | 17 | - 场景自动化:基于自动化系统平台,能够结合当前系统上下文和外部环境并基于事先定义好的条件来做一系列的变更或分析需求。 18 | 19 | - 数据驱动智能化:在场景自动化的基础上,结合严格定义的系统指标或业务指标(Metrics),具备系统关键指标的实时采集、分析、计算能力,再基于特定的算法模型主动识别确定性问题并驱动问题的告警/预警、路由和解决执行。 20 | 21 | Kubernetes 细化的应用程序的分解粒度,同时将服务发现、配置管理、负载均衡和健康检查等作为基础设施的功能,简化了应用程序的开发。而 Kubernetes 这种声明式配置尤其适合 CI/CD 流程,况且现在还有如 Helm、Draft、Spinnaker、Skaffold 等开源工具可以帮助我们发布 Kuberentes 应用。 22 | 23 | ![](https://assets.ng-tech.icu/item/20230418224147.png) 24 | 25 | 有了基于 Kubernetes 的 CI/CD 流程后,又诞生了 GitOps 和 SecOps(Security Operation)。 26 | -------------------------------------------------------------------------------- /02~自动化运维/设施即代码/Pulumi.md: -------------------------------------------------------------------------------- 1 | # Pulumi 2 | 3 | 虽然 Terraform 在基础设施编程世界中地位稳固,但 Pulumi 却填补了其中的一个空白。尽管 Terraform 是一个久经考验的常备选项,但其声明式编程特质,深受抽象机制不足和可测试性有限的困扰。如果基础设施完全是静态的,那么 Terraform 就够用了。但是动态基础设施但定义,要求使用真正的编程语言。Pulumi 允许以 TypeScript/JavaScript、Python 和 Go 语言(无需标记语言或模板)编写配置信息,这使其脱颖而出。Pulumi 专注于原生云架构,包括容器、无服务器函数和数据服务,并为 Kubernetes 提供了良好的支持。最近,AWS CDK 的推出对其形成了挑战,但 Pulumi 仍然是该领域唯一的能独立于任何云平台厂商的工具。我们期望将来人们能更广泛地采用 Pulumi,并期待出现能对其提供支持的可行的工具和知识生态系统。 4 | -------------------------------------------------------------------------------- /02~自动化运维/设施即代码/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wx-chevalier/DevOps-Notes/d7b6420975e9914f5512ae398dd926d6fc08796f/02~自动化运维/设施即代码/README.md -------------------------------------------------------------------------------- /02~自动化运维/设施即代码/Terraform.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wx-chevalier/DevOps-Notes/d7b6420975e9914f5512ae398dd926d6fc08796f/02~自动化运维/设施即代码/Terraform.md -------------------------------------------------------------------------------- /02~自动化运维/设计理念/体系设计.md: -------------------------------------------------------------------------------- 1 | # 自动化运维的体系设计 2 | 3 | ![完整的自动化运维体系示意图](https://assets.ng-tech.icu/item/20230416204356.png) 4 | 5 | # 设计目标 6 | 7 | ## 指标精细透明 8 | 9 | 能够对系统各指标(系统、业务)进行精准、细致、体系化、实时的监控。通常来讲,衡量一个系统的监控体系做的是否足够好在于我们能否基于这套指标监控体系讲清楚当前业务发生的行为以及行为(正常行为和异常行为)产生的原因,超出当前业务或系统体系则需结合上下游系统一起来诊断。因此,我们一般会从两个视角来定义应用系统关键指标:业务视角和系统视角,这两个视角密不可分(如接口调用量和业务单量)。我们将指标分为面向最终结果的指标和面向过程的指标,这些指标同样也需要精确无歧义的定义,只有这样我们才能做到既能直观了解到系统发生了什么,也能快速定位背后的原因。最后,指标数据采集和展现的实时性非常重要,关系到我们能否快速了解系统最新的行为。 10 | 11 | ## 问题快速发现 12 | 13 | 能否及时主动的发现系统、业务异常。基于设计良好的监控指标体系,我们能快速掌握当前业务及系统运行情况,结合我们对业务或系统的专业了解能很快识别出当前系统运行是否正常。如果我们把这些业务或系统可能发生的异常行为通过相关的指标值来表达,则可以基于监控大盘与告警系统做到快速、主动的感知具体异常行为的发生。更近一步,若能再融入大数据算法模型,把告警升级为预警则效果更好。 14 | 15 | ## 预案自动执行 16 | 17 | 能够自动执行系统容灾或备份链路等系统预设的应急方案。如果我们能用监控指标数据准确定义异常发生时的系统行为且能做到快速识别并有明确的异常处理系统化方案,则可以基于预设的异常条件与处理方案在异常发生时自动触发系统流程来解决异常或降低异常对系统影响面,为后续开发的介入创造主动性。 18 | 19 | ## 变更安全可控 20 | 21 | 系统变更(业务规则、系统配置等)可灰度执行、数据影响可追溯、变更可快速回滚。通过分析线上故障发现,很大比例的故障是在系统发生变更时产生,针对变更(包括但不限于系统配置项变更、数据订正、业务规则切换、发布等),我们一定要有快速回滚方案。同时为了控制变更对系统可能产生的影响,一定要有变更灰度执行或灰度生效的机制,对于较常用的变更操作,特别是针对某类场景的组合类变更一定要有工具化、流程化、系统化的解决方案,尽可能降低因人为操作而导致出错的概率。 22 | 23 | ## 答疑高效支持 24 | 25 | 针对内部、外部的答疑(问题的定位、分析、排查)提供高效、自助的一站式解决方案。开发团队每天都会花费大量精力应对系统内部或外部的问题咨询与答疑,即使如此仍难免未能支持好所有人的需求。如果对系统的异常行为有清晰的定义和系统化排查与解决方案,则会极大的降低团队内部排查问题的工作量;再进一步,如果我们把常见的问题抽象成通用的问题分析、处理平台并提供一站式解决方案提供我们的客户,则不仅将极大降低开发团队在线上咨询方面处理的投入度,提升客户满意度,更重要的是避免了排查和解决问题时大量的线上操作行为,提升了系统安全与稳定性。 26 | 27 | # 设计原则 28 | 29 | 核心思路是把一切变更操作标准化、流程化、自助化、自动化,降低人工干预程度,提升操作效率。实现这张架构图并迭代演进是一个跨多个职能团队协作(Cross-Functional Autonomous Teams)的工作,一切要以客户需求出发,进行持续的抽象和迭代。 30 | 31 | 一个好的自动化运维管控系统平台绝不仅仅是一个功能复杂的工具集,它应具备良好的系统化架构与设计,需要和业务系统密切配合又不关心业务处理的细节,基于(问题)场景为用户提供简单直接的解决方案。管控系统和业务系统最大的区别是管控系统需要为业务系统服务,帮助业务系统快速定位问题、解决问题,而不是替业务系统解决问题。一个极端的例子是管控系统里面包含大量直接操作业务系统库表的工具集并自定义组装业务变更的逻辑,这样一旦业务模型升级或逻辑发生变化时,该管控系统就失去了应用的意义。 32 | 33 | ## 监控数据采集 34 | 35 | 监控大盘是观察系统的眼睛,一个系统的监控指标是否精细、完整和实时直接关系到这个系统的可运维性,监控指标又分为两大类:业务系统依赖的基础设施的运行时指标(系统类指标)和业务系统自身的业务指标(业务类指标,又分为业务结果数据数据和业务执行过程数据)。具体需要监控哪些数据主要从两个角度来梳理:系统类指标主要从可能会影响系统稳定的点来梳理哪些系统数据显性化有助于我们快速分析定位问题;业务类指标要从业务关心的目标结果数据以及影响这些目标结果达成的过程数据来梳理。目前集团内业务系统依赖的基础中间件、存储、VM 等关键系统指标数据非常全面,所以我们的侧重点在业务类指标的梳理和完善上。又由于指标采集的工具、数据分析计算平台都很完备,做好系统数据的监控采集并不难。 36 | 37 | ## 异常自动识别 38 | 39 | 我们常从异常、失败的角度来做数据的埋点、采集和监控,很大一部分异常可以直接通过设定单维度监控预警阈值来进行识别,从而做到精准监控;部分异常需要结合上下文或上下游依赖的数据利用业务知识做二次分析判断,如监控到快递公司某条线路的包裹时效出现波动,由于快递网络包裹配送是一个多角色协同的场景,具体哪个环节出了问题还需要结合更细粒度的数据来分析,这里可能会引入一些算法模型。还有部分异常当前还做不到自动判断,需要人工干预。此外,目前还有一种高阶的做法是基于 AI 技术做异常预警,基于当前的数据可以预测异常即将发生。 40 | 41 | ## 根因分析定位 42 | 43 | 这个领域基本上是模板驱动(Automated pattern discovery),前提是能够准确分析某类异常发生的根本原因且在对应的业务系统自动化体系里有现成的解决方案,否则就只能人工介入做决策。在依靠人工对异常问题处理的干预的同时,我们也能够沉淀更多的自动解决方案。 44 | 45 | ## 异常/变更处理 46 | 47 | 整个体系最重要的环节,包含预设的解决方案(系统具备的自动处理能力)、变更安全管控模块、对外核心处理能力的集成与驱动。 48 | 49 | - 预设的解决方案:通过业务知识的沉淀形成所谓的专家库,这些沉淀一方面来自于系统业务逻辑设计时制定的规则,另外一方面来自于日常对各种问题处理时的积累,它是一个不断迭代优化的过程。 50 | 51 | - 变更安全管控模块:自动化体系建设确实能够提升解决问题的效率,但也使线上系统变更的成本变得更低了,为保证线上变更的安全性,需要对关键的变更做好权限控制,配置类变更需要做好版本控制和灰度发布,同时也要具备变更暂停和快速回滚的能力。对于大数量的变更或大量任务重试等还需要考虑限速限流的能力,避免把下游系统“打垮”,同时基于“重监控、轻管控”的原则,系统也要做好变更操作的关键记录便于事后追溯,有些变更带来的影响具备较长的延时性,这时记录信息能够起到非常关键的作用。 52 | 53 | - 对外核心处理能力的集成与驱动:自动化管控系统不应涉及到太多的业务细节,它可能需要基于某个场景来协同多个系统单元来提供整体的自动化/自助化解决方案,但是每个系统单元的能力应该由各系统独自封装并以 API 的形式提供出来。自动化运维管控系统是目标驱动的,不关心 API 实现的细节,如:“我们需要修正某个电子面单包裹信息里面的路由分单规则并更新信息至快递公司”,业务运维管控系统里面对小二提供的是个一键修正的功能。在管控系统实现层面可能会分别依赖电子面单系统、分单系统提供的不同 API,如计算路由分单码的接口、更新电子面单单据信息的接口、信息下发合作伙伴的接口等,至于每个接口内部如何实现管控系统并不关心。业务系统需要保证每个独立 API 具备可重试和幂等的原则,并由管控系统来保证结果的最终执行,即使执行不成功原则上也不影响原有业务系统的数据和逻辑(由于非事物一致性)。基础系统也同样遵循这个原则,只不过当前阿里体系内部研发基础设施非常完备,基本上常用的中间件体系都有配套良好的运维控制系统,因此我们对这类系统的运维变更需求都是登录对应中间件管控平台操作,也有部分中间件产品对外开放了常用的 API(基本都是 RESTful 风格)供业务自动化运维管控系统来集成。 54 | 55 | ## 安全机制 56 | 57 | 这里的安全指系统或数据安全。在研发人员心中自动化管控系统的重要性通常低于其服务的业务系统的,因此在系统架构设计、代码质量、研发规范、安全等级等方面投入的精力和重视程度会打折扣。笔者曾见到一些系统的安全 Bug 在流程里面校验不通过利用安全白名单机制绕开,这其实是不可取的,一个功能齐全的自动化运维管控系统对线上数据、业务变更的权限很大,可视作一个内部超级账号,即使内网很安全,我们也要避免意外发生。 58 | -------------------------------------------------------------------------------- /02~自动化运维/设计理念/场景分析.md: -------------------------------------------------------------------------------- 1 | # 自动化运维场景分析 2 | 3 | 1)业务要升级某个业务规则,小二需要在若干系统管理后台里做新规则配置,如业务规则应用的系统,风控管理的系统等等,经常出现某新人不熟悉完整流程漏了某个系统的配置,导致完整的线上业务流程中断,由于业务中断的原因有多种,如何快速定位到并彻底解决这类问题成为痛点。 4 | 5 | 2)现在大数据算法在业务中发挥着巨大的价值,除了常见的推荐搜索外,在订单路由和履行决策等场景也大量应用。当升级某个算法模型时,如何做到按照最小业务单元的控制粒度来执行灰度,在出现新模型召回率、准确率下跌时如何做到快速回滚并对受影响的订单快速定位、分析和修复。 6 | 7 | 3)在分布式系统架构中,通过异步消息解耦复杂系统之间的强依赖是非常常见和优雅的架构设计策略,特别是一个 center/platform 级别系统通常会向依赖它的上下游系统发出一些自身业务单据操作或其他实体事件的 MQ 信息做为业务执行的触发条件与依据。为了避免引入过于复杂的系统设计,大家普遍采取非事务一致性消息模式,当遇到消费者系统故障或消息系统故障等各种因素导致某些消费者(consumer)出现消息丢失的情形时,作为 provider 或 consumer 如何快速发现并补全这类丢失的消息。 8 | 9 | 4)某算法引擎是个 CPU 计算密集型系统,但是由于 VM 资源隔离不干净经常出现同一台宿主机上的 VM 相互干扰导致 st 持续飙高,一旦出现这种现象就会导致算法引擎无法基于承诺的 SAL 给上游返回计算结果,从而影响业务行为。每次遇到这种情况,引擎的开发同学会第一时间分析是否为 st 飙高导致,一旦确认则通过 kill jvm 来粗暴快速的解决此次问题。此类 case 非常频繁,大多数通过客户反馈来驱动问题排查,在虚拟化资源隔离问题未彻底解决之前,作为上游的业务系统如何更高效、及时、主动的解决这类问题; 10 | 11 | 5)我们时常遇到线上突然告警,然后开发同学介入排查并执行预案(一般是几个配置变更)的场景,一般来说处理思路有如下几种:对上游做限流降级、对下游做依赖降级或启用备用方案、对某个变更做快速回滚。对于此类场景我们能否把其中有明确异常信号及处理流程的解决步骤流程化自动化,然后再去人工介入彻底解决呢?人的响应能力毕竟是有极限的,特别是非工作时段,如果能做到先“自动止血”尽可能降低影响面,然后再人工介入,业务上所受的影响会得到一定程度的降低。我们在业务上对异常的定义、识别、定位需要快速精准,要有备用解决方案,采用类似“熔断机制”的自主可控的处理思路来解决问题。 12 | -------------------------------------------------------------------------------- /02~自动化运维/设计理念/流水线即代码.md: -------------------------------------------------------------------------------- 1 | # 流水线即代码 2 | 3 | 流水线即代码技术强调,用于构建、测试和部署我们应用程序或基础设施的交付流水线配置,都应以代码形式展现。这些代码应置于版本控制系统中,并切分成包含自动化测试和部署的可复用组件。随着组织逐渐演变为构建微服务或微前端的去中心化自治团队,人们越来越需要以代码形式管理流水线这种工程实践,来保证组织内部构建和部署软件的一致性。这种需求使得业界出现了很多交付流水线模板和工具,它们可以以标准的方式构建、部署服务和应用。这些工具用大多采用声明式交付流水线的形式,采用一个流水线蓝图,来执行一个交付生命周期中不同阶段的任务,如构建、测试和部署,而不用关心实现细节。以代码形式来完成构建、测试和部署流水线的能力,应该成为选择 CI/CD 工具的评估标准之一。 4 | -------------------------------------------------------------------------------- /02~自动化运维/运维脚本/README.md: -------------------------------------------------------------------------------- 1 | # 运维脚本 2 | 3 | 本部分对常见的运维脚本进行梳理与归纳。 4 | -------------------------------------------------------------------------------- /02~自动化运维/运维脚本/数据库.md: -------------------------------------------------------------------------------- 1 | # MySQL 2 | 3 | ```sh 4 | $ show full processlist; 5 | $ SELECT HOST FROM information_schema.processlist where user='dbname' and INFO like '%tbname%'" 6 | ``` 7 | 8 | ```sh 9 | #!/bin/bash 10 | 11 | COUNTER=0 12 | tmp_file=$1 13 | 14 | while [ $COUNTER -lt 10000 ]; 15 | do 16 | ss=`mysql -uroot -N -e"SELECT HOST FROM information_schema.processlist where user='dbname' and INFO like '%tbname%'";` 17 | echo $ss>>${tmp_file} 18 | let COUNTER=COUNTER+1 19 | done 20 | 21 | # 然后使用 awk 命令检索 22 | # awk -F":" '{print $1}' ${tmp_file}| sort | uniq 23 | ``` 24 | 25 | ## 数据库备份 26 | 27 | ```sh 28 | #!/bin/sh 29 | 30 | #auto backup mysql 31 | #wugk 2012-07-14 32 | #PATH DEFINE 33 | 34 | BAKDIR=/data/backup/mysql/`date +%Y-%m-%d` 35 | MYSQLDB=www 36 | MYSQLPW=backup 37 | MYSQLUSR=backup 38 | 39 | if[ $UID -ne 0 ];then 40 | echo This script must use administrator or root user ,please exit! 41 | sleep 2 42 | exit 0 43 | fi 44 | 45 | if[ ! -d $BAKDIR ];then 46 | mkdir -p $BAKDIR 47 | else 48 | echo This is $BAKDIR exists ,please exit …. 49 | sleep 2 50 | exit 51 | fi 52 | 53 | ###mysqldump backup mysql 54 | 55 | /usr/bin/mysqldump -u$MYSQLUSR -p$MYSQLPW -d $MYSQLDB >/data/backup/mysql/`date +%Y-%m-%d`/www_db.sql 56 | 57 | cd $BAKDIR ; tar -czf www_mysql_db.tar.gz *.sql 58 | 59 | cd $BAKDIR ;find . -name “*.sql” |xargs rm -rf[ $? -eq 0 ]&&echo “This `date +%Y-%m-%d` RESIN BACKUP is SUCCESS” 60 | 61 | cd /data/backup/mysql/ ;find . -mtime +30 |xargs rm -rf 62 | ``` 63 | -------------------------------------------------------------------------------- /02~自动化运维/运行成本/README.md: -------------------------------------------------------------------------------- 1 | # 运行成本自动估算 2 | 3 | 对于今天的组织来说,自动化评估、跟踪和预测云基础设施的运行成本是必要的。云供应商精明的定价模型,以及基于定价参数的费用激增,再加上现代架构的动态本质,常常导致让人吃惊的运行成本。例如,无服务架构基于 API 访问量的费用,事件流方案中基于流量的费用,以及数据处理集群中基于运行任务数量的费用,它们都具有动态的本质,会随着架构演进而产生改变。当我们的团队在云平台上管理基础设施时,将运行成本实现为架构适应度函数是他们的早期活动之一。这意味着我们的团队可以观察运行服务的费用,并同交付的价值进行对比;当看到与期望或可接受的结果之间存在偏差时,他们就会探讨架构是否应该继续演进了。对运行成本的观察和计算需要被实现为自动化的函数。 4 | -------------------------------------------------------------------------------- /03~监控告警/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wx-chevalier/DevOps-Notes/d7b6420975e9914f5512ae398dd926d6fc08796f/03~监控告警/.DS_Store -------------------------------------------------------------------------------- /03~监控告警/APM/README.md: -------------------------------------------------------------------------------- 1 | # 应用性能管理 (APM) 与分布式链路追踪 (Distributed Tracing) 2 | 3 | 从功能定位上看,业务实时监控服务 定位于重量级的应用性能管理类(Application Performance Management, 简称 APM)工具,包含的功能相对丰富。应用程序通过挂载 Agent 方式接入监控,Agent 内部功能相对丰富,包括性能监控,用户体验监控,链路追踪,故障诊断,等多种功能。 4 | 5 | 而链路追踪定位于分布式链路追踪解决方案工具,功能比较专一,专业面向解决分布式环境下的链路追踪这一个问题。用户通过接入链路追踪 SDK 来实现分布式链路追踪,SDK 本身只负责链路监控,功能相对专注。 6 | 7 | ## 接入方式 8 | 9 | ![无侵入式接入 vs 基于标准的侵入式接入](https://s2.ax1x.com/2020/01/01/lJgE8I.png) 10 | 11 | 定位于 APM 的业务实时监控服务的监控接入方式使用的是业界商业化 APM 工具中比较流行的无侵入式接入方案。用户无需改动代码,即可接入。不过一般需要在应用程序中加载 Agent,需要修改程序启动方式。例如以业务实时监控服务为例,在启动 Java 程序时需要增加 -javaagent 启动参数。 12 | 13 | 定位于分布式链路追踪的链路追踪产品是基于开源产品 Jaeger, Zipkin 等开源产品和开源标准 Opentracing 的监控产品。用户可以基于以上任意一种标准 SDK 接入到链路追踪中。这样的好处是: 14 | 15 | - 已在用 Jaeger, Zipkin 或其他 Opentracing 标准 SDK 的应用可无缝迁移到链路追踪产品中,而不用修改代码; 16 | 17 | - 由于产品 SDK 是基于开源标准的,因此用户不用担心 lock-in 问题; 18 | 19 | - 借助社区力量,用户可以一次性大量支持多种开发语言,使得面向异构环境的开发者在监控方面接入门槛大幅度降低。 20 | 21 | ![业务实时监控与链路追踪](https://s2.ax1x.com/2020/01/01/lJ2PyV.png) 22 | -------------------------------------------------------------------------------- /03~监控告警/README.md: -------------------------------------------------------------------------------- 1 | # 监控告警 2 | 3 | 本部分主要关注服务端系统的监控与告警。前端相关的监控体系建设请参考 [Web Series](https://github.com/wx-chevalier/Web-Notes)。 4 | 5 | ![监控与告警体系思维脑图](https://s1.ax1x.com/2020/08/08/aIFbSf.png) 6 | 7 | ## 监控系统的目标与作用 8 | 9 | 监控系统在运维中扮演着至关重要的角色。无论你是监控系统的开发者还是使用者,都需要明确其目标和作用: 10 | 11 | 1. 实时数据采集:涵盖硬件、操作系统、中间件、应用程序等各个层面。 12 | 2. 实时状态反馈:通过多维度统计和可视化,实时展示监控对象的状态。 13 | 3. 预知故障和告警:提前识别故障风险,及时发出告警。 14 | 4. 辅助故障定位:提供故障发生时的各项指标数据,协助分析和定位。 15 | 5. 支持性能调优:为性能优化提供数据支持,如慢 SQL、接口响应时间等。 16 | 6. 辅助容量规划:为服务器、中间件及应用集群的容量规划提供数据支撑。 17 | 7. 支持自动化运维:为智能运维(如自动扩容、服务降级)提供数据基础。 18 | 19 | ## 有效使用监控系统的关键点 20 | 21 | 拥有优秀的监控系统只是第一步,更重要的是如何有效使用它。成熟的研发团队通常会制定监控规范,统一使用方法: 22 | 23 | 1. 深入了解监控对象:掌握监控对象的工作原理,如监控 JVM 需了解其堆内存结构和垃圾回收机制。 24 | 2. 确定关键监控指标:选择合适的指标来描述监控对象的状态,如接口监控可包括请求量、响应时间、超时量、异常量等。 25 | 3. 设置合理的告警阈值和等级:定义适当的告警触发条件和相应的故障等级,避免无效告警。 26 | 4. 建立完善的故障处理流程:制定清晰的故障响应流程和 on-call 机制,确保及时处理告警。 27 | 28 | ## 黑盒监控与白盒监控 29 | 30 | ### 黑盒监控 31 | 32 | 传统 IT 运维常用 Nagios 等工具进行黑盒监控,提供系统停机、服务器/服务停机、CPU 高消耗等基本信号。这种监控方式有助于识别问题症状,但难以揭示根本原因。 33 | 34 | ### 白盒监控 35 | 36 | 白盒监控深入系统内部,帮助确定问题根源,并可通过趋势分析预防潜在问题。它包括: 37 | 38 | 1. 日志记录 39 | 2. 性能指标 40 | 3. 分布式跟踪 41 | 42 | 当正确使用这些工具时,可能就不再需要黑盒监控,但保留黑盒监控作为补充仍然是明智的选择。 43 | 44 | ## 监控数据采集方式 45 | 46 | 1. 日志:重要的监控数据来源,可使用 Rsyslog、Logstash、Filebeat、Flume 等工具采集。 47 | 2. JMX:适用于 Java 服务,多数监控系统集成了 JMX 采集插件。 48 | 3. REST API:如 Hadoop、ElasticSearch 提供的监控数据接口。 49 | 4. OpenMetrics:源于 Prometheus,可能成为未来监控的行业标准。 50 | 5. 命令行:一些服务提供本地命令输出监控指标。 51 | 6. 主动上报:服务直接将监控指标推送到监控系统。 52 | 7. 埋点:侵入式但灵活的监控数据采集方式,可提供详细的业务指标。 53 | 8. 其他方式:如 Zookeeper 的四字命令,MySQL 的 show status 命令等。 54 | 55 | - [我经历过的监控系统演进史](https://mp.weixin.qq.com/s/uk0qKcmlHwlCeC_zJhWgow) 56 | -------------------------------------------------------------------------------- /03~监控告警/全链路监控/README.md: -------------------------------------------------------------------------------- 1 | # 全链路监控 2 | 3 | # Links 4 | 5 | - https://mp.weixin.qq.com/s/ZfyTKg22p_QFJwZcoJUTzw 主流微服务全链路监控系统之战 6 | -------------------------------------------------------------------------------- /03~监控告警/开源监控系统/SkyWalking/README.md: -------------------------------------------------------------------------------- 1 | # SkyWalking 2 | 3 | 官方给 SkyWalking 的定义是一个分布式系统的应用程序性能监视工具,也是一个开源的可观测平台, 用于从服务和云原生基础设施收集、分析、聚合及可视化数据。SkyWalking 提供了一种简便的方式来清晰地观测分布式系统, 甚至横跨多个云平台。SkyWalking 更是一个现代化的应用程序性能监控(Application Performance Monitoring)系统, 尤其专为云原生、基于容器的分布式系统设计。 4 | 5 | ## SkyWalking 的功能 6 | 7 | SkyWalking 在官方文档中给出了如下功能: 8 | 9 | - 多种监控手段。可以通过语言探针和 service mesh 获得监控是数据。 10 | - 多个语言自动探针。包括 Java,.NET Core 和 Node.JS。 11 | - 轻量高效。无需大数据平台,和大量的服务器资源。 12 | - 模块化。UI、存储、集群管理都有多种机制可选。 13 | - 支持告警。 14 | - 优秀的可视化解决方案。 15 | 16 | 作为一个 APM 工具,这些功能应该还挺实用的。不过还没有开始使用 SkyWalking,这些功能等使用过了再进行讲解。 17 | 18 | ## SkyWalking 的使用场景 19 | 20 | 在许多不同的场景下, SkyWalking 为观察和监控分布式系统提供了解决方案。首先是像传统的方式那样, SkyWalking 为服务提供了自动打点的代理, 如 Java, C# , Node.js , Go , PHP 以及 Nginx LUA(包括 Python 和 C++ 调用的 SDK 捐献)。对于多数语言,持续部署环境,云原生基础设施正变得更加强大,但也更加复杂。Skywalking 的服务网格接收器可以让 Skywalking 接收来自服务网格框架(例如 Istio , Linkerd)的遥测数据,以帮助用户理解整个分布式系统。 21 | 22 | 总之, SkyWalking 为 服务(service), 服务实例(service instance), 以及 端点(endpoint) 提供了可观测能力。服务(Service), 实例(Instance) 以及 端点(Endpoint) 等概念在如今随处可见, 所以让我们先了解一下他们在 SkyWalking 中都表示什么意思: 23 | 24 | - 服务(Service). 表示对请求提供相同行为的一组工作负载. 在使用打点代理或 SDK 的时候,你可以定义服务的名字. SkyWalking 还可以使用在 Istio 等平台中定义的名称。 25 | - 服务实例(Service Instance). 上述的一组工作负载中的每一个工作负载称为一个实例. 就像 Kubernetes 中的 pods 一样,服务实例未必就是操作系统上的一个进程. 但当你在使用打点代理的时候, 一个服务实例实际就是操作系统上的一个真实进程. 26 | - 端点(Endpoint). 对于特定服务所接收的请求路径, 如 HTTP 的 URI 路径和 gRPC 服务的类名 + 方法签名。 27 | 28 | 使用 SkyWalking 时, 用户可以看到服务与端点之间的拓扑结构, 每个服务/服务实例/端点的性能指标, 还可以设置报警规则。除此之外, 你还可以通过以下方式集成 29 | 30 | - 其他分布式追踪使用 Skywalking 原生代理和 Zipkin , Jaeger 和 OpenCensus 的 SDK; 31 | - 其他度量指标系统,例如 Prometheus, Sleuth, Micrometer。 32 | -------------------------------------------------------------------------------- /03~监控告警/监控指标/README.md: -------------------------------------------------------------------------------- 1 | # 监控系统指标 2 | 3 | 监控已然成为了整个产品生命周期非常重要的一环,运维关注硬件和基础监控,研发关注各类中间件和应用层的监控,产品关注核心业务指标的监控。可见,监控的对象已经越来越立体化。在系统的质量保障中,我们常常希望能实现所谓的立体化监控,实时感知,提前预警。但是越全面,成本越高。所以,根据所处的时期从中挑选合适的监控方式更加重要。本节即着重讨论我们在搭建监控体系时候的指标考量。 4 | 5 | # 指标的划分 6 | 7 | 对于监控指标,我们可以有很多种的划分方式。其一即根据目标来划分,将其分为系统指标、程序指标、业务指标等。 8 | 9 | - 系统指标主要是网络 IO、网络延迟、磁盘 IO、磁盘占用大小、CPU 使用率、内存使用率、交换分区等等。 10 | - 程序指标除了和系统指标一样的 CPU 使用率、内存使用率这种外部表现的指标之外,还有应用程序错误数、应用程序请求量、应用平均响应时间这种内部表现的指标;对于程序指标的落地我们常常就会徘徊于侵入式与非侵入式两种。 11 | - 业务指标即每一个业务会经过的关键状态,都可以作为业务指标来监控。但是由于业务指标往往不具有通用性,所以,需要手动在程序里埋点打桩。因此,对业务指标的监控必然是侵入性的。 12 | 13 | 无论业务系统如何复杂,监控指标如何眼花缭乱,但万变不离其宗,监控的目的无非是为了解服务运行状况、发现服务故障和帮助定位故障原因。为了达成这个目的,Google SRE 总结的监控四个黄金指标对我们添加监控具有非常重要的指导意义。 14 | 15 | ![Google SRE 黄金指标](https://assets.ng-tech.icu/item/20230417211805.png) 16 | 17 | 其中,吞吐量(Throughout)与时延(Latency)是衡量软件系统的最常见的两个指标,系统的吞度量(承压能力)与请求对 CPU 的消耗、外部接口、IO 等等紧密关联;单个请求对 CPU 消耗越高,外部系统接口、IO 影响速度越慢,系统吞吐能力越低,反之越高。吞吐量与时延是天生矛盾的,吞吐量增加也就意味着同一时间请求并发的增加;而由于资源的限制,同一时刻可以处理的请求数是固定的,取决于整个请求处理过程中最小的那个环节。当并发请求数大于这个值时,就会有请求排队等待被处理。所以,要提升服务的吞吐量,必定会增加整体延迟。另外,如果服务的延迟(单个请求的耗时)减少,由于排队的请求的等待时间也减少了,所以吞吐量会上升。 18 | 19 | # Logging,Metrics 和 Tracing 20 | 21 | 笔者在 DevOps 中的设计的三个关键方面即是:Logging,Metrics 和 Tracing,分别对应着日志聚合、监控与告警以及分布式追踪。Logging,Metrics 和 Tracing 有各自专注的部分: 22 | 23 | - Logging:用于记录离散的事件。例如,应用程序的调试信息或错误信息。它是我们诊断问题的依据。 24 | - Metrics:用于记录可聚合的数据。例如,队列的当前深度可被定义为一个度量值,在元素入队或出队时被更新;HTTP 请求个数可被定义为一个计数器,新请求到来时进行累加。 25 | - Tracing:用于记录请求范围内的信息。例如,一次远程方法调用的执行过程和耗时。它是我们排查系统性能问题的利器。 26 | 27 | ![Logging, Metrics, Tracing 三者同异](https://assets.ng-tech.icu/item/20230417211822.png) 28 | 29 | 通过上述信息,我们可以对已有系统进行分类。例如,Zipkin 专注于 tracing 领域;Prometheus 开始专注于 metrics,随着时间推移可能会集成更多的 tracing 功能,但不太可能深入 logging 领域;ELK,阿里云日志服务这样的系统开始专注于 logging 领域,但同时也不断地集成其他领域的特性到系统中来,正向上图中的圆心靠近。 30 | 31 | 度量作为时序数据,是跨时间间隔的可聚合和测量的数字。度量针对存储和数据处理进行了优化,因为它们只是一段时间内聚合的数字。基于度量的监控的一个优点是度量生成和存储的开销是恒定的,它不像基于日志的监控那样,与系统负载的增加成正比,随之改变。这意味着磁盘和处理利用率不会根据流量的增加而改变。磁盘存储利用率仅根据时序数据库上存储的数据而增加,当你在应用程序代码中添加新指标或启动新服务/容器/主机时,才会发生这种情况。 32 | 33 | 度量比查询和聚合日志数据更有效。但是日志可以提供准确的数据,如果你想获得服务器响应时间的准确平均值,你可以记录它们,然后在 ELK 上编写聚合查询。度量不是百分之百准确,而是使用一些统计算法。类似 Prometheus 和常见的度量客户端这些工具实现了一些高级算法,以便为我们提供最准确的数字。 34 | 35 | # 指标枚举 36 | 37 | ## 硬件监控 38 | 39 | 包括:电源状态、CPU 状态、机器温度、风扇状态、物理磁盘、raid 状态、内存状态、网卡状态。 40 | 41 | ## 服务器基础监控 42 | 43 | - CPU:单个 CPU 以及整体的使用情况 44 | - 内存:已用内存、可用内存 45 | - 磁盘:磁盘使用率、磁盘读写的吞吐量 46 | - 网络:出口流量、入口流量、TCP 连接状态 47 | 48 | ## 数据库监控 49 | 50 | 包括:数据库连接数、QPS、TPS、并行处理的会话数、缓存命中率、主从延时、锁状态、慢查询 51 | 52 | ## 中间件监控 53 | 54 | - Nginx:活跃连接数、等待连接数、丢弃连接数、请求量、耗时、5XX 错误率 55 | - Tomcat:最大线程数、当前线程数、请求量、耗时、错误量、堆内存使用情况、GC 次数和耗时 56 | - 缓存:成功连接数、阻塞连接数、已使用内存、内存碎片率、请求量、耗时、缓存命中率 57 | - 消息队列:连接数、队列数、生产速率、消费速率、消息堆积量 58 | 59 | ## 应用监控 60 | 61 | - HTTP 接口:URL 存活、请求量、耗时、异常量 62 | - RPC 接口:请求量、耗时、超时量、拒绝量 63 | - JVM:GC 次数、GC 耗时、各个内存区域的大小、当前线程数、死锁线程数 64 | - 线程池:活跃线程数、任务队列大小、任务执行耗时、拒绝任务数 65 | - 连接池:总连接数、活跃连接数 66 | - 日志监控:访问日志、错误日志 67 | - 业务指标:视业务来定,比如 PV、订单量等 68 | 69 | # Links 70 | 71 | - https://donggeitnote.com/2021/07/10/monitor/ 常见监控系统 Metric 实现讨论总结 72 | -------------------------------------------------------------------------------- /03~监控告警/监控指标/实践案例/README.md: -------------------------------------------------------------------------------- 1 | # 实践案例 2 | -------------------------------------------------------------------------------- /03~监控告警/监控指标/程序指标/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wx-chevalier/DevOps-Notes/d7b6420975e9914f5512ae398dd926d6fc08796f/03~监控告警/监控指标/程序指标/README.md -------------------------------------------------------------------------------- /03~监控告警/监控指标/程序指标/响应时延.md: -------------------------------------------------------------------------------- 1 | # 延迟与响应指标 2 | 3 | # 延迟 4 | 5 | 延迟(latency)和 响应时间(response time)经常用作同义词,但实际上它们并不一样。响应时间是客户所看到的,除了实际处理请求的时间(服务时间(service time))之外,还包括网络延迟和排队延迟。延迟是某个请求等待处理的持续时长,在此期间它处于 休眠(latent)状态,并等待服务。从客户端来看,延迟就是从发送请求到接收响应的整体耗时,包括:请求的网络耗时,请求在服务端的处理耗时以及响应的网络耗时。吞吐量则是服务在一定的并发下,每秒可以处理的请求数。服务延迟的上升不仅仅体现在用户体验的下降,也有可能会导致请求堆积并最终演变为整个业务系统的雪崩。以下为延迟指标的主要关注点: 6 | 7 | - 基础监控:IO 等待、网络延迟; 8 | - 业务监控:业务相关指标主要需要关注核心功能的响应时长。比如 Zookeeper 的延迟指标 zk_avg_latency,ElasticSearch 的索引、搜索延迟和慢查询。 9 | 10 | 与错误指标类似,白盒延迟指标通常仅能代表系统内部延迟,建议为主要功能或接口添加黑盒监控来采集端到端的延迟指标。 11 | 12 | ## 中位数 13 | 14 | 每个灰条表代表一次对服务的请求,其高度表示请求花费了多长时间。大多数请求是相当快的,但偶尔会出现需要更长的时间的异常值。这也许是因为缓慢的请求实质上开销更大,例如它们可能会处理更多的数据。但即使(你认为)所有请求都花费相同时间的情况下,随机的附加延迟也会导致结果变化,例如:上下文切换到后台进程,网络数据包丢失与 TCP 重传,垃圾收集暂停,强制从磁盘读取的页面错误,服务器机架中的震动等。 15 | 16 | ![展示了一个服务100次请求响应时间的均值与百分位数](https://s2.ax1x.com/2020/02/02/1tgSAA.md.png) 17 | 18 | 通常报表都会展示服务的平均响应时间,但平均值并不是一个非常好的指标,因为它不能告诉你有多少用户实际上经历了这个延迟。通常使用百分位点(percentiles)会更好。如果将响应时间列表按最快到最慢排序,那么中位数(median)就在正中间:举个例子,如果你的响应时间中位数是 200 毫秒,这意味着一半请求的返回时间少于 200 毫秒,另一半比这个要长。 19 | 20 | 如果想知道典型场景下用户需要等待多长时间,那么中位数是一个好的度量标准:一半用户请求的响应时间少于响应时间的中位数,另一半服务时间比中位数长。中位数也被称为第 50 百分位点,有时缩写为 p50。注意中位数是关于单个请求的;如果用户同时发出几个请求(在一个会话过程中,或者由于一个页面中包含了多个资源),则至少一个请求比中位数慢的概率远大于 50%。 21 | 22 | ## 百分点位 23 | 24 | 为了弄清异常值有多糟糕,可以看看更高的百分位点,例如第 95、99 和 99.9 百分位点(缩写为 p95,p99 和 p999)。它们意味着 95%,99%或 99.9%的请求响应时间要比该阈值快,例如:如果第 95 百分位点响应时间是 1.5 秒,则意味着 100 个请求中的 95 个响应时间快于 1.5 秒,而 100 个请求中的 5 个响应时间超过 1.5 秒。 25 | 26 | 响应时间的高百分位点(也称为尾部延迟(tail latencies))非常重要,因为它们直接影响用户的服务体验。例如亚马逊在描述内部服务的响应时间要求时以 99.9 百分位点为准,即使它只影响一千个请求中的一个。另一方面,优化第 99.99 百分位点(一万个请求中最慢的一个)被认为太昂贵了,不能为亚马逊的目标带来足够好处。减小高百分位点处的响应时间相当困难,因为它很容易受到随机事件的影响,这超出了控制范围,而且效益也很小。 27 | 28 | 百分位点通常用于服务级别目标(SLO, service level objectives)和服务级别协议(SLA, service level agreements),即定义服务预期性能和可用性的合同 SLA 可能会声明,如果服务响应时间的中位数小于 200 毫秒,且 99.9 百分位点低于 1 秒,则认为服务工作正常(如果响应时间更长,就认为服务不达标)。这些指标为客户设定了期望值,并允许客户在 SLA 未达标的情况下要求退款。 29 | 30 | 排队延迟(queueing delay)通常占了高百分位点处响应时间的很大一部分。由于服务器只能并行处理少量的事务(如受其 CPU 核数的限制),所以只要有少量缓慢的请求就能阻碍后续请求的处理,这种效应有时被称为 头部阻塞(head-of-line blocking)。即使后续请求在服务器上处理的非常迅速,由于需要等待先前请求完成,客户端最终看到的是缓慢的总体响应时间。因为存在这种效应,测量客户端的响应时间非常重要。 31 | 32 | 为测试系统的可扩展性而人为产生负载时,产生负载的客户端要独立于响应时间不断发送请求。如果客户端在发送下一个请求之前等待先前的请求完成,这种行为会产生人为排队的效果,使得测试时的队列比现实情况更短,使测量结果产生偏差。 33 | 34 | ## 微服务中的百分点位 35 | 36 | 在多重调用的后端服务里,高百分位数变得特别重要。即使并行调用,最终用户请求仍然需要等待最慢的并行调用完成。如下图所示,只需要一个缓慢的调用就可以使整个最终用户请求变慢。即使只有一小部分后端调用速度较慢,如果最终用户请求需要多个后端调用,则获得较慢调用的机会也会增加,因此较高比例的最终用户请求速度会变慢(效果称为尾部延迟放大)。 37 | 38 | 如果您想将响应时间百分点添加到您的服务的监视仪表板,则需要持续有效地计算它们。例如,您可能希望在最近 10 分钟内保持请求响应时间的滚动窗口。每一分钟,您都会计算出该窗口中的中值和各种百分数,并将这些度量值绘制在图上。 39 | 40 | 简单的实现是在时间窗口内保存所有请求的响应时间列表,并且每分钟对列表进行排序。如果对你来说效率太低,那么有一些算法能够以最小的 CPU 和内存成本(如前向衰减,t-digest 或 HdrHistogram)来计算百分位数的近似值。请注意,平均百分比(例如,减少时间分辨率或合并来自多台机器的数据)在数学上没有意义 - 聚合响应时间数据的正确方法是添加直方图。 41 | 42 | ![当一个请求需要多个后端请求时,单个后端慢请求就会拖慢整个终端用户的请求](https://s2.ax1x.com/2020/02/02/1t2VxK.md.png) 43 | 44 | # RT | 响应时间 45 | 46 | 响应时间即 RT,处理一次请求所需要的平均处理时间。对于 RT,客户端和服务端是大不相同的,因为请求从客户端到服务端,需要经过广域网,所以客户端 RT 往往远大于服务端 RT,同时客户端的 RT 往往决定着用户的真实体验,服务端 RT 往往是评估我们系统好坏的一个关键因素。 47 | 48 | 假设我们的服务端只有一个线程,那么所有的请求都是串行执行,我们可以很简单的算出系统的 QPS,也就是:QPS = 1000ms/RT。假设一个 RT 过程中 CPU 计算的时间为 49ms,CPU Wait Time 为 200ms,那么 QPS 就为 1000/49+200 = 4.01。CPU Time 就是一次请求中,实际用到计算资源。CPU Time 的消耗是全流程的,涉及到请求到应用服务器,再从应用服务器返回的全过程。实际上这取决于你的计算的复杂度。 49 | 50 | CPU Wait Time 是一次请求过程中对于 IO 的操作,CPU 这段时间可以理解为空闲的,那么此时要尽量利用这些空闲时间,也就是增加线程数。CPU 利用率是业务系统利用到 CPU 的比率,因为往往一个系统上会有一些其他的线程,这些线程会和 CPU 竞争计算资源,那么此时留给业务的计算资源比例就会下降,典型的像,GC 线程的 GC 过程、锁的竞争过程都是消耗 CPU 的过程。甚至一些 IO 的瓶颈,也会导致 CPU 利用率下降(CPU 都在 Wait IO,利用率当然不高)。 51 | 52 | 用户平均请求等待时间(Time per request)计算公式:处理完成所有请求数所花费的时间/(总请求数 / 并发用户数),即 53 | Time per request = Time taken for tests /(Complete requests / Concurrency Level) 54 | 55 | 服务器平均请求等待时间(Time per request: across all concurrent requests),计算公式:处理完成所有请求数所花费的时间 / 总请求数,即 Time taken for / testsComplete requests 可以看到,它是吞吐率的倒数。同时,它也等于用户平均请求等待时间/并发用户数,即 Time per request / Concurrency Level 56 | -------------------------------------------------------------------------------- /03~监控告警/监控指标/程序指标/应用.md: -------------------------------------------------------------------------------- 1 | # 应用性能监控 2 | 3 | # Java 4 | 5 | > 本部分参阅 [Java 应用性能监控](https://github.com/wx-chevalier/Java-Notes)一节。 6 | -------------------------------------------------------------------------------- /03~监控告警/监控指标/程序指标/服务吞吐量.md: -------------------------------------------------------------------------------- 1 | # 吞吐量 2 | 3 | 流量指标可以指系统层面的网络和磁盘 IO,服务层面的 QpS、PV 和 UV 等数据。流量和突增或突减都可能预示着系统可能出现问题(攻击事件、系统故障等)。以下为流量主要关注的方面: 4 | 5 | - 基础监控:磁盘和网卡 IO; 6 | - 业务监控:核心功能流量,例如通过 QpS/PV/UV 等通常能够代表 Web 服务的流量,而 ElasticSearch 的流量可用索引创建速率、搜索速率表示。 7 | 8 | 我们通常说的网站流量(traffic)就是指网站的访问量,是用来描述访问一个网站的用户数量以及用户所浏览的网页数量等指标,常用的统计指标包括网站的独立用户数量、总用户数量(含重复访问者)、网页浏览数量、每个用户的页面浏览数量、用户在网站的平均停留时间等。 9 | 10 | 网站访问量的衡量标准一个是 IP,另一个是 PV,常以日为标准,即日独立 IP 和 PV 来计算. 11 | 12 | - 访问数(IP):即 Internet Protocol,指独立 IP 数。00:00-24:00 内相同 IP 地址只被计算一次。 13 | - 综合浏览量(PV):即 Page View, 即页面浏览量或点击量,用户每次刷新即被计算一次。 14 | 15 | 二者的联系与区别:PV 高不一定代表来访者多;PV 与来访者的数量成正比,但是 PV 并不直接决定页面的真实来访者数量。比如一个网站就你一个人进来,通过不断的刷新页面,也可以制造出非常高的 PV。IP 是一个反映网络虚拟地址对象的概念,独立用户是一个反映实际使用者的概念,每个独立用户相对于每个 IP,更加准确地对应一个实际的浏览者。使用独立用户作为统计量,可以更加准确的了解单位时间内实际上有多少个访问者来到了相应的页面。 16 | 17 | 一个独立 IP 可以产生多个 PV,所以 PV 个数>=IP 个数。 18 | 19 | - PV(Page View)值:是指一定时间范围内所有浏览该网站的访问者请求的页面数量之合。(例如:该网站一天有 500 个访问者,每个访问者浏览的页面数量平均为 8 页,则每天的 PV 是 500×8=4000) 20 | - Hits 值:是指对每个页面元素的请求数量。(一个页面中任何一个图片或者 flash 文件都算是一个页面元素) 21 | - 日浏览字节数:即日流量,是指一天内,访问者请求的所有页面元素的字节数之和。 22 | 23 | # 访问量指标 24 | 25 | - PV 即 page view,页面浏览量 用户每一次对网站中的每个页面访问均被记录 1 次。用户对同一页面的多次刷新,访问量累计。 26 | - UV 即 Unique visitor,独立访客 通过客户端的 cookies 实现。即同一页面,客户端多次点击只计算一次,访问量不累计。 27 | - IP 即 Internet Protocol,本意本是指网络协议,在数据统计这块指通过 ip 的访问量。即同一页面,客户端使用同一个 IP 访问多次只计算一次,访问量不累计。 28 | 29 | # QPS & TPS & RPS 30 | 31 | TPS:Transactions Per Second(每秒传输的事物处理个数),即服务器每秒处理的事务数。TPS 包括一条消息入和一条消息出,加上一次用户数据库访问。(业务 TPS = CAPS × 每个呼叫平均 TPS)。TPS 是软件测试结果的测量单位。一个事务是指一个客户机向服务器发送请求然后服务器做出反应的过程。客户机在发送请求时开始计时,收到服务器响应后结束计时,以此来计算使用的时间和完成的事务个数。一般的,评价系统性能均以每秒钟完成的技术交易的数量来衡量。系统整体处理能力取决于处理能力最低模块的 TPS 值。 32 | 33 | QPS:每秒查询率 QPS 是对一个特定的查询服务器在规定时间内所处理流量多少的衡量标准,在因特网上,作为域名系统服务器的机器的性能经常用每秒查询率来衡量。 34 | 35 | 对应 fetches/sec,即每秒的响应请求数,也即是最大吞吐能力。 36 | 37 | - 并发连接数(The number of concurrent connections):某个时刻服务器所接受的请求数目,简单的讲,就是一个会话。 38 | - 并发用户数(The number of concurrent users,Concurrency Level):要注意区分这个概念和并发连接数之间的区别,一个用户可能同时会产生多个会话,也即连接数。 39 | 40 | QPS(Queries Per Second)每秒能处理查询数目。是一台服务器每秒能够相应的查询次数,是对一个特定的查询服务器在规定时间内所处理流量多少的衡量标准。QPS 是每秒钟处理完请求的次数。这里的请求不是指一个查询或者数据库查询,是包括一个业务逻辑的整个流程,也就是说每秒钟响应的请求次数。 41 | 42 | TPS(Transactions Per Second)指每秒处理的事务数目;事务是指一个客户机向服务器发送请求然后服务器做出反应的过程。TPS 的过程包括:客户端请求服务端、服务端内部处理、服务端返回客户端,客户机在发送请求时开始计时,收到服务器响应后结束计时,以此来计算使用的时间和完成的事务个数,最终利用这些信息作出的评估分。 43 | 44 | RPS(Requests Per Second) | 吞吐率: 服务器并发处理能力的量化描述,单位是 reqs/s,指的是某个并发用户数下单位时间内处理的请求数。某个并发用户数下单位时间内能处理的最大请求数,称之为最大吞吐率。 45 | 46 | # 饱和度 47 | 48 | 饱和度可以理解为服务的利用率,可以代表系统承受的压力。所以饱和度与流量息息相关,流量的上升一般也会导致饱和度的上升。通常情况下,每种业务系统都应该有各自的饱和度指标。在很多业务系统中,消息队列长度是一个比较重要的饱和度指标,除此之外 CPU、内存、磁盘、网络等系统资源利用率也可以作为饱和度的一种体现方式。 49 | 50 | 基础监控自然包含 CPU、内存、磁盘和网络利用率、内存堆栈利用率、文件句柄数、TCP 连接数等;业务监控: 51 | 52 | - 基础功能单元使用率,大多数系统对其基础的功能单元都有其处理能力的上限,接近或达到该上限时可能会导致服务的错误、延迟增大。例如 HDFS 的 Block 数量上升会导致 NameNode 堆内存使用率上升,Kafka 的 Topics 和 Partitions 的数量、Zookeeper 的 node 数的上升都会对系统产生压力。 53 | 54 | - 消息队列长度,不少系统采用消息队列存放待处理数据,所以消息队列长度在一定程度上可以代表系统的繁忙程度。如 ElasticSearch、HDFS 等都有队列长度相关指标可供采集。 55 | 56 | # Links 57 | -------------------------------------------------------------------------------- /03~监控告警/监控指标/系统指标/CPU/CPU.md: -------------------------------------------------------------------------------- 1 | # CPU & 线程 2 | 3 | 和 CPU 相关的指标主要有以下几个: 4 | 5 | - CPU 利用率(CPU Utilization) 6 | - CPU 平均负载(Load Average) 7 | - 上下文切换次数(Context Switch) 8 | 9 | 常用的工具有 top、ps、uptime、vmstat、pidstat 等。 10 | 11 | CPU 异常指标的分析思路包括了: 12 | 13 | - CPU 利用率:如果我们观察某段时间系统或应用进程的 CPU 利用率一直很高(单个 core 超过 80%),那么就值得我们警惕了。我们可以多次使用 jstack 命令 dump 应用线程栈查看热点代码,非 Java 应用可以直接使用 perf 进行 CPU 采采样,离线分析采样数据后得到 CPU 执行热点(Java 应用需要符号表进行堆栈信息映射,不能直接使用 perf)。 14 | 15 | - CPU 平均负载:平均负载高于 CPU 数量 70%,意味着系统存在瓶颈点,造成负载升高的原因有很多,在这里就不展开了。需要注意的是,通过监控系统监测平均负载的变化趋势,更容易定位问题,有时候大文件的加载等,也会导致平均负载瞬时升高。如果 1 分钟/5 分钟/15 分钟的三个值相差不大,那说明系统负载很平稳,则不用关注,如果这三个值逐渐降低,说明负载在渐渐升高,需要关注整体性能; 16 | 17 | - CPU 上下文切换:上下文切换这个指标,并没有经验值可推荐(几十到几万都有可能),这个指标值取决于系统本身的 CPU 性能,以及当前应用工作的情况。但是,如果系统或者应用的上下文切换次数出现数量级的增长,就有很大概率说明存在性能问题,如非自愿上下切换大幅度上升,说明有太多的线程在竞争 CPU。 18 | 19 | CPU 上的的一些异动,通常也可以从线程上观测到,但需要注意的是,线程问题并不完全是由 CPU 导致的。与线程相关的指标,主要有下面几个(均都可以通过 JDK 自带的 jstack 工具直接或间接得到):应用中的总的线程数、应用中各个线程状态的分布、线程锁的使用情况,如死锁、锁分布等。 20 | 21 | 关于线程,可关注的异常有:线程总数过多(体现在 CPU 就是导致频繁的上下文切换,可能是线程池设置不当)、WAITING/BLOCKED 线程过多(线程数设置过多或锁竞争剧烈)、存在大量消耗 CPU 的线程等。 22 | 23 | # 问题排查 24 | 25 | 我们更应该关注 CPU 负载,CPU 利用率高一般不是问题,CPU 负载 是判断系统计算资源是否健康的关键依据。 26 | 27 | ```sh 28 | # 按照 CPU/内存的使用情况列出前10 的进程 29 | $ ps axo %mem,pid,euser,cmd | sort -nr | head -10 30 | $ ps -aeo pcpu,user,pid,cmd | sort -nr | head -10 31 | 32 | # 显示系统整体的 CPU利用率和闲置率 33 | $ grep "cpu " /proc/stat | awk -F ' ' '{total = $2 + $3 + $4 + $5} END {print "idle \t used\n" $5*100/total "% " $2*100/total "%"}' 34 | ``` 35 | 36 | ## CPU 利用率高 & 平均负载高 37 | 38 | 这种情况常见于 CPU 密集型的应用,大量的线程处于可运行状态,I/O 很少,常见的大量消耗 CPU 资源的应用场景有: 39 | 40 | - 正则操作 41 | - 数学运算 42 | - 序列化/反序列化 43 | - 反射操作 44 | - 死循环或者不合理的大量循环 45 | - 基础/第三方组件缺陷 46 | 47 | 排查高 CPU 占用的一般思路:通过 jstack 多次(> 5 次)打印线程栈,一般可以定位到消耗 CPU 较多的线程堆栈。或者通过 Profiling 的方式(基于事件采样或者埋点),得到应用在一段时间内的 on-CPU 火焰图,也能较快定位问题。 48 | 49 | 还有一种可能的情况,此时应用存在频繁的 GC(包括 Young GC、Old GC、Full GC),这也会导致 CPU 利用率和负载都升高。排查思路:使用 jstat -gcutil 持续输出当前应用的 GC 统计次数和时间。频繁 GC 导致的负载升高,一般还伴随着可用内存不足,可用 free 或者 top 等命令查看下当前机器的可用内存大小。 50 | 51 | CPU 利用率过高,是否有可能是 CPU 本身性能瓶颈导致的呢?也是有可能的。可以进一步通过 vmstat 查看详细的 CPU 利用率。用户态 CPU 利用率(us)较高,说明用户态进程占用了较多的 CPU,如果这个值长期大于 50%,应该着重排查应用本身的性能问题。内核态 CPU 利用率(sy)较高,说明内核态占用了较多的 CPU,所以应该着重排查内核线程或者系统调用的性能问题。如果 us + sy 的值大于 80%,说明 CPU 可能不足。 52 | 53 | ## CPU 利用率低 & 平均负载高 54 | 55 | 这种情况常见于 I/O 密集型进程,这很容易理解,毕竟平均负载就是 R 状态进程和 D 状态进程的和,除掉了第一种,就只剩下 D 状态进程了(产生 D 状态的原因一般是因为在等待 I/O,例如磁盘 I/O、网络 I/O 等)。 56 | 57 | 使用 vmstat 1 定时输出系统资源使用,观察 %wa(iowait) 列的值,该列标识了磁盘 I/O 等待时间在 CPU 时间片中的百分比,如果这个值超过 30%,说明磁盘 I/O 等待严重,这可能是大量的磁盘随机访问或直接的磁盘访问(没有使用系统缓存)造成的,也可能磁盘本身存在瓶颈,可以结合 iostat 或 dstat 的输出加以验证,如 %wa(iowait) 升高同时观察到磁盘的读请求很大,说明可能是磁盘读导致的问题。 58 | 59 | 此外,耗时较长的网络请求(即网络 I/O)也会导致 CPU 平均负载升高,如 MySQL 慢查询、使用 RPC 接口获取接口数据等。这种情况的排查一般需要结合应用本身的上下游依赖关系以及中间件埋点的 trace 日志,进行综合分析。 60 | 61 | ## CPU 上下文切换次数变高 62 | 63 | 先用 vmstat 查看系统的上下文切换次数,然后通过 pidstat 观察进程的自愿上下文切换(cswch)和非自愿上下文切换(nvcswch)情况。 64 | 65 | 如果自愿上下文切换次数较高,意味着 CPU 存在资源获取等待,比如说,I/O、内存等系统资源不足等。如果是非自愿上下文切换次数较高,可能的原因是应用内线程数过多,导致 CPU 时间片竞争激烈,频频被系统强制调度,此时可以结合 jstack 统计的线程数和线程状态分布加以佐证。 66 | -------------------------------------------------------------------------------- /03~监控告警/监控指标/系统指标/CPU/perf 与火焰图/README.md: -------------------------------------------------------------------------------- 1 | # perf 2 | 3 | perf 是 linux 下一个非常强大的性能分析工具,通过它可以分析出进程运行过程中的主要时间都花在了哪些地方。它是 Linux 系统原生提供的性能分析工具,会返回 CPU 正在执行的函数名以及调用栈(stack)。通常,它的执行频率是 99Hz(每秒 99 次),如果 99 次都返回同一个函数名,那就说明 CPU 这一秒钟都在执行同一个函数,可能存在性能问题。 4 | 5 | ```sh 6 | $ sudo perf record -F 99 -p 13204 -g -- sleep 30 7 | ``` 8 | 9 | 上面的代码中,perf record 表示记录,-F 99 表示每秒 99 次,-p 13204 是进程号,即对哪个进程进行分析,-g 表示记录调用栈,sleep 30 则是持续 30 秒。运行后会产生一个庞大的文本文件。如果一台服务器有 16 个 CPU,每秒抽样 99 次,持续 30 秒,就得到 47,520 个调用栈,长达几十万甚至上百万行。 10 | 11 | 结合著名的 [FlameGraph](https://github.com/brendangregg/FlameGraph.git) 火焰图工具,我们能够快速定位时间占用较多的函数调用。 12 | 13 | ```sh 14 | # 执行采样 15 | $ perf record -e cpu-clock -g -p ${PID} 16 | 17 | # 用 perf script 工具对 perf.data 进行解析 18 | perf script -i perf.data &> perf.unfold 19 | 20 | # 将 perf.unfold 中的符号进行折叠 21 | ./stackcollapse-perf.pl perf.unfold &> perf.folded 22 | 23 | # 生成 svg 火焰图 24 | /flamegraph.pl perf.folded > perf.svg 25 | ``` 26 | -------------------------------------------------------------------------------- /03~监控告警/监控指标/系统指标/CPU/perf 与火焰图/火焰图解析.md: -------------------------------------------------------------------------------- 1 | # 火焰图解析 2 | 3 | 火焰图(flame graph)是性能分析的利器,是基于 perf 结果产生的 SVG 图片,用来展示 CPU 的调用栈。 4 | 5 | ![火焰图解析](https://pic.imgdb.cn/item/622db03f5baa1a80ab3b0512.jpg) 6 | 7 | - y 轴表示调用栈,每一层都是一个函数。调用栈越深,火焰就越高,顶部就是正在执行的函数,下方都是它的父函数。 8 | - x 轴表示抽样数,如果一个函数在 x 轴占据的宽度越宽,就表示它被抽到的次数多,即执行的时间长。注意,x 轴不代表时间,而是所有的调用栈合并后,按字母顺序排列的。 9 | 10 | 火焰图就是看顶层的哪个函数占据的宽度最大。只要有"平顶"(plateaus),就表示该函数可能存在性能问题。颜色没有特殊含义,因为火焰图表示的是 CPU 的繁忙程度,所以一般选择暖色调。 11 | 12 | # 互动性 13 | 14 | 火焰图是 SVG 图片,可以与用户互动。 15 | 16 | (1)鼠标悬浮 17 | 18 | 火焰的每一层都会标注函数名,鼠标悬浮时会显示完整的函数名、抽样抽中的次数、占据总抽样次数的百分比。下面是一个例子。 19 | 20 | ```sh 21 | mysqld'JOIN::exec (272,959 samples, 78.34 percent) 22 | ``` 23 | 24 | (2)点击放大 25 | 26 | 在某一层点击,火焰图会水平放大,该层会占据所有宽度,显示详细信息。 27 | 28 | ![火焰图](https://pic.imgdb.cn/item/622dd29b5baa1a80ab4d2f23.jpg) 29 | 30 | 左上角会同时显示"Reset Zoom",点击该链接,图片就会恢复原样。 31 | 32 | (3)搜索 33 | 34 | 按下 Ctrl + F 会显示一个搜索框,用户可以输入关键词或正则表达式,所有符合条件的函数名会高亮显示。 35 | 36 | # 火焰图示例 37 | 38 | 下面是一个简化的火焰图例子。首先,CPU 抽样得到了三个调用栈。 39 | 40 | ```sh 41 | func_c 42 | func_b 43 | func_a 44 | start_thread 45 | 46 | func_d 47 | func_a 48 | start_thread 49 | 50 | func_d 51 | func_a 52 | start_thread 53 | ``` 54 | 55 | 上面代码中,start_thread 是启动线程,调用了 func_a。后者又调用了 func_b 和 func_d,而 func_b 又调用了 func_c。经过合并处理后,得到了下面的结果,即存在两个调用栈,第一个调用栈抽中 1 次,第二个抽中 2 次。 56 | 57 | ```sh 58 | start_thread;func_a;func_b;func_c 1 59 | start_thread;func_a;func_d 2 60 | ``` 61 | 62 | 有了这个调用栈统计,火焰图工具就能生成 SVG 图片。 63 | 64 | ![SVG 图片](https://pic.imgdb.cn/item/622dd2e35baa1a80ab4d4c7c.jpg) 65 | 66 | 上面图片中,最顶层的函数 g()占用 CPU 时间最多。d()的宽度最大,但是它直接耗用 CPU 的部分很少。b()和 c()没有直接消耗 CPU。因此,如果要调查性能问题,首先应该调查 g(),其次是 i()。另外,从图中可知 a()有两个分支 b()和 h(),这表明 a()里面可能有一个条件语句,而 b()分支消耗的 CPU 大大高于 h()。 67 | 68 | # 局限 69 | 70 | 两种情况下,无法画出火焰图,需要修正系统行为。 71 | 72 | (1)调用栈不完整 73 | 74 | 当调用栈过深时,某些系统只返回前面的一部分(比如前 10 层)。 75 | 76 | (2)函数名缺失 77 | 78 | 有些函数没有名字,编译器只用内存地址来表示(比如匿名函数)。 79 | 80 | # 浏览器的火焰图 81 | 82 | Chrome 浏览器可以生成页面脚本的火焰图,用来进行 CPU 分析。打开开发者工具,切换到 Performance 面板。然后,点击"录制"按钮,开始记录数据。这时,可以在页面进行各种操作,然后停止"录制"。这时,开发者工具会显示一个时间轴。它的下方就是火焰图。 83 | 84 | ![浏览器的火焰图](https://pic.imgdb.cn/item/622dd3145baa1a80ab4d5f16.jpg) 85 | 86 | 浏览器的火焰图与标准火焰图有两点差异:它是倒置的(即调用栈最顶端的函数在最下方);x 轴是时间轴,而不是抽样次数。 87 | 88 | ![浏览器的火焰图](https://pic.imgdb.cn/item/622dd3255baa1a80ab4d65bf.jpg) 89 | -------------------------------------------------------------------------------- /03~监控告警/监控指标/系统指标/CPU/sar.md: -------------------------------------------------------------------------------- 1 | # 系统进程 2 | 3 | sar 4 | 5 | 是目前 Linux 上最为全面的系统性能分析工具之一,但可能没有预装。在 centos 上使用以下命令即可安装。 6 | 7 | yum install sysstat -y 8 | sar 主要的好处是可以看到历史,显示友好,可以对结果进行二次处理。sar 还有图形化工具,执行 sar -A 即可获得所有数据。 9 | 10 | https://github.com/vlsi/ksar 11 | 针对于 CPU 方面,我们关注: 12 | ➊ sar -u 默认 13 | ➋ sar -P ALL 每颗 cpu 的使用状态信息 14 | ➌ sar -q cpu 队列的长度,runq-sz>cpu count 就表明有瓶颈了 15 | ➍ sar -w 每秒上下文交换 16 | 17 | mpstat 18 | 19 | 还有 pidstat,包括彩色的 dstat,功能都差不多 20 | 21 | load 为 1 代表的是啥 22 | 23 | 针对这个问题,误解还是比较多的。很多同学认为,load 达到 1,系统就到了瓶颈,这不完全正确。 24 | load 的值和 cpu 核数息息相关: 25 | ➊ 单核的 cpu 达到 100%,load 约 1 26 | ➋ 双核的 cpu 都达到 100%,load 约 2 27 | ➌ 四核的 cpu 都达到 100%,load 约为 4 28 | 29 | ## CPU 30 | 31 | CPU 利用率是业务系统利用到 CPU 的比率,因为往往一个系统上会有一些其他的线程,这些线程会和 CPU 竞争计算资源,那么此时留给业务的计算资源比例就会下降,典型的像,GC 线程的 GC 过程、锁的竞争过程都是消耗 CPU 的过程。甚至一些 IO 的瓶颈,也会导致 CPU 利用率下降(CPU 都在 Wait IO,利用率当然不高)。 32 | 33 | ## 内存 34 | 35 | ```sh 36 | # 查看系统当前的内存 37 | $ free -h 38 | total used free shared buff/cache available 39 | Mem: 7.8G 1.2G 627M 85M 6.0G 6.0G 40 | Swap: 0B 0B 0B 41 | ``` 42 | 43 | 上图中总内存与可用内存差值出现不一致性,是因为 OS 发现系统的物理内存有大量剩余时,为了提高 IO 的性能,就会使用多余的内存当做文件缓存。 44 | 45 | ## CPU 利用率详解 46 | 47 | /proc/stat 存储的是系统的一些统计信息。 48 | 49 | ```sh 50 | cpu 117450 5606 72399 476481991 1832 0 2681 0 0 0 51 | cpu0 31054 90 19055 119142729 427 0 1706 0 0 0 52 | cpu1 22476 3859 18548 119155098 382 0 272 0 0 0 53 | cpu2 29208 1397 19750 119100548 462 0 328 0 0 0 54 | cpu3 34711 258 15045 119083615 560 0 374 0 0 0 55 | 56 | (us) (ni) (sy) (id) (wa) (hi) (si) (st) (guest) (guest_nice) 57 | ``` 58 | 59 | 对于 CPU 利用率描述,Linux man-pages 用的都是 time(time running,time spent,time stolen)这个单词。这里的统计数据,其实就是 CPU 从系统启动至当前,各项(us, sy, ni, id, wa, hi, si, st)占用的时间,单位是 jiffies。通过 sysconf(\_SC_CLK_TCK) 可以获得 1 秒被分成多少个 jiffies。一般是 100,即 1 jiffies == 0.01 s。 60 | 61 | 计算 CPU 使用率的基本原理就是从 /proc/stat 进行采样和计算。最简单的方法,一秒采样一次 /proc/stat,如: 62 | 第 N 秒采样得到 cpu_total1 = us1 + ni1 + sy1 + id1 + wa1 + hi1 + si1 + st1 + guest1 + guest_nice1 63 | 第 N+1 秒采样得到 cpu_total2 = us2 + ni2 + sy2 + id2 + wa2 + hi2 + si2 + st2 + guest2 + guest_nice2 64 | us 的占比为 (us2 - us1) / (cpu_total2 - cpu_total1)。 65 | 66 | nice 是一个可以修改进程调度优先级的命令,在 Linux 中,一个进程有一个 nice 值,代表的是这个进程的调度优先级。越 nice(nice 值越大)的进程,调度优先级越低,越会“谦让”,所以它的获得 CPU 的机会就越低。ni 代表的是 niced 用户态进程消耗的 CPU。 67 | 68 | 如果 sy 过高,说明程序调用 Linux 系统调用的开销很大,不同的系统调用开销不一样,pthread_create 的开销比较大。 69 | 70 | wa 高,不能说明系统的 IO 有问题。如果整个系统只有简单任务不停地进行 IO,此时的 wa 可能很高,而系统磁盘的 IO 也远远没达到上限。假设有个单核的系统。CPU 并不会真的“死等” IO。此时的 CPU 实际是 idle 的,如果有其它进程可以运行,则运行其它进程,此时 CPU 时间就不算入 iowait。如果此时系统没有其它进程需要运行,则 CPU 需要“等”这次 IO 完成才可以继续运行,此时“等待”的时间算入 iowait。wa 低,也不能说明系统的 IO 没问题。假设机器进行大量的 IO 任务把磁盘带宽打得慢慢的,同时还有计算任务把 CPU 也跑得满满的。此时 wa 很低,但系统 IO 压力很大。 71 | 72 | 系统调用会触发软中断,网卡收到数据包后,网卡驱动会通过软中断通知 CPU。 73 | 74 | ```sh 75 | $ iperf -s -i 1 # 服务端 76 | 77 | $ iperf -c 192.168.1.4 -i 1 -t 60 # 客户端,可以开几个 terminal 执行多个客户端,这样 si 的变化才会比较明显 78 | 79 | %Cpu(s): 1.7 us, 74.1 sy, 0.0 ni, 8.0 id, 0.0 wa, 0.0 hi, 16.2 si, 0.0 st 80 | ``` 81 | 82 | st 和虚拟化相关,利用虚拟化技术,一台 32 CPU 核心的物理机,可以创建出几十上百个单 CPU 核心的虚拟机。这在公有云场景下,简称“超卖”。大部分情况下,物理服务器的资源有大量是闲置的。此时,“超卖”并不会造成明显影响。当很多虚拟机的 CPU 压力变大,此时物理机的资源明显不足,就会造成各个虚拟机之间相互竞争、相互等待。st 就是用来衡量被 Hypervisor “偷去” 给其它虚拟机使用的 CPU。这个值越高,说明这台物理服务器的资源竞争越激烈。 83 | -------------------------------------------------------------------------------- /03~监控告警/监控指标/系统指标/CPU/stat.md: -------------------------------------------------------------------------------- 1 | # vmstat 2 | 3 | 使用 vmstat 命令,可以查看到上下文切换次数这个指标,如下表所示,每隔 1 秒输出 1 组数据: 4 | 5 | ```sh 6 | $ vmstat 1 7 | procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu----- 8 | r b swpd free buff cache si so bi bo in cs us sy id wa st 9 | 0 0 0 5921968 1536888 16818972 0 0 0 75 1 0 4 2 95 0 0 10 | ``` 11 | 12 | 上表的 cs(context switch)就是每秒上下文切换的次数,按照不同场景,CPU 上下文切换还可以分为中断上下文切换、线程上下文切换和进程上下文切换三种,但是无论是哪一种,过多的上下文切换,都会把 CPU 时间消耗在寄存器、内核栈以及虚拟内存等数据的保存和恢复上,从而缩短进程真正运行的时间,导致系统的整体性能大幅下降。vmstat 的输出中 us、sy 分别用户态和内核态的 CPU 利用率,这两个值也非常具有参考意义。 13 | 14 | vmstat 的输只给出了系统总体的上下文切换情况,要想查看每个进程的上下文切换详情(如自愿和非自愿切换),需要使用 pidstat,该命令还可以查看某个进程用户态和内核态的 CPU 利用率。 15 | 16 | # dstat 17 | 18 | ```sh 19 | --total-cpu-usage-- -dsk/total- -net/total- ---paging-- ---system-- 20 | usr sys idl wai stl| read writ| recv send| in out | int csw 21 | 4 1 95 0 0| 735B 592k| 0 0 | 0 0 |5465 33k 22 | 8 3 90 0 0| 0 168k| 428k 429k| 0 0 | 10k 41k 23 | 3 1 97 0 0| 0 208k| 128k 149k| 0 0 |8106 31k 24 | ``` 25 | 26 | # pidstat 27 | 28 | ```sh 29 | Linux 4.15.0-58-generic (master) 11/19/2019 _x86_64_ (8 CPU) 30 | 31 | 01:58:10 PM UID PID %usr %system %guest %wait %CPU CPU Command 32 | 01:58:10 PM 0 1 0.34 0.23 0.00 0.00 0.57 0 systemd 33 | 01:58:10 PM 0 2 0.00 0.00 0.00 0.00 0.00 2 kthreadd 34 | 01:58:10 PM 0 7 0.00 0.01 0.00 0.01 0.01 0 ksoftirqd/0 35 | ``` 36 | -------------------------------------------------------------------------------- /03~监控告警/监控指标/系统指标/CPU/top.md: -------------------------------------------------------------------------------- 1 | # top 2 | 3 | 使用 top 命令,可以查看到 CPU 利用率、CPU 平均负载这两个指标。 4 | 5 | ```sh 6 | # 指定查看用户,键入数字 1 查看单个 CPU 的负载,P/M/T 分别切换按照 CPU、内存、CPU 占用时间排序 7 | $ top -u oracle 8 | 9 | # Cpu(s): 87.3%us, 1.2%sy, 0.0%ni, 27.6%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st 10 | us: user cpu time (or) % CPU time spent in user space 11 | sy: system cpu time (or) % CPU time spent in kernel space 12 | ni: user nice cpu time (or) % CPU time spent on low priority processes 13 | id: idle cpu time (or) % CPU time spent idle 14 | wa: io wait cpu time (or) % CPU time spent in wait (on disk) 15 | hi: hardware irq (or) % CPU time spent servicing/handling hardware interrupts 16 | si: software irq (or) % CPU time spent servicing/handling software interrupts 17 | st: steal time - - % CPU time in involuntary wait by virtual cpu while hypervisor is servicing another processor (or) % CPU time stolen from a virtual machine 18 | 19 | # 表格列 20 | 21 | # PID:进程的ID 22 | # USER:进程所有者 23 | # PR:进程的优先级别,越小越优先被执行 24 | # NInice:值 25 | # VIRT:进程占用的虚拟内存 26 | # RES:进程占用的物理内存 27 | # SHR:进程使用的共享内存 28 | # S:进程的状态。S表示休眠,R表示正在运行,Z表示僵死状态,N表示该进程优先值为负数 29 | # %CPU:进程占用CPU的使用率 30 | # %MEM:进程使用的物理内存和总内存的百分比 31 | # TIME+:该进程启动后占用的总的CPU时间,即占用CPU使用时间的累加值。 32 | # COMMAND:进程启动命令名称 33 | ``` 34 | 35 | 第一行显示的内容:当前时间、系统运行时间以及正在登录用户数。load average 后的三个数字,依次表示过去 1 分钟、5 分钟、15 分钟的平均负载(Load Average)。平均负载是指单位时间内,系统处于可运行状态(正在使用 CPU 或者正在等待 CPU 的进程,R 状态)和不可中断状态(D 状态)的平均进程数,也就是平均活跃进程数,它和 CPU 使用率并没有直接关系。 36 | 37 | 第三行的内容表示 CPU 利用率,每一列的含义可以使用 man 查看。CPU 使用率体现了单位时间内 CPU 使用情况的统计,以百分比的方式展示。计算方式为:CPU 利用率 = 1 -(CPU 空闲时间)/ CPU 总的时间。需要注意的是,通过性能分析工具得到的 CPU 的利用率其实是某个采样时间内的 CPU 平均值。注:top 工具显示的的 CPU 利用率是把所有 CPU 核的数值加起来的,即 8 核 CPU 的利用率最大可以到达 800%(可以用 htop 等更新一些的工具代替 top)。 38 | 39 | ![default](https://user-images.githubusercontent.com/5803001/39466197-45bac832-4d5a-11e8-9c90-1cbdc0762b49.png) 40 | 41 | 1 处表示系统负载,它表示当前正在等待被 cpu 调度的进程数量,这个值小于系统 vcpu 数(超线程数)的时候是比较正常的,一旦大于 vcpu 数,则说明并发运行的进程太多了,有进程迟迟得不到 cpu 时间。这种情况给用户的直观感受就是敲任何命令都卡。 42 | 43 | 2 处表示当前系统的总进程数,通常该值过大的时候就会导致 load average 过大。 44 | 45 | 3 处表示 cpu 的空闲时间,可以反应 cpu 的繁忙程度,该值较高时表示系统 cpu 处于比较清闲的状态,如果该值较低,则说明系统的 cpu 比较繁忙。需要注意的是,有些时候该值比较高,表示 cpu 比较清闲,但是 load average 依然比较高,这种情况很可能就是因为进程数太多,进程切换占用了大量的 cpu 时间,从而挤占了业务运行需要使用的 cpu 时间。 46 | 47 | 4 处表示进程 IO 等待的时间,该值较高时表示系统的瓶颈可能出现在磁盘和网络。 48 | 49 | 5 处表示系统的剩余内存,反应了系统的内存使用情况。 50 | 51 | 6 处表示单个进程的 cpu 和内存使用情况。关于 top 命令中各个指标含义的进一步描述可以参见: 52 | 53 | 此外,我们也可以使用扩展 [htop](https://github.com/hishamhm/htop) 或者 [glances](https://github.com/nicolargo/glances);如果针对容器监控,可以使用 [ctop](https://github.com/bcicen/ctop)。 54 | 55 | - 在命令行输入 top,然后 shift+p 查看占用 CPU 最高的进程,记下进程号 56 | - 在命令行输入 top -Hp 进程号,查看占用 CPU 最高的线程 57 | - 使用 printf 0x%x 线程号,得到其 16 进制线程号 58 | - 使用 jstack 进程号得到 java 执行栈,然后 grep16 进制找到相应的信息 59 | 60 | ps -eo %cpu,pid |sort -n -k1 -r | head -n 1 | awk '{print $2}' |xargs top -b -n1 -Hp | grep COMMAND -A1 | tail -n 1 | awk '{print $1}' | xargs printf 0x%x 61 | 62 | 找到使用 CPU 最高的进程之使用 CPU 最高的线程的 16 进制号。 63 | 64 | - 如果 load 超过了 cpu 核数,则负载过高 65 | - 如果 wa 过高,可初步判断 IO 有问题 66 | - sy,si,hi,st,任何一个超过 5%,都有问题 67 | - 进程状态长时处于 D、Z、T 状态,提高注意度 68 | - cpu 不均衡,判断亲和性和优先级问题 ➊ 如果 load 超过了 cpu 核数,则负载过高 69 | - 如果 wa 过高,可初步判断 IO 有问题 70 | - sy,si,hi,st,任何一个超过 5%,都有问题 71 | - 进程状态长时处于 D、Z、T 状态,提高注意度 72 | - cpu 不均衡,判断亲和性和优先级问题 73 | 74 | 除了关注类似 top 的一些指标,还有: 75 | 76 | - b 置于等待队列(等待资源、等待输入/输出)的内核线程数目。数字过大则 cpu 太忙。 77 | - cs 如果频繁的进行上下文切换,则考虑是否是线程数开的过多 78 | - si/so 显示了交换分区的现状,有时候会造成 cpu 问题,一并关注 79 | 80 | # htop 81 | 82 | # ctop 83 | -------------------------------------------------------------------------------- /03~监控告警/监控指标/系统指标/CPU/中间件.md: -------------------------------------------------------------------------------- 1 | # 中间件性能监控 2 | -------------------------------------------------------------------------------- /03~监控告警/监控指标/系统指标/README.md: -------------------------------------------------------------------------------- 1 | # 常用的性能监控 2 | 3 | 从系统、中间件、应用程序三个维度去考虑,在实际运行时,这三者往往是相辅相成、相互影响的。系统是为应用提供了运行时环境,系统如果存在瓶颈,将会导致应用/中间件的性能下降;而应用/中间件的不合理设计,也会体现在系统资源上。因此,分析瓶颈点时,需要我们结合从不同角度分析出的结果,抽出共性,得到最终的结论。 4 | 5 | 其次,建议先从应用层入手,分析图中标注的高频指标,抓出最重要的、最可疑的、最有可能导致性能的点,得到初步的结论后,再去系统层进行验证。这样做的好处是:很多性能瓶颈点体现在系统层,会是多变量呈现的,譬如,应用 GC 出现了异常,在应用层通过 JDK 自带的工具很容易观测到,但是体现在系统层上,可能会发现应用当前的 CPU、内存都不太正常,这就给我们的分析思路带来了困扰。 6 | 7 | 最后,如果瓶颈点在应用层和系统层均呈现出多变量分布,建议此时使用 JProfiler 等工具对应用进行 Profiling,获取应用的综合性能信息(注:Profiling 指的是在应用运行时,通过事件(Event-based)、统计抽样(Sampling Statistical)或植入附加指令(Byte-Code instrumentation)等方法,收集应用运行时的信息,来研究应用行为的动态分析方法)。譬如,可以对 CPU 进行抽样统计,结合各种符号表信息,得到一段时间内应用内的代码热点。 8 | 9 | # Linux 10 | 11 | 性能工具(Linux Performance Tools-full)图出自系统性能专家 Brendan Gregg。该图从 Linux 内核的各个子系统出发,列出了我们在对各个子系统进行性能分析时,可使用的工具,涵盖了监测、分析、调优等性能优化的方方面面。除了这张全景图之外,Brendan Gregg 还单独提供了基准测试工具(Linux Performance Benchmark Tools)图、性能监测工具(Linux Performance Observability Tools)图等。 12 | 13 | ![Linux Performance Tools](https://s2.ax1x.com/2019/11/18/M6g2iq.png) 14 | 15 | 上图虽好,却对分析经验要求较高,适用性和完整性不是很好。笔者将具体的工具同性能指标结合了起来,同时从不同的层次去描述了性能瓶颈点的分布。下图中系统层的工具分为 CPU、内存、磁盘(含文件系统)、网络等部分,同时引入了 JDK、Trace、Dump 分析、Profiling 等常用的组件层和应用层中的工具。 16 | 17 | ![常用 Linux 性能监控命令](https://s2.ax1x.com/2019/11/18/McwFOI.png) 18 | 19 | > 本部分仅列举出常用的命令,具体命令的使用请参考 [Linux 命令实践](https://github.com/wx-chevalier/Linux-Notes)。 20 | 21 | # Links 22 | 23 | - 参考[用十条命令在一分钟内检查 Linux 服务器性能](http://www.infoq.com/cn/news/2015/12/linux-performance) 24 | 25 | - [How Do I Find The Largest Top 10 Files and Directories On a Linux / UNIX / BSD?](http://www.cyberciti.biz/faq/how-do-i-find-the-largest-filesdirectories-on-a-linuxunixbsd-filesystem/) 26 | 27 | - https://zhuanlan.zhihu.com/p/68139649 28 | -------------------------------------------------------------------------------- /03~监控告警/监控指标/系统指标/内存/内存.md: -------------------------------------------------------------------------------- 1 | # 内存 2 | 3 | 和内存相关的指标主要有以下几个,常用的分析工具有:top、free、vmstat、pidstat 以及 JDK 自带的一些工具。 4 | 5 | - 系统内存的使用情况,包括剩余内存、已用内存、可用内存、缓存/缓冲区; 6 | - 进程(含 Java 进程)的虚拟内存、常驻内存、共享内存; 7 | - 进程的缺页异常数,包含主缺页异常和次缺页异常; 8 | - Swap 换入和换出的内存大小、Swap 参数配置; 9 | - JVM 堆的分配,JVM 启动参数; 10 | - JVM 堆的回收,GC 情况。 11 | 12 | 使用 free 可以查看系统内存的使用情况和 Swap 分区的使用情况,top 工具可以具体到每个进程,如我们可以用使用 top 工具查看 Java 进程的常驻内存大小(RES),这两个工具结合起来,可用覆盖大多数内存指标。下面是使用 free 命令的输出: 13 | 14 | ```sh 15 | $ free -h 16 | total used free shared buff/cache available 17 | Mem: 125G 6.8G 54G 2.5M 64G 118G 18 | Swap: 2.0G 305M 1.7G 19 | ``` 20 | 21 | Swap 的作用就是把一块磁盘空间或者一个本地文件当成内存来使用,包括换出和换入两个过程。Swap 需要读写磁盘数据,所以性能不是很高,事实上,包括 ElasticSearch、Hadoop 在内绝大部分 Java 应用都建议关掉 Swap,这是因为内存的成本一直在降低,同时这也和 JVM 的垃圾回收过程(GC)有关:JVM 在 GC 的时候会遍历所有用到的堆的内存,如果这部分内存被 Swap 出去了,遍历的时候就会有磁盘 I/O。Swap 分区的升高一般和磁盘的使用强相关,具体分析时,需要结合缓存时候用、swappiness 阈值以及匿名页和文件页的活跃情况综合分析。 22 | 23 | buff/cache 是缓存和缓冲区的大小。缓存(cache):是从磁盘读取的文件的或者向磁盘写文件时的临时存储数据,面向文件。使用 cachestat 可以查看整个系统缓存的读写命中情况,使用 cachetop 可以观察每个进程缓存的读写命中情况。缓冲区(buffer)是写入磁盘数据或从磁盘直接读取的数据的临时存储,面向块设备。free 命令的输出中,这两个指标是加在一起的,使用 vmstat 命令可以区分缓存和缓冲区,还可以看到 Swap 分区换入和换出的内存大小。 24 | 25 | 了解到常见的内存指标后,常见的内存问题又有哪些?总结如下: 26 | 27 | - 系统剩余内存/可用不足(某个进程占用太多、系统本身内存不足),内存溢出; 28 | - 内存回收异常:内存泄漏(进程在一段时间内内存使用持续走高)、GC 频率异常; 29 | - 缓存使用过大(大文件读取或写入)、缓存命中率不高; 30 | - 缺页异常过多(频繁的 I/O 读); 31 | - Swap 分区使用异常(使用过大); 32 | 33 | ```sh 34 | # 按照 Swap 分区的使用情况列出前 10 的进程 35 | $ for file in /proc/*/status ; do awk '/VmSwap|Name|^Pid/{printf $2 " " $3}END{ print ""}' $file; done | sort -k 3 -n -r | head -10 36 | ``` 37 | 38 | 内存相关指标异常后,分析思路是怎么样的? 39 | 40 | - 用 free/top 查看内存的全局使用情况,如系统内存的使用、Swap 分区内存使用、缓存/缓冲区占用情况等,初步判断内存问题存在的方向:进程内存、缓存/缓冲区、Swap 分区; 41 | 42 | - 观察一段时间内存的使用趋势。如通过 vmstat 观察内存使用是否一直在增长;通过 jmap 定时 dump 对象列表,判断是否存在内存泄漏,通过 cachetop 命令,定位缓冲区升高的根源等; 43 | 44 | - 根据内存问题的类型,结合应用本身,进行详细分析。 45 | 46 | 使用 free 发现缓存/缓冲区占用不大,排除缓存/缓冲区对内存的影响后 -> 使用 vmstat 或者 sar 观察一下各个进程内存使用变化趋势 -> 发现某个进程的内存时候用持续走高 -> 如果是 Java 应用,可以使用 jmap / VisualVM / heap dump 分析等工具观察对象内存的分配,或者通过 jstat 观察 GC 后的应用内存变化 -> 结合业务场景,定位为内存泄漏/GC 参数配置不合理/业务代码异常等。 47 | 48 | # 问题排查 49 | 50 | 内存分为系统内存和进程内存(含 Java 应用进程),一般我们遇到的内存问题,绝大多数都会落在进程内存上,系统资源造成的瓶颈占比较小。对于 Java 进程,它自带的内存管理自动化地解决了两个问题:如何给对象分配内存以及如何回收分配给对象的内存,其核心是垃圾回收机制。 51 | 52 | 垃圾回收虽然可以有效地防止内存泄露、保证内存的有效使用,但也并不是万能的,不合理的参数配置和代码逻辑,依然会带来一系列的内存问题。此外,早期的垃圾回收器,在功能性和回收效率上也不是很好,过多的 GC 参数设置非常依赖开发人员的调优经验。比如,对于最大堆内存的不恰当设置,可能会引发堆溢出或者堆震荡等一系列问题。 53 | 54 | ## 系统内存不足 55 | 56 | Java 应用一般都有单机或者集群的内存水位监控,如果单机的内存利用率大于 95%,或者集群的内存利用率大于 80%,就说明可能存在潜在的内存问题(注:这里的内存水位是系统内存)。 57 | 58 | 除了一些较极端的情况,一般系统内存不足,大概率是由 Java 应用引起的。使用 top 命令时,我们可以看到 Java 应用进程的实际内存占用,其中 RES 表示进程的常驻内存使用,VIRT 表示进程的虚拟内存占用,内存大小的关系为:VIRT > RES > Java 应用实际使用的堆大小。除了堆内存,Java 进程整体的内存占用,还有方法区/元空间、JIT 缓存等,主要组成如下: 59 | 60 | Java 应用内存占用 = Heap(堆区)+ Code Cache(代码缓存区) + Metaspace(元空间)+ Symbol tables(符号表)+ Thread stacks(线程栈区)+ Direct buffers(堆外内存)+ JVM structures(其他的一些 JVM 自身占用)+ Mapped files(内存映射文件)+ Native Libraries(本地库)+ ... 61 | 62 | Java 进程的内存占用,可以使用 jstat -gc 命令查看,输出的指标中可以得到当前堆内存各分区、元空间的使用情况。堆外内存的统计和使用情况,可以利用 NMT(Native Memory Tracking,HotSpot VM Java8 引入)获取。线程栈使用的内存空间很容易被忽略,虽然线程栈内存采用的是懒加载的模式,不会直接使用 +Xss 的大小来分配内存,但是过多的线程也会导致不必要的内存占用,可以使用 jstackmem 这个脚本统计整体的线程占用。 63 | 64 | 系统内存不足的排查思路: 65 | 66 | - 首先使用 free 查看当前内存的可用空间大小,然后使用 vmstat 查看具体的内存使用情况及内存增长趋势,这个阶段一般能定位占用内存最多的进程; 67 | 68 | - 分析缓存 / 缓冲区的内存使用。如果这个数值在一段时间变化不大,可以忽略。如果观察到缓存 / 缓冲区的大小在持续升高,则可以使用 pcstat、cachetop、slabtop 等工具,分析缓存 / 缓冲区的具体占用; 69 | 70 | - 排除掉缓存 / 缓冲区对系统内存的影响后,如果发现内存还在不断增长,说明很有可能存在内存泄漏 71 | 72 | ## Java 内存溢出 73 | 74 | 内存溢出是指应用新建一个对象实例时,所需的内存空间大于堆的可用空间。内存溢出的种类较多,一般会在报错日志里看到 OutOfMemoryError 关键字。常见内存溢出种类及分析思路如下: 75 | 76 | - java.lang.OutOfMemoryError: Java heap space。原因:堆中(新生代和老年代)无法继续分配对象了、某些对象的引用长期被持有没有被释放,垃圾回收器无法回收、使用了大量的 Finalizer 对象,这些对象并不在 GC 的回收周期内等。一般堆溢出都是由于内存泄漏引起的,如果确认没有内存泄漏,可以适当通过增大堆内存。 77 | 78 | - java.lang.OutOfMemoryError: GC overhead limit exceeded。原因:垃圾回收器超过 98%的时间用来垃圾回收,但回收不到 2%的堆内存,一般是因为存在内存泄漏或堆空间过小。 79 | 80 | - java.lang.OutOfMemoryError: Metaspace 或 java.lang.OutOfMemoryError: PermGen space。排查思路:检查是否有动态的类加载但没有及时卸载,是否有大量的字符串常量池化,永久代/元空间是否设置过小等。 81 | 82 | - java.lang.OutOfMemoryError: unable to create new native Thread。原因:虚拟机在拓展栈空间时,无法申请到足够的内存空间。可适当降低每个线程栈的大小以及应用整体的线程个数。此外,系统里总体的进程/线程创建总数也受到系统空闲内存和操作系统的限制,请仔细检查。注:这种栈溢出,和 StackOverflowError 不同,后者是由于方法调用层次太深,分配的栈内存不够新建栈帧导致。 83 | 84 | 此外,还有 Swap 分区溢出、本地方法栈溢出、数组分配溢出等 OutOfMemoryError 类型。 85 | 86 | ## Java 内存泄漏 87 | 88 | Java 内存泄漏可以说是开发人员的噩梦,内存泄漏与内存溢出不同则,后者简单粗暴,现场也比较好找。内存泄漏的表现是:应用运行一段时间后,内存利用率越来越高,响应越来越慢,直到最终出现进程假死。 89 | 90 | Java 内存泄漏可能会造成系统可用内存不足、进程假死、OOM 等,排查思路却不外乎下面两种: 91 | 92 | - 通过 jmap 定期输出堆内对象统计,定位数量和大小持续增长的对象; 93 | - 使用 Profiler 工具对应用进行 Profiling,寻找内存分配热点。 94 | -------------------------------------------------------------------------------- /03~监控告警/监控指标/系统指标/磁盘/README.md: -------------------------------------------------------------------------------- 1 | # 磁盘文件 2 | 3 | 在分析和磁盘相关的问题时,通常是将其和文件系统同时考虑的,下面不再区分。和磁盘/文件系统相关的指标主要有以下几个,常用的观测工具为 iostat 和 pidstat,前者适用于整个系统,后者可观察具体进程的 I/O。 4 | 5 | - 磁盘 I/O 利用率:是指磁盘处理 I/O 的时间百分比; 6 | - 磁盘吞吐量:是指每秒的 I/O 请求大小,单位为 KB; 7 | - I/O 响应时间,是指 I/O 请求从发出到收到响应的间隔,包含在队列中的等待时间和实际处理时间; 8 | - IOPS(Input/Output Per Second):每秒的 I/O 请求数; 9 | - I/O 等待队列大小,指的是平均 I/O 队列长度,队列长度越短越好; 10 | 11 | 如何判断磁盘的指标出现了异常? 12 | 13 | - 当磁盘 I/O 利用率长时间超过 80%,或者响应时间过大(对于 SSD,从 0.0x 毫秒到 1.x 毫秒不等,机械磁盘一般为 5ms~10ms),通常意味着磁盘 I/O 存在性能瓶颈; 14 | 15 | - 如果 %util 很大,而 rkB/s 和 wkB/s 很小,一般是因为存在较多的磁盘随机读写,最好把随机读写优化成顺序读写,(可以通过 strace 或者 blktrace 观察 I/O 是否连续判断是否是顺序的读写行为,随机读写应可关注 IOPS 指标,顺序读写可关注吞吐量指标); 16 | 17 | - 如果 avgqu-sz 比较大,说明有很多 I/O 请求在队列中等待。一般来说,如果单块磁盘的队列长度持续超过 2,一般认为该磁盘存在 I/O 性能问题。 18 | 19 | io 请求越大,需要消耗的时间就会越长。对于块设备而言,时间分成 2 个部分:寻道与读或写操作。 20 | 21 | 注意此处的寻道不能简单地理解成磁盘磁头旋转到指定位置,因为后备块设备可能是 RAID,可能是 SSD,我们理解写入前的准备动作。准备工作完成之后,写入 4K 和写入 128KB,明显写入 128KB 的工作量要更大一些,因此很容易理解随机写入 128KB 给块设备带来的负载要比随机写入 4K 给块设备带来的负载要高一些。 22 | 23 | ## 磁盘的性能评价 24 | 25 | SAN(Storage Area Network, 存储区域网络)和 NAS 存储(Network Attached Storage,网络附加存储)一般都具备 2 个评价指标:IOPS 和带宽(throughput),两个指标互相独立又相互关联。体现存储系统性能的最主要指标是 IOPS。下面,将介绍一下这两个参数的含义。 26 | 27 | IOPS (Input/Output Per Second)即每秒的输入输出量(或读写次数),是衡量磁盘性能的主要指标之一。IOPS 是指单位时间内系统能处理的 IO 请求数量,IO 请求通常为读或写数据操作请求。随机读写频繁的应用,如 OLTP(Online Transaction Processing),IOPS 是关键衡量指标。另一个重要指标是数据吞吐量(Throughput),指单位时间内可以成功传输的数据数量。对于大量顺序读写的应用,如 VOD(Video On Demand),则更关注吞吐量指标。 28 | 29 | 每秒 IO 吞吐量= IOPS\* 平均 IO SIZE。从公式可以看出:IO SIZE 越大,IOPS 越高,那么每秒 IO 的吞吐量就越高。因此,我们会认为 IOPS 和吞吐量的数值越高越好。实际上,对于一个磁盘来讲,这两个参数均有其最大值,而且这两个参数也存在着一定的关系。 30 | 31 | IOPS 可细分为如下几个指标: 32 | 33 | - Toatal IOPS,混合读写和顺序随机 IO 负载情况下的磁盘 IOPS,这个与实际 IO 情况最为相符,大多数应用关注此指标。 34 | - Random Read IOPS,100%随机读负载情况下的 IOPS。 35 | - Random Write IOPS,100%随机写负载情况下的 IOPS。 36 | - Sequential Read IOPS,100%顺序读负载情况下的 IOPS。 37 | - Sequential Write IOPS,100%顺序写负载情况下的 IOPS。 38 | 39 | ## IOPS 计算公式 40 | 41 | 对于磁盘来说一个完整的 IO 操作是这样进行的:当控制器对磁盘发出一个 IO 操作命令的时候,磁盘的驱动臂(Actuator Arm)带读写磁头(Head)离开着陆区(Landing Zone,位于内圈没有数据的区域),移动到要操作的初始数据块所在的磁道(Track)的正上方,这个过程被称为寻址(Seeking),对应消耗的时间被称为寻址时间(Seek Time);但是找到对应磁道还不能马上读取数据,这时候磁头要等到磁盘盘片(Platter)旋转到初始数据块所在的扇区(Sector)落在读写磁头正上方的之后才能开始读取数据,在这个等待盘片旋转到可操作扇区的过程中消耗的时间称为旋转延时(Rotational Delay);接下来就随着盘片的旋转,磁头不断的读/写相应的数据块,直到完成这次 IO 所需要操作的全部数据,这个过程称为数据传送(Data Transfer),对应的时间称为传送时间(Transfer Time)。完成这三个步骤之后一次 IO 操作也就完成了。 42 | 43 | 在我们看硬盘厂商的宣传单的时候我们经常能看到 3 个参数,分别是平均寻址时间、盘片旋转速度以及最大传送速度,这三个参数就可以提供给我们计算上述三个步骤的时间。 44 | 45 | 第一个寻址时间,考虑到被读写的数据可能在磁盘的任意一个磁道,既有可能在磁盘的最内圈(寻址时间最短),也可能在磁盘的最外圈(寻址时间最长),所以在计算中我们只考虑平均寻址时间,也就是磁盘参数中标明的那个平均寻址时间,这里就采用当前最多的 10krmp 硬盘的 5ms。 46 | 47 | 第二个旋转延时,和寻址一样,当磁头定位到磁道之后有可能正好在要读写扇区之上,这时候是不需要额外额延时就可以立刻读写到数据,但是最坏的情况确实要磁盘旋转整整一圈之后磁头才能读取到数据,所以这里我们也考虑的是平均旋转延时,对于 10krpm 的磁盘就是(60s/10k)\*(1/2) = 2ms。 48 | 49 | 第三个传送时间,磁盘参数提供我们的最大的传输速度,当然要达到这种速度是很有难度的,但是这个速度却是磁盘纯读写磁盘的速度,因此只要给定了单次 IO 的大小,我们就知道磁盘需要花费多少时间在数据传送上,这个时间就是 IO Chunk Size / Max Transfer Rate。 50 | 51 | 现在我们就可以得出这样的计算单次 IO 时间的公式。 52 | 53 | IO Time = Seek Time + 60 sec/Rotational Speed/2 + IO Chunk Size/Transfer Rate 54 | 55 | 于是我们可以这样计算出 IOPS。 56 | 57 | IOPS = 1/IO Time = 1/(Seek Time + 60 sec/Rotational Speed/2 + IO Chunk Size/Transfer Rate) 58 | 59 | 对于给定不同的 IO 大小我们可以得出下面的一系列的数据 60 | 61 | 4K (1/7.1 ms = 140 IOPS) 62 |    5ms + (60sec/15000RPM/2) + 4K/40MB = 5 + 2 + 0.1 = 7.1 63 |    8k (1/7.2 ms = 139 IOPS) 64 |    5ms + (60sec/15000RPM/2) + 8K/40MB = 5 + 2 + 0.2 = 7.2 65 |    16K (1/7.4 ms = 135 IOPS) 66 |    5ms + (60sec/15000RPM/2) + 16K/40MB = 5 + 2 + 0.4 = 7.4 67 |    32K (1/7.8 ms = 128 IOPS) 68 |    5ms + (60sec/15000RPM/2) + 32K/40MB = 5 + 2 + 0.8 = 7.8 69 |    64K (1/8.6 ms = 116 IOPS) 70 |    5ms + (60sec/15000RPM/2) + 64K/40MB = 5 + 2 + 1.6 = 8.6 71 | 72 | 从上面的数据可以看出,当单次 IO 越小的时候,单次 IO 所耗费的时间也越少,相应的 IOPS 也就越大。 73 | 74 | 上面我们的数据都是在一个比较理想的假设下得出来的,这里的理想的情况就是磁盘要花费平均大小的寻址时间和平均的旋转延时,这个假设其实是比较符合我们实际情况中的随机读写,在随机读写中,每次 IO 操作的寻址时间和旋转延时都不能忽略不计,有了这两个时间的存在也就限制了 IOPS 的大小。现在我们考虑一种相对极端的顺序读写操作,比如说在读取一个很大的存储连续分布在磁盘的的文件,因为文件的存储的分布是连续的,磁头在完成一个读 IO 操作之后,不需要从新的寻址,也不需要旋转延时,在这种情况下我们能到一个很大的 IOPS 值,如下。 75 | 76 | 4K (1/0.1 ms = 10000 IOPS) 77 |    0ms + 0ms + 4K/40MB = 0.1 78 |    8k (1/0.2 ms = 5000 IOPS) 79 |    0ms + 0ms + 8K/40MB = 0.2 80 |    16K (1/0.4 ms = 2500 IOPS) 81 |    0ms + 0ms + 16K/40MB = 0.4 82 |    32K (1/0.8 ms = 1250 IOPS) 83 |    0ms + 0ms + 32K/40MB = 0.8 84 |    64K (1/1.6 ms = 625 IOPS) 85 |    0ms + 0ms + 64K/40MB = 1.6 86 | 87 | 相比第一组数据来说差距是非常的大的,因此当我们要用 IOPS 来衡量一个 IO 系统的系能的时候我们一定要说清楚是在什么情况的 IOPS,也就是要说明读写的方式以及单次 IO 的大小,当然在实际当中,特别是在 OLTP 的系统的,随机的小 IO 的读写是最有说服力的。 88 | 89 | 另外,对于同一个磁盘(或者 LUN),随着每次 IO 读写数据的大小不通,IOPS 的数值也不是固定不变的。例如,每次 IO 写入或者读出的都是连续的大数据块,此时 IOPS 相对会低一些;在不频繁换道的情况下,每次写入或者读出的数据块小,相对来讲 IOPS 就会高一些。也就是说,IOPS 也取决与 IO 块的大小,采用不同 IO 块的大小测出的 IOPS 值是不同的。对一个具体的 IOPS, 可以了解它当时测试的 IO 块的尺寸。并且 IOPS 都具有极限值,表 1 列出了各种磁盘的 IOPS 极限值。 90 | 91 | # 问题排查 92 | 93 | - 用工具输出磁盘相关的输出的指标,常用的有 %wa(iowait)、%util,根据输判断磁盘 I/O 是否存在异常,譬如 %util 这个指标较高,说明有较重的 I/O 行为; 94 | 95 | - 使用 pidstat 定位到具体进程,关注下读或写的数据大小和速率; 96 | 97 | - 使用 lsof + 进程号,可查看该异常进程打开的文件列表(含目录、块设备、动态库、网络套接字等),结合业务代码,一般可定位到 I/O 的来源,如果需要具体分析,还可以使用 perf 等工具进行 trace 定位 I/O 源头。 98 | 99 | 需要注意的是,%wa(iowait)的升高不代表一定意味着磁盘 I/O 存在瓶颈,这是数值代表 CPU 上 I/O 操作的时间占用的百分比,如果应用进程的在这段时间内的主要活动就是 I/O,那么也是正常的。 100 | 101 | 网络 I/O 存在瓶颈,可能的原因如下: 102 | 103 | - 一次传输的对象过大,可能会导致请求响应慢,同时 GC 频繁; 104 | 105 | - 网络 I/O 模型选择不合理,导致应用整体 QPS 较低,响应时间长; 106 | 107 | - RPC 调用的线程池设置不合理。可使用 jstack 统计线程数的分布,如果处于 TIMED_WAITING 或 WAITING 状态的线程较多,则需要重点关注。举例:数据库连接池不够用,体现在线程栈上就是很多线程在竞争一把连接池的锁; 108 | 109 | - RPC 调用超时时间设置不合理,造成请求失败较多; 110 | 111 | Java 应用的线程堆栈快照非常有用,除了上面提到的用于排查线程池配置不合理的问题,其他的一些场景,如 CPU 飙高、应用响应较慢等,都可以先从线程堆栈入手。 112 | -------------------------------------------------------------------------------- /03~监控告警/监控指标/系统指标/磁盘/fio.md: -------------------------------------------------------------------------------- 1 | # fio 2 | 3 | # Links 4 | 5 | - https://blog.csdn.net/weixin_43226231/article/details/100177892 6 | -------------------------------------------------------------------------------- /03~监控告警/监控指标/系统指标/网络/网络.md: -------------------------------------------------------------------------------- 1 | # 网络 2 | 3 | 网络这个概念涵盖的范围较广,在应用层、传输层、网络层、网络接口层都有不同的指标去衡量。这里我们讨论的网络,特指应用层的网络,通常使用的指标如下: 4 | 5 | - 网络带宽:表示链路的最大传输速率; 6 | - 网络吞吐:表示单位时间内成功传输的数据量大小; 7 | - 网络延时:表示从网络请求发出后直到收到远端响应,所需要的时间; 8 | - 网络连接数和错误数; 9 | 10 | 一般来说,应用层的网络瓶颈有如下几类: 11 | 12 | - 集群或机器所在的机房的网络带宽饱和,影响应用 QPS/TPS 的提升; 13 | - 网络吞吐出现异常,如接口存在大量的数据传输,造成带宽占用过高; 14 | - 网络连接出现异常或错误; 15 | - 网络出现分区。 16 | 17 | 带宽和网络吞吐这两个指标,一般我们会关注整个应用的,通过监控系统可直接得到,如果一段时间内出现了明显的指标上升,说明存在网络性能瓶颈。对于单机,可以使用 sar 得到网络接口、进程的网络吞吐。 18 | 19 | 使用 ping 或者 hping3 可以得到是否出现网络分区、网络具体时延。对于应用,我们更关注整个链路的时延,可以通过中间件埋点后输出的 trace 日志得到链路上各个环节的时延信息。使用 netstat、ss 和 sar 可以获取网络连接数或网络错误数。 20 | 21 | ```sh 22 | # 查看系统当前网络连接数 23 | $ netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}' 24 | ``` 25 | 26 | # mtr 27 | 28 | MTR 是一个简单的跨平台命令行网络诊断工具,将常用的 traceroute 和 ping 程序的功能组合到一个工具中。以与 traceroute 类似的方式,mtr 打印有关数据包从运行 mtr 的主机到用户指定的目标主机的路由的信息。运行 mtr 后,它将探查本地系统与您指定的远程主机之间的网络连接。它首先在主机之间建立每个网络跃点(网桥,路由器和网关等)的地址,然后对其进行 ping(发送 ICMP ECHO 请求的序列)以确定每个计算机的链路质量。 29 | 30 | 该工具已预装在大多数 Linux 发行版中,我们也可以手动添加: 31 | 32 | ```s 33 | $ sudo apt install mtr 34 | $ sudo yum install mtr 35 | $ sudo dnf install mtr 36 | ``` 37 | 38 | 使用 mtr 的最简单示例是提供远程计算机的域名或 IP 地址作为参数,例如 google.com 或 216.58.223.78。此命令将向您显示实时更新的路由跟踪报告,直到您退出程序(通过按 q 或 Ctrl + C)。 39 | 40 | ```s 41 | $ mtr google.com 42 | OR 43 | $ mtr 216.58.223.78 44 | 45 | Start: Thu Jun 28 12:10:13 2018 46 | HOST: TecMint Loss% Snt Last Avg Best Wrst StDev 47 | 1.|-- 192.168.0.1 0.0% 5 0.3 0.3 0.3 0.4 0.0 48 | 2.|-- 5.5.5.211 0.0% 5 0.7 0.9 0.7 1.3 0.0 49 | 3.|-- 209.snat-111-91-120.hns.n 80.0% 5 7.1 7.1 7.1 7.1 0.0 50 | 4.|-- 72.14.194.226 0.0% 5 1.9 2.9 1.9 4.4 1.1 51 | 5.|-- 108.170.248.161 0.0% 5 2.9 3.5 2.0 4.3 0.7 52 | 6.|-- 216.239.62.237 0.0% 5 3.0 6.2 2.9 18.3 6.7 53 | 7.|-- bom05s12-in-f14.1e100.net 0.0% 5 2.1 2.4 2.0 3.8 0.5 54 | ``` 55 | 56 | 常见的参数用法如下: 57 | 58 | ```s 59 | # 强制展示 IP 地址 60 | $ mtr -n google.com 61 | 62 | # 同时展示域名与 IP 63 | $ mtr -b google.com 64 | 65 | # 使用 TCP 或者 UDP 66 | $ mtr --tcp test.com 67 | $ mtr --udp test.com 68 | 69 | # 设置测试包的大小 70 | $ mtr -r -s PACKETSIZE -c 5 google.com >mtr-report 71 | ``` 72 | 73 | 您可以使用-r 标志将其设置为报告模式,该标志是用于生成有关网络质量的统计信息的有用选项。您可以将此选项与-c 选项一起使用以指定 ping 的数量。由于统计信息已打印到标准输出,因此您可以将其重定向到文件以供以后分析。 74 | 75 | ```s 76 | $ mtr -r -c 5 google.com >mtr-report 77 | $ mtr -rw -c 5 google.com >mtr-report 78 | $ mtr -o "LSDR NBAW JMXI" 216.58.223.78 79 | ``` 80 | -------------------------------------------------------------------------------- /03~监控告警/监控指标/统计与告警策略/异常检测.md: -------------------------------------------------------------------------------- 1 | # 异常检测 2 | 3 | 在定期搜集应用的多维度运行指标之后,我们即需要运用异常检测算法来发现潜在的问题目标。首先需要对于指标进行特征选取与处理,譬如关联性处理、指标转换等。然后针对稳定区间、非稳定区间,用不同的离群点检测算法来综合打分做处理。 4 | 5 | # 错误 6 | 7 | 错误是指当前系统发生的错误请求和错误率,是需要在添加监控时首要关注的指标。基础监控维度的宕机、磁盘(坏盘或文件系统错误)、进程或端口挂掉、网络丢包等故障。业务监控则较为复杂,可能包含以下方面: 8 | 9 | - 核心功能处理错误,每种系统都有特定的核心功能,比如 HDFS 的文件块读写、Zookeeper 对 Key 的读写和修改操作。 10 | - 基础功能单元丢失或异常,这里的基础功能单元是指一个系统功能上的基本单位,例如 HDFS 的 Block、Kafka 的 Message,这种基础数据的丢失一般都会对业务功能造成直接的影响。 11 | - Master 故障,对于中心化的分布式系统来说,Master 的健康状况都是重中之重。例如 HDFS 的 NameNode、Zookeeper 的 Leader,ElasticSearch 的 MasterNode。 12 | - 可用节点数,对于分布式系统来说,可用节点数也是非常重要的,比如 Zookeeper、ETCD 等系统需要满足可用节点数大于不可用节点数才能保证功能的正常。 13 | 14 | 除白盒监控外,主要功能或接口、以及内部存在明显边界的功能模块和上游依赖模块,都应该添加黑盒端到端监控。 15 | 16 | - MTTF, Mean Time To Failure,系统平均运行多长时间才发生故障,越长越好 17 | - MTTR, Mean Time To Recover,故障平均修复时间,越短越好 18 | 19 | 可用性计算公式:`Availability= MTTF /(MTTF+MTTR)` 20 | -------------------------------------------------------------------------------- /03~监控告警/监控指标/统计与告警策略/统计与告警策略.md: -------------------------------------------------------------------------------- 1 | # 统计与告警 2 | 3 | 在搜集到时序监控指标后,我们需要对原始指标进行求和等统计操作以得到实际有意义的值。 4 | 5 | # 统计策略 6 | 7 | 以性能统计为例,业界对性能统计有两种方式: 1.通过分位数计算; 2.通过平均值计算. 这两种方式的优缺点恰好是相反的。 8 | 9 | - 通过分位数计算:这种方式可以很大程度上避免受到少量极端异常,举个例子,同一个页面,有四次访问,页面完全加载时间分别是 2 秒、1 秒、3 秒、100 秒,按照平均值算得出来的结果是 26.5 秒,显然没有反映出大多数用户的真实状态. 而通过 75 分位数得出的结论是 3 秒。 10 | - 通过平均值计算:平均值计算方式恰好相反,容易受到极端值干扰,但通俗易懂,是使用最广泛的统计指标。 11 | 12 | # 告警策略 13 | 14 | 所以这里需要引入一个告警策略,使得告警更加的人性化,这个机制的核心就是 4 点: 15 | 16 | - 梳理不同的告警级别 17 | - 制定告警频率以及做好收敛(主要是去重、合并数量) 18 | - 决定不同的告警级别通过什么形式发出通知(短信、手机通知、邮件等) 19 | - 发给谁(比如,是不是需要“轮转”或者“逐级上报”这样) 20 | -------------------------------------------------------------------------------- /03~监控告警/监控指标/黄金指标/README.md: -------------------------------------------------------------------------------- 1 | # Google SRE 黄金指标 2 | 3 | 当我们设计复杂系统时,生产环境系统的可观察性是必须的,期望通过观察告诉我们什么时候,哪里出现了问题。 4 | 5 | - 平时了解服务运行状况。 6 | - 异常时,可发现服务故障,并定位故障原因。 7 | - 事后,对异常点做分析,看是否在高峰期发生,或者持续更久,是否会出事故,如何解决。 8 | 9 | Four Golden Signals 是 Google 针对大量分布式监控的经验总结,4 个黄金指标可以在服务级别帮助衡量终端用户体验、服务中断、业务影响等层面的问题。观察那些指标,按照《SRE:Google 运维解密》中描述的,监控的四个黄金指标如后: 延迟、流量、错误、饱和度。 10 | 11 | ![黄金指标示意](https://assets.ng-tech.icu/superbed/2021/07/22/60f985f25132923bf80a49cf.jpg) 12 | 13 | 这四类监控指标,在具体的业务和基础设施、中间件场景,要监控的项各有不同: 14 | 15 | | | 基础设施 | 业务监控 | 16 | | -------- | --------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | 17 | | 错误类 | 宕机;磁盘(坏盘或文件系统错误);进程或端口挂掉;网络丢包; | 错误日志;业务状态码、错误码走势; | 18 | | 延迟类 | IO 等待;网络延迟; | 接口、服务的平均耗时、TP90、TP99、TP999 等;DB、缓存的慢查询; | 19 | | 流量类 | 网络和磁盘 IO; | 服务层面的 QPS、PV 和 UV;各状态业务订单 TPM;针对音频流媒体系统来说,这个指标可能是网络 I/O 速率,或者并发会话数量;针对键值对存储系统来说,指标可能是每秒交易数量,或每秒的读取操作数量; | 20 | | 饱和度类 | 系统资源利用率:CPU、内存、磁盘、网络等;饱和度:等待线程数,队列积压长度; | 该服务是否可以正常处理两倍的流量,是否可以应对 10%的额外流量,或者甚至应对当前更少的流量?预测:看起来数据库会在 4 个小时内填满硬盘; | 21 | 22 | ![Google SRE 黄金指标](https://assets.ng-tech.icu/item/20230418224219.png) 23 | 24 | - 延迟:服务请求所需时间。记录用户所有请求所需的时间,重点是要区分成功请求的延迟时间和失败请求的延迟时间。例如在数据库或者其他关键祸端服务异常触发 HTTP 500 的情况下,用户也可能会很快得到请求失败的响应内容,如果不加区分计算这些请求的延迟,可能导致计算结果与实际结果产生巨大的差异。除此以外,在微服务中通常提倡“快速失败”,开发人员需要特别注意这些延迟较大的错误,因为这些缓慢的错误会明显影响系统的性能,因此追踪这些错误的延迟也是非常重要的。 25 | 26 | - 通讯量:监控当前系统的流量,用于衡量服务的容量需求。流量对于不同类型的系统而言可能代表不同的含义。例如,在 HTTP REST API 中, 流量通常是每秒 HTTP 请求数; 27 | 28 | - 错误:监控当前系统所有发生的错误请求,衡量当前系统错误发生的速率。对于失败而言有些是显式的(比如, HTTP 500 错误),而有些是隐式(比如,HTTP 响应 200,但实际业务流程依然是失败的)。对于一些显式的错误如 HTTP 500 可以通过在负载均衡器(如 Nginx)上进行捕获,而对于一些系统内部的异常,则可能需要直接从服务中添加钩子统计并进行获取。 29 | 30 | - 饱和度:衡量当前服务的饱和度。主要强调最能影响服务状态的受限制的资源。例如,如果系统主要受内存影响,那就主要关注系统的内存状态,如果系统主要受限与磁盘 I/O,那就主要观测磁盘 I/O 的状态。因为通常情况下,当这些资源达到饱和后,服务的性能会明显下降。同时还可以利用饱和度对系统做出预测,比如,“磁盘是否可能在 4 个小时候就满了”。 31 | 32 | # RED 方法 33 | 34 | RED 方法是 Weave Cloud 在基于 Google 的“4 个黄金指标”的原则下结合 Prometheus 以及 Kubernetes 容器实践,细化和总结的方法论,特别适合于云原生应用以及微服务架构应用的监控和度量。主要关注以下三种关键指标: 35 | 36 | - (请求)速率:服务每秒接收的请求数。 37 | - (请求)错误:每秒失败的请求数。 38 | - (请求)耗时:每个请求的耗时。 39 | 40 | 在“4 大黄金信号”的原则下,RED 方法可以有效的帮助用户衡量云原生以及微服务应用下的用户体验问题。 41 | 42 | # USE 方法 43 | 44 | USE 方法全称"Utilization Saturation and Errors Method",主要用于分析系统性能问题,可以指导用户快速识别资源瓶颈以及错误的方法。正如 USE 方法的名字所表示的含义,USE 方法主要关注与资源的:使用率(Utilization)、饱和度(Saturation)以及错误(Errors)。 45 | 46 | - 使用率:关注系统资源的使用情况。这里的资源主要包括但不限于:CPU,内存,网络,磁盘等等。100%的使用率通常是系统性能瓶颈的标志。 47 | - 饱和度:例如 CPU 的平均运行排队长度,这里主要是针对资源的饱和度(注意,不同于 4 大黄金信号)。任何资源在某种程度上的饱和都可能导致系统性能的下降。 48 | - 错误:错误计数。例如:“网卡在数据包传输过程中检测到的以太网网络冲突了 14 次”。 49 | 50 | 通过对资源以上指标持续观察,通过以下流程可以知道用户识别资源瓶颈: 51 | 52 | ![img](https://gblobscdn.gitbook.com/assets%2F-LBdoxo9EmQ0bJP2BuUi%2F-LPS8LQB5PdyyY0X1z6h%2F-LPS8NI0J-F_01SeCTRB%2FUSEMethod.png?alt=media) 53 | -------------------------------------------------------------------------------- /03~监控告警/监控系统设计/README.md: -------------------------------------------------------------------------------- 1 | # 监控与告警体系 2 | 3 | 在系统运维一章中我们就已经讨论了独立 Linux 服务器中简单的系统指标的获取与分析,本篇着重讨论复杂分布式系统下基于度量的监控解决方案,广义的监控往往还会涉及日志聚合与分布式追踪等。 4 | 5 | # 监控系统流程 6 | 7 | 无论是开源的监控系统还是自研的监控系统,监控的整个流程大同小异,一般都包括以下模块: 8 | 9 | - 数据采集:采集的方式有很多种,包括日志埋点进行采集(通过 Logstash、Filebeat 等进行上报和解析),JMX 标准接口输出监控指标,被监控对象提供 REST API 进行数据采集(如 Hadoop、ES),系统命令行,统一的 SDK 进行侵入式的埋点和上报等。 10 | 11 | - 数据传输:将采集的数据以 TCP、UDP 或者 HTTP 协议的形式上报给监控系统,有主动 Push 模式,也有被动 Pull 模式。 12 | 13 | - 数据存储:有使用 MySQL、Oracle 等 RDBMS 存储的,也有使用时序数据库 RRDTool、OpentTSDB、InfluxDB 存储的,还有使用 HBase 存储的。 14 | 15 | - 数据展示:数据指标的图形化展示。 16 | 17 | - 监控告警:灵活的告警设置,以及支持邮件、短信、IM 等多种通知通道。 18 | 19 | # Links 20 | 21 | - https://mp.weixin.qq.com/s/hUuZQVK1uYjXTqx2q1fZCg 22 | -------------------------------------------------------------------------------- /03~监控告警/监控系统设计/存储设计.md: -------------------------------------------------------------------------------- 1 | # 数据存储设计 2 | -------------------------------------------------------------------------------- /03~监控告警/监控系统设计/监控系统对比.md: -------------------------------------------------------------------------------- 1 | # 监控系统对比 2 | 3 | 开源监控系统也经历了非常多的迭代: 4 | 5 | - 老牌监控系统:Zabbix, Nagios, Cacti, Ganglia, Garafana 6 | - 新型监控系统:Open-Falcon, Prometheus 7 | 8 | # Zabbix 9 | 10 | Zabbix 是由 Alexei Vladishev 开源的分布式监控系统,支持多种采集方式和采集客户端,同时支持 SNMP、IPMI、JMX、Telnet、SSH 等多种协议,它将采集到的数据存放到数据库中,然后对其进行分析整理,如果符合告警规则,则触发相应的告警。Zabbix 1998 年诞生,核心组件采用 C 语言开发,Web 端采用 PHP 开发。它属于老牌监控系统中的优秀代表,监控功能很全面,使用也很广泛,差不多有 70%左右的互联网公司都曾使用过 Zabbix 作为监控解决方案。 11 | 12 | ![Zabbix 截图](https://s1.ax1x.com/2020/08/09/a7wjj1.png) 13 | 14 | Zabbix Server 将收集的监控数据存储到 Zabbix Database 中。Zabbix Database 支持常用的关系型数据库,例如 MySQL、PostgreSQL、Oracle 等,默认 MySQL。Zabbix Web 页面(PHP 编写)负责数据查询。Zabbix 由于使用了关系型数据存储时序数据,所以在监控大规模集群时常常在数据存储方面捉襟见肘。为此 Zabbix 4.2 版本后也开始支持时序数据存储,不过目前还不成熟。Zabbix 的架构设计如下: 15 | 16 | ![Zabbix 架构图](https://s1.ax1x.com/2020/08/09/a709AO.png) 17 | 18 | - **Zabbix Server:**核心组件,C 语言编写,负责接收 Agent、Proxy 发送的监控数据,也支持 JMX、SNMP 等多种协议直接采集数据。同时,它还负责数据的汇总存储以及告警触发等。 19 | - **Zabbix Proxy:**可选组件,对于被监控机器较多的情况下,可使用 Proxy 进行分布式监控,它能代理 Server 收集部分监控数据,以减轻 Server 的压力。 20 | - **Zabbix Agentd:**部署在被监控主机上,用于采集本机的数据并发送给 Proxy 或者 Server,它的插件机制支持用户自定义数据采集脚本。Agent 可在 Server 端手动配置,也可以通过自动发现机制被识别。数据收集方式同时支持主动 Push 和被动 Pull 两种模式。 21 | - **Database:**用于存储配置信息以及采集到的数据,支持 MySQL、Oracle 等关系型数据库。同时,最新版本的 Zabbix 已经开始支持时序数据库,不过成熟度还不高。 22 | - **Web Server:**Zabbix 的 GUI 组件,PHP 编写,提供监控数据的展现和告警配置。 23 | 24 | ## 优势 25 | 26 | - **产品成熟:**由于诞生时间长且使用广泛,拥有丰富的文档资料以及各种开源的数据采集插件,能覆盖绝大部分监控场景。 27 | - **采集方式丰富:**支持 Agent、SNMP、JMX、SSH 等多种采集方式,以及主动和被动的数据传输方式。 28 | - **较强的扩展性**:支持 Proxy 分布式监控,有 agent 自动发现功能,插件式架构支持用户自定义数据采集脚本。 29 | - **配置管理方便**:能通过 Web 界面进行监控和告警配置,操作方便,上手简单。 30 | 31 | ## 缺陷 32 | 33 | - **性能瓶颈**:机器量或者业务量大了后,关系型数据库的写入一定是瓶颈,官方给出的单机上限是 5000 台,个人感觉达不到,尤其现在应用层的指标越来越多。虽然最新版已经开始支持时序数据库,不过成熟度还不高。 34 | - **应用层监控支持有限:**如果想对应用程序做侵入式的埋点和采集(比如监控线程池或者接口性能),zabbix 没有提供对应的 sdk,通过插件式的脚本也能曲线实现此功能,个人感觉 zabbix 就不是做这个事的。 35 | - **数据模型不强大**:不支持 tag,因此没法按多维度进行聚合统计和告警配置,使用起来不灵活。 36 | - **方便二次开发难度大**:Zabbix 采用的是 C 语言,二次开发往往需要熟悉它的数据表结构,基于它提供的 API 更多只能做展示层的定制。 37 | 38 | # ELK 监控生态 39 | 40 | ELK (Elasticsearch,Logstash,Kibana) 是 Elastic 公司提供的三个开源组件。在日常工作中,我们需要进行日志分析场景:直接对日志文件进行 grep、awk 等正则操作,获取我们想要的信息。在大规模的场景中,日志文件分布在不同的服务器上,且文件非常大,逐台操作性能非常低。比如 Nginx 日志,Mysql 慢查询日志,应用 log 日志等。ELK 提供一整套的解决方案,可以帮助我们快速全站查询。 41 | 42 | 下图是 Mysql 慢查询的截图,通过 Python 脚本,可以实时读取 Mysql 慢查询日志,并写入 ES,方便查看线上问题。 43 | 44 | ![](https://ww1.sinaimg.cn/large/007rAy9hgy1g0f3f3fcn3j30gm07qq3f.jpg) 45 | 46 | 下图是服务器的 dashboard,通过模糊匹配,可以快速查询相关服务器组的性能指标。 47 | 48 | ![](https://ww1.sinaimg.cn/large/007rAy9hgy1g0f3f3fcn3j30gm07qq3f.jpg) 49 | 50 | # Open-Falcon 51 | 52 | Open-Falcon 是小米开源的监控系统,灵活的数据采集,水平扩展能力以及高效的告警策略帮助我们快速监控服务端的信息。小米初期也使用的 Zabbix 进行监控,但是机器量和业务量上来后,Zabbix 就有些力不从心了。因此,后来自主研发了 Open-Falcon,在架构设计上吸取了 Zabbix 的经验,同时很好地解决了 Zabbix 的诸多痛点。 53 | 54 | ![Open Falcon 截图](https://s1.ax1x.com/2020/08/09/a70x2j.md.png) 55 | 56 | Open-Falcon 用 Go 语言开发而成,包括小米、滴滴、美团等在内的互联网公司都在使用它,是一款灵活、可扩展并且高性能的监控方案,主要组件包括了: 57 | 58 | - Falcon-agent:用 Go 语言开发的 Daemon 程序,运行在每台 Linux 服务器上,用于采集主机上的各种指标数据,主要包括 CPU、内存、磁盘、文件系统、内核参数、Socket 连接等,目前已经支持 200 多项监控指标。并且,Agent 支持用户自定义的监控脚本。 59 | 60 | - Hearthbeat server:简称 HBS 心跳服务,每个 Agent 都会周期性地通过 RPC 方式将自己的状态上报给 HBS,主要包括主机名、主机 IP、Agent 版本和插件版本,Agent 还会从 HBS 获取自己需要执行的采集任务和自定义插件。 61 | 62 | - Transfer:负责接收 Agent 发送的监控数据,并对数据进行整理,在过滤后通过一致性 Hash 算法发送到 Judge 或者 Graph。 63 | 64 | - Graph:RRD 数据上报、归档、存储的组件。Graph 在收到数据以后,会以 RRDtool 的数据归档方式来存储,同时提供 RPC 方式的监控查询接口。 65 | 66 | - Judge:告警模块,Transfer 转发到 Judge 的数据会触发用户设定的告警规则,如果满足,则会触发邮件、微信或者回调接口。这里为了避免重复告警引入了 Redis 暂存告警,从而完成告警的合并和抑制。 67 | 68 | - Dashboard:面向用户的监控数据查询和告警配置界面。 69 | 70 | ![Open Falcon 组件架构](https://s2.ax1x.com/2019/10/02/udT9qP.jpg) 71 | 72 | ## 优势 73 | 74 | - **自动采集能力**:Falcon-agent 能自动采集服务器的 200 多个基础指标(比如 CPU、内存等),无需在 server 上做任何配置,这一点可以秒杀 Zabbix. 75 | - **强大的存储能力**:底层采用 RRDTool,并且通过一致性 hash 进行数据分片,构建了一个分布式的时序数据存储系统,可扩展性强。 76 | - **灵活的数据模型:**借鉴 OpenTSDB,数据模型中引入了 tag,这样能支持多维度的聚合统计以及告警规则设置,大大提高了使用效率。 77 | - **插件统一管理:**Open-Falcon 的插件机制实现了对用户自定义脚本的统一化管理,可通过 HeartBeat Server 分发给 agent,减轻了使用者自主维护脚本的成本。 78 | - **个性化监控支持**:基于 Proxy-gateway,很容易通过自主埋点实现应用层的监控(比如监控接口的访问量和耗时)和其他个性化监控需求,集成方便。 79 | 80 | ## 缺陷 81 | 82 | - **整体发展一般:**社区活跃度不算高,同时版本更新慢,有些大厂是基于它的稳定版本直接做二次开发的,关于以后的前景其实有点担忧。 83 | - **UI 不够友好**:对于业务线的研发来说,可能只想便捷地完成告警配置和业务监控,但是它把机器分组、策略模板、模板继承等概念全部暴露在 UI 上,感觉在围绕这几个概念设计 UI,理解有点费劲。 84 | - **安装比较复杂:**个人的亲身感受,由于它是从小米内部衍生出来的,虽然去掉了对小米内部系统的依赖,但是组件还是比较多,如果对整个架构不熟悉,安装很难一蹴而就。 85 | 86 | # Prometheus 87 | 88 | Prometheus 是一套开源的监控、报警、时间序列数据库的组合;它的灵感来自谷歌的 Borgmon,一个实时的时间序列监控系统,Borgmon 使用这些时间序列数据来识别问题并发出警报。Prometheus 最初由前谷歌 SRE Matt T. Proud 开发,并转为一个研究项目。在 Proud 加入 SoundCloud 之后,他与另一位工程师 Julius Volz 合作开发了 Prometheus。后来其他开发人员陆续加入了这个项目,并在 SoundCloud 内部继续开发,最终于 2015 年 1 月公开发布。 89 | 90 | ![Prometheus 截图](https://s1.ax1x.com/2020/08/09/a7BldK.md.png) 91 | 92 | Prometheus 的优势在于其易于安装使用,外部依赖较少;并且直接按照分布式、微服务架构模式进行设计,支持服务自动化发现与代码集成。Prometheus 能够自定义多维度的数据模型,内置强大的查询语句,搭配其丰富的社区扩展,能够轻松实现数据可视化。 93 | 94 | ![Prometheus 生态系统](https://assets.ng-tech.icu/item/20230418223837.png) 95 | 96 | Prometheus 由两个部分组成,一个是监控报警系统,另一个是自带的时序数据库(TSDB)。上图是 Prometheus 整体架构图,左侧是各种符合 Prometheus 数据格式的 exporter,除此之外为了支持推动数据类型的 Agent,可以通过 Pushgateway 组件,将 Push 转化为 Pull。Prometheus 甚至可以从其它的 Prometheus 获取数据,组建联邦集群。Prometheus 的基本原理是通过 HTTP 周期性抓取被监控组件的状态,任意组件只要提供对应的 HTTP 接口并且符合 Prometheus 定义的数据格式,就可以接入 Prometheus 监控。 97 | 98 | ![Prometheus 架构图](https://s1.ax1x.com/2020/08/09/a7BGJe.md.png) 99 | 100 | - **Prometheus Server:**核心组件,用于收集、存储监控数据。它同时支持静态配置和通过 Service Discovery 动态发现来管理监控目标,并从监控目标中获取数据。此外,Prometheus Server 也是一个时序数据库,它将监控数据保存在本地磁盘中,并对外提供自定义的 PromQL 语言实现对数据的查询和分析。 101 | - **Exporter:**用来采集数据,作用类似于 agent,区别在于 Prometheus 是基于 Pull 方式拉取采集数据的,因此,Exporter 通过 HTTP 服务的形式将监控数据按照标准格式暴露给 Prometheus Server,社区中已经有大量现成的 Exporter 可以直接使用,用户也可以使用各种语言的 client library 自定义实现。 102 | - **Push gateway:**主要用于瞬时任务的场景,防止 Prometheus Server 来 pull 数据之前此类 Short-lived jobs 就已经执行完毕了,因此 job 可以采用 push 的方式将监控数据主动汇报给 Push gateway 缓存起来进行中转。 103 | - **Alert Manager:**当告警产生时,Prometheus Server 将告警信息推送给 Alert Manager,由它发送告警信息给接收方。 104 | - **Web UI:**Prometheus 内置了一个简单的 web 控制台,可以查询配置信息和指标等,而实际应用中我们通常会将 Prometheus 作为 Grafana 的数据源,创建仪表盘以及查看指标。 105 | 106 | ## 优势 107 | 108 | - **轻量管理:**架构简单,不依赖外部存储,单个服务器节点可直接工作,二进制文件启动即可,属于轻量级的 Server,便于迁移和维护。 109 | - **较强的处理能力**:监控数据直接存储在 Prometheus Server 本地的时序数据库中,单个实例可以处理数百万的 metrics。 110 | - **灵活的数据模型:**同 Open-Falcon,引入了 tag,属于多维数据模型,聚合统计更方便。 111 | - **强大的查询语句:**PromQL 允许在同一个查询语句中,对多个 metrics 进行加法、连接和取分位值等操作。 112 | - **很好地支持云环境**:能自动发现容器,同时 K8s 和 etcd 等项目都提供了对 Prometheus 的原生支持,是目前容器监控最流行的方案。 113 | 114 | ## 缺陷 115 | 116 | - **功能不够完善:**Prometheus 从一开始的架构设计就是要做到简单,不提供集群化方案,长期的持久化存储和用户管理,而这些是企业变大后所必须的特性,目前要做到这些只能在 Prometheus 之上进行扩展。 117 | - **网络规划变复杂**:由于 Prometheus 采用的是 Pull 模型拉取数据,意味着所有被监控的 endpoint 必须是可达的,需要合理规划网络的安全配置。 118 | 119 | # 综合对比 120 | 121 | 从开发语言上看,为了应对高并发和快速迭代的需求,监控系统的开发语言已经慢慢从 C 语言转移到 Go。不得不说,Go 凭借简洁的语法和优雅的并发,在 Java 占据业务开发,C 占领底层开发的情况下,准确定位中间件开发需求,在当前开源中间件产品中被广泛应用。 122 | 123 | 从系统成熟度上看,Zabbix 是老牌的监控系统:Zabbix 是在 1998 年出现的,系统功能比较稳定,成熟度较高。而 Prometheus 和 Open-Falcon 都是最近几年才诞生的,虽然功能还在不断迭代更新,但站在巨人的肩膀之上,在架构设计上借鉴了很多老牌监控系统的经验。 124 | 125 | 从系统扩展性方面看,Zabbix 和 Open-Falcon 都可以自定义各种监控脚本,并且 Zabbix 不仅可以做到主动推送,还可以做到被动拉取,Prometheus 则定义了一套监控数据规范,并通过各种 exporter 扩展系统采集能力。 126 | 127 | 从数据存储方面来看,Zabbix 采用关系数据库保存,这极大限制了 Zabbix 采集的性能,Open-Falcon 采用 RDD 数据存储,并且可以对接到 OpenTSDB,而 Prometheus 自研一套高性能的时序数据库,在 V3 版本可以达到每秒千万级别的数据存储,通过对接第三方时序数据库扩展历史数据的存储。 128 | 129 | 从配置和维护的复杂度上看,Prometheus 只有一个核心 server 组件,一条命令便可以启动,相比而言,其他系统配置相对麻烦,尤其是 Open-Falcon。 130 | 131 | 从社区活跃度上看,目前 Zabbix 社区活跃度比较低,Open-Falcon 虽然也比较活跃,但基本都是国内的公司参与,Prometheus 在这方面占据绝对优势,社区活跃度最高,并且受到 CNCF 的支持,后期的发展值得期待。 132 | 133 | 从容器支持角度看,由于 Zabbix 出现得比较早,当时容器还没有诞生,自然对容器的支持也比较差。Open-Falcon 虽然提供了容器的监控,但支持力度有限。Prometheus 的动态发现机制,不仅可以支持 Swarm 原生集群,还支持 Kubernetes 容器集群的监控,是目前容器监控最好解决方案。Zabbix 在传统监控系统中,尤其是在服务器相关监控方面,占据绝对优势。伴随着容器的发展,Prometheus 开始成为主导及容器监控方面的标配,并且在未来可见的时间内被广泛应用。总体来说,对比各种监控系统的优劣,Prometheus 可以说是目前监控领域最锋利的“瑞士军刀”了。 134 | -------------------------------------------------------------------------------- /03~监控告警/监控系统设计/采集设计.md: -------------------------------------------------------------------------------- 1 | # 埋点与侵入式 2 | 3 | 对于应用程序错误数、应用程序请求量、应用平均响应时间的监控,这里是一个分水岭,因为这里想要做到无侵入的效果,需要做一些额外的工作,否则只能编写大量的“埋点”代码。比如,是不是有一个网关来统一进行流量分发?是不是有一个统一的 RPC 框架、数据库访问框架等等。如果有这样的统一模块就好办了,直接在这些模块里增加监控功能。 4 | 5 | # 数据存储 6 | 7 | 关于采集到的数据如何存储,主流的选择是将数据写入到一个时序数据库中。 8 | 9 | - Prometheus 提供了丰富的数据模型和查询语句,容易上手,很容易集成到现有的环境中,但是 Prometheus 的集群和 HA 架构并不成熟,需要额外的开发,并不适合。 10 | 11 | - InfluxDB 是在 Prometheus 之后才提出的,并且提供商业的伸缩和集群化服务,相比 Prometheus 的 metrics 存储,InfluxDB 还能处理事件类型的数据,对于大部分公司而言,商业化基本不会考虑。 12 | 13 | - OpenTSDB 是一个基于 Hadoop 和 Hbase 的分布式事件序列数据库,相比 Prometheus 和 InfluxDB,OpenTSDB 的横向扩缩容很容易 (需要有丰富的 Hadoop/HBase 维护经验), 同时官方 Open-falcon 支持 OpenTSDB。 14 | 15 | 在 Prometheus 中收集所有指标后,你可以使用 Grafana 可视化这些指标。关于数据展示的选型,在没有自研能力的情况下,Grafana 是不二选择。Grafana 的告警功能强大方便,同时支持钉钉,Webhook 等,满足公司所有的需求。与此同时,我们将 Grafana 和 Docker 技术结合,实现了 Grafana 高可用、自愈和无限扩展能力。 16 | -------------------------------------------------------------------------------- /04~日志聚合/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wx-chevalier/DevOps-Notes/d7b6420975e9914f5512ae398dd926d6fc08796f/04~日志聚合/.DS_Store -------------------------------------------------------------------------------- /04~日志聚合/ELK/README.md: -------------------------------------------------------------------------------- 1 | # ELK 日志系统搭建 2 | -------------------------------------------------------------------------------- /04~日志聚合/Flume/README.md: -------------------------------------------------------------------------------- 1 | # Flume 2 | 3 | Flume NG 是一个分布式、可靠、可用的系统,它能够将不同数据源的海量日志数据进行高效收集、聚合、移动,最后存储到一个中心化数据存储系统中。由原来的 Flume OG 到现在的 Flume NG,进行了架构重构,并且现在 NG 版本完全不兼容原来的 OG 版本。经过架构重构后,Flume NG 更像是一个轻量的小工具,非常简单,容易适应各种方式日志收集,并支持 failover 和负载均衡。Flume 初始的发行版本目前被统称为 Flume OG(original generation ),属于 Cloudera。但随着 Flume 功能的扩展,Flume OG 代码工程臃肿、核心组件设计不合理、核心配置不标准等缺点暴露出来,尤其是在 Flume OG 的最后一个发行版本 0.94.0 中,日志传输不稳定的现象尤为严重,为了解决这些问题,2011 年 10 月 22 号,Cloudera 完成了 Flume-728,对 Flume 进行了里程碑式的改动:重构核心组件、核心配置以及代码架构,重构后的版本统称为 Flume NG(next generation );改动的另一原因是将 Flume 纳入 apache 旗下,Cloudera Flume 改名为 Apache Flume。 4 | 5 | ## Features 6 | 7 | flume 的数据流由事件 (Event) 贯穿始终。事件是 Flume 的基本数据单位,它携带日志数据 ( 字节数组形式 ) 并且携带有头信息,这些 Event 由 Agent 外部的 Source 生成,当 Source 捕获事件后会进行特定的格式化,然后 Source 会把事件推入 ( 单个或多个 )Channel 中。你可以 把 Channel 看作是一个缓冲区,它将保存事件直到 Sink 处理完该事件。Sink 负责持久化日志或者把事件推向另一个 Source。 8 | 9 | - 可靠性当节点出现故障时,日志能够被传送到其他节点上而不会丢失。Flume 提供了三种级别的可靠性保障,从强到弱依次分别为:end-to-end (收到数据 agent 首先将 event 写到磁盘上,当数据传送成功后,再删除;如果数据发送失败,可以重新发送。),Store on failure (这也是 scribe 采用的策略,当数据接收方 crash 时,将数据写到本地,待恢复后,继续发送),Besteffort(数据发送到接 收方后,不会进行确认)。 10 | - 可恢复性还是靠 Channel。推荐使用 FileChannel,事件持久化在本地文件系统里 ( 性能较差 )。 11 | -------------------------------------------------------------------------------- /04~日志聚合/Flume/安装与配置.md: -------------------------------------------------------------------------------- 1 | # Flume 安装与配置 2 | 3 | 建议直接下载 Flume 的预编译版本,下载地址 :[这里](http://www.apache.org/dyn/closer.lua/flume/1.6.0/apache-flume-1.6.0-bin.tar.gz) 4 | 5 | | Component Interface | Type Alias | Implementation Class | 6 | | ----------------------------------------------- | ------------------- | ----------------------------------------------------------------------------------------------------- | 7 | | \*.Channel | memory | \*.channel.MemoryChannel | 8 | | \*.Channel | jdbc | \*.channel.jdbc.JdbcChannel | 9 | | \*.Channel | file | \*.channel.file.FileChannel | 10 | | \*.Channel | – | \*.channel.PseudoTxnMemoryChannel | 11 | | \*.Channel | – | org.example.MyChannel | 12 | | \*.Source | avro | \*.source.AvroSource | 13 | | \*.Source | netcat | \*.source.NetcatSource | 14 | | \*.Source | seq | \*.source.SequenceGeneratorSource | 15 | | \*.Source | exec | \*.source.ExecSource | 16 | | \*.Source | syslogtcp | \*.source.SyslogTcpSource | 17 | | \*.Source | multiport_syslogtcp | \*.source.MultiportSyslogTCPSource | 18 | | \*.Source | syslogudp | \*.source.SyslogUDPSource | 19 | | \*.Source | spooldir | \*.source.SpoolDirectorySource | 20 | | \*.Source | http | \*.source.http.HTTPSource | 21 | | \*.Source | thrift | \*.source.ThriftSource | 22 | | \*.Source | jms | \*.source.jms.JMSSource | 23 | | \*.Source | – | \*.source.avroLegacy.AvroLegacySource | 24 | | \*.Source | – | \*.source.thriftLegacy.ThriftLegacySource | 25 | | \*.Source | – | org.example.MySource | 26 | | \*.Sink | null | \*.sink.NullSink | 27 | | \*.Sink | logger | \*.sink.LoggerSink | 28 | | \*.Sink | avro | \*.sink.AvroSink | 29 | | \*.Sink | hdfs | \*.sink.hdfs.HDFSEventSink | 30 | | \*.Sink | hbase | \*.sink.hbase.HBaseSink | 31 | | \*.Sink | asynchbase | \*.sink.hbase.AsyncHBaseSink | 32 | | \*.Sink | elasticsearch | \*.sink.elasticsearch.ElasticSearchSink | 33 | | \*.Sink | file_roll | \*.sink.RollingFileSink | 34 | | \*.Sink | irc | \*.sink.irc.IRCSink | 35 | | \*.Sink | thrift | \*.sink.ThriftSink | 36 | | \*.Sink | – | org.example.MySink | 37 | | \*.ChannelSelector | replicating | \*.channel.ReplicatingChannelSelector | 38 | | \*.ChannelSelector | multiplexing | \*.channel.MultiplexingChannelSelector | 39 | | \*.ChannelSelector | – | org.example.MyChannelSelector | 40 | | \*.SinkProcessor | default | \*.sink.DefaultSinkProcessor | 41 | | \*.SinkProcessor | failover | \*.sink.FailoverSinkProcessor | 42 | | \*.SinkProcessor | load_balance | \*.sink.LoadBalancingSinkProcessor | 43 | | \*.SinkProcessor | – | | 44 | | \*.interceptor.Interceptor | timestamp | \*.interceptor.TimestampInterceptor\$Builder | 45 | | \*.interceptor.Interceptor | host | \*.interceptor.HostInterceptor\$Builder | 46 | | \*.interceptor.Interceptor | static | \*.interceptor.StaticInterceptor\$Builder | 47 | | \*.interceptor.Interceptor | regex_filter | \*.interceptor.RegexFilteringInterceptor\$Builder | 48 | | \*.interceptor.Interceptor | regex_extractor | \*.interceptor.RegexFilteringInterceptor\$Builder | 49 | | \*.channel.file.encryption.KeyProvider\$Builder | jceksfile | \*.channel.file.encryption.JCEFileKeyProvider | 50 | | \*.channel.file.encryption.KeyProvider\$Builder | – | org.example.MyKeyProvider | 51 | | \*.channel.file.encryption.CipherProvider | aesctrnopadding | \*.channel.file.encryption.AESCTRNoPaddingProvider | 52 | | \*.channel.file.encryption.CipherProvider | – | org.example.MyCipherProvider | 53 | | \*.serialization.EventSerializer\$Builder | text | \*.serialization.BodyTextEventSerializer\$Builder | 54 | | \*.serialization.EventSerializer\$Builder | avro_event | \*.serialization.[Flume](https://www.iteblog.com/archives/tag/flume)EventAvroEventSerializer\$Builder | 55 | | \*.serialization.EventSerializer\$Builder | – | org.example.MyEventSerializer\$Builder | 56 | 57 | ## Avro Source+Memory Channel+Logger Sink 58 | 59 | 使用 Avro Source 接收外部数据源,Logger 作为 sink,即通过 Avro RPC 调用,将数据缓存在 channel 中,然后通过 Logger 打印出调用发送的数据。配置 Agent,修改配置文件 conf/flume-conf.properties,内容如下: 60 | 61 | ``` 62 | # Define a memory channel called ch1 on agent1 63 | agent1.channels.ch1.type = memory 64 | 65 | # Define an Avro source called avro-source1 on agent1 and tell it 66 | # to bind to 0.0.0.0:41414. Connect it to channel ch1. 67 | agent1.sources.avro-source1.channels = ch1 68 | agent1.sources.avro-source1.type = avro 69 | agent1.sources.avro-source1.bind = 0.0.0.0 70 | agent1.sources.avro-source1.port = 41414 71 | 72 | # Define a logger sink that simply logs all events it receives 73 | # and connect it to the other end of the same channel. 74 | agent1.sinks.log-sink1.channel = ch1 75 | agent1.sinks.log-sink1.type = logger 76 | 77 | # Finally, now that we've defined all of our components, tell 78 | # agent1 which ones we want to activate. 79 | agent1.channels = ch1 80 | agent1.channels.ch1.capacity = 1000 81 | agent1.sources = avro-source1 82 | agent1.sinks = log-sink1 83 | ``` 84 | 85 | 首先,启动 Agent 进程: 86 | 87 | ``` 88 | bin/flume-ng agent -c ./conf/ -f conf/flume-conf.properties -Dflume.root.logger=DEBUG,console -n agent1 89 | ``` 90 | 91 | 然后,启动 Avro Client,发送数据: 92 | 93 | ``` 94 | bin/flume-ng avro-client -c ./conf/ -H 0.0.0.0 -p 41414 -F /usr/local/programs/logs/sync.log -Dflume.root.logger=DEBUG,console 95 | ``` 96 | 97 | ## Avro Source+Memory Channel+HDFS Sink 98 | 99 | 配置 Agent,修改配置文件 conf/flume-conf-hdfs.properties,内容如下: 100 | 101 | ``` 102 | # Define a source, channel, sink 103 | agent1.sources = avro-source1 104 | agent1.channels = ch1 105 | agent1.sinks = hdfs-sink 106 | 107 | # Configure channel 108 | agent1.channels.ch1.type = memory 109 | agent1.channels.ch1.capacity = 1000000 110 | agent1.channels.ch1.transactionCapacity = 500000 111 | 112 | # Define an Avro source called avro-source1 on agent1 and tell it 113 | # to bind to 0.0.0.0:41414. Connect it to channel ch1. 114 | agent1.sources.avro-source1.channels = ch1 115 | agent1.sources.avro-source1.type = avro 116 | agent1.sources.avro-source1.bind = 0.0.0.0 117 | agent1.sources.avro-source1.port = 41414 118 | 119 | # Define a logger sink that simply logs all events it receives 120 | # and connect it to the other end of the same channel. 121 | agent1.sinks.hdfs-sink1.channel = ch1 122 | agent1.sinks.hdfs-sink1.type = hdfs 123 | agent1.sinks.hdfs-sink1.hdfs.path = hdfs://h1:8020/data/flume/ 124 | agent1.sinks.hdfs-sink1.hdfs.filePrefix = sync_file 125 | agent1.sinks.hdfs-sink1.hdfs.fileSuffix = .log 126 | agent1.sinks.hdfs-sink1.hdfs.rollSize = 1048576 127 | agent1.sinks.hdfs-sink1.rollInterval = 0 128 | agent1.sinks.hdfs-sink1.hdfs.rollCount = 0 129 | agent1.sinks.hdfs-sink1.hdfs.batchSize = 1500 130 | agent1.sinks.hdfs-sink1.hdfs.round = true 131 | agent1.sinks.hdfs-sink1.hdfs.roundUnit = minute 132 | agent1.sinks.hdfs-sink1.hdfs.threadsPoolSize = 25 133 | agent1.sinks.hdfs-sink1.hdfs.useLocalTimeStamp = true 134 | agent1.sinks.hdfs-sink1.hdfs.minBlockReplicas = 1 135 | agent1.sinks.hdfs-sink1.fileType = SequenceFile 136 | agent1.sinks.hdfs-sink1.writeFormat = TEXT 137 | ``` 138 | 139 | 首先,启动 Agent 进程: 140 | 141 | ``` 142 | bin/flume-ng agent -c ./conf/ -f conf/flume-conf.properties -Dflume.root.logger=DEBUG,console -n agent1 143 | ``` 144 | 145 | 然后,启动 Avro Client,发送数据: 146 | 147 | ``` 148 | bin/flume-ng avro-client -c ./conf/ -H 0.0.0.0 -p 41414 -F /usr/local/programs/logs/sync.log -Dflume.root.logger=DEBUG,console 149 | ``` 150 | 151 | 可以查看同步到 HDFS 上的数据: 152 | 153 | ``` 154 | hdfs dfs -ls /data/flume 155 | ``` 156 | 157 | 结果示例,如下所示: 158 | 159 | ``` 160 | -rw-r--r-- 3 shirdrn supergroup 1377617 2014-09-16 14:35 /data/flume/sync_file.1410849320761.log 161 | -rw-r--r-- 3 shirdrn supergroup 1378137 2014-09-16 14:35 /data/flume/sync_file.1410849320762.log 162 | -rw-r--r-- 3 shirdrn supergroup 259148 2014-09-16 14:35 /data/flume/sync_file.1410849320763.log 163 | ``` 164 | 165 | ## Spooling Directory Source+Memory Channel+HDFS Sink 166 | 167 | 配置 Agent,修改配置文件 flume-conf-spool.properties,内容如下: 168 | 169 | ``` 170 | # Define source, channel, sink 171 | agent1.sources = spool-source1 172 | agent1.channels = ch1 173 | agent1.sinks = hdfs-sink1 174 | 175 | # Configure channel 176 | agent1.channels.ch1.type = memory 177 | agent1.channels.ch1.capacity = 1000000 178 | agent1.channels.ch1.transactionCapacity = 500000 179 | 180 | # Define and configure an Spool directory source 181 | agent1.sources.spool-source1.channels = ch1 182 | agent1.sources.spool-source1.type = spooldir 183 | agent1.sources.spool-source1.spoolDir = /home/shirdrn/data/ 184 | agent1.sources.spool-source1.ignorePattern = event(_\d{4}\-\d{2}\-\d{2}_\d{2}_\d{2})?\.log(\.COMPLETED)? 185 | agent1.sources.spool-source1.batchSize = 50 186 | agent1.sources.spool-source1.inputCharset = UTF-8 187 | 188 | # Define and configure a hdfs sink 189 | agent1.sinks.hdfs-sink1.channel = ch1 190 | agent1.sinks.hdfs-sink1.type = hdfs 191 | agent1.sinks.hdfs-sink1.hdfs.path = hdfs://h1:8020/data/flume/ 192 | agent1.sinks.hdfs-sink1.hdfs.filePrefix = event_%y-%m-%d_%H_%M_%S 193 | agent1.sinks.hdfs-sink1.hdfs.fileSuffix = .log 194 | agent1.sinks.hdfs-sink1.hdfs.rollSize = 1048576 195 | agent1.sinks.hdfs-sink1.hdfs.rollCount = 0 196 | agent1.sinks.hdfs-sink1.hdfs.batchSize = 1500 197 | agent1.sinks.hdfs-sink1.hdfs.round = true 198 | agent1.sinks.hdfs-sink1.hdfs.roundUnit = minute 199 | agent1.sinks.hdfs-sink1.hdfs.threadsPoolSize = 25 200 | agent1.sinks.hdfs-sink1.hdfs.useLocalTimeStamp = true 201 | agent1.sinks.hdfs-sink1.hdfs.minBlockReplicas = 1 202 | agent1.sinks.hdfs-sink1.fileType = SequenceFile 203 | agent1.sinks.hdfs-sink1.writeFormat = TEXT 204 | agent1.sinks.hdfs-sink1.rollInterval = 0 205 | ``` 206 | 207 | 启动 Agent 进程,执行如下命令: 208 | 209 | ``` 210 | bin/flume-ng agent -c ./conf/ -f conf/flume-conf-spool.properties -Dflume.root.logger=INFO,console -n agent1 211 | ``` 212 | 213 | 可以查看 HDFS 上同步过来的数据: 214 | 215 | ``` 216 | hdfs dfs -ls /data/flume 217 | ``` 218 | 219 | 结果示例,如下所示: 220 | 221 | ``` 222 | -rw-r--r-- 3 shirdrn supergroup 1072265 2014-09-17 10:52 /data/flume/event_14-09-17_10_52_00.1410922355094.log 223 | -rw-r--r-- 3 shirdrn supergroup 1072265 2014-09-17 10:52 /data/flume/event_14-09-17_10_52_00.1410922355095.log 224 | -rw-r--r-- 3 shirdrn supergroup 1072265 2014-09-17 10:52 /data/flume/event_14-09-17_10_52_00.1410922355096.log 225 | -rw-r--r-- 3 shirdrn supergroup 1072265 2014-09-17 10:52 /data/flume/event_14-09-17_10_52_00.1410922355097.log 226 | -rw-r--r-- 3 shirdrn supergroup 1530 2014-09-17 10:53 /data/flume/event_14-09-17_10_52_00.1410922355098.log 227 | -rw-r--r-- 3 shirdrn supergroup 1072265 2014-09-17 10:53 /data/flume/event_14-09-17_10_53_00.1410922380386.log 228 | -rw-r--r-- 3 shirdrn supergroup 1072265 2014-09-17 10:53 /data/flume/event_14-09-17_10_53_00.1410922380387.log 229 | -rw-r--r-- 3 shirdrn supergroup 1072265 2014-09-17 10:53 /data/flume/event_14-09-17_10_53_00.1410922380388.log 230 | -rw-r--r-- 3 shirdrn supergroup 1072265 2014-09-17 10:53 /data/flume/event_14-09-17_10_53_00.1410922380389.log 231 | -rw-r--r-- 3 shirdrn supergroup 1072265 2014-09-17 10:53 /data/flume/event_14-09-17_10_53_00.1410922380390.log 232 | ``` 233 | 234 | ## Exec Source+Memory Channel+File Roll Sink 235 | 236 | 配置 Agent,修改配置文件 flume-conf-file.properties,内容如下: 237 | 238 | ``` 239 | # Define source, channel, sink 240 | agent1.sources = tail-source1 241 | agent1.channels = ch1 242 | agent1.sinks = file-sink1 243 | 244 | # Configure channel 245 | agent1.channels.ch1.type = memory 246 | agent1.channels.ch1.capacity = 1000000 247 | agent1.channels.ch1.transactionCapacity = 500000 248 | 249 | # Define and configure an Exec source 250 | agent1.sources.tail-source1.channels = ch1 251 | agent1.sources.tail-source1.type = exec 252 | agent1.sources.tail-source1.command = tail -F /home/shirdrn/data/event.log 253 | agent1.sources.tail-source1.shell = /bin/sh -c 254 | agent1.sources.tail-source1.batchSize = 50 255 | 256 | # Define and configure a File roll sink 257 | # and connect it to the other end of the same channel. 258 | agent1.sinks.file-sink1.channel = ch1 259 | agent1.sinks.file-sink1.type = file_roll 260 | agent1.sinks.file-sink1.batchSize = 100 261 | agent1.sinks.file-sink1.serializer = TEXT 262 | agent1.sinks.file-sink1.sink.directory = /home/shirdrn/sink_data 263 | ``` 264 | 265 | 启动 Agent 进程,执行如下命令: 266 | 267 | ``` 268 | bin/flume-ng agent -c ./conf/ -f conf/flume-conf-file.properties -Dflume.root.logger=INFO,console -n agent1 269 | ``` 270 | 271 | 可以查看 File Roll Sink 对应的本地文件系统目录 /home/shirdrn/sink_data 下,示例如下所示: 272 | 273 | ``` 274 | -rw-rw-r-- 1 shirdrn shirdrn 13944825 Sep 17 11:36 1410924990039-1 275 | -rw-rw-r-- 1 shirdrn shirdrn 11288870 Sep 17 11:37 1410924990039-2 276 | -rw-rw-r-- 1 shirdrn shirdrn 0 Sep 17 11:37 1410924990039-3 277 | -rw-rw-r-- 1 shirdrn shirdrn 20517500 Sep 17 11:38 1410924990039-4 278 | -rw-rw-r-- 1 shirdrn shirdrn 16343250 Sep 17 11:38 1410924990039-5 279 | ``` 280 | 281 | # Architecture Overview: 架构概览 282 | 283 | Flume NG 架构,如图所示: 284 | 285 | 主要有一下几个核心概念: 286 | 287 | - Event:一个数据单元,带有一个可选的消息头 288 | - Flow:Event 从源点到达目的点的迁移的抽象 289 | - Client:操作位于源点处的 Event,将其发送到 Flume Agent 290 | - Agent:一个独立的 Flume 进程,包含组件 Source、Channel、Sink 291 | - Source:用来消费传递到该组件的 Event 292 | - Channel:中转 Event 的一个临时存储,保存有 Source 组件传递过来的 Event 293 | - Sink:从 Channel 中读取并移除 Event,将 Event 传递到 Flow Pipeline 中的下一个 Agent(如果有的话) 294 | 295 | 外部系统产生日志,直接通过 Flume 的 Agent 的 Source 组件将事件(如日志行)发送到中间临时的 channel 组件,最后传递给 Sink 组件,HDFS Sink 组件可以直接把数据存储到 HDFS 集群上。一个最基本 Flow 的配置,格式如下: 296 | 297 | ``` 298 | # list the sources, sinks and channels for the agent 299 | .sources = 300 | .sinks = 301 | .channels = 302 | 303 | # set channel for source 304 | .sources..channels = ... 305 | .sources..channels = ... 306 | 307 | # set channel for sink 308 | .sinks..channel = 309 | .sinks..channel = 310 | ``` 311 | 312 | 尖括号里面的,我们可以根据实际需求或业务来修改名称。下面详细说明: 313 | 314 | - `` 表示配置一个 Agent 的名称,一个 Agent 肯定有一个名称。 315 | - ` ` 是 Agent 的 Source 组件的名称,消费传递过来的 Event。 316 | - ` ` 是 Agent 的 Channel 组件的名称。 317 | - ` ` 是 Agent 的 Sink 组件的名称,从 Channel 中消费(移除)Event。 318 | 319 | 上面配置内容中,第一组中配置 Source、Sink、Channel,它们的值可以有 1 个或者多个;第二组中配置 Source 将把数据存储(Put )到 哪一个 Channel 中,可以存储到 1 个或多个 Channel 中,同一个 Source 将数据存储到多个 Channel 中,实际上是 Replication;第三组中配置 Sink 从哪一个 Channel 中取(Task )数据,一个 Sink 只能从一个 Channel 中取数据。 320 | 321 | ## Flow Pipeline 322 | 323 | ### 多个 Agent 顺序连接 324 | 325 | 可以将多个 Agent 顺序连接起来,将最初的数据源经过收集,存储到最终的存储系统中。这是最简单的情况,一般情况下,应该控制这种顺序连接的 Agent 的数量,因为数据流经的路径变长了,如果不考虑 failover 的话,出现故障将影响整个 Flow 上的 Agent 收集服务。 326 | 327 | ### 多个 Agent 的数据汇聚到同一个 Agent 328 | 329 | 这种情况应用的场景比较多,比如要收集 Web 网站的用户行为日志,Web 网站为了可用性使用的负载均衡的集群模式,每个节点都产生用户行为日志,可以为每 个节点都配置一个 Agent 来单独收集日志数据,然后多个 Agent 将数据最终汇聚到一个用来存储数据存储系统,如 HDFS 上。 330 | 331 | ### 多路(Multiplexing ) Agent 332 | 333 | 。 334 | 335 | #### Replication 336 | 337 | Replication 方式,可以将 最前端的数据源复制多份,分别传递到多个 channel 中,每个 channel 接收到的数据都是相同的,配置格式,如下所示: 338 | 339 | ``` 340 | # List the sources, sinks and channels for the agent 341 | .sources = 342 | .sinks = 343 | .channels = 344 | 345 | # set list of channels for source (separated by space) 346 | .sources..channels = 347 | 348 | # set channel for sinks 349 | .sinks..channel = 350 | .sinks..channel = 351 | 352 | .sources..selector.type = replicating 353 | ``` 354 | 355 | 上面指定了 selector 的 type 的值为 replication,其他的配置没有指定,使用的 Replication 方式,Source1 会将数据分 别存储到 Channel1 和 Channel2,这两个 channel 里面存储的数据是相同的,然后数据被传递到 Sink1 和 Sink2。 356 | 357 | #### Multiplexing 358 | 359 | Multiplexing 方式,selector 可以根据 header 的值来确定数据传递到哪一个 channel,配置格式,如下所示: 360 | 361 | ``` 362 | # Mapping for multiplexing selector 363 | .sources..selector.type = multiplexing 364 | .sources..selector.header = 365 | .sources..selector.mapping. = 366 | .sources..selector.mapping. = 367 | .sources..selector.mapping. = 368 | #... 369 | 370 | .sources..selector.default = 371 | ``` 372 | 373 | 上面 selector 的 type 的值为 multiplexing,同时配置 selector 的 header 信息,还配置了多个 selector 的 mapping 的值,即 header 的值:如果 header 的值为 Value1、Value2,数据从 Source1 路由到 Channel1;如果 header 的值为 Value2、Value3,数据从 Source1 路由到 Channel2。 374 | 375 | ### Load Balance: 负载均衡 376 | 377 | Load balancing Sink Processor 能够实现 load balance 功能,上图 Agent1 是一个路由节点,负责将 Channel 暂存的 Event 均衡到对应的多个 Sink 组件上,而每个 Sink 组件分别连 接到一个独立的 Agent 上,示例配置,如下所示: 378 | 379 | ``` 380 | a1.sinkgroups = g1 381 | a1.sinkgroups.g1.sinks = k1 k2 k3 382 | a1.sinkgroups.g1.processor.type = load_balance 383 | a1.sinkgroups.g1.processor.backoff = true 384 | a1.sinkgroups.g1.processor.selector = round_robin 385 | a1.sinkgroups.g1.processor.selector.maxTimeOut=10000 386 | ``` 387 | 388 | Failover Sink Processor 能够实现 failover 功能,具体流程类似 load balance,但是内部处理机制与 load balance 完全不同:Failover Sink Processor 维护一个优先级 Sink 组件列表,只要有一个 Sink 组件可用,Event 就被传递到下一个组件。如果一个 Sink 能够成功处理 Event,则会加入到一个 Pool 中,否则会被移出 Pool 并计算失败次数,设置一个惩罚因子,示例配置如下所示: 389 | 390 | ``` 391 | a1.sinkgroups = g1 392 | a1.sinkgroups.g1.sinks = k1 k2 k3 393 | a1.sinkgroups.g1.processor.type = failover 394 | a1.sinkgroups.g1.processor.priority.k1 = 5 395 | a1.sinkgroups.g1.processor.priority.k2 = 7 396 | a1.sinkgroups.g1.processor.priority.k3 = 6 397 | a1.sinkgroups.g1.processor.maxpenalty = 20000 398 | ``` 399 | -------------------------------------------------------------------------------- /04~日志聚合/Flume/组件类型.md: -------------------------------------------------------------------------------- 1 | # Flume 中的组件类型 2 | 3 | # Source 4 | 5 | | **Source 类型** | **说明** | 6 | | -------------------------- | ------------------------------------------------------------ | 7 | | Avro Source | 支持 Avro 协议(实际上是 Avro RPC),内置支持 | 8 | | Thrift Source | 支持 Thrift 协议,内置支持 | 9 | | Exec Source | 基于 Unix 的 command 在标准输出上生产数据 | 10 | | JMS Source | 从 JMS 系统(消息、主题)中读取数据,ActiveMQ 已经测试过 | 11 | | Spooling Directory Source | 监控指定目录内数据变更 | 12 | | Twitter 1% firehose Source | 通过 API 持续下载 Twitter 数据,试验性质 | 13 | | Netcat Source | 监控某个端口,将流经端口的每一个文本行数据作为 Event 输入 | 14 | | Sequence Generator Source | 序列生成器数据源,生产序列数据 | 15 | | Syslog Sources | 读取 syslog 数据,产生 Event,支持 UDP 和 TCP 两种协议 | 16 | | HTTP Source | 基于 HTTP POST 或 GET 方式的数据源,支持 JSON、BLOB 表示形式 | 17 | | Legacy Sources | 兼容老的 Flume OG 中 Source(0.9.x 版本) | 18 | 19 | # Channel 20 | 21 | | **Channel 类型** | **说明** | 22 | | -------------------------- | ---------------------------------------------------------------------------------------------------- | 23 | | Memory Channel | Event 数据存储在内存中 | 24 | | JDBC Channel | Event 数据存储在持久化存储中,当前 Flume Channel 内置支持 Derby | 25 | | File Channel | Event 数据存储在磁盘文件中 | 26 | | Spillable Memory Channel | Event 数据存储在内存中和磁盘上,当内存队列满了,会持久化到磁盘文件(当前试验性的,不建议生产环境使用) | 27 | | Pseudo Transaction Channel | 测试用途 | 28 | | Custom Channel | 自定义 Channel 实现 | 29 | 30 | # Sink 31 | 32 | | **Sink 类型** | **说明** | 33 | | ------------------- | ------------------------------------------------------ | 34 | | HDFS Sink | 数据写入 HDFS | 35 | | Logger Sink | 数据写入日志文件 | 36 | | Avro Sink | 数据被转换成 Avro Event,然后发送到配置的 RPC 端口上 | 37 | | Thrift Sink | 数据被转换成 Thrift Event,然后发送到配置的 RPC 端口上 | 38 | | IRC Sink | 数据在 IRC 上进行回放 | 39 | | File Roll Sink | 存储数据到本地文件系统 | 40 | | Null Sink | 丢弃到所有数据 | 41 | | HBase Sink | 数据写入 HBase 数据库 | 42 | | Morphline Solr Sink | 数据发送到 Solr 搜索服务器(集群) | 43 | | ElasticSearch Sink | 数据发送到 Elastic Search 搜索服务器(集群) | 44 | | Kite Dataset Sink | 写数据到 Kite Dataset,试验性质的 | 45 | | Custom Sink | 自定义 Sink 实现 | 46 | -------------------------------------------------------------------------------- /04~日志聚合/README.md: -------------------------------------------------------------------------------- 1 | # 日志聚合 2 | 3 | 日志是系统中发生的事件,是来自系统的详细的优先级消息。日志最大缺点是处理、存储和运输的成本高。它们包含发生在系统中的每个请求的数据。如果你在数百台服务器上运行应用程序,则需要将它们小心地汇聚到一个中心位置,否则无法在每一台服务器上查看它们。 4 | 5 | 类似 SLF4J、log4j、log4net 这样的库(根据你所使用的技术栈有很多选项)用于创建格式化的纯文本日志。最常见的应用程序日志传送方式是将它们写入到磁盘上的文件,然后使用 FileBeat 等工具将它们发送到 ELK。但是应用程序也可以将日志直接发送到日志聚合器。 6 | 7 | Docker 添加了一项功能,将日志发送到中心日志存储库,如 ELK 技术栈。我知道的大多数中央日志存储库都支持 Graylog 扩展日志格式(GELF),我想这就是 docker 引擎的传输方式。 8 | -------------------------------------------------------------------------------- /04~日志聚合/系统设计/多租户隔离.md: -------------------------------------------------------------------------------- 1 | # 多租户隔离 2 | 3 | 然而日志采集并不仅仅是单一用户/应用需要完成的工作,例如一个典型的服务器上需要采集的日志数据有:资源类 Metric 数据、系统监控日志、Nginx 访问数据、中间件请求数据、安全审计日志、各类应用中各个不同组件的日志等等;如果应用 docker 话,保守估计一个 docker 内的应用有 6-7 类日志,一台物理机运行 50 个 docker,那即使采集 docker 内的日志就有 300 多种配置。 4 | 5 | 多租户隔离技术早在 20 世纪 60 年代的大型主机中就已经开始使用,发展到今天非常多的应用/系统都应用了该技术。在每种不同的应用/系统中对于多租户隔离都有不同的诠释。 6 | 7 | 首先需要搞清楚日志采集场景下的多租户隔离需具备哪些特性,这里我们总结以下 5 点:隔离性、公平性、可靠性、可控性、性价比 8 | 9 | 隔离性:多租户隔离最基本特性,多个采集工作之间互不影响,部分采集配置阻塞不影响其他正常采集 10 | 公平性:保证各个阶段(读取、处理、发送)多个配置之间的公平性,不能因为某个配置下日志写入量大而导致其他配置被处理的概率降低 11 | 可靠性:无论在何种场景,可靠性都至关重要,多租户隔离下,如果部分采集阻塞,agent 可以暂停该配置采集,但恢复时需尽可能保证数据不丢失 12 | 可控性:可控性主要体现在资源和行为的可控,agent 需要具备控制各个配置的资源占用在合理范围,并且具备控制采集速率、暂停/开启等行为 13 | 性价比:以上特性最终方案实现时最需要关注的就是性价比,如何在尽可能少的资源占用情况下实现尽可能优的多租户隔离方案才是技术可行性与适用性的关键 14 | 15 | | | logstash | fluentd | filebeat | 16 | | ------ | ------------------------------------------------ | -------------------------------------------- | ------------------------------------ | 17 | | 隔离性 | 每个配置至少 1 个线程,独立的可持久化队列 | 每个配置至少 1 个线程,独立的可持久化队列 | 每个配置若干 go runtime,独立队列 | 18 | | 公平性 | 各配置间无协调,基于多线程调度 | 各配置间无协调,基于多线程调度 | 各配置间无协调,基于 go runtime 调度 | 19 | | 可靠性 | 基于可持久化队列缓存保证 | 基于可持久化队列缓存保证 | 队列满后停止采集 | 20 | | 可控性 | 可控制持久化队列资源,删除配置停采,支持远程配置 | 可控制持久化队列资源,删除配置停采,本地配置 | 可控制队列资源占用,删除配置停采 | 21 | | 性价比 | 较低 | 较低 | 较高 | 22 | 23 | Logstash、Fluentd 和 Filebeat 都属于 pipeline 的架构,根据语言不同,分别使用独立的线程/go runtime 实现了 pipeline 功能,每个 pipeline 内部顺序执行,各个 pipeline 间互相独立运行,此种方式隔离性较好,实现较为简单,在小规模场景下较为适用。然而随着配置数量增长,相应的线程数/go runtime 呈等比上升,在采集配置较多的情况下资源难以控制;而且由于各个 pipeline 间完全依赖底层(操作系统/go runtime)调度,当 CPU 资源无法全部满足时,数据量较高的配置会占用较多的执行时间,导致其他数据较少的配置获取资源的概率降低。 24 | -------------------------------------------------------------------------------- /04~日志聚合/系统设计/采集与调度.md: -------------------------------------------------------------------------------- 1 | # 采集与调度 2 | 3 | # 基于时间片的采集 4 | 5 | 业界主流的 Agent 对于每个配置会分配独立的线程/go runtime 来进行数据读取,但是单线程足以完成所有配置的事件处理以及数据读取,数据读取的瓶颈并不在于计算而是磁盘,对于正常的服务器,每秒基本不可能产生超过 100MB 的日志,而 logtail 数据读取线程可完成每秒 200MB 以上的数据读取(SSD 速率可以更高)。单线程的另一个优势是可以使事件处理和数据读取在无锁环境下运行,相对多线程处理性价比较高。 6 | 7 | ![基于时间片的采集](http://5b0988e595225.cdn.sohucs.com/q_70,c_zoom,w_640/images/20171119/62c74f5dcc96470394f69e00160887bf.webp) 8 | 9 | # 多级高低水位反馈队列 10 | 11 | 基于时间片的采集调度保证了各个配置的日志在数据读取时得到公平的调度,满足了多租户隔离中基本的公平性,但对于隔离性并未起到帮助作用。例如当部分采集配置因处理复杂或网络异常等原因阻塞时,阻塞配置依然会进行处理,最终会导致队列到达上限而阻塞数据读取线程,影响其他正常配置。 12 | 13 | ![多级高低水位反馈队列](http://5b0988e595225.cdn.sohucs.com/q_70,c_zoom,w_640/images/20171119/8f741176284d486e9394fd9691e17f56.webp) 14 | 15 | 这里的多级指的是处理过程的多级,即各个处理过程间会有一个这样的队列且相邻队列互相关联 16 | 17 | 例如在 Logtail 的数据读取、处理、发送流程中需要在读取->解析以及解析->发送间各自设置一个这样的队列 18 | 19 | 高低水位: 20 | 21 | 单一队列中设置了高低两个水位 22 | 23 | 当队列增长到高水位时,停止非紧急数据写入(例如进程重启时、数据拆分等特殊情况允许写入) 24 | 25 | 当队列从高水位消费到低水位时,再次允许写入 26 | 27 | 反馈: 28 | 29 | 反馈分为同步和异步两种 30 | 31 | 在准备读取当前队列数据时会同步检查下一级队列状态,当下级队列到达高水位时跳过此队列 32 | 33 | 当前队列从高水位消费到低水位时,异步通知关联的前一级队列 34 | 35 | ![](http://5b0988e595225.cdn.sohucs.com/q_70,c_zoom,w_640/images/20171119/502ceb2c24c540d1ab53762bb2266e54.webp) 36 | 37 | 由于多个配置存在,所以我们会为每个配置创建一组队列,每个队列使用指针数组实现,每一级中所有配置队列公用一个锁,对于性能以及内存消耗较为友好。Logtail 中的多级高低水位反馈队列结构如下: 38 | 39 | ![](http://5b0988e595225.cdn.sohucs.com/q_70,c_zoom,w_640/images/20171119/17766d48b23947728f5eab578604d91b.webp) 40 | 41 | 我们以日志解析这个步骤的工作方式来观察多级反馈队列的行为: 42 | 43 | 初始状态下解析线程处理 Wait 状态,当有数据到达或下一级发送线程某一配置的队列从高水位消费到低水位时,进入 FindJob 状态; 44 | 45 | FindJob 会从上一次处理的队列位置顺序查找当前有数据且下一级队列可以写入的队列,若查找到则进行 Process 状态,否则进行 Wait 状态; 46 | 47 | Process 对于当前 job 解析完后,判断该 job 所属队列是否从高水位到达低水位,若是则进入 Feedback 状态,否则回到 FindJob 查找下一个有效 job; 48 | 49 | Feedback 状态会向关联的上一级队列发送信号,参数携带当前队列 ID,用以触发上一级流程运行,信号发送完毕后进入 FindJob 状态; 50 | 51 | 基于多级高低水位反馈队列的处理过程中,当遇到下一级阻塞的队列时直接跳过,防止因阻塞 Job 的处理导致线程阻塞,具有较高的隔离性;FindJob 会记录上一次查找的队列 ID,下次查找时会从该 ID 之后的队列开始,保证了各个配置间调度的公平性。 52 | 53 | # 流控以及阻塞处理 54 | 55 | 上一节的多级高低水位反馈队列解决了多配置间的隔离性和公平性问题,但对于可控性以及可靠性方面还存在一些问题。例如: 56 | 57 | 无法精确控制每个配置的的采集流量,只能通过删除采集配置停止采集 58 | 59 | 如果某一配置完全阻塞时,当该配置关联日志文件轮转,恢复阻塞时将丢失轮转前的数据 60 | 61 | 这里主要包括三个部分:事件处理、数据读取逻辑以及数据发送控制: 62 | 63 | 事件处理与数据读取无关,即使读取关联的队列满也照常处理,这里的处理主要是更新文件 meta、将轮转文件放入轮转队列,具体可查看上一篇文章;此种方式可保证即使在配置阻塞/暂停的情况下依然保证及时文件轮转也不会丢失数据; 64 | 65 | 当配置关联的解析队列满时,如果将事件重新放回队列尾,则会造成较多的无效调度,使 CPU 空转。因此我们在遇到解析队列满时,将该事件放到一个专门的 blocked 队列中,当解析队列异步反馈时重新将 blocked 队列中的数据放回事件队列; 66 | 67 | Sender 中每个配置的队列关联一个 SenderInfo,SenderInfo 中记录该配置当前网络是否正常、Quota 是否正常以及最大允许的发送速率。每次 Sender 会根据 SenderInfo 中的状从队列中取数据,这里包括:网络失败重试、Quota 超限重试、状态更新、流控等逻辑 68 | -------------------------------------------------------------------------------- /05~SRE/99~参考资料/2020~《站点可靠性工作手册》/README.md: -------------------------------------------------------------------------------- 1 | # [站点可靠性工作手册](https://github.com/redbearder/The-Site-Reliability-Workbook-CHS/tree/master) 2 | -------------------------------------------------------------------------------- /05~SRE/API 安全/README.md: -------------------------------------------------------------------------------- 1 | # API 安全 2 | -------------------------------------------------------------------------------- /05~SRE/Linux 安全加固/Linux 安全加固.md: -------------------------------------------------------------------------------- 1 | # Linux 安全加固 2 | -------------------------------------------------------------------------------- /05~SRE/README.md: -------------------------------------------------------------------------------- 1 | # SRE 2 | 3 | 最早讨论 SRE 来源于 Google 这本书《Site Reliability Engineering: How Google Runs Production Systems》。由 Google SRE 关键成员分享他们是如何对软件进行生命周期的整体性关注,以及为什么这样做能够帮助 Google 成功地构建、部署、监控和运维世界上现存最大的软件系统。 4 | 5 | 可了解到 SRE 的定义: 6 | 7 | > Site reliability engineering (SRE) is a discipline that incorporates aspects of software engineering and applies them to infrastructure and operations problems. The main goals are to create scalable and highly reliable software systems. 8 | 9 | 其中有句形象描述 SRE 工作的描述: 10 | 11 | > SRE is "what happens when a software engineer is tasked with what used to be called operations." 12 | 13 | 即 SRE 的目标是构建可扩展和高可用的软件系统,通过软件工程的方法解决基础设施和操作相关的问题。在 Google SRE 书中,对 SRE 日常工作状态有个准确的描述:至多 50% 的时间精力处理操作相关事宜,50% 以上的精力通过软件工程保障基础设施的稳定性和可扩展性。 14 | 15 | 基于上述描述,我对 SRE 的理解是: 16 | 17 | - 职责:保障基础设施的稳定性和可扩展性 18 | - 核心:解决问题 19 | - 方法:通过操作类事务积累问题经验,通过编码等方式提升问题的解决效率 20 | 21 | # Links 22 | 23 | - https://cubox.pro/c/cqFMWn 我对 SRE 的理解 24 | -------------------------------------------------------------------------------- /05~SRE/备份/README.md: -------------------------------------------------------------------------------- 1 | # 安全加固 2 | 3 | # 用户权限 4 | 5 | ```sh 6 | # 查询最近登录到系统的用户和系统重启的时间和日期 7 | $ last reboot | less 8 | ``` 9 | 10 | # Links 11 | 12 | - https://www.freebuf.com/articles/system/218407.html?hmsr=toutiao.io&utm_medium=toutiao.io&utm_source=toutiao.io 最全 Linux 应急响应技巧 13 | -------------------------------------------------------------------------------- /05~SRE/备份/文件备份.md: -------------------------------------------------------------------------------- 1 | # 系统安全加固中的文件备份 2 | 3 | # 文件备份 4 | 5 | 在每月第一天备份并压缩/etc 目录的所有内容,存放在/root/bak 目录里,且文件名为如下形式 yymmdd_etc,yy 为年,mm 为月,dd 为日。 6 | 7 | ```sh 8 | #!/bin/sh 9 | DIRNAME=`ls /root | grep bak` 10 | if [ -z "$DIRNAME" ] ; then 11 | mkdir /root/bak 12 | cd /root/bak 13 | fi 14 | YY=`date +%y` 15 | MM=`date +%m` 16 | DD=`date +%d` 17 | BACKETC=$YY$MM$DD_etc.tar.gz 18 | tar zcvf $BACKETC /etc 19 | echo “fileback finished!” 20 | ``` 21 | 22 | 编写任务定时器: 23 | 24 | ```sh 25 | echo “0 0 1 * * /bin/sh /usr/bin/fileback” >; /root/etcbakcron 26 | crontab /root/etcbakcron 27 | 或使用crontab -e 命令添加定时任务: 28 | 0 1 * * * /bin/sh /usr/bin/fileback 29 | ``` 30 | -------------------------------------------------------------------------------- /05~SRE/零信任/README.md: -------------------------------------------------------------------------------- 1 | # 零信任架构 2 | 3 | # Links 4 | 5 | - [零信任实践分享](https://ckev.in/j/ztcn/): 本文的笔者是陈志杰,2015 至 2020 年有幸参与了谷歌生产环境零信任(Zero Trust in Production Environments)的理论和实践。在此背景下开发的 Binary Authorization for Borg (BAB) 系统已经在谷歌生产环境中实现了全面覆盖:任何人在生产环境中以任何服务的身份运行任何软件包之前,都必须为目标服务建立一个足够强的 BAB 安全策略。不符合 BAB 安全策略的程序将不会被允许以相应服务的身份运行。[ ] 6 | 7 | - https://www.infoq.cn/article/9k4PmXl3GLiXh6LOQWMU 读懂零信任:起源、发展与架构 8 | -------------------------------------------------------------------------------- /99~参考资料/2020~Devops Basics/README.md: -------------------------------------------------------------------------------- 1 | 这个仓库 [devops-basics](https://github.com/tungbq/devops-basics) 是一个全面的 DevOps 工具链学习资源集合。以下是对该仓库的总结: 2 | 3 | 1. 目的:为 DevOps 新手和有经验的工程师提供实用的文档和实践场所,帮助提升 DevOps 技能。 4 | 5 | 2. 主要特点: 6 | 7 | - 涵盖广泛:包含 30 多个重要的 DevOps 主题,如 Docker、Kubernetes、Terraform、Ansible 等。 8 | - 资源丰富:每个主题都提供概述、官方文档链接、速查表和额外资源。 9 | - 实践导向:提供基础示例和高级示例,便于动手实践。 10 | - 持续更新:仓库保持活跃,定期添加新内容。 11 | 12 | 3. 结构组织: 13 | 14 | - 按主题分类,每个主题都有独立的文件夹。 15 | - 包含 README、基础示例、高级示例和其他相关资源。 16 | 17 | 4. 主要内容: 18 | 19 | - 容器技术:Docker、Kubernetes、Helm 20 | - 配置管理:Ansible、Terraform 21 | - CI/CD:Jenkins、GitHub Actions、GitLab CI 22 | - 云服务:AWS、Azure、OpenStack 23 | - 监控和日志:ELK Stack、Prometheus 24 | - 编程语言:Python、Groovy、Shell 脚本 25 | - 架构和设计:微服务、系统架构 26 | - 其他工具:Git、Nginx、HAProxy、Kafka 等 27 | 28 | 5. 社区参与: 29 | 30 | - 鼓励贡献,提供详细的贡献指南。 31 | - 有活跃的 issue 和 pull request。 32 | 33 | 6. 额外资源: 34 | 35 | - 提供相关的其他仓库链接,如 devops-practice 和 devops-project。 36 | - 包含其他优质 DevOps 学习资源的链接。 37 | 38 | 7. 受欢迎程度: 39 | - 拥有 1.6k 星标,表明受到社区的广泛认可。 40 | - 135 个 fork,显示有不少人在此基础上进行个人学习或开发。 41 | 42 | 总的来说,这个仓库是一个全面、实用的 DevOps 学习资源,适合各级别的 DevOps 工程师使用。它不仅提供了理论知识,还强调实践,并且保持持续更新,是一个值得关注和使用的 DevOps 学习平台。 43 | 44 | [Source](https://github.com/tungbq/devops-basics) 45 | -------------------------------------------------------------------------------- /INTRODUCTION.md: -------------------------------------------------------------------------------- 1 | # 本篇导读 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Creative Commons Legal Code 2 | 3 | CC0 1.0 Universal 4 | 5 | CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE 6 | LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN 7 | ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS 8 | INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES 9 | REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS 10 | PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM 11 | THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED 12 | HEREUNDER. 13 | 14 | Statement of Purpose 15 | 16 | The laws of most jurisdictions throughout the world automatically confer 17 | exclusive Copyright and Related Rights (defined below) upon the creator 18 | and subsequent owner(s) (each and all, an "owner") of an original work of 19 | authorship and/or a database (each, a "Work"). 20 | 21 | Certain owners wish to permanently relinquish those rights to a Work for 22 | the purpose of contributing to a commons of creative, cultural and 23 | scientific works ("Commons") that the public can reliably and without fear 24 | of later claims of infringement build upon, modify, incorporate in other 25 | works, reuse and redistribute as freely as possible in any form whatsoever 26 | and for any purposes, including without limitation commercial purposes. 27 | These owners may contribute to the Commons to promote the ideal of a free 28 | culture and the further production of creative, cultural and scientific 29 | works, or to gain reputation or greater distribution for their Work in 30 | part through the use and efforts of others. 31 | 32 | For these and/or other purposes and motivations, and without any 33 | expectation of additional consideration or compensation, the person 34 | associating CC0 with a Work (the "Affirmer"), to the extent that he or she 35 | is an owner of Copyright and Related Rights in the Work, voluntarily 36 | elects to apply CC0 to the Work and publicly distribute the Work under its 37 | terms, with knowledge of his or her Copyright and Related Rights in the 38 | Work and the meaning and intended legal effect of CC0 on those rights. 39 | 40 | 1. Copyright and Related Rights. A Work made available under CC0 may be 41 | protected by copyright and related or neighboring rights ("Copyright and 42 | Related Rights"). Copyright and Related Rights include, but are not 43 | limited to, the following: 44 | 45 | i. the right to reproduce, adapt, distribute, perform, display, 46 | communicate, and translate a Work; 47 | ii. moral rights retained by the original author(s) and/or performer(s); 48 | iii. publicity and privacy rights pertaining to a person's image or 49 | likeness depicted in a Work; 50 | iv. rights protecting against unfair competition in regards to a Work, 51 | subject to the limitations in paragraph 4(a), below; 52 | v. rights protecting the extraction, dissemination, use and reuse of data 53 | in a Work; 54 | vi. database rights (such as those arising under Directive 96/9/EC of the 55 | European Parliament and of the Council of 11 March 1996 on the legal 56 | protection of databases, and under any national implementation 57 | thereof, including any amended or successor version of such 58 | directive); and 59 | vii. other similar, equivalent or corresponding rights throughout the 60 | world based on applicable law or treaty, and any national 61 | implementations thereof. 62 | 63 | 2. Waiver. To the greatest extent permitted by, but not in contravention 64 | of, applicable law, Affirmer hereby overtly, fully, permanently, 65 | irrevocably and unconditionally waives, abandons, and surrenders all of 66 | Affirmer's Copyright and Related Rights and associated claims and causes 67 | of action, whether now known or unknown (including existing as well as 68 | future claims and causes of action), in the Work (i) in all territories 69 | worldwide, (ii) for the maximum duration provided by applicable law or 70 | treaty (including future time extensions), (iii) in any current or future 71 | medium and for any number of copies, and (iv) for any purpose whatsoever, 72 | including without limitation commercial, advertising or promotional 73 | purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each 74 | member of the public at large and to the detriment of Affirmer's heirs and 75 | successors, fully intending that such Waiver shall not be subject to 76 | revocation, rescission, cancellation, termination, or any other legal or 77 | equitable action to disrupt the quiet enjoyment of the Work by the public 78 | as contemplated by Affirmer's express Statement of Purpose. 79 | 80 | 3. Public License Fallback. Should any part of the Waiver for any reason 81 | be judged legally invalid or ineffective under applicable law, then the 82 | Waiver shall be preserved to the maximum extent permitted taking into 83 | account Affirmer's express Statement of Purpose. In addition, to the 84 | extent the Waiver is so judged Affirmer hereby grants to each affected 85 | person a royalty-free, non transferable, non sublicensable, non exclusive, 86 | irrevocable and unconditional license to exercise Affirmer's Copyright and 87 | Related Rights in the Work (i) in all territories worldwide, (ii) for the 88 | maximum duration provided by applicable law or treaty (including future 89 | time extensions), (iii) in any current or future medium and for any number 90 | of copies, and (iv) for any purpose whatsoever, including without 91 | limitation commercial, advertising or promotional purposes (the 92 | "License"). The License shall be deemed effective as of the date CC0 was 93 | applied by Affirmer to the Work. Should any part of the License for any 94 | reason be judged legally invalid or ineffective under applicable law, such 95 | partial invalidity or ineffectiveness shall not invalidate the remainder 96 | of the License, and in such case Affirmer hereby affirms that he or she 97 | will not (i) exercise any of his or her remaining Copyright and Related 98 | Rights in the Work or (ii) assert any associated claims and causes of 99 | action with respect to the Work, in either case contrary to Affirmer's 100 | express Statement of Purpose. 101 | 102 | 4. Limitations and Disclaimers. 103 | 104 | a. No trademark or patent rights held by Affirmer are waived, abandoned, 105 | surrendered, licensed or otherwise affected by this document. 106 | b. Affirmer offers the Work as-is and makes no representations or 107 | warranties of any kind concerning the Work, express, implied, 108 | statutory or otherwise, including without limitation warranties of 109 | title, merchantability, fitness for a particular purpose, non 110 | infringement, or the absence of latent or other defects, accuracy, or 111 | the present or absence of errors, whether or not discoverable, all to 112 | the greatest extent permissible under applicable law. 113 | c. Affirmer disclaims responsibility for clearing rights of other persons 114 | that may apply to the Work or any use thereof, including without 115 | limitation any person's Copyright and Related Rights in the Work. 116 | Further, Affirmer disclaims responsibility for obtaining any necessary 117 | consents, permissions or other rights required for any use of the 118 | Work. 119 | d. Affirmer understands and acknowledges that Creative Commons is not a 120 | party to this document and has no duty or obligation with respect to 121 | this CC0 or use of the Work. 122 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Contributors][contributors-shield]][contributors-url] 2 | [![Forks][forks-shield]][forks-url] 3 | [![Stargazers][stars-shield]][stars-url] 4 | [![Issues][issues-shield]][issues-url] 5 | [![license: CC BY-NC-SA 4.0](https://img.shields.io/badge/license-CC%20BY--NC--SA%204.0-lightgrey.svg)][license-url] 6 | 7 | 8 |
9 |

10 | 11 | Logo 12 | 13 | 14 |

DevOps Series

15 | 16 |

17 | 软件开发后:测试、部署、监控、运维 18 |
19 | 在线阅读 >> 20 |
21 |
22 | 速览手册 23 | · 24 | Report Bug 25 | · 26 | 参考资料 27 |

28 |

29 | 30 | 31 | 32 | # Introduction | 前言 33 | 34 | ![概念图](https://assets.ng-tech.icu/item/20230417211711.png) 35 | 36 | DevOps 与 SRE 实战涵盖了笔者对于大型软件系统开发与运维工程中的偏交付、运维向的知识沉淀。DevOps 的出现,运维的身份职责发生了转变,它不再是专门跑任务脚本或者与机器打交道的人,而是变成了 OpenStack 或者 Kubernetes 的专家,通过搭建/管理相关的分布式集群,为研发提供可靠的应用运行环境。DevOps 更重要的方面还是改变了应用交付的流程,从传统的搭火车模式走向持续交付,应用的架构和形态改变了,其方法论也随之而改变。DevOps 和持续交付也被认为是云原生应用的要素。至于 AIOps 是 DevOps 在实践 AI 过程中的一些应用,称不上是范式的改变,AI 在运维领域还远远取代不了人的作用。 37 | 38 | > 本书的精排目录导航版请参考 [https://ng-tech.icu/books/DevOps-Notes](https://ng-tech.icu/books/DevOps-Notes)。 39 | 40 | ## 背景分析 41 | 42 | 分布式架构解决了互联网应用吞吐量的瓶颈;越来越成熟的分布式中间件也屏蔽了分布式系统的复杂度,提升了开发工程师的工作效率;自动化运维工具则提升了运维工程师的工作效率。但是,由于目标不同,在固有的将开发和运维划分为不同部门的组织结构中,部门之间的配合并不总是很默契的。开发部门的驱动力通常是频繁交付新特性,而运维部门则更关注服务的可靠性。两者目标的不匹配使得部门之间产生了鸿沟,从而降低了业务交付的速度与价值。 43 | 44 | 直到 DevOps 方法论出现,开发与运维之间的鸿沟才得以渐渐消失;通常,影响一个项目的三个因素分别是速度(时间)、可靠性和成本。开发需要有按时交付的速度,而运营需要有可靠性。DevOps 可以保证以低成本的方式实现速度和可靠性,帮助开发工程师和运维工程师在实现各自目标的前提下,向最终用户交付价值最大化、质量最高的成果的一系列基本原则。DevOps 在软件开发和交付流程中强调“在产品管理、软件开发以及运维之间进行沟通与协作”。DevOps 是一种使持续交付成为可能的理念,关注于所有人共同协作以改进开发效率方面的衡量(比如生产力),同时增加稳定性并降低平均故障修复时间。 45 | 46 | ![DevOps 概念释义](https://pic1.imgdb.cn/item/635f68bc16f2c2beb1f5515c.jpg) 47 | 48 | DevOps 是一种公司文化的变迁,它代表了开发、运维和测试等环节之间的协作,因此多种工具可以组成一个完整的 DevOps 工具链。Chef 的创始人 Adam Jacob 将 DevOps 定义为一种文化和专业的运动。DevOps 会涉及到各种模式,包括:持续改进、组织文化、学习曲线、持续交付、持续学习、持续协作和自动化: 49 | 50 | - 价值流,它指一个组织针对客户的需求所执行的各项交付活动的顺序。也就是指你如何把一个想法最终变现的过程。 51 | - 交付时间,它指价值流从开始到结束,全程转化的耗时。一般情况下,交付时间是指呈现到客户眼前所花费的时间。 52 | - 周期时间,它始于按照需求所开展的工作,终于准备好交付项目的时候。 53 | - 交付时间的掌控能力,意味着我们对 DevOps 的运用水平。 54 | - 部署交付时间,反映了我们在自动化方面的水平。 55 | 56 | 由此可见,组织应遵循 DevOps 的模式和实践方式,以减少交付的时间。他们完全可以从中选取诸如:放大反馈或加强持续学习文化等一个或多个适合自身的 DevOps 方法。GitOps 被认为是下一代的 DevOps,让运维工作变得与写代码的方式一样,将 Git 仓库作为运维工作的“the single source of truth”,这对于多云、混合云和多集群部署是非常有价值的。Git 所具备的版本管理能力让运维工作变得更加可溯与可控。总的说来,易用性解决的是软件开发效率、工程质量和人力成本问题。 57 | 58 | ![DevOps 全回环](https://s3.ax1x.com/2020/12/22/rrB2NQ.png) 59 | 60 | # Nav | 关联导航 61 | 62 | ![思维脑图](https://assets.ng-tech.icu/item/20230417211728.png) 63 | 64 | - 如果您想搭建 APM 监控体系,那么建议阅读[监控体系](./监控体系)系列章节。 65 | 66 | # About | 关于 67 | 68 | 69 | 70 | ## Contributing 71 | 72 | Contributions are what make the open source community such an amazing place to be learn, inspire, and create. Any contributions you make are **greatly appreciated**. 73 | 74 | 1. Fork the Project 75 | 2. Create your Feature Branch (`git checkout -b feature/AmazingFeature`) 76 | 3. Commit your Changes (`git commit -m 'Add some AmazingFeature'`) 77 | 4. Push to the Branch (`git push origin feature/AmazingFeature`) 78 | 5. Open a Pull Request 79 | 80 | 81 | 82 | ## Acknowledgements 83 | 84 | - [Awesome-Lists](https://github.com/wx-chevalier/Awesome-Lists): 📚 Guide to Galaxy, curated, worthy and up-to-date links/reading list for ITCS-Coding/Algorithm/SoftwareArchitecture/AI. 💫 ITCS-编程/算法/软件架构/人工智能等领域的文章/书籍/资料/项目链接精选。 85 | 86 | - [Awesome-CS-Books](https://github.com/wx-chevalier/Awesome-CS-Books): :books: Awesome CS Books/Series(.pdf by git lfs) Warehouse for Geeks, ProgrammingLanguage, SoftwareEngineering, Web, AI, ServerSideApplication, Infrastructure, FE etc. :dizzy: 优秀计算机科学与技术领域相关的书籍归档。 87 | 88 | ## Copyright & More | 延伸阅读 89 | 90 | 笔者所有文章遵循[知识共享 署名 - 非商业性使用 - 禁止演绎 4.0 国际许可协议](https://creativecommons.org/licenses/by-nc-nd/4.0/deed.zh),欢迎转载,尊重版权。您还可以前往 [NGTE Books](https://ng-tech.icu/books-gallery/) 主页浏览包含知识体系、编程语言、软件工程、模式与架构、Web 与大前端、服务端开发实践与工程架构、分布式基础架构、人工智能与深度学习、产品运营与创业等多类目的书籍列表: 91 | 92 | [![NGTE Books](https://s2.ax1x.com/2020/01/18/19uXtI.png)](https://ng-tech.icu/books-gallery/) 93 | 94 | 95 | 96 | 97 | [contributors-shield]: https://img.shields.io/github/contributors/wx-chevalier/DevOps-Notes.svg?style=flat-square 98 | [contributors-url]: https://github.com/wx-chevalier/DevOps-Notes/graphs/contributors 99 | [forks-shield]: https://img.shields.io/github/forks/wx-chevalier/DevOps-Notes.svg?style=flat-square 100 | [forks-url]: https://github.com/wx-chevalier/DevOps-Notes/network/members 101 | [stars-shield]: https://img.shields.io/github/stars/wx-chevalier/DevOps-Notes.svg?style=flat-square 102 | [stars-url]: https://github.com/wx-chevalier/DevOps-Notes/stargazers 103 | [issues-shield]: https://img.shields.io/github/issues/wx-chevalier/DevOps-Notes.svg?style=flat-square 104 | [issues-url]: https://github.com/wx-chevalier/DevOps-Notes/issues 105 | [license-shield]: https://img.shields.io/github/license/wx-chevalier/DevOps-Notes.svg?style=flat-square 106 | [license-url]: https://github.com/wx-chevalier/DevOps-Notes/blob/master/LICENSE.txt 107 | -------------------------------------------------------------------------------- /_sidebar.md: -------------------------------------------------------------------------------- 1 | - 1 00~DevOps 文化 [1] 2 | - 1.1 99~参考资料 [2] 3 | - [1.1.1 万字长文带你彻底搞懂什么是 DevOps](/00~DevOps%20文化/99~参考资料/2021-万字长文带你彻底搞懂什么是%20DevOps.md) 4 | - [1.1.2 必致(BizDevOps)](/00~DevOps%20文化/99~参考资料/2023-必致(BizDevOps).md) 5 | - [2 01~持续集成与交付 [4]](/01~持续集成与交付/README.md) 6 | - 2.1 CI [1] 7 | - [2.1.1 CI](/01~持续集成与交付/CI/CI.md) 8 | - [2.2 交付规范 [1]](/01~持续集成与交付/交付规范/README.md) 9 | - [2.2.1 交付系统要求](/01~持续集成与交付/交付规范/交付系统要求.md) 10 | - 2.3 变更与发布 [2] 11 | - [2.3.1 多策略部署](/01~持续集成与交付/变更与发布/多策略部署.md) 12 | - [2.3.2 风险评估](/01~持续集成与交付/变更与发布/风险评估.md) 13 | - 2.4 平台工具 [3] 14 | - [2.4.1 Jenkins](/01~持续集成与交付/平台工具/Jenkins/README.md) 15 | 16 | - [2.4.2 Spinnaker [1]](/01~持续集成与交付/平台工具/Spinnaker/README.md) 17 | - [2.4.2.1 部署配置](/01~持续集成与交付/平台工具/Spinnaker/部署配置.md) 18 | - [2.4.3 Tekton](/01~持续集成与交付/平台工具/Tekton/README.md) 19 | 20 | - [3 02~自动化运维 [5]](/02~自动化运维/README.md) 21 | - [3.1 AIOps](/02~自动化运维/AIOps/README.md) 22 | 23 | - [3.2 设施即代码 [2]](/02~自动化运维/设施即代码/README.md) 24 | - [3.2.1 Pulumi](/02~自动化运维/设施即代码/Pulumi.md) 25 | - [3.2.2 Terraform](/02~自动化运维/设施即代码/Terraform.md) 26 | - 3.3 设计理念 [3] 27 | - [3.3.1 体系设计](/02~自动化运维/设计理念/体系设计.md) 28 | - [3.3.2 场景分析](/02~自动化运维/设计理念/场景分析.md) 29 | - [3.3.3 流水线即代码](/02~自动化运维/设计理念/流水线即代码.md) 30 | - [3.4 运维脚本 [1]](/02~自动化运维/运维脚本/README.md) 31 | - [3.4.1 数据库](/02~自动化运维/运维脚本/数据库.md) 32 | - [3.5 运行成本](/02~自动化运维/运行成本/README.md) 33 | 34 | - [4 03~监控告警 [5]](/03~监控告警/README.md) 35 | - [4.1 APM](/03~监控告警/APM/README.md) 36 | 37 | - [4.2 全链路监控](/03~监控告警/全链路监控/README.md) 38 | 39 | - 4.3 开源监控系统 [1] 40 | - [4.3.1 SkyWalking](/03~监控告警/开源监控系统/SkyWalking/README.md) 41 | 42 | - [4.4 监控指标 [5]](/03~监控告警/监控指标/README.md) 43 | - [4.4.1 实践案例](/03~监控告警/监控指标/实践案例/README.md) 44 | 45 | - [4.4.2 程序指标 [3]](/03~监控告警/监控指标/程序指标/README.md) 46 | - [4.4.2.1 响应时延](/03~监控告警/监控指标/程序指标/响应时延.md) 47 | - [4.4.2.2 应用](/03~监控告警/监控指标/程序指标/应用.md) 48 | - [4.4.2.3 服务吞吐量](/03~监控告警/监控指标/程序指标/服务吞吐量.md) 49 | - [4.4.3 系统指标 [4]](/03~监控告警/监控指标/系统指标/README.md) 50 | - 4.4.3.1 CPU [6] 51 | - [4.4.3.1.1 CPU](/03~监控告警/监控指标/系统指标/CPU/CPU.md) 52 | - [4.4.3.1.2 perf 与火焰图 [1]](/03~监控告警/监控指标/系统指标/CPU/perf%20与火焰图/README.md) 53 | - [4.4.3.1.2.1 火焰图解析](/03~监控告警/监控指标/系统指标/CPU/perf%20与火焰图/火焰图解析.md) 54 | - [4.4.3.1.3 sar](/03~监控告警/监控指标/系统指标/CPU/sar.md) 55 | - [4.4.3.1.4 stat](/03~监控告警/监控指标/系统指标/CPU/stat.md) 56 | - [4.4.3.1.5 top](/03~监控告警/监控指标/系统指标/CPU/top.md) 57 | - [4.4.3.1.6 中间件](/03~监控告警/监控指标/系统指标/CPU/中间件.md) 58 | - 4.4.3.2 内存 [1] 59 | - [4.4.3.2.1 内存](/03~监控告警/监控指标/系统指标/内存/内存.md) 60 | - [4.4.3.3 磁盘 [1]](/03~监控告警/监控指标/系统指标/磁盘/README.md) 61 | - [4.4.3.3.1 fio](/03~监控告警/监控指标/系统指标/磁盘/fio.md) 62 | - 4.4.3.4 网络 [1] 63 | - [4.4.3.4.1 网络](/03~监控告警/监控指标/系统指标/网络/网络.md) 64 | - 4.4.4 统计与告警策略 [2] 65 | - [4.4.4.1 异常检测](/03~监控告警/监控指标/统计与告警策略/异常检测.md) 66 | - [4.4.4.2 统计与告警策略](/03~监控告警/监控指标/统计与告警策略/统计与告警策略.md) 67 | - [4.4.5 黄金指标](/03~监控告警/监控指标/黄金指标/README.md) 68 | 69 | - [4.5 监控系统设计 [3]](/03~监控告警/监控系统设计/README.md) 70 | - [4.5.1 存储设计](/03~监控告警/监控系统设计/存储设计.md) 71 | - [4.5.2 监控系统对比](/03~监控告警/监控系统设计/监控系统对比.md) 72 | - [4.5.3 采集设计](/03~监控告警/监控系统设计/采集设计.md) 73 | - [5 04~日志聚合 [3]](/04~日志聚合/README.md) 74 | - [5.1 ELK](/04~日志聚合/ELK/README.md) 75 | 76 | - [5.2 Flume [2]](/04~日志聚合/Flume/README.md) 77 | - [5.2.1 安装与配置](/04~日志聚合/Flume/安装与配置.md) 78 | - [5.2.2 组件类型](/04~日志聚合/Flume/组件类型.md) 79 | - 5.3 系统设计 [2] 80 | - [5.3.1 多租户隔离](/04~日志聚合/系统设计/多租户隔离.md) 81 | - [5.3.2 采集与调度](/04~日志聚合/系统设计/采集与调度.md) 82 | - [6 05~SRE [4]](/05~SRE/README.md) 83 | - [6.1 API 安全](/05~SRE/API%20安全/README.md) 84 | 85 | - 6.2 Linux 安全加固 [2] 86 | - 6.2.1 99~参考资料 [2] 87 | - [6.2.1.1 Linux Hardening Guide](/05~SRE/Linux%20安全加固/99~参考资料/2022-Linux%20Hardening%20Guide.md) 88 | - [6.2.1.2 How To Secure A Linux Server](/05~SRE/Linux%20安全加固/99~参考资料/2023-How%20To%20Secure%20A%20Linux%20Server.md) 89 | - [6.2.2 Linux 安全加固](/05~SRE/Linux%20安全加固/Linux%20安全加固.md) 90 | - 6.3 备份 [1] 91 | - [6.3.1 文件备份](/05~SRE/备份/文件备份.md) 92 | - [6.4 零信任](/05~SRE/零信任/README.md) 93 | 94 | - [7 INTRODUCTION](/INTRODUCTION.md) -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Developer-Zero-To-Mastery 7 | 8 | 9 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 34 | 38 | 40 | 45 | 46 |
47 | 64 | 97 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 143 | 144 | 145 | 146 | 155 | 156 | 157 | --------------------------------------------------------------------------------