Big Ball of Mud,中文名称“一坨翔”。本文的上篇:"噢,你的代码像一坨翔。然后呢?",我们从解决方案出发,妄图通过不断尝试不同的药来解决问题。这种从解决方案出发的态度随处可见,比如问啥叫微服务,服务多微才叫微服务。JSON+HTTP好,还是 Protobuf 好。RPC好还是走消息队列好。
不要问什么是微服务,要问微服务能够给你带来什么。如果不知道什么叫”好“,你怎么知道哪个好呢?从老板的角度来说,他们真正只在乎两件事情:
然后他们假装会在乎
实际上打心底里,最重要的还就是前两点。少用一点机器根本不用你上 Protobuf 来省出来,消息队列再怎么高效,都没有本质的提升。什么叫质的提升?某厂一个小姑娘带着老板的尚方宝剑去各个业务组敲打一圈,一下子收归几千台空闲机。这就叫质的提升。当我们得知真相之后,正在做各种性能优化的码农的心是崩溃的。和稳定性与交付速度相比,性能和成本绝对不是什么值得在台面上讨论的问题。即便要解决这个问题,也轮不到用技术手段来解决。就像中国的银行有所谓的“窗口指导”一样,领机器的时候卡严一点,比什么都管用。
用户体验也是一样的。互联网企业最常做的事情是灰度,拿一部份用户做小白鼠。另外一个常见的做法是最终一致性,碰上点故障那就是最终也一致不了。个别用户碰到一点奇葩的现象实在是太平常了。老板们关心是大部分用户的体验是不是好,至于长尾的体验,实在是顾不过来的。业务逻辑是不是写得非常完善,事务处理是不是天衣无缝。这个都不是最重要的事情。让系统来解决99.9%的事情,剩下的0.1%,交给RD和客服去处理就好了。这对有手写raft协议的追求的人来说是一件很崩溃的事情,但是这个是对大部分业务来说最经济的选择。不需要你搞一个多完备的东西出来,偶尔出错就出错呗。
那么稳定性和交付速度就是最重要的两个指标了。
把一个单体应用切分为多个进程,独立部署是必然的。
我们应该拆分成,咳咳,独立的微服务。这不是废话么。问题是怎么拆?我现在觉得,其实怎么拆都行,因为都比合在一起要强。
单体应用的最大问题是它一个部署就阻塞了所有其他人的上线。而众所周知,我们谁都没有测试,至少是没有可以保证业务不挂掉的测试。真正的冒烟测试,都是用上线灰度的方式来做的。剩下的功能测试,是接下来数天里用线上开关的方式逐步地放量来做的。线下的测试么,我就呵呵了,你懂的。单体应用的存在,使得每个功能可以被分配到灰度时间变少了。这么多公司都在拆微服务,最重要的收益是让每个模块能够独享自己的灰度时间,从而大幅减少因为上线破坏旧的功能引起的故障。
无论怎么拆分,都会比合在一起要好。这里"好”,指的是少出故障。实际上是怎么切的,反而不是那么重要的事情,只要能切得开,哪怕你是复制一份代码呢?
我的判断是,90%的一坨翔不是因为业务自身有多么多么复杂。而是因为不懂得拒绝,总是做老好人,什么事情都干。就是因为你总是做劳模,替所有人干所有的事,屎盆子才会扣在你的头上。要想避免一坨翔,要从学会甩锅开始做起。传你五条甩锅心法,保平安
所有这些招数,和上篇里列举的那些架构模式没有本质区别,不过是换了一个说法。但是我们这次很明白自己的需求是什么。提高团队的自主性,不要被周边系统连累。一个需求,尽量一个团队搞定。减少跨团队沟通的需要,提高所有人的效率。如果开的药方可以做到这一点,就是一个好药方。
甩锅心法第一则,立字据
哪怕是亲兄弟,也要明算账。坚决不要和其他的服务共用db。我的是我的,你的是你的。
各做各的业务,你要存什么,你自己存去。别挤到一个庞大的Order表里。让你和其他的服务之间,有明确的起止边界,是甩锅最重要的事情。当出了问题的时候,你的责任非常清楚,看看输入,看看输出,一目了然。要不然某个Order上的字段错了,到底是谁写错了都搞不清楚,大家都有读写权限。最极端的情况,流程的每一个步骤都可以切出一个独立的服务出来。
让每个服务有自己的存储,自己独立去面对最终客户,目的是为了让有需求来的时候,每个服务的团队可以更快响应。他们上可接客户,下可接存储,拥有了最大的自主性。而与其他的团队之间也有很清晰的接口(连产品经理都可以说得出来的),从而最小化了沟通成本。
其实所有在数据库里有 1:1 关系的表都有类似的问题。我们可以选择一个表n个字段。也可以选择把表分为两个,然后1:1对应。从快速试错,满足业务需求的角度,拆分出独立的表是更优的做法。也就可以表达为,如果要加一个功能,优先选择建一个新的模块,把这个特例的需求搞定。而不是去修改现有的表,把功能写到现有代码里。
代码重用,从来就不是老板们关心的事情。快速实现需求才是。从90年代的OO理论,到现代的微服务。我觉得最大的进步就是大家觉醒了,快速实现 != 代码重用。与其给场景A加两个字段,给场景B加三个字段。不如连同代码和数据,一切都切分出去好了。
甩锅心法第二招,透传
在查询接口上最恶心的事情是要把一堆杂七杂八的东西都放在一起返回。甚至很多数据都不属于你,是别的团队提供的。要想减少你替别人做嫁衣(想一想,对方年终奖会分给你多少?),最佳的办法是甩锅。与其让别人返回一个enum给你,然后你吭哧吭哧地翻译成中文,拼装出其他需要的数据。直接开一个map透传的接口,你要给用户什么数据,你自己搞,爷不伺候了。因为你提供的是透传的接口,后端的系统有什么字段要加,也不会再来找你了。
无论前台是一种什么形式
都有办法从前到后透传,技术上都不是问题。如果可能,尽量让客户端取多次,在前台界面拼装。如果可能的话,让一个团队为最终结果负责,而不是做成两个团队来接力的模式。接力掉棒了,就会有扯皮的事情。
做业务流程的同学,总是会被其他的兄弟部门找过来。你能不能在用户下单的时候,调我一下接口,做个xyz啊?你能不能在送达了之后,把配送时间写到某个redis里,我们数据分析要用哇?
别做老好人,学会拒绝。凡是和我的本质工作不相关的,请不要让我来实现。我把事件放到kafka里,你们自己来拿。RPC 和消息队列最本质的区别,不是网络开销,不是提高并发,而是职责的反转。
在 RPC 模式下,责任是在 A 团队的。如果 B 挂了,A 要负责重试。如果 B 一直挂,A 团队的负责人要接告警,然后打电话给B团队的人。
在消息队列的模式下,A是甩锅甩得很彻底的。没有人会闲的没事,帮 B 去监控一下他消费的offset。那不是我的责任,是你的责任。
B有两个常见的借口:
别慌,该甩的锅,坚决要甩。不能有妇人之仁。
让消息队列的团队,额外提供一个 http caller 帮助残废的B去消费数据。怎么消费好搞,让 B 自己和基础架构的人去谈。A,概不负责。
如果消费的时候需要一些关联的数据,A提供读的接口,B自己来取。如果单条读太慢,可以提供批量读的接口。用户调用你的RPC的接口也不会把所有的数据都给你啊,还不是要读数据库么。为什么消费队列的时候就指望队列里有你处理逻辑的所有需要的数据呢?
在某个时间点上要发生的事情,不一定要一个地方都写完了。把事件放入队列,让相关方自己来取。他们自己去负责自己的事情,去取自己需要的数据。
好说话的合作伙伴,通过透传和写队列,都可以搞定。但是世界并不是这么简单的
确实是我自己的业务逻辑需要,比如我需要读订单,需要读用户信息。你能够让db的读接口也走队列么?肯定不行嘛。总是会有一些服务和别的服务不一样,你是甩不掉的。你们必须紧密协作,完成共同的kpi。
问题是如何判断,你依赖的服务是真的必要的强依赖,还是强赖着不走?我现在觉得最有效的手段是,问他愿不愿意跟你同归于尽。
做为A,你去问B这个问题:如果你挂了,我也连累地挂了。然后每分钟几百万的损失你来承担,ok不ok?
如果B的答案是ok,我们共同来担这个责任。这就是真爱哇。如果B犹豫了,你就知道这是个假的伙伴。因为稳定性是老板最关注的事情,只有拿这个去切,才能真正切开。如果你问B,你愿不愿意走Kafka?B肯定会说,RPC不是走得好好的么。
哪怕在你的返回值上,有B提供的数据,也是同样的问题。还是问你自己这个问题。当B挂的时候,你是宁愿这个字段是空呢,还是让整个接口都挂掉?部分字段为空,大不了体验受损,也肯定是好过整体故障的。
这个“you jump, I jump”的问题,不仅仅对接口这个级别有效。更可以深入到字段的级别。也许A必须及时调用B,哪怕B挂了,A确实要负责B的重试。因为A和B共同推动了业务流程的前进,不把棒可靠地交到了B手里,A和B都没有好果子吃。但是并不代表,B提的一切要求就是合理的了。也许B给你提了一个20多个字段的接口,未必每个字段都是必须的。还是同样的做法,问问你自己,是希望某个字段为空,还是要死保稳定性。
在稳定性的高压下,一切同步接口都有变成异步的可能。哪怕99%正常的时候是同步调用,在那1%的故障场景下,所有人都可以接受一个异步的体验的,总好过挂掉的体验。而现在的中间件技术,提供的是要么全RPC,要么全异步的非黑即白的解决方案。并没有特别好的现成的方案来支持“平时是同步的,故障时改成异步的”这样的用法。
和外部的系统打交道,我们一般有这么两招
缓存一份对方提供的数据。提高访问速度,在B挂掉的时候,提供兜底方案。
第二种做法是不直接依赖B,只订阅 B 的变化,写入自己的数据库。
这两种模式在你挂了,没法让B来背锅的场合是可以的。比如B是一个外部的国企。你就把B的可用性的责任,背到了自己的身上。如果B是你的队友,你要相信他们。你依赖的缓存是同机房的某台机器,B也可以把他的服务部署到你的机房啊。依赖自己的缓存,和依赖B没有本质区别。从全公司的角度来说,大家都做一份缓存,只是多复制了一份数据而已。和B签订好SLA,如果B挂了,慢了,让他们来背锅。
这种把一个存储前档一个数据服务的做法,有什么作用?如果只是增删改查的话确实没有啥用。如果只是解决分库分表,那确实不如改名叫dbproxy得了。为啥要搞出这样的队友来?我自己依赖数据库不行么?在前台应用比较丰富的情况,一些公共的业务上的规则要得到保证(比如全平台封禁)只能在中台来做。
甩锅第五招,相信你的队友,让他们提供SLA,有些底,你是不用兜的。
因为稳定性的需求,切分是绝对必须的。做好灰度发布是最最重要的事情。
切分就是一个学会拒绝做老好人,不断甩锅的过程。按照我给的几条心法,没有什么锅是不能往外甩的了。
最后解放思想,不要固守什么模式什么原则。评价好坏只有两条硬性指标:系统是不是稳定,是不是能快速响应需求变化。
愿各位少谈一点主义,多解决一点问题。各司其职,多写点代码,少开些会,早点下班。
原网址: 访问
创建于: 2019-03-24 03:29:42
目录: default
标签: 无
未标明原创文章均为采集,版权归作者所有,转载无需和我联系,请注明原出处,南摩阿彌陀佛,知识,不只知道,要得到
java windows火焰图_mob64ca12ec8020的技术博客_51CTO博客 - 在windows下不可行,不知道作者是怎样搞的 监听SpringBoot 服务启动成功事件并打印信息_监听springboot启动完毕-CSDN博客 SpringBoot中就绪探针和存活探针_management.endpoint.health.probes.enabled-CSDN博客 u2u转换板 - 嘉立创EDA开源硬件平台 Spring Boot 项目的轻量级 HTTP 客户端 retrofit 框架,快来试试它!_Java精选-CSDN博客 手把手教你打造一套最牛的知识笔记管理系统! - 知乎 - 想法有重合-理论可参考 安宇雨 闲鱼 机械键盘 客制化 开贴记录 文本 linux 使用find命令查找包含某字符串的文件_beijihukk的博客-CSDN博客_find 查找字符串 ---- mac 也适用 安宇雨 打字音 记录集合 B站 bilibili 自行搭建 开坑 真正的客制化 安宇雨 黑苹果开坑 查找工具包maven pom 引用地 工具网站 Dantelis 介绍的玩轴入坑攻略 --- 关于轴的一些说法 --- 非官方 ---- 心得而已 --- 长期开坑更新 [本人问题][新开坑位]关于自动化测试的工具与平台应用 机械键盘 开团 网站记录 -- 能做一个收集的程序就好了 不过现在没时间 -- 信息大多是在群里发的 - 你要让垃圾佬 都去一个地方看难度也是很大的 精神支柱 [超级前台]sprinbboot maven superdesk-app 记录 [信息有用] [环境准备] [基本完成] [sebp/elk] 给已创建的Docker容器增加新的端口映射 - qq_30599553的博客 - CSDN博客 [正在研究] Elasticsearch, Logstash, Kibana (ELK) Docker image documentation elasticsearch centos 安装记录 及 启动手记 正式服务器 39 elasticsearch 问题合集 不断更新 6.1.1 | 6.5.1 两个版本 博客程序 - 测试 - bug记录 等等问题 laravel的启动过程解析 - lpfuture - 博客园 OAuth2 Server PHP 用 Laravel 搭建带 OAuth2 验证的 RESTful 服务 | Laravel China 社区 - 高品质的 Laravel 和 PHP 开发者社区 利用Laravel 搭建oauth2 API接口 附 Unauthenticated 解决办法 - 煮茶的博客 - SegmentFault 思否 使用 OAuth2-Server-php 搭建 OAuth2 Server - 午时的海 - 博客园 基于PHP构建OAuth 2.0 服务端 认证平台 - Endv - 博客园 Laravel 的 Artisan 命令行工具 Laravel 的文件系统和云存储功能集成 浅谈Chromium中的设计模式--终--Observer模式 浅谈Chromium中的设计模式--二--pre/post和Delegate模式 浅谈Chromium中的设计模式--一--Chromium中模块分层和进程模型 DeepMind 4 Hacking Yourself README.md update 20211011
Laravel China 简书 知乎 博客园 CSDN博客 开源中国 Go Further Ryan是菜鸟 | LNMP技术栈笔记 云栖社区-阿里云 Netflix技术博客 Techie Delight Linkedin技术博客 Dropbox技术博客 Facebook技术博客 淘宝中间件团队 美团技术博客 360技术博客 古巷博客 - 一个专注于分享的不正常博客 软件测试知识传播 - 测试窝 有赞技术团队 阮一峰 语雀 静觅丨崔庆才的个人博客 软件测试从业者综合能力提升 - isTester IBM Java 开发 使用开放 Java 生态系统开发现代应用程序 pengdai 一个强大的博主 HTML5资源教程 | 分享HTML5开发资源和开发教程 蘑菇博客 - 专注于技术分享的博客平台 个人博客-leapMie 流星007 CSDN博客 - 舍其小伙伴 稀土掘金 Go 技术论坛 | Golang / Go 语言中国知识社区
最新评论