当前位置: 首页 > 科技观察

疯狂的1592亿!京东麦平台618备战实践总结

时间:2023-03-17 20:18:48 科技观察

近日,京东好事连连,“谷歌5.5亿美元入股京东,大幕终于落下,累计订单金额达到1592亿元。”京东1592亿元的惊人战绩离不开强大的技术支持,下面京东麦平台资深架构师王新东将为大家揭秘京东年考背后的备考实战。作为技术研发人员,我们常开玩笑地说,京东只每年做两件事,一个是618,一个是双11!诚然,每一次大促都是一次全员操练。在这场战斗中,技术人员在团队合作、技术提升、和用户意识。很难想象有比如此规模的促销更好的锻炼方式。京麦平台是目前京东唯一所有商家都在使用的一站式店铺运营和管理平台。在京麦的帮助下,商家可以实现产品发布、订单打印、仓库发货、订单消息接收等一系列日常工作,京麦平台聚集了众多ISV厂商提供商户ts功能更丰富,更好赋能商家。京麦平台的技术架构也在随着京东业务的快速发展而演进。从早期简单的Nginx+Tomcat部署,到功能服务的模块化、独立部署,我们享受着微服务带来的便利,但同时也给我们准备大促带来了诸多挑战。首先确定自己的准备思路,梳理核心流程,找出薄弱环节,针对薄弱环节进行针对性优化。同时,配合压力测试验证优化结果。优化和压力测试将是一个迭代过程。后面我们会进行实战演练,比如降级开关,防止实际情况出现时准备好的功能不可用。***我们会做一轮培训,在工具的使用上,快速定位问题,总结以往的经验教训。从心理层面来说,我们也需要心理咨询。大促期间出现的问题可不是小问题。研发人员在这样的压力下处理问题有时会变形。我们会在这方面做心理疏解。中间我们可以用几个规则,第28条规则,找出20%的重要核心功能,比如京麦的登录、交易、价格门新闻推送。在寻找弱点的时候,我们可以试试墨菲定律的几条规则,“会出错的事情总会出错”,“如果你担心某事会发生,那么它可能就会发生。”我们也会让大家列出我们心目中最不容易出问题的系统和功能点,并重点关注。是的,我们应该关注他们。我们常用的准备技巧肯定不是重启、回滚、加机。我个人的总结是:分离技术缓存技术SQL优化快速失败降级限流下面一一介绍。分离技术说“天下大事,久合必分,久分必合”,但在软件架构领域,却一直是分工的趋势。例如,京麦平台提供ISV服务、京麦自有客户端等平台服务,以及监控服务、日志服务、消息服务等。这就需要业务服务的隔离和部署,离线分析和在线运行的隔离,也可以采用线程隔离,比如JSF中对每个不同的重要服务单独线程组的方法。在数据库层面,主从分离,京麦平台的业务读多写少,可以充分利用分库的资源。还可以对数据库进行细分,按照主要业务拆分不同的数据库,结合RPC使用,进一步降低数据库层面的耦合度。缓存技术如果说软件中真有灵丹妙药,我认为就是缓存。当你遇到性能优化的瓶颈,想要抗体积的时候,你就会想到缓存。这里有个铁律,就是对外暴露的接口一定不能直接到达数据库。我们常用的缓存是Redis+JVMcache。在计算Redis的渗透率时,我们可以通过UMP来实现,在一个方法的总入口中埋点,比如统计1分钟调用M次,在请求Redis的入口埋点,统计调用N次在1分钟内,计算***率:N/M。在使用Redis的时候,要注意key的值比较大。往往高值会导致Redis集群访问热点,直接kill掉单个节点。在这种情况下,我们需要拆分这么大的密钥。同时缓存是基于DB的,也就是没有设置超时时间,所以全部被Redis抵制。对于本地缓存,我们常用的是Guava-cache。通过本地缓存,我们可以做三级保护,或者支持数据等,如果数据是“体积小”、“读操作频繁”、“变化操作少”的,用这个嵌入式会很合适缓存。在SQL优化的每一次重大推广之前,我们都要对系统中的慢SQL进行抓取,而这种工作的投入产出比非常高,意味着可以以很小的代价带来很大的性能收益。在大多数情况下,SQL性能问题都是由于缺少索引引起的。这可能是因为后续业务变化太快,遗漏了上线前的codereview。这个时候就需要统一了。索引的使用也存在错误。比如index字段是string类型,但是程序请求DB的时候传的是long类型。有时我们在添加索引的时候,需要看一下判别。索引判别的计算方法是唯一索引值/记录总数。值越接近1,区分度越高。MySQL会过滤掉更多的多行数据。还有,加索引最好结合MySQL的执行计划来判断。有时候我们做的join操作太多了,比如超过3张表,就要考虑拆解这些SQL语句。然后在数据库层面,我可以把历史数据调出来,减少数据量,达到提高查询速度的目的。Fastfailfastfail策略其实是一种自我保护措施,比如调用第三方接口超时。如果超时时间设置过长,流量较大,会造成请求线程积压;如果这时候有线程隔离就好了。如果碰巧没有,那么访问量会很快导致CPU飙升。京麦平台的一个特点就是会调用大量的第三方接口服务,我们会为每个方法动态设置超时时间。如果UMP告警结合JVM性能数据,我们会降低这个接口的超时阈值,通过Zookeeper发送给各个服务节点。在大促之前,我们会重点检查MySQL、Redis、JSF等RPC调用的超时设置,确保每次RPC调用都有上限阈值。关于RPC调用超时,这里稍微多说一点,有时候我们会发现调用者的表现超过了500ms,而服务端却在100ms徘徊。除了检查网关延迟和TCP重传之外,我们还需要注意任何成熟的RPC框架都不会允许业务线程直接参与网络请求。RPC会提供一个消息队列,调用者直接和消息队列打交道。这时,我们就要考虑是不是队列有问题了。降级限流技术其实是一种救命之术。降级一般有两种:隐藏降级和容错降级。对于一些非核心功能,比如京麦的麦圈、服务号、论坛等功能,他们只是请求公共资源,比如MySQL、Redis。为了减少这种竞争,我们会暗中降级这些功能,直接切断RPC调用,不再发起远程调用,不再返回null或其他异常提示,减少对公共资源的访问。降级开关目前是京麦通过统一配置中心使用的。同样,限流技术也是京麦平台中极其重要的措施,尤其是对京麦网关的调用。我们目前使用的是令牌桶方式。实现方式是GuavaRateLimiter,简单有效。结合统一的配置中心,我们可以动态调整限流阈值。无需重启服务器即可实现快速限速策略调整。我们在网关里面还有一个设置,就是并发度,是在方法的粒度上,对于每个调用第三方的接口,都有一个并发度的值设置。而且是动态设置,也是通过Zookeeper下发给各个服务节点的。并发的具体实现是通过JDK的Semaphore。下面说说监控配置和性能压测。监控配置是必不可少的,我们要求自己在用户发现问题之前安装问题。通常在开发上线的时候,我们应该有一个统一的要求,就是每次RPC调用都要有监听和错误栈输出。准备期其实是对监控配置的一个治理过程。监控配置key要规范化,比如***.mysql.***、***.redis.***等,这样我们就可以一眼就知道操作的是什么资源。在备战过程中,京麦平台使用AOP将所有类似调用统一标准化,再结合Python脚本统一调整监控阈值。这样一方面我们完成了我们可能漏掉的监控,另一方面我们的监控配置也会按照统一的规则生成。性能压力测试是检查我们优化结果的好方法。在压测过程中,我们在关注QPS的同时,也结合服务器的CPU、IO、内存等机器性能指标来定位我们的性能瓶颈。***预估我们系统的承载能力,为申请服务器或Docker资源提供数据支持。压测工具的开发可以自己写脚本,借助jmeter、loadrunner等工具,也可以有计划地联系性能压测团队,协助他们执行。最难的是产生真正的压力。还有一个准备点,返璞归真,返代码,查看关键核心功能,查看难闻的代码。例如,很多表的SQL语句被join,日志输出没有使用条件方法或占位符方法,日志重复打印,try代码块放在事务中,循环体包含低性能语句,并且在lock代码块调用等处执行RPC***,我们可以想想自己在准备什么。总结历次大促,我认为准备工作主要在工具、知识、经验三个方面:工欲善其事,必先利其器。我们必须有一些好的工具帮助我们解决问题,比如MDC(包括CPU、网络监控等)、UMP(京东自研方法性能、可用??性等监控平台)、CAP(容器的整体监控,包括CPU负载等信息查看)。知识的高低是我们日积月累的积累,是我们认识的提高,是我们在使用工具时的引导。经验是我们对以往大大小小的教训的总结,可以借鉴他人的经验,防止类似的事情再次发生。以“固本垒打,打呆账”四个字来结束对618战争准备工作的总结,最重要的一点还是要求我们平时做好战争准备。作者:王鑫东简介:目前在京东工作,一直从事京麦平台的架构设计和开发,熟悉各种开源软件架构。在Web开发和架构优化方面具有丰富的实践经验。在NIO领域有多年的设计和开发经验,对HTTP和TCP长连接技术有深入的研究和理解。目前主要致力于移动和PC平台网关技术的优化和实施。