陈金窗 刘政委 张其栋 郑少斌
读完需要
20
分钟速读仅需 7 分钟
本文摘自于《Prometheus 监控技术与实战》一书,从云计算时代的业务特点出发,探讨了云计算监控的目标和挑战,梳理了云资源监控的范围及监控系统实现的一般方式。接着从开源监控软件的演进出发,简单介绍了 Zabbix、OpenTSDB 等常用监控系统。最后详细介绍 Prometheus 云原生监控系统的产生、发展、特点,以及成功部署可获得的运营优势。
1
云计算监控的目标和挑战
1.1
云计算监控目标
监控系统的目标是:提供对复杂信息系统的全面监控,反映云资源池的健康状况和可用性情况,得到一个可控制、可预测的云环境,支持云业务安全、稳定、高效、持续地运行;同时,有效地控制管理成本,规范管理工作,实现运行管理的智能化和高效性,提高整体的维护水平;及时掌握各种资源现状和运行信息,为决策提供支持。
监控是运维团队眼睛的延伸。监控系统应当解决三个问题:“出问题了吗?”“哪里出了问题?”“是什么问题?”
在《SRE:Google 运维解密》一书中指出,监控系统需要有效地支持白盒监控和黑盒监控。通过白盒监控能够了解其内部的实际运行状态,观察监控指标能够预判可能出现的问题,从而对潜在的不确定因素进行优化。而黑盒监控,常见的如 HTTP 探针、TCP 探针等,可以在系统或者服务发生故障时快速通知相关人员进行处理。通过建立完善的监控体系,可以达到以下目的。
长期趋势分析:通过对监控样本数据的持续收集和统计,对监控指标进行长期趋势分析。例如,通过对磁盘空间增长率的判断,我们可以提前预测在未来什么时间节点上需要对资源进行扩容。
对照分析:两个版本的系统运行资源使用情况的差异如何?在不同容量情况下系统的并发和负载变化如何?通过监控能够方便地对系统进行跟踪和比较。
告警:当系统出现或者即将出现故障时,监控系统需要迅速反应并通知管理员,从而能够对问题进行快速处理或者提前预防问题的发生,避免对业务产生影响。
故障分析与定位:当问题发生后,需要对问题进行调查和处理。通过对比分析不同监控数据与历史数据,能够找到并解决根源问题。
数据可视化:通过可视化仪表盘能够直接获取系统的运行状态、资源使用情况,以及服务运行状态等直观的信息。
网站可靠性工程师 SRE(Site Reliability Engineer)的终极责任是确保该服务可以正常运转。为达成这个目标,SRE 定义了一套服务可靠性层级模型,需要完成开发监控系统、规划容量、处理紧急事件、确保事故根源被跟踪修复等一系列工作。
服务可靠性层级模型
监控系统是服务可靠性层级中的最底层。离开了监控系统,就没有能力辨别一个系统是否在正常提供服务。没有一套设计周全的监控体系就如同蒙着眼睛狂奔。作为一个合格的系统运维人员,需要先于用户发现系统中存在的问题。没有监控的支持,上层应急事件处理、事后总结/问题根因分析、测试+发布、容量规划、软件开发、产品设计也就没有了根基。
1.2
云计算监控挑战
要对基于现代基础设施的应用系统进行监控,将面临 DevOps 实践和基础架构代码化,监控系统将会迎接若干重大挑战。
挑战 1:持续变更
在运维中需要监测偏离正常行为的信号,这里所说的“正常行为”是假设系统已经稳定运行了很长时间。然而,在一个大型复杂环境中,变更是常态。这些变更来自于:
云计算的弹性,使得基础设施资源变得更灵活。
自动化的 DevOps 运维,触发很多零散的运维操作(例如升级、重配置、备份),零散的运维、持续部署和部署实践使得软件变更更加频繁。
持续变更中,监控的参数频繁变更,监控系统参数也经常需要随着变更。
系统基础设施和系统本身的持续变更使得监控参数的设置变得复杂。即使向相同的虚拟机提交请求,仍然存在巨大的性能差别。这些差别来自于你无法控制的因素,如你得到的 CPU 的类型。你的监控可能需要调整以适应这种变化,或者你可以配置缩放控制器,以便用新的虚拟机来代替性能下降或提升的虚拟机。
自动化设置警报、告警和阈值。监控配置过程是另一个 DevOps 过程,应该实现自动化。当提供一台新服务器时,应该在监控系统中自动注册这台服务器;当服务器停止使用时,应该自动触发注销流程。
挑战 2:自下而上还是自上而下
监控的主要目的是尽可能快地发现缺陷、错误或小规模的故障,以便能够尽早做出反应。我们很自然地采用了自下而上的方式进行监控:根据聚合值,低层中的错误和单个模块中的错误,可以在它们传播和影响到上层应用服务器或者应用本身之前被发现。这里要面临两个挑战:
需要监控越来越多的模块级别和其他低级别的内容。一个应用由多个组件组成,可能部署在上百台服务器上,依赖于网络和存储组件的支持。在实际环境中,把这些监控信息相关联并找到根源是非常困难的。
在云中,低层基础设施和服务器之间有正常和异常的分配,例如,服务器漂移的终止操作、伸缩以及滚动升级,或者实例失效或者资源共享不稳定等,导致监控服务器非常复杂。
采取自上而下的方法来监控基于云的和高度复杂的系统是解决以上问题的一种尝试,通过监控上层或者聚合数据,从顶层问题出发再以智能的方式深入低层数据。仍然必须收集低层数据,但不会系统化地监控错误。这种方式也面临挑战:
发现问题时可能为时已晚。当在上层注意到有错误时,阻止影响的扩大可能已经来不及了。
如何深入到低层数据。现代分布式系统有内置的容错机制来掩盖故障和错误,防止在系统层面出现问题直接影响用户体验,因此,检测到上层问题距离低层根本故障原因出现,可能已经过去相当长的一段时间了。
从最初发生故障到扩散到整个系统并变得明显,可能需要经过很长一段时间。不能简单地依赖上层错误检测的时间戳,也不能假设与原始问题相关的指标和日志还仍然存在,很可能随着网络的僵死一起消失。
挑战 3:复杂的微服务架构
在云环境中监控系统面临另一个挑战是对微服务架构的监控。每个微服务组件可能是一个独立部署,每个外部请求都可能要穿越大量内部服务才能得到响应。如果一个服务响应变慢,那么整个响应时间就会拉长。在微服务中识别并修复响应慢的节点,对于偶尔发生的性能问题。很难做到尽早确定。在具有大量节点的微服务架构中,如何在这些仍然工作的节点中找出响应慢的节点?如何定义“慢”?如何选择合适的阈值?
挑战 4:大容量的分布式数据
在大型系统中,监控每件事情会引入性能、传输和存储方面的巨大开销。一个大型系统很容易生成数百万个事件以及指标数据,每秒都会产生大量的日志。处理庞大的数据会面临如下挑战:
在时间间隔很小的范围内收集指标,性能开销是巨大的。根据系统当前的状态,运维应该使用变化的和可调节的时间间隔,而不是一些固定的时间间隔。如有产生异常的迹象或者当出现了一个偶尔发生的操作时,能用细粒度监控;当情况解决或操作结束时再返回到大的时间间隔。
应该使用现代分布式日志或消息系统来进行数据收集,而不是自己构建一个。分布式日志系统(如 Logstash)能收集所有种类的日志,并在数据运输前进行大量的本地处理。这种类型的系统允许你减少性能开销、消除噪声,甚至在本地识别错误。
应该使用高级机器学习算法来处理噪声、不一致性和大容量数据。
2
云计算监控的范围和架构
2.1
监控管理的范围
在《The Art of Monitoring》一书中,James Turnbull 描述了一种现代的监控体系架构,由大型互联网公司(例如谷歌、亚马逊、Facebook 等)的运维工程师开发和使用。该架构通常是由很多开源工具构成的,例如 Nagios 和 Zenoss 等,用这些工具定制和部署所能达到的监控规模是同类商业软件很难实现的。
在业务逻辑、应用程序和运行环境层级上收集数据,在每一层,以事件、日志和指标为监控对象。可以在所有服务器上使用特定文件来存储日志,但最好将所有日志发送到公共日志服务中,这样更利于聚合、查询和清除。此外,在应用程序栈的所有层级中收集指标,能更好地了解系统的活动状态。在操作系统级别,可以收集 CPU、内存、磁盘或网络的使用率等。
事件路由器负责事件的存储和转发:支持监控可视化、趋势分析、告警、异常检测等。通过采集、存储和聚合所有监控信息,能实现更深入的分析和健康检查。事件路由器用于存储与服务(和它们支持的应用程序与运行环境)有关的配置,可以实现基于阈值的告警和健康检查。
监控体系架构
(来源:The Art of Monitoring,James Turnbull,June 11,2016)
监控管理的范围包括构成资源服务的所有 IT 资源,云计算环境下的监控对象除了包括传统的资源,还包括对虚拟化资源的监控。
2.2
监控系统的基本架构
被监控的系统可以是独立的应用程序或服务的集合,也可以是单独的应用程序。如果系统主动地提供了被监控的数据,那么监控是入侵式的且影响系统设计;如果系统不主动提供被监控的数据,那么监控是非入侵的。外部系统可以通过健康检查、性能或事务监控来监控系统或者应用级别的状态。
通过代理或者非代理收集的数据最后都发送到监控中心数据库中。一般来说这个中心数据库是分布式的,是逻辑上的中心而不是物理上的中心。数据从初始收集到中心数据库的每一步都可以进行过滤和聚合。判断过滤和聚合量的条件包括:生产数据的大小、本地节点的潜在故障和必要通信的传输粒度。因为本地节点可能发生故障且数据变得不可用,所以从本地节点获取数据并监控是重要的。将所有数据直接发送到中心数据库可能会导致网络阻塞,因此,在设计监控架构时,选择从本地节点到中心数据库之间的中间步骤以及在每一步过滤和聚合数据是重要的架构决策。
监控系统的基本架构
一旦监控数据被收集起来,就可以做很多事情。可以配置报警来触发警告以通知运维人员或其他系统。使用图形化和仪表盘,可以将系统状态的变化可视化地展现给运维人员。监控系统也允许运维人员得到详细的监控数据和日志,这对错误诊断、根本原因分析和确定解决问题的最佳方案具有重要的作用。
由于监控数据的使用需求不断增长,所以很多公司开始对监控系统和整体应用系统采用统一的日志和以指标为中心的“发布-订阅”架构。越来越多的数据类型,包括非传统日志和指标数据,都放入统一的数据库中,各种其他系统(不管是否与监控相关)都可以订阅其感兴趣的数据。
3
百花齐放的开源监控软件工具
前面简单介绍了监控系统的基本架构,与之相关的解决方案已经有很多。
3.1
监控系统成熟度
监控系统有 4 个发展阶段,也是度量监控系统的方法,以及对监控改进的指南,可用于评估当前监控系统的成熟度级别以及可采用的改进步骤。第 1 级是组件监控,可以反映每个组件的状态并根据策略进行警报通知。第 2 级是对各层级进行监控,从各个层级、角度收集运行信息,包括各种指标度量值、输出日志、服务追踪信息等。第 3 级不仅查看所有的状态、事件和度量,还查看依赖关系并跟踪动态变更情况,数据用可视化工具展现,以实时洞察整个系统的总体运行情况。第 4 级是智能化,是更远大愿景的一部分,能够在发生故障之前发送警报,通过扩展或重路由服务来实现自我治愈、异常检测等。
监控系统成熟度
当从监控成熟度第 1 级晋升到第 2 级,将获得对系统更深入的洞察力,将更好地理解服务的可用性和性能。从第 2 级到第 3 级,将可以在整个 IT 系统中获得全栈的可见性,并精确地理解业务流程、应用程序和基础架构之间的依赖关系。无论是云计算、应用程序、还是基础设施,都可以采用更加主动的监控方法来支持数字企业的需求。最后进入第 4 级时,将获得预测分析能力,这将帮助企业预测可能发生的问题、指出可能的原因,IT 维护更智能、敏捷、高效。
对于监控系统软件,开源的解决方案有流量监控(MRTG、Cacti、Smokeping、Graphite 等)和性能告警(Nagios、Zabbix、Zenoss Core、Ganglia、OpenTSDB 等),每种软件都有自己的特点和功能,有各自的侧重点和目标,然而,在设计理念和实现方法上都大同小异,具有共同特征。例如,都具有采集数据、分析展示、告警以及简单的故障自动处理等环节。下面简单介绍监控系统发展演进过程中出现的两个最常用的开源软件。
3.2
Zabbix
Zabbix 是一个基于 Web 界面的提供分布式系统监视以及网络监视功能的企业级开源解决方案。
Zabbix 工作数据流
Zabbix 能监视各种网络参数,保证服务系统的安全运营,并提供良好的通知机制使系统管理员能够快速定位/解决存在的各种问题。Zabbix 由两部分构成—Zabbix server 与可选组件 Zabbix agent。Zabbix server 可以单独监视远程服务器的服务状态;同时也可以与 Zabbix agent 配合,可以轮询 Zabbix agent 主动接收监视数据,还可被动接收 Zabbix agent 发送的数据。另外,Zabbix server 支持 SNMP、IPMI、JMX、Telnet、SSH 等多种协议,将采集到的数据存放到数据库,然后对其进行分析整理,若达到条件触发则告警。Zabbix 支持二次开发,其灵活的扩展性和丰富的功能是其他监控系统所不能比拟的,相对来说,它的总体功能做得非常优秀。
3.3
OpenTSDB
OpenTSDB 通过 HBase 存储所有的时序(无须采样)来构建一个分布式、可伸缩的时间序列数据库。它支持秒级数据采集所有指标,支持永久存储,可以做容量规划,并可很容易地接入现有的报警系统。OpenTSDB 可以从大规模的集群(包括集群中的网络设备、操作系统、应用程序)中获取相应的指标,并进行存储、索引以及服务,从而使这些数据更容易被人理解,如 Web 化、图形化等。
在对实时性要求比较高的场景中,OpenTSDB 是一个很好的选择。它支持秒级的数据采集,这是之前其他监控系统很难实现的。因得益于其存储系统的选择,它支持大数据分析,在大型的基础设施监控中也得到较为广泛的使用。
OpenTSDB 的数据流图
4
Prometheus 监控系统
Prometheus(普罗米修斯,有时简称 Prom)是一个开源的容器和微服务监测和预警工具集。Prometheus 是为提供丰富度量指标、又不影响目标系统性能而设计的、高度可定制的云原生监控系统。Prometheus 已经成为主流开源的监测工具,受到了广大用户的欢迎,对于那些严重依赖容器和微服务的人来说,Prometheus 是他们最佳的选择。Prometheus 适用于各种规模、各个行业。Prometheus 已经具备完整的生态,包括与监控密切关联的报警系统,也非常方便与第三方的监控系统集成,成为监控报警平台。Prometheus 为现代 DevOps 工作流提供了关键组件,监视云原生应用程序和基础设施,并与 CNCF 另一个流行的项目 Kubernetes 完美协同。
4.1
应运而生,茁壮成长
1. Prometheus 简史
Prometheus 是由 SoundCloud 开发的开源监控报警系统和时序数据库(Time Series Database,TSDB)。Prometheus 受 Google 的 Brogmon 监控系统的启发(Kubernetes 是从 Google 的 Brog 系统演变而来的),从 2012 年开始由前 Google 工程师在 SoundCloud 以开源软件的形式进行研发,并且于 2015 年初对外发布早期版本。2016 年 5 月继 Kubernetes 之后成为第二个正式加入 CNCF 基金会的项目,同年 6 月正式发布 1.0 版本。2017 年底发布了基于全新存储层的 2.0 版本,能更好地与容器平台、云平台配合。2018 年 8 月,Prometheus 已成为 CNCF 历史上第二个“毕业”的项目。
Prometheus 历史故事
从前,在加利福尼亚州山景城有一家公司,名为 Google。该公司经营着一系列产品,最著名的是广告 ERM 搜索引擎平台。为了运行这些不同的产品,公司构建了一个名为 Borg 的平台。Borg 系统是“一个集群管理器,它运行数十万个作业,来自数千个不同的应用程序跨越多个集群,每个集群都有多达数万台机器”。开源容器管理器 Kubernetes 的大部分遗产都归功于 Borg。Borg 在 Google 部署后不久,人们就意识到,若要应对这种复杂性,则需要一个类似功能的监控系统。Google 建立了这个系统并命名为 Borgmon。(备注:Borg 和 Borgmon 都从未公开过。直到最近,人们才了解它们是如何工作的)。
Prometheus 的灵感来自 Google 的 Borgmon。Matt T. Proud(前 Google 员工)最初将其作为研究项目开发的。在 Proud 加入 SoundCloud 之后,他与另一位工程师 Julius Volz 合作,开发 Prometheus。后来其他开发者也加入了进来,并在 SoundCloud 内部继续研发,最终在 2015 年 1 月发布了公开版本。
与 Borgmon 一样,Prometheus 主要对基于云和基于容器的动态微服务、服务和应用程序提供近实时监控。SoundCloud 是这些架构模式的较早使用者。现在,Prometheus 被很多公司采纳,通常用于类似的监控,但也用于监控更传统的体系结构。
2. 成为开源社区热点、监控主流
Prometheus 使用开源的 Go 语言编写,并且在 Apache 2.0 许可下授权,该项目有着非常活跃的开发者和用户社区。现在已经成为一个独立的开源项目核,并且独立于任何公司。
Prometheus 作为新一代的云原生监控系统,目前 GitHub 上已超过 2 万颗星。超过 650 多位贡献者参与到 Prometheus 的研发工作上,并且有 120 多项的第三方集成。从 2012 年 11 月开始至今,Prometheus 持续成为监控领域的热点。
在 2016 年之后,Prometheus 综合排名持续提升,且速度最快。Prometheus 很有活力,开发者可以自己写导出器(exporter),每个监控参数都可控,并能很快定位到问题。
3. Prometheus 设计理念
Prometheus 能抓取或拉取应用程序导出的时间序列数据。应用程序本身经常通过客户端函数库或导出器(导出程序,作为 HTTP 端点)呈现出时间序列数据。导出器和客户端函数库可用于多种语言、框架和开源应用程序,例如用于 Apache、Nginx 等 Web 服务器以及 MySQL 等数据库。
Prometheus 关注的是近期发生的事情,而不是跟踪数周或数月的数据。因为大多数监视查询和警报都是从最近的(通常不到一天的)数据生成的。Prometheus 假设用户试图修复的问题是最近的,因此最有用的数据是最近的数据。Prometheus 监控数据默认保留 15 天。
Prometheus 设计理念
Prometheus 还有一个推送网关,可以用来接收少量数据,例如获取不能被直接抓取的监控目标的指标数据。
4.2
功能完善、监控所有层级指标
传统的监控解决方案需要多种监控工具组合。
传统复杂的多种监控手段组合
和其他监控系统相比,Prometheus 功能强大,可以监控所有层级的指标(见表 1),简化了监控复杂度。
表 1 Prometheus 监控所有层级指标
Prometheus 监控解决方案,简化系统部署
4.3
开放、高效、易用的完整解决方案
Prometheus 是一个开源的完整监控解决方案,对传统监控系统的测试和告警模型进行了彻底的颠覆,形成了基于集中化的规则计算、统一分析和告警管理的新模型。相比于传统监控系统,Prometheus 具有大量优点。
1. 易管理性
Prometheus 核心部分只有一个单独的二进制文件,不存在任何的第三方依赖(数据库、缓存等)。唯一需要的就是本地磁盘,因此不会有潜在关联的故障风险。Prometheus 基于 Pull 模型的架构方式,可以在任何环境(本地主机、开发环境、测试环境等)搭建监控系统。对于一些复杂的情况,还可以结合 Prometheus 的服务发现能力动态地管理监控目标。
2. 更契合的架构
采用 Push 模型的监控系统,客户端需要在服务端上进行注册及监控数据推送;而在 Prometheus 采用的 Pull 模型架构里,具体的数据拉取行为是完全由服务端决定的。服务端可以基于某种服务发现机制自动发现监控对象,多个服务端之间能够通过集群机制实现数据分片。Push 模型想要实现相同的功能,通常需要客户端进行配合,而这在微服务架构里是比较困难的。Prometheus 建议用户监控服务的内部状态,可以基于 Prometheus 提供的丰富 Client 库,很容易地在应用程序中添加支持 Prometheus 的监控指标,用户可以获取服务和应用内部真正的运行状态信息。
3. 灵活的数据模型
在 Prometheus 里,监控数据是由值、时间戳和标签表组成的,其中,监控数据的源信息完全记录在标签表里;同时,Prometheus 支持在监控数据采集阶段对监控数据的标签表进行修改,这使其具备强大的扩展能力。
4. 良好的性能,强大的查询能力
在监控系统中大量的监控任务必然产生大量的数据,Prometheus 不仅可以高效地处理这些数据,还提供了 PromBench 基准测试。在硬件资源满足的情况下,对于单实例 Prometheus 可以处理数以百万的监控指标以及数十万个数据点。
Prometheus 内置了一套强大的数据查询语言 PromQL。PromQL 提供了大量的数据计算函数,大部分情况下用户都可以直接通过 PromQL 从 Prometheus 里查询到需要的聚合数据。PromQL 也可应用于数据可视化(如 Grafana)以及事件告警。
5. 可扩展性
Prometheus 架构非常简单,可以在每个数据中心、每个团队中运行独立的 Prometheus 服务器实例。对于大型环境,Prometheus 支持联邦(federation)集群方式,把多个 Prometheus 实例集成单个逻辑集群。当单个 Prometheus 服务器实例处理的任务量过大时,通过功能分区(sharding)结合联邦集群可以对其进行扩展。
6. 健全的生态,开放、易于与第三方系统集成
使用 Prometheus 可以快速搭建监控服务,并且可以方便地在应用程序中进行集成。目前已支持 Java、JMX、Python、Go、Ruby、.Net、Node.js 等语言的客户端软件开发工具(SDK),基于这些 SDK 可以很容易地将应用程序纳入到 Prometheus 的监控中,或者开发自己的监控数据收集程序。同时,Prometheus 还支持与其他监控系统进行集成,如 Graphite、Statsd、Collected、Scollector、muini、Nagios 等。甚至可以在不使用 Prometheus 的情况下,采用 Prometheus 的 client library 使应用程序支持监控数据采集。
Prometheus 社区提供了大量第三方实现的监控数据采集支持,如 JMX、CloudWatch、EC2、MySQL、PostgresSQL、Haskell、Bash、SNMP、Consul、Haproxy、Mesos、Bind、CouchDB、Django、Memcached、RabbitMQ、Redis、RethinkDB、Rsyslog 等。
7. 可视化
Prometheus 服务器中自带了一个 Prometheus UI,通过这个 UI 可以方便地对数据进行查询,并且支持直接以图形化的形式展示数据。最新的 Grafana 可视化工具已经完美支持 Prometheus,基于 Grafana 可以创建精美、炫酷的监控视图。基于 Prometheus 提供的 API,还可以实现自己的监控可视化 UI。
Prometheus 虽然具有上述优势,但其仍然无法满足微服务监控的所有需求,具体的不足之处有:
• 仅适用于监控维度,要用于日志监控、分布式追踪等还有待完善。
• 告警规则和告警联系人仅支持静态文件配置。
• 原生支持的数据聚合函数有限,且不支持扩展。
想对监控 Prometheus 技术有更深入的了解,推荐阅读《Prometheus 监控技术与实战》。
推荐语:Prometheus 是云监控领域的瑞士军刀,本书全方位介绍 Prometheus 的原理架构以及应用场景,包括与 OpenStack、Docker、Kubernetes、Spring Boot、日志系统的结合,以及构建监控系统的高可用方案等。作者作为一线开发者,本书集结了多年实战经验的结晶。
5
福利时间
中生代技术联合机械工业华章图书给大家带来福利时间。
送书规则:截止2020年5月24日13:30前在留言区,分享你在云技术监控方面的心得与踩坑经验、或者对新技术的更新、迭代有何独特的个人见解,精选留言点赞前3名各送出此书一本。
注:获得赠书资格的读者须于8小时内联系小编发送详细收货信息,逾期则视为主动放弃。
想要加入中生代架构群的小伙伴,请添加群合伙人大白的微信
申请备注(姓名+公司+技术方向)才能通过哦!
END
#接力技术,链接价值#
精彩推荐
当我们在谈数字化转型的时候,我们在谈什么?
漫画:程序员每天的6场战斗
Spring Cloud入门,看这篇就够了!
如此沙雕的代码注释,还是程序员会玩!
阿里云MVP乔帮主:五大类型负载均衡的原理场景详解(文末赠书)
阿里高专王夕宁:Istio网关之南北向流量管理
漫画推荐
1. 漫画:程序员和产品经理撕得真是太太太太厉害了
2. 漫画:程序员真的是太太太太太太太太难了!
3. 漫画:普通程序员 vs 优秀程序员
4. 漫画:35岁的IT何去何从?
5. 漫画:从修灯泡来看各种 IT 岗位,你是哪一种?
6. 漫画:一批90后已经30岁了,更扎心的是…
7. 图解:这才是程序员加班的真正原因!
8. 漫画:中国互联网往事(2000-2020)
好文点个在看吧!
点击阅读原文可以当当特惠购书哦,优惠码【K3FT5X】