网站建设维护单位,贵州建设职业技术学院教务网站,怎么做质量高的网站,网络教育室内设计专业↑ ???? 万字长文不想看#xff0c;那就听一听叭 ↑为什么你的程序总是出现 bug#xff1f;凭什么让改 bug 占据了你大部分的时间#xff1f;看完本文#xff0c;保证你能设计出更稳定的程序#xff0c;摆脱 bug 的缠绕#xff0c;做项目更安心#xff01;记得我在学… ↑ ???? 万字长文不想看那就听一听叭 ↑为什么你的程序总是出现 bug凭什么让改 bug 占据了你大部分的时间看完本文保证你能设计出更稳定的程序摆脱 bug 的缠绕做项目更安心记得我在学校的时候做的那些项目不是为了应付课程作业就是为了参加比赛时展示用因此对项目的质量要求非常低。到底有多低呢大部分的项目只要基本的功能可以使用就算完成了完全不考虑任何的异常情况。甚至只要能成功运行一次让我截几张图放到 PPT 或者实验报告里足够向老师交差或者应付比赛答辩就行。那项目出现 bug 怎么办呢如果测试的时候发现有些功能不可用那很简单不管他直接 PS 一张正常运行的图就行。如果比赛的时候发现有些功能不可用那也很简单把锅甩给 “现场网络不好” 就行。但是这些 “小技巧” 在企业中是行不通的企业级项目必须为企业带来实际的价值容不得半点马虎和欺骗。我第一次进入企业实习时还保留着自己在学校开发项目的狼性 ????只要能够完成基本功能就行保证以最快的速度完成开发。有一天当我洋洋得意准备早点下班时测试同学走过来跟我说。“喂你的程序有 bug这里用户下单怎么金额是负的”写个 bug对于我一个初入职场的小白这是人生中第一次有人说我的代码有 bug我有问题我不对劲。当时我脑海的第一个念头竟然是怎么把这个 bug 糊弄过去而不是怎么去更正看来我已经养成了非常不好的习惯。那之后几天我又连续收到了测试提出的多个 bug然后将他们一个个改正。如果将这样一个漏洞百出的程序发布上线带来的损失是不可估量的现在想想仍心有余悸。二八原则 开发 1 天改 bug 4 天这件事之后我意识到在企业中开发项目不能只追求开发时的效率还要注重项目的稳定性否则带来的额外返工时间远比开发时节省的时间要长而且会影响同事对你的看法。如果将开发时产生的 bug 遗留到线上后果更是不堪设想后来在字节跳动和腾讯这两家大公司工作后我进一步认识到了项目稳定性有多重要并且积累了更多只有在大公司才能学到的提升项目稳定性的经验。我总结了 10 个开发中通常不会考虑到的风险点以及 16 个减少风险、提升项目稳定性的方法分享给大家~在分享这些之前先讲个故事。达摩克利斯之剑古希腊传说中达摩克利斯是公元前 4 世纪意大利叙拉古的僭主古希腊统治者独有的称号狄奥尼修斯二世的朝臣他非常喜欢奉承狄奥尼修斯。他奉承道“作为一个拥有权力和威信的伟人狄奥尼修斯实在很幸运。”于是狄奥尼修斯提议与他交换一天的身份那他就可以尝试到首领的命运。在晚上举行的宴会里达摩克利斯非常享受成为国王的感觉。当晚餐快结束的时候他抬头才注意到王位上方仅用一根马鬃悬挂着的利剑。他立即失去了对美食和美女的兴趣并请求僭主放过他他再也不想得到这样的幸运。达摩克利斯之剑这个故事告诉我们什么呢在和平安宁之后时刻存在着危险与不安。当一个人获取多少荣誉和地位他都要付出同样多的代价。地位越高看似越安全实则越危险。居安思危对随时可能带来的严重后果要做到谨慎。那么这和软件开发又有什么关系呢下面就让我来揭秘软件开发中的达摩克利斯之剑。危机四伏“在和平安宁之后时刻存在着危险与不安。”软件开发正是如此表面上机器是 “死” 的只会按照人输入的指令或编好的程序来执行一成不变听话的很。好像我们写好代码扔到机器上后就可以高枕无忧。但真的是这样么我们真的可以信任机器和程序么其实在程序世界中危机四伏人为因素、环境因素等可能都会对我们的程序产生影响。因此我们必须时刻坚守软件开发的不信任原则保持 overly pessimistic过于悲观把和程序有关的一切请求、服务、接口、返回值、机器、框架、中间件等等都当做不可信的步步为营、处处设防。程序世界里的不信任原则那为什么写个代码要这么小心翼翼什么都不信任呢大项目的苦衷“当一个人获取多少荣誉和地位他都要付出同样多的代价。”软件开发中项目价值越大需要承受的压力也越大来听听大项目的苦衷吧。我是一个身价过亿的大项目每天服务着上千万的用户帮助他们获得知识与快乐。我的小伙伴们只看到我身上的光环和荣耀但是他们看不到我背负的压力和风险今天终于有机会和大家倾诉我的苦衷了。记得很多年前我还是个孩子只有几个小主人开发我那段时间我成长的很快。虽然只有几十个人使用我但我感到非常轻松和快乐偶尔偷会儿懒也不会被人发现。后来我的功能越来越多越来越强大。每天有数之不尽的新面孔来和我打招呼并享受我提供的服务。渐渐地更多开发者在我身上留下了印记我感觉自己正在变得复杂也开始感受到了压力。我再也找不到机会偷懒因为我一旦休息就会让我的主人们损失一比不小的财富。如今我已经是一个成熟的大项目了每天有上千万的用户依赖我我终于拥有了更大的价值却也增加了很多烦恼感受到了更大的危险。首先同时服务千万用户每秒钟都可能会有几十万、甚至几百万个请求需要我来处理因此我必须每时每刻无休止地高负载工作且不说休息哪怕稍微慢了一点就会遭到用户的投诉主人们也会因此受到批评。我的运行必须依靠很多兄弟们的支撑因此我必须和兄弟们好好相处哪怕一个兄弟倒了我都会受到影响。在我强大的实力背后有一颗非常脆弱的心。经历了那么多次的强化和改造我的功能逐渐变多的同时也因此被植入了各种框架和插件体积像滚雪球一般越来越大不知道什么时候就会爆炸。以至于主人们每次改动我时都要万分谨慎我的成长也变得十分缓慢。复杂然而最让我感到恐惧的是那些坏家伙们他们和正常的用户不同有的不断制造请求试图将我击垮。有的绕到我的背后试图直接控制我。有的对我虎视眈眈监视并记录我的一举一动。还有的尝试各种非法操作想从我身上牟取暴利。作为一个大项目真是太累了我不知道我还能坚持多久。真的可信么“地位越高看似越安全实则越危险。”如今是一个软件开源和共享的时代我们在开发项目时或多或少会使用到网上现有的资源比如依赖包、工具、组件、框架、接口、现成的云服务等等这些资源能够大大提升我们的开发效率。就拿云服务来说几乎已经成了我们开发必备的资源以前我们想要做一个网站可能需要自己买一台物理服务器然后连通网络再把项目部署上去。而如今直接登录大公司的云官网像腾讯云、阿里云然后租一台云服务器就行了非常省事。云服务再说说现在主流的开发框架以前做一个简单的网站界面可能只会使用 HTML、CSS、JavaScript 这三种最基础的技术而如今网站的样式和交互越来越复杂我们不得不使用一些知名的框架来提升开发效率比如 Vue 和 React。听起来好像没有任何问题你也根本不会去怀疑什么因为我们天生带着对大公司或者说是对名气的信任。但是你知道么当你决定使用其他人的资源时你就已经把项目系统的部分掌控权、甚至可能是半条命都交出去了。那么不妨思考一下你使用的这些资源真的可信么下面 10 个问题可能改变你对开发的认知。1. 开发工具可信么我们通常是在大而全的开发工具中编写代码比如 JetBrains IDEA 或者 Vscode。很多刚开始写代码的同学、甚至是一些经验丰富的老手都对开发工具保持绝对的信任。比如你在键盘上敲击 a那编辑器界面上显示的一定是 a。但是由于内存不足等种种原因开发工具其实也会抽风。比如你想要调用某个函数通常敲击函数名前几个字母后开发工具就会自动给你提示完整的函数名但如果开发工具没有给你提示你首先怀疑的是这个函数不存在而不是编辑器没有按预期给出提示。遇到这种情况可以稍等编辑器一下或者进一步确认函数是否真的不存在而不是立刻创建一个新的函数。又或是项目无法运行怎么排查都觉得没问题这时不妨重新启动下开发工具或者清理一下缓存说不定项目就能正常运行了还有很多非常有意思的情况比如编辑器一片大红各种提示错误但是项目依然能成功运行。为什么不能运行为什么能运行因此不要绝对相信开发工具。2. 开源项目可信么现在是一个软件开源的时代在 GitHub 等开源项目平台上能够找到大量优秀的开源项目好的开源项目甚至可以得到 10 万多个关注那这些知名的开源项目可信么不完全可信从每个开源项目的 Issues 就能看出这点而且通常越大的项目被发现的问题越多比如 Vue 项目累积提出并关闭了 8000 多个问题。Vue 项目的问题我记得自己有一次使用知名的开源服务器 Tomcat就遇到了 bug每次接受到特定的请求都会报错。刚开始我根本没有怀疑是 Tomcat 的问题而是绞尽脑汁地想自己的代码哪里写错了。后来经过反复的排查和搜索终于确认了就是 Tomcat 本身的 bug虽然开源项目并不完全可信但是相对于私有项目而言所有对项目感兴趣的同学可以共同发现项目中的问题并加以解决在一定程度上还是能够提高项目的可靠性的。3. 依赖库可信么我们在开发项目时通常会用到大量的依赖库。直接在官方依赖源比如 Maven 和 npm搜索依赖库然后使用包管理器用一行命令或者编写配置文件就能够让其自动安装依赖非常方便。但是这些发布到官方源的依赖库就可信么且不说基本每个开发者都有机会发布依赖库到官方就算是互联网大公司的依赖库也未必可信。给我印象最深刻的就是阿里巴巴的 JSON 序列化类库 fastjson几乎无人不知、无人不晓因为其极快的解析速度广受好评。但是这个库被多次曝光存在高危漏洞可以让攻击者远程执行命令一般的开发者根本不会发现这点从而给项目带来了极大的危害。因此在选用依赖库的时候要做好充分的调研尽量确认依赖库的安全并且保证不要和已有的依赖冲突。4. 编程语言可信么Java 是一种强类型语言具有健壮性。这句话我相信所有学过 Java 的同学都再熟悉不过了。但是强类型编程语言就一定可信么这里可能有同学就要表示怀疑了如果我们一直使用的最基础最底层的编程语言都存在 bug那我们怎么去相信建立在这些编程语言上的框架呢然而真相是所有的编程语言都有 bug而且基本每次编程语言发布新版本时都会对一些历史 bug 进行修正。就 Java 而言甚至还有一个专门记录 bug 的数据库Java Bug 数据库但是对于大多数开发者来说我相信即使在程序中偶然触发了编程语言本身的 bug也没有足够的自信去质疑而是直接修改代码来绕过。确实质疑编程语言需要一定的基础和知识储备但是一旦发现了程序中莫名其妙的问题建议大家不要直接忽略可以花一些时间去探索研究说不定你就成功地发现了一个重大的 bug也能够加深对这门编程语言的理解。5. 服务器可信么服务器是项目赖以生存的宿主服务器的性能和稳定性将直接影响到项目进程。无论是个人开发者还是企业通常都会直接租用大公司提供的云服务器来部署项目省去了自己搭建和维护的麻烦。但是大公司的云服务器就可信么不完全可信即使现在的云服务器提供商都承诺自己的服务 SLA服务级别协议可以达到 5 个 999.999% 一年约宕机 5 分钟甚至 6 个 999.9999% 一年约宕机 30 秒但是仍然存在一定的风险。有一个非常有名的案例在 2013 年中国最大的社交通讯软件出现大规模的故障多达几亿用户受到影响。原因竟然是市政道路建设的一个不注意把网络光缆挖断了就导致该软件所在服务器的无法访问。除了可用性的不可信之外可能还有一些安全隐私方面的问题。当然云服务商通常是不会获取用户的数据的但也没有办法绝对相信他们。毕竟数据的隐私对企业至关重要这也是为什么大的公司都会搭建属于自己的服务器机房和网络。机房6. 数据库可信么企业中的大多数业务数据都是存放在数据库中的通过项目后端程序来操作和查询数据库中的数据。和服务器一样我们可以使用软件自己搭建数据库比如 MySQL也可以直接租用大公司的云数据库那么数据库可信么其实在企业后端项目中数据库通常是性能瓶颈相对比较脆弱当访问并发量大一点时数据库的查询性能就会下降严重时可能整个宕机即使是大公司提供的云数据库服务遇到慢查询需要较长时间的查询时可能也无从应对。数据库中的数据其实也未必可信有时管理员的一个误操作不小心删除数据或添加了一条错误数据可能就会影响用户造成损失。更有甚者竟然删库跑路不讲码德删库跑路因此不要过于信任数据库应当使用缓存之类的技术帮助数据库分担压力并定期备份。否则一旦数据库宕机或数据丢失带来的损失是不可估量的7. 缓存服务可信么缓存是开发高性能程序必备的技术通过将数据库等查询较慢的数据存放在内存中直接从内存中读取数据以提升查询性能。有了缓存之后项目不仅能够支持更多人同时查询数据还能够保护数据库。目前比较主流的缓存技术有 Redis、Memcached 等可以自己在服务器搭建也可以直接租用大公司提供的云缓存服务。存储键值对的缓存那么缓存服务是否可信呢项目的并发量不是特别大的话一般的缓存技术就足以支持了但是如果项目的量级很大可能缓存也无法承受住压力严重时就会宕机。而一旦缓存挂掉大量的查询命令会直接请求数据库于是数据库也会在瞬间挂掉严重时还会导致整个项目瘫痪因此在使用缓存时需要对并发量进行评估通过搭建集群和数据同步保证高可用性。此外还要预防缓存雪崩、缓存穿透、缓存击穿等问题简单解释一下。缓存雪崩指大量缓存在同一时间过期请求都访问不到缓存全部打到数据库上导致数据库挂掉。缓存穿透持续访问缓存中不存在的 key 导致请求直接打到数据库上导致数据库挂掉。缓存击穿一个被大量请求高频访问的热点 key 突然过期导致请求瞬间全部打到数据库上导致数据库挂掉。如果不预防这三个问题即使是租用大公司的缓存服务也一样吹弹可破。雪崩8. 对象存储可信么项目中经常会有用户上传图片或文件的功能这类数据通常较大用数据库存储不太方便。虽然我们可以将文件直接存到服务器上但更好的做法是使用专门的对象存储服务。可以简单地把对象存储当做一个大的文件夹我们可以通过它直接上传和下载文件。大的云服务商也都提供了专业的对象存储服务而无需自己搭建那么对象存储可信么一般情况下上传到对象存储的文件是不会缺失或丢失的而且还可以将已上传的数据进行跨园区同步起到备份的作用。跨园区同步但是记得有一次上传到对象存储上的文件和源文件竟然不一致大小足足少了 1M。起初我以为是文件上传到对象存储时会自动被压缩但是将对象存储中的文件下载到本地后发现的确和源文件不一致虽然出现这种情况的概率极其小但从那一刻起我再也不相信对象存储了。再用自己的真实经历来聊聊对象存储的跨园区同步。因为个人负责的业务比较重要万一单个机房整体挂掉可能分分钟是几十万元的损失因此我为对象存储配置了自动跨园区同步将文件先上传至广州机房然后数据会自动同步到上海机房且运维同学承诺自动同步的延迟不超过 15 分钟。我相信大部分开发者配置数据同步后也就不管了相信它一定会自动同步的。结果后面我编写程序去做同步监控、对比数据时发现经常出现数据未同步的情况比例高达 10%因此不能完全相信对象存储虽然大部分情况下大公司的对象存储服务很可靠但不能确保万无一失。尤其是同步备份的场景下是否真的同步成功了又有多少同学关心过呢不妨写个程序去验证和保障。9. API 接口可信么在开发中我们经常会调用其他系统提供的 API 接口来轻松实现某种功能。比如查询某地的天气可以直接调用其他人提供的天气查询接口而无需自己编写。我们也可以提供 API 接口给其他人使用尤其是在微服务架构中各服务之间都是以接口调用的形式实现交互协作的。几乎所有的 API 接口提供者都会说自己的接口有多安全、请放心使用那么 API 接口真的可信么其实API 接口是最不可信的资源首先API 接口的提供方可以是任何开发者很难通过他们的一面之词来确定接口的稳定性和安全性。即使这个接口性能很高、也很安全但是你并不了解有多少人和你在同时使用这个接口也许只有你又也许是 100 万个其他的开发者呢在这个竞争条件下接口的 qpsquery per second 每秒查询数还能达到预期么接口返回时长真的不会超时么更有甚者偷偷地把 API 接口改动了却没有给调用者发送通知这样接口的调用方全部都会调用失败严重影响项目的运行因此我们在调用第三方 API 接口时一定要慎重、慎重、再慎重此外如果我们是 API 接口的提供者也要注意保护好自己的 API 接口避免同时被太多的开发者调用导致接口挂掉。API 存在复杂的调用关系10. Serverless 可信么如果说服务器不可信那我们干脆就不租服务器了直接租用大公司提供的 Serverless 服务来作为项目的后台不就行了Serverless 指无服务器架构并不是真的不需要服务器而是将项目接口的部署、运维等需要对服务器的操作交给服务商去做让开发者无需关心服务器专心写代码就好。docker 容器听起来非常爽那 Serverless可信么使用 Serverless虽然能够大大提升开发和运维效率但是其相对服务器等资源而言更不可信首先Serverless 本身就是部署在服务器上的难免会受到服务器的影响。其次Serverless 服务不会长期保持应用的状态而是随着请求的到来而启动存在冷启动时期虽然也有很多相关的优化和解决方案但仍无法精确地保证接口的性能尤其是在高并发场景下性能往往达不到预期。最重要的是当你选择使用 Serverless 服务时你就和某云服务提供商绑定了后续想要迁移是非常困难的试想一下你项目的所有功能都交给别人来维护真的是好事么一旦云服务提供商改造了架构或接口你的代码也要随之改动而这种改动却不是由自己控制的当然Serverless 具有非常多的优点也是云计算技术发展的必然趋势只是希望大家在使用前考虑到那些可能的风险并做好应对措施。云计算时代总结正是因为我们太过信任那些名气大、看似安全的资源所以其背后的危险才更难以被察觉带来的后果往往也更致命防御性编程“居安思危对随时可能带来的严重后果要做到谨慎。”在软件开发中虽然项目表面上能够正常运行但风险无处不在因此我们要学习防御性编程思想。把自己当成一个杠精不要相信任何人尽力去发现程序中的风险积极防御。下面给大家分享 16 个防御性编程的方法学习之后能够大大减少程序中的风险。祈祷性编程1. 编程习惯要减少程序中的风险首先要养成良好的编程习惯。首先在写代码时一定要保持良好的心态不要仓促或者以完成任务的心态去写代码。如果仅仅是为了完成需求那么很有可能不会注意到代码中的风险甚至是发现了风险也懒得去修补这样确实能够节约开发的时间但是后面出现问题后你还是要花费更多的时间去排查、沟通和修复 bug。拔苗助长适得其反。在写代码时如果在一个地方多次使用相同且复杂的变量名或字符串建议不要手动去敲而是用大家最喜欢的 “复制粘贴”防止因为手误而导致的 bug。复制粘贴一把梭此外我们在代码中应该加强对返回值的检查并且选择安全的语法和数据结构避免使用被废弃的语法。不同的编程语言也有不同的最佳编程习惯比如在 Java 语言中应该对所有可能为 NULL 的变量进行检查防止 NPENULL Pointer Error 空指针异常在开发多线程程序时选用线程安全的 ConcurrentHashMap 而不是 HashMap 等等。还可以利用 Assert断言来保证程序运行中的变量值符合预期。推荐使用一个自带检查功能的编辑器来书写代码在我们编写代码时会自动检查出错误还能给出好的编码风格的建议能够大大减少开发时的风险。此外在代码提交前一定要多次检查代码尤其是那些复制粘贴过来的文件经常会出现遗漏的修改。提交代码后也可以找有经验的同事帮忙阅读和检查下代码代码审查进一步保证没有语法和逻辑错误。编辑器语法检查和提示2. 异常处理程序的运行风云变幻同一段代码在不同情况下也可能会产生不同的结果甚至是异常。因此很多主流的编程语言中都有异常处理机制比如在 Java 中先用 try 捕获异常、再用 catch 处理异常、最后用 finally 释放资源和善后。在编程时要合理利用异常处理机制来防御代码中可能出现的种种问题。通常在异常处理中我们会记录错误日志、执行错误上报和告警、重试等。比如不信任数据库那就在查询和操作数据时添加异常处理一旦数据库抽风导致操作失败就在日志中记录失败信息并通过邮件、短信等告警方式通知到开发者就能第一时间发现问题并排查。必要时还可以实现自动重试省去一部分人工操作。异常啦3. 请求校验所有的请求都是不可信的哪怕是在公司内网也有可能因为一些失误导致发出了错误的请求。因此我们编写的每个接口在实现具体的业务逻辑前一定要先对请求参数加上校验下面列举几种常见的校验方式参数类型校验比如请求参数应该是 Integer 整型而不是 Long 长整数类型。值合法性校验比如整数的范围大于等于 0、字符串长度大于 5或者满足某种特定格式比如手机号、身份证等。用户权限校验很多接口需要登录用户或者管理员才能调用因此必须通过请求参数请求头来判断当前用户的身份被一个普通用户下载了 VIP 付费电影肯定是不合理的4. 流量控制上面提到所有的请求都是不可信的不仅仅是请求的值还有请求的量和频率。对于所有接口都要限制它的调用频率防止接口被大量瞬时的请求刷爆。对于付费接口还要防止用户对接口的请求数超过原购买数。此外还有一种容易被忽视的情况假如你的接口 A 中又调用了其他人的接口 B也许你的接口 A 自身的逻辑能够承受每秒 1000 个请求但是你确定接口 B 可以承受么因此需要进行流量控制不仅仅是预防接口被刷爆还可以保护内部的服务和调用。什么你说你的接口很牛逼每秒能抗 100 万个请求也没有调用其他的服务那我就找 100 万  1 个人同时请求你的接口看你怕不怕DDOS 分布式拒绝服务攻击常用的流量控制按照不同的粒度可分为用户流控限制每个用户在一定时间内对某个接口的调用数。接口流控限制一定时间内某个接口的总调用数。单机流控限制一定时间内单台服务器上的项目所有接口的总调用数。分布式流控限制一定时间内项目所有服务器的总请求数。当然除了上面提到的几种方式外流控可以非常灵活也有很多优秀的限流工具。比如 Java 语言 Guava 库的 RateLimiter 令牌桶单机限流、阿里的 Sentinel 分布式限流框架等。Sentinel 流控面板5. 回滚有时我们对项目的操作可能是错误的可能是人工操作也可能是机器操作从而导致了一些线上故障。这时可以选择回滚。回滚是指撤销某个操作将项目还原到之前的状态这里介绍几种常见的回滚操作。数据回滚有时我们想要批量插入数据但是数据插入到一半时程序突然出现异常这个时候我们就需要把之前插入成功的数据进行回滚就好像什么都没发生过一样。否则可能存在数据不一致的风险。最常见的方式就是使用事务来处理数据库的批量操作当出现异常时执行数据库客户端的回滚方法即可。配置回滚如果将项目的配置信息比如数据库链接地址写死到代码中一旦配置错了或者地址发生变更就要重新修改代码非常麻烦。比较好的方式是将配置发布到配置中心进行管理让项目去动态读取配置中心的配置。如果不小心发布了错误的配置可以直接在配置中心进行回滚将配置还原。发布回滚没有人能保证自己的代码正确无误很多时候项目在测试环境验证时没有发现任何问题但是一上线就漏洞百出。这就说明我们最新发布的代码是存在问题的。这时最简单的做法就是进行版本回滚将之前能够正常运行的代码重新打包发布。大公司一般都有自己的项目发布平台能够使用界面一键回滚自动发布以前版本的项目包。6. 多级缓存上面提到缓存对项目是非常重要的不仅是提升性能的利器也是数据库的保护伞。但如果缓存挂掉怎么办呢有两种方案第一种是为缓存搭建集群从而保证缓存的高可用。Redis 集群但是一切都不可信集群也有可能挂掉那么可以用第二种方案一级缓存挂掉我们就再搞一个二级缓存顶上通常在高并发项目中我们会设计多级缓存即分布式缓存  本地缓存。当请求需要获取数据时先从分布式缓存比如 Redis 中查询如果分布式缓存集体宕机那就从本地缓存中获取数据。这样即使缓存挂掉也能够帮助系统支撑一段时间。这里可能和一些多级缓存的设计不同有时我们会把本地缓存作为一级缓存缓存一些热点数据本地缓存找不到值时才去访问分布式缓存。这种设计主要解决的问题是减少对分布式缓存的请求量并进一步提升性能和上面的设计目的不同。多级缓存设计7. 服务熔断和降级每年的双十一我们会准时守着屏幕上的抢购页面只为等待那一个 “请稍后再试”我们的项目其实远比想象的要脆弱很多服务经常因为各种原因出现问题。比如搞活动时大量用户同时访问会导致对项目服务的请求增多如果项目顶不住压力就会挂掉。为了防止这种风险我们可以采用服务降级策略如果系统实在无法为所有用户提供服务那就退而求其次给用户直接返回一个 “友好的” 提示或界面而不是强行让项目顶着压力过劳死。配合服务熔断技术可以根据系统的负载等指标来动态开启或关闭降级。比如机器的 CPU 被占用爆满时就开启降级直接返回错误当机器 CPU 恢复正常时再正常返回数据、执行操作。Hystrix 就是比较有名的微服务熔断降级框架。Hystrix8. 主动检测上面提到即使是大公司的同步服务也可能会出现同步不及时甚至是数据丢失的情况。因此为了进一步保证同步成功、数据的准确我们可以主动检测。比如编写一个定时脚本或者任务每隔一段时间去检查原地址和目标地址的数据是否一致或者通过一些逻辑来检查数据是否正确。当然也可以在每次数据同步结束后都立即去检测更加保险。主动检测9. 数据补偿当检测出数据不一致后我们就要进行数据补偿比如将没有同步的数据再次进行同步、将不一致的数据进行更新等。除了用来解决主动检测出的数据不一致数据补偿也被广泛用于业务设计和架构设计中。比如调用某个接口查询数据失败后停顿一段时间然后自动重试或者从其他地方获取数据。又如消息队列的生产者发送消息失败时应该自动进行补发和记录而不是直接把这条消息作废。数据补偿的思想本质上是保证数据的最终一致性数据出错不可怕知错能改就是好孩子。这种思想也被广泛应用于分布式事务等场景中。10. 数据备份数据是企业的生命因此我们必须尽可能地保证数据的安全和完整。很多同学会把自己重要的文件存放在多个地方比如自己的电脑、网盘上等等。同样在软件开发中我们也应该把重要的数据复制多份作为副本存放在不同的地方。这样即使一台服务器挂了也可以从其他的服务器上获取到数据减少了风险。数据备份11. 心跳机制接口可是个复杂多变的家伙如果我们的项目依赖其他的接口来完成功能那么最好保证该接口一直活着否则可能会影响项目的运行。举个例子我们在使用银行卡支付时肯定需要调用银行提供的接口来获取银行卡的余额信息如果这个接口挂了获取不到余额用户也就无法支付也就损失了一笔收入因此我们需要时刻和重要的接口保持联系防止他们不小心死了。可以采用心跳机制定时调用该接口或者发送一个心跳包来判断该接口是否仍然存活。一旦调用超时或者失败可以立刻进行排查和处理从而大大减少了事故的影响时长。心跳检测12. 冗余设计在系统资源和容量评估时我们要做一些冗余设计比如数据库目前的总数据量有 1G那么如果要将数据库的数据同步到其他存储比如 Elasticsearch时至少要多预留一倍的存储空间即 2G来应对后面可能的数据增长。业务的发展潜力越大冗余的倍数也可以越多但也要注意不要过分冗余毕竟资源也是很贵的啊其实冗余设计是一种重要的设计思想。当我们设计业务或者系统架构时不能只局限于当前的条件而是要考虑到以后的发展选择一种相对便于扩展的模式。否则之后项目越做越大每一次对项目的改动都步履维艰。13. 弹性扩缩容梦想还是要有的说不定突然我们原先只有 100 人使用的小项目突然就火了有几十万新用户要来使用。但是由于我们的项目只部署在一台服务器上根本无法支撑那么多人直接挂掉导致这些用户非常扫兴再也不想用我们的项目了。梦想破碎了这也是常见的风险我们可以使用弹性扩缩容技术系统会根据当前项目的使用和资源占用情况自动扩充或缩减资源。比如当系统压力较大时多分配几台机器容器当系统压力较小时减少几台机器。这样不仅能够有效应对突发的流量增长还能够在平时节约成本并省去了人工分配调整机器的麻烦。14. 异地多活前面提到服务器是不可信的别说一个服务器挂掉由于一些天灾人祸整个机房都有可能集体挂掉和备份不同异地多活是指在不同城市建立独立的数据中心正常情况下用户无论访问哪一个地点的业务系统都能够得到正确的服务即同时有多个 “活” 的服务。而某个地方业务异常的时候用户能够访问其他地方正常的业务系统从而获得正确的服务。如此一来即使广州的机房跨了咱还有上海的上海的跨了咱还有北京的。同时活着的服务越多系统就越可靠但同时成本也越高、越复杂因此几乎都是大公司才做异地多活。千万不要让正常情况下的投入大于故障发生的损失饿了么异地多活技术实现一总体介绍15. 监控告警项目的运行不可能一直正常但是我们不可能 24 小时盯着电脑屏幕来监视项目的运行情况吧又不能完全不管项目出了 bug 等着用户来投诉。因此最好的方式是给业务添加监控告警当程序出现异常时信息会上报到监控平台并第一时间给开发者发送通知。还可以通过监控平台实时查看项目的运行情况出了问题也能更快地定位。Grafana 监控平台16. 线上诊断和热修复既然程序世界一切都不可信危险无处不在那么干脆就做最坏的打算假设线上程序一定会出 bug。既然防不胜防那就严阵以待在 bug 出现时用最快的速度修复它来减少影响。通常我们要改 bug也需要经历改动代码、提交代码、合并代码、打包构建、发布上线等一系列流程。等流程走完了可能系统都透心凉了。为提高效率我们可以使用线上诊断和热修复技术。在出现 bug 时先用线上诊断工具轻松获取项目的各运行状态和代码执行信息提升排查效率。发现问题后使用热修复技术直接修改运行时的代码无需重新构建和重启项目在 Java 中我们可以使用阿里开源的诊断工具 Arthas同时支持线上热修复功能。也可以自己编写脚本来实现但是相对复杂一些。Arthas Logo看到这里肯定有同学会吐槽怎么写个程序要考虑那么多和功能无关的问题。本来五分钟就能写完的代码现在可能一个小时都写不完超凶其实并不是所有的项目都要做到绝对的安全当然我们也做不到而是我们应该时刻保持居安思危的思想把防御性编程当做自己的习惯。实际情况下要根据项目的量级、受众、架构、紧急程度等因素来综合评估将项目做到何种程度的安全而不是过度设计、杞人忧天。让我们把时间慢下来在开发前先冷静思考预见并规避风险不要让达摩克利斯之剑落下。点小花花让他们知道你 “在看” 我