“在分布式应用中,最常见的问题是什么呢?” “一个分布式应用部署上去后,还要关注什么?” “这服务的远程调用依赖似乎有点多…” 前言 在 《微服务的战争:级联故障和雪崩》中有提到,在一个分布式应用中,最常见,最有危险性之一的点就是级联故障所造成的雪崩,而其对应的解决方案为根据特定的规则/规律进行流量控制和熔断降级,避免请求发生堆积,保护自身应用,也防止服务提供方进一步过载。 简单来讲就是,要控制访问量的流量,要防各类调用的强/弱依赖,才能保护好应用程序的底线。 诉求,期望 诉求:作为一个业务,肯定是希望自家的应用程序,能够全年无休,最低限度也要有个 4 个 9,一出突发性大流量,在资源贫乏的窗口期,就马上能够自动恢复。 期望:万丈高楼平地起,我们需要对应用程序进行流量控制、熔断降级。确保在特定的规则下,系统能够进行容错,只处理自己力所能及的请求。若有更一步诉求,再自动扩缩容,提高系统资源上限。 解决方案 要如何解决这个问题呢,可以关注到问题的核心点是 “系统没有任何的保护的情况下”,因此核心就是让系统,让你的应用程序有流量控制的保护。一般含以下几个方面: 来自端控制:在业务/流量网关处内置流量控制、熔断降级的外部插件,起到端控制的效果。 来自集群/节点控制:在统一框架中内建流量控制、熔断降级的处理逻辑,起到集群/节点控制的效果。 来自 Mesh 控制:通过 ServiceMesh 来实现流量控制、熔断降级。侵入性小,能带来多种控制模式,但有利有弊。
“你说说,没有仪表盘的车,你敢开吗?” “没有仪表盘的车开在路上,你怎么知道现在是什么情况?” “客户说你这车又崩了,咋知道什么时候好的?啥时候出的问题?” 前言 将思考转换到现实的软件系统中,可想而知没有监控系统的情况下,也就是没有 ”仪表盘“ 的情况下实在是太可怕了。 你的故障永远都是你的客户告诉你的,而…在什么时候发生的,你也无法确定,只能通过客户的反馈倒推时间节点,最后从错误日志中得到相对完整的日志信息。 问题 更要命的是你无法掌握主动权,错误日志有可能会有人漏记录,平均修复时间(MTTR)更不用想了,需要从 0.1 开始定位,先看 APP 是哪个模块报错,再猜测是哪个服务导致,再打开链路追踪系统,或是日志平台等。 稍微复杂些的,排查来来往往基本都是半小时、一小时以上,那 4 个 9 肯定是达不到的了,以此几次 P0 几小时怕不是业务绩效也凉凉,因为故障修复的速度实在是太慢了。 那归根到底,想破局怎么办,核心第一步就是要把监控告警的整个生态圈给建设好。 监控定义 常说监控监控,监控的定义就是监测和控制,检测某些事物的变化,以便于进行控制。在常见的软件系统中,大多分为三大观察类别: 业务逻辑:项目所对应的服务其承担的业务逻辑,通常需要对其进行度量。例如:每秒的下单数等。 应用程序:应用程序。例如:统一的基础框架。
以前经常有读者问我,哪儿可以找到 Go 语言的前世今生,这种时候我们往往会告诉他去看 issues 和 proposals。但资料有点分散,且没有索引体系。因此不少人新入门的读者读着读着就跑偏了,又或是在第一步找资料上就被拦住了。 最近欧神(@changkun)低调的发布了 《Go: A Documentary》,这个文档收集了 Go 开发过程中许多有趣(公开可见的)的问题,讨论,提案,CL 和演讲,其目的是为 Go 历史提供全面的参考。 个人认为这份资料非常的有价值,相当于欧神把资料索引整理好了,强烈推荐对 Go 语言感兴趣的读者进行阅读: 内容索引主要分为: Sources Committers Core Authors Compiler/Runtime Team Library/Tools/Security/Community Group Interviews Timeline Language Design Misc Slice Package Management (1.
大家好,我是煎鱼。 小咸鱼经过前文所提到的折磨人的 “微服务拆分、微服务环境” 问题后,终于顺顺利利的上到了测试环境进行测试。 这时候开发、测试同学又闹新的头疼了,测了一轮下来。发现好好的。结果发现一上生产就有一些地方有问题,发现没测到。 这到底是为什么呢? 背景 在以往,小咸鱼他们团队都是传统的大单体应用。也就是一体化应用,包含了前端、后端等模块,具备天然的协调性: 测试同学能够很方便的就直接测到前后端接口。 测试能够直接对系统本身进行集成测试。 但现在,做了微服务化(雏形)后,小咸鱼他们就翻车了,为什么呢? 因为考虑到微服务,微服务就是向往单拎一个服务出来,都可以独立修改,独立发布。于是小咸鱼提交了一个迭代的几个服务变更,想着实现一把 “敏捷” 发布。 结果一上线就炸了,一大堆的 BUG,光荣加班到晚上 12 点。 这实质上是缺乏端到端测试的一个问题,单服务,无法明确系统正在正常运行。 端到端测试 在测试的质量保障上,我们要站在用户视角去验证这个系统,保障整体的系统可用性,而不是单纯的前端 BFF,又或是后端 Server 的某些接口能够正常运行。 在定义上端到端测试(End-to-end Test)是一种用于测试整个应用程序的流程是否符合预期的测试技术。测试同学会模拟用户真实的使用场景,通过用户界面测试应用程序。 如下图: 与小咸鱼团队那种单纯只测接口的方式不同,端到端测试是面向业务的。
“微服务的战争” 是一个关于微服务设计思考的系列题材,主要是针对在微服务化后所出现的一些矛盾/冲突点,不涉及具体某一个知识点深入。如果你有任何问题或建议,欢迎随时交流。 背景 在经历 微服务的战争:级联故障和雪崩 的 P0 级别事件后,你小手一摊便葛优躺了。开始进行自我复盘,想起这次排查经历,由于现在什么基础设施都还没有,因此在接收到客户反馈后,你是通过错误日志进行问题检查的。 但在级联错误中,错误日志产生的实在是太多了,不同的服务不同的链路几乎都挤在一起,修复时间都主要用在了翻日志上,翻了好几页才找到了相对有效的错误信息。 如果下一次在出现类似的问题,可不得了,MTTR 太久了,4 个 9 很快就会用完。这时候你想到了业界里经常被提起的一个利器,那就是 “分布式链路追踪系统”。粗略来讲,能够看到各种应用的调用依赖: 其中最著名的是 Google Dapper 论文所介绍的 Dapper。源于 Google 为了解决可能由不同团队,不同语言,不同模块,部署在不同服务器,不同数据中心的所带来的软件复杂性(很难去分析,无法做定位),构建了一个的分布式跟踪系统: 自此就开启了业界在分布式链路的启发/启蒙之路,很多现在出名的分布式链路追踪系统都是基于 Google Dapper 论文发展而来,基本原理和架构都大同小异。若对此有兴趣的可具体查看 Google Dapper,非常有意思。
“微服务的战争” 是一个关于微服务设计思考的系列题材,主要是针对在微服务化后所出现的一些矛盾/冲突点,不涉及具体某一个知识点深入。如果你有任何问题或建议,欢迎随时交流。 在 微服务的战争:统一且标准化 中,经过好几周与不同业务组不同事业部的跨部门讨论后,终于把初始的标准化方案给定下来了,大家欢快的使用起了内部的统一框架,疯狂的创建起了新服务,没隔多久服务调用链就变成了下图: 服务间存在多次内部调用,服务 A =》服务 B =》服务 C =》服务D,而 服务 E =》 服务 B,服务 F =》服务 E,也就是存在着多个流量入口,且依赖相同的服务。 背景 服务与服务中,总存在业务服务,公共服务,基础服务等类型。但在某一个夜晚,突然发现 BFF 调用后端服务开始逐渐不正常,客户给你截图反馈问题,你发现有点问题: 单从表现来看,你发现是 BFF 调用服务 A 极度缓慢,也不知道怎么了…正当以为是服务 A 出问题,想着万能重启一下时。你在日志平台和链路追踪系统一看,发现了大量的错误日志和缓慢,让你略微震惊,一时间不知道从何下手。
“微服务的战争” 是一个关于微服务设计思考的系列题材,主要是针对在微服务化后所出现的一些矛盾/冲突点,不涉及具体某一个知识点深入。如果你有任何问题或建议,欢迎随时交流。 开天辟地 在远古开天辟地时,大单体转换成微服务化后,服务的数量越来越多。每起一个新的服务,就得把项目的目录结构,基础代码重新整理一遍,并且很有可能都是从最初的 template 上 ctrl+c,ctrl+v 复制出来的产物,如下: 但是基于 template 的模式,很快就会遇到各种各样的新问题: 随着跨事业部/业务组的使用增多,你根本不知道框架的 template 是什么时间节点被复制粘贴出去的,也不知道所对应的 commit-id 是什么,更不知道先前的 BUG 修复了没,也不知道有没有其他开发人员私下改过被复制走的 template。 简单来讲,就是不具备可维护性,相对独立,BUG 可能一样,但却没有版本可规管。这时候,就可以选择做一个内部基础框架和对应的内部工具(已经有用户市场了),形成一个脚手架闭环: 通过基础工具+基础接口的方式,就可以解决项目A、B、C…的基础框架版本管理和公共维护的问题,且在遇到框架 BUG 时,只需要直接 upgrade 就好了。而在框架维护者层面,还能通过注册机制知道目前基础框架的使用情况(例如:版本分布),便于后续的迭代和规划。 同时若内部微服务依赖复杂,可以将脚手架直接 “升级”,再做多一层基础平台,通过 CI/CD 平台等关联创建应用,选择应用类型等基本信息,然后关联创建对应的应用模板、构建工具、网关、数据库、接口平台、初始化自动化用例等:
“微服务的战争” 是一个关于微服务设计思考的系列题材,主要是针对在微服务化后所出现的一些矛盾/冲突点,不涉及具体某一个知识点深入。如果你有任何问题或建议,欢迎随时交流。 微服务,这三个字正在席卷着目前的互联网软件行业,尤其在近几年云原生迸发后,似乎人人都对微服务有了更广泛的使用和理解,张口就是各种各样的问号,有着强大的好奇心。 无独有偶,我有一个朋友鲤鱼在内部微服务的早期(每个业务组起步)就经常遇到下述的对话: 张三:为什么要拆现在的代码? 鲤鱼:因为 !@)&&#@!)&#!&)@!&! 的原因。 张三:那即将要做的 “微服务” 是按照什么维度去拆分的服务? 鲤鱼:常见的一般根据 !@#*@!#&!(@&!@)#@ 的方式来拆分。 张三:照你这么说好像也不大对,我看每个业务组拆分的维度似乎都不大一样? 鲤鱼:嗯,每个业务组还有自己的见解,不会完全相同。
从我开始写技术文章起,不知不觉近三年过去了,咨询和催我出书和读者逐年递增,在 2019 年算是达到一个高峰。当然,综合考虑下我也是一直拒绝的,觉得火候还不够。 直至 2019.09 月,polaris 主动找到了我,说有事情想找我商量,本着 “如果你在纠结一件事情做还是不做,不如先做了看看结果,至少不会后悔” 的想法,更何况是长期被 Ping,因此我一口答应下来,故事自此开始了。 本书定位 本书不直接介绍 Go 语言的语法基础,内容将面向项目实践,同时会针对核心细节进行分析。而在实际项目迭代中,常常会出现或多或少的事故,因此本书也针对 Go 语言的大杀器(分析工具)以及常见问题进行了全面讲解。 本书适合已经大致学习了 Go 语言的基础语法后,想要跨越到下一个阶段的开发人员,可以填补该阶段的空白和进一步拓展你的思维方向。 读者定位 基本了解 Go 语言的语法和使用方式的开发人员。 想要进行 Go 相关项目实践和进一步摸索的开发人员。 希望熟悉 Go 常用分析工具的开发人员。 本书大纲 本书针对常见的项目类型,主要细分为 5 + 1 板块,分别是命令行、HTTP、RPC、Websocket 应用、进程内缓存以及 Go 中的大杀器。
在上周的文章《为什么容器内存占用居高不下,频频 OOM》 中,我根据现状进行了分析和说明,收到了很多读者的建议和疑惑,因此有了这一篇文章,包含更进一步的说明和排查。 疑问 一般系统内存过高的情况下,可以通过 free -m 查看当前系统的内存使用情况: 在发现是系统内存占用高后,就会有读者会提到,为什么不 “手动清理 Cache”,因为 Cache 高的话,可以通过 drop_caches 的方式来清理: 清理 page cache: $ echo 1 > /proc/sys/vm/drop_caches 清理 dentries 和 inodes: $ echo 2 > /proc/sys/vm/drop_caches 清理 page cache、dentries 和 inodes: $ echo 3 > /proc/sys/vm/drop_caches 但新问题又出现了,因为我们的命题是在容器中,在 Kubernetes 中,若执行 drop_caches 相关命令,将会对 Node 节点上的所有其他应用程序产生影响,尤其是那些占用大量 IO 并由于缓冲区高速缓存而获得更好性能的应用程序,可能会产生 “负面” 后果。