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

京东手机商品详情页技术解密

时间:2023-03-13 14:41:54 科技观察

京东手机单品页承载着每次大促期间的所有流量入口。它天然地被赋予了抗压的标签,对系统的稳定性和性能有着极其严格的要求。另外,单品页面本身的业务复杂度也比较高。单品页面有几十个垂直业务流程,展示需要个性化的单品页面。另外依赖50+基础服务,略有抖动,对整体服务质量会有比较大的影响,所以在之前的大促中出现了各种问题,不断打磨,不断优化升级,目前的系统架构可以支持近百万QPS的即时访问,而且今年的双11表现非常稳定,借此机会和大家分享一下。1、先说说APP界面开发的特点。1、手机网络和流量受限。手机商品页面向APP提供的API受运营商网络限制。为了减少客户端和后台握手的过程,界面内容大而全,涵盖了页面的所有内容。没有办法像浏览器BS的结构那样有大量的ajax请求;API接口依赖于几十个基础服务,任何一个接口的抖动对接口整体性能的影响都很大,所以必须依赖并发请求,减少接口抖动叠加的影响;单品页面图片信息较多,商品主图、插画、推荐商品、手机配件、排行榜等图片信息比较多,单图大小对流量影响很大的手机。所有发送的图片都是webp格式,大大减少了网络传输流量。2、适配不同分辨率、不同网络环境、不同系统版本的手机不同环境下的用户体验是不同的。比如弱网、低版本、分辨率差的手机,会保持最基本的购物车流程,减少一些增值的体验;图片的显示大小也会根据网络环境和分辨率进行适配。3.APP版本兼容新业务需求,尽可能变化兼容旧版本,但部分业务很难兼容旧版本,所以系统中有很多版本适配逻辑,这增加了系统的复杂性;如果客户端出现重大bug,又没有hotfix的情况下,服务器需要针对特定??版本打补丁,这也增加了代码复杂度和后期维护成本。因此,大大放大了APP界面开发的逻辑复杂度和后续的维护成本。2.单品页面业务系统架构这是目前单品页面系统的整体架构图。其他核心交易流程,如购物车、下单等,基本类似。单品页面系统主要有三个进程:OpenResty、Tracer-Collect、Tomcat,其中包含几个旁路系统。OpenResty是nginx层的web容器。它的主要职责是做静态和限流防刷。只有清洗后的流量才会流向tomcat的java进程进行真正的业务处理。Tracer-Collect过程异步通过bypassBurypoints到统一的监控平台进行实时数据分析。三、核心技术点1、OpenResty是今年618之前架构的一个变化。主要有以下几点需要考虑:业务需求,业务流量达到一定程度,需要前置静态数据和限流策略,多在前端拦截更多的流量,减轻业务系统的压力;ngx_openresty模块有效地将Nginx服务器转变为强大的web应用服务器,其高可用和高并发能力在其他0级系统中得到了很好的验证。按照规范,Lua是一种脚本语言,相对于Java语言其发展相对开放。例如,一个方法可以返回多个对象,这不适合长期的Java开发人员。在灰度过程中及时发现并修复,所以使用Lua来满足要求。除特殊需要外,不会进行过多的业务逻辑处理;任何技术改动都必须格外谨慎,并进行持续的灰度测试。我们逐渐从一台机器灰度到一组,再扩散到一个通道,**全量,并且具备实时埋藏异常数据的能力,及时发现灰度过程中的问题。一旦发现问题,必须有开关实时降级。Lua语言在很多团队使用的过程中遇到了各种各样的问题。在今年双十一的总结会上,也有团队分享了大促期间的lua死锁问题。我们这里遇到的一个场景是zk的配置数据同步到lua的时候有一定概率会出现死锁。原因:lua运行在nginx主线程中,而zk却在nginx主线程外启动了一个新的threadwatch。当zk更新时,这个新线程通知数据更新。这时候,我们直接在这个新的线程中调用lua代码,就会有死锁的可能。解决方法:在这个新线程中,不要直接调用lua代码,而是直接进入nginx主线程,通过http协议更新配置数据。2.静态数据单品页面提供给APP的API包括两个关键点,一个是静态接口,一个是动态接口数据。这里所说的静态界面主要是指静态界面数据,包括商品图片、基本信息、门店商户信息、颜色尺码、延保等。去年双11期间,由于部分热门商品的访问量较大,数量jimdb集群单个shard的连接数和操作数很高,服务压力太大。集群整体服务性能变差,所以为此进行了三级热点优化:(1CDN众所周知,CDN本来承载的是业务静态流量的热点数据,但是上面说到后端有很多适配工作,包括平台,网络环境,分辨率大小,要知道Android的分辨率是多种多样的,所以CDN很难在这个逻辑中发挥作用,所以今年针对这个逻辑进行了优化,接口发送给APP的数据都是标准的数据格式,并给APP相应的适配规则,APP根据规则动态适配,大大提高了缓存效率。另外,不要忘记添加各种开关控制和数据监控点,这也是APP开发的一个重要功能,如果APP发送的版本出现各种未知情况,那将是一场灾难。fore618历经各种灰度终于顺利上线。在618期间发挥了重要作用,CDN攻击率达到60%以上,从大促的0:00开始,大部分人还是把注意力集中在少数热门产品上。这是第一层保护。(2OpenResty(Nginx+Lua)层是静态的。上面说了这一层的重点是数据静态化和防刷,大家可能会有疑惑,CDN已经把大部分流量都屏蔽了,为什么还需要这一层?CDN只屏蔽***版App的热点流量,M通道是走内网网关的,不走CDN,老版App不走CDN,所以这一层主要依赖Nginx的共享缓存,分配100M共享空间,大促期间命中率可以达到接近20%。(3JVM本地缓存JVM的堆内存主要用于基础信息的本地缓存以及商品的特殊属性信息,支持动态接口商品热点数据,依赖Guava组件实现的LRU缓存淘汰算法,大概5000个热点sku数据,数据量约5M,这是第三层数据保护.攻击率2左右大促销期间7%。另外强调一下,这里的java对象可以动态配置为弱引用或者软引用。一般推荐使用弱引用,避免内存增长过快,导致频繁GC。3.数据异构,降低强依赖数据异构带来的好处是可以降低一些基础服务的强依赖。之前老板提到的目标之一就是基础服务暂停,上层业务还能好好生存,但是京东。从数据量上来说,成本是非常巨大的,所以APP单品页面中有些数据是异构的,以减少对基础服务接口的强依赖,主要是商品的基础数据,扩展属性信息,详细信息产品的数据。之后通过中间件JMQ进行增量数据同步变化,使用缓存中间件jimdb(redis缓存)进行存储。4.并发请求和异步APP单品页面是前期的野蛮开发。很多RPC依赖是极其不合理的。比如没有依赖的层级概念,超长的超时设置,同时依赖内外网接口,导致服务质量有任何下降,网络抖动对整体API影响很大,所以进行了SOA改造出去。主要工作是将单品页面系统从大网关中分离出来,然后制定服务接入标准并进行改造。第三个方面是并行上游基础服务调用,系统整体的并发性和稳定性都有了很大的提升。服务依赖的标准依赖接口必须是内网服务,不允许依赖外网服务;接口超时时间不超过100ms,除商品、价格、库存等部分核心数据外,其他不会重试;核心接口必须可用支持跨机房双活容灾。客户端出现问题,一定是可以切换的,一定要有降级方案;RPC调用依赖中间件JSF,是一种点对点的长连接服务,减少了每次连接建立的成本。HTTP依赖需要经过内网的LB,增加了一层代理开销,会造成一些不可控的问题。随着流量的不断增加,并行化遇到了瓶颈。每个请求都会创建大量的线程。线程维护和上下文切换本身的成本消耗CPU资源。因此,在现有HttpClient和JSF基础组件异步支持的基础上,进一步开发异步改造,单机压测效果还是比较明显的,并发能力提升40%。5、要对系统流量进行一定程度的监控,对系统各个维度的监控尤为重要,可以帮助我们缩短故障排查和定位问题的时间,甚至有助于风险预警。目前,APP业务从用户到后端的全服务链监控非常重要。完善,包括各个运营商入口流量的监控,内外网质量,负载均衡,网关流量监控,我会在下一个单品页面重点介绍业务层的监控。下面是业务监控系统数据异步埋葬的结构。主要分为两类数据。***业务指标数据,如单品页面各渠道的访问数据,通过UDP协议实时嵌入到Kafka中,再由Storm实时在线分析形成最终需要的数据落地。另一类是大流量数据,比如系统异常信息落入磁盘日志,然后通过logCollector异步发送给Kafka。这类数据在磁盘IO和网卡IO流量中占比很大。对于磁盘IO,会按照100M的文件大小生成日志文件。搬走后,删除操作。网卡IO在数据传输过程中有限速,以1m/s的速度进行传输,可以动态调整,基本不会对业务造成任何影响。大促高峰期,会按照一定比例降级。.业务系统除了基本的服务器指标CPU和MEM监控、服务性能、可用??性监控外,还引入了几个实用的业务能力监控:方法树监控,每次请求通过单品页面SOA系统的方法类作为一个节点来形成这样一棵树。这棵树很直观的看出了系统内部的依赖结构关系和任意一个节点请求量的大小。时间以红色告警标注,任何故障都可以集中在特定的点上,大大提高了故障定位和处理的时间;异常监控,对系统所依赖的外部服务,以及任何内部系统抛出的异常堆栈信息进行异步记录,并进行实时统计和告警,对控制系统的健康起着至关重要的作用;用户行为追踪,详细记录了用户在什么时候做了什么以及当时的网络情况,方便用户回放问题发生时的场景,快速帮助用户解决问题。还有很多监控细节。以上几种监控方式对现在的业务系统很有帮助,也很实用。现在业务系统非常透明,任何人都可以清楚地看到系统的健康状况,而且一些服务具有自动容错的能力,为系统的整体稳定性提供了非常大的保障。6、限流手段京东APP所有商品价格和库存都是分区域的,所以很多刷子和爬虫不停地爬取京东各个区域的价格、库存和促销信息。一个明显的特点是,当大量刷扫时,处于登录状态的用户比例会明显降低,所以单品页面对用户的实时行为数据进行分析和控制:流量清洗能力,实时分析并根据用户的pin和IP进行清洗,可以根据登录和未登录做不同的策略;系统过载保护能力,系统不能随时挂掉,对明显恶意的流量按照一定的策略进行清洗和排队,保证流量不超过系统限制负载,同时给用户一些更友好的交互体验。7、压力测试单个商品页面的压力测试比较麻烦。一方面,压测的流量大,可能导致线上出现很多不可预知的问题。另一方面,涉及的基础服务很多,涉及的人也很多。压测需要协调上下游几十人的支持,协调成本比较高。第三个方面,压测的商品数量在百万级,每次压测的SKU都会变化,脚本变化比较大。第一次压测完成后,需要人工形成压测报告,分析其中的薄弱环节。因此,APP制作了自己的压测平台,通过流程帮助解决以上问题:启动压测任务,自动采集压测数据,并生成需要的压测脚本;隔离在线流量;通知相关方确认压力测试时间和压力测试方案;根据压测脚本一步步执行压测任务;形成压力测试报告,分析测试过程中的压力问题。压测数据准备:重放线上流量日志,根据压测目标放大到一定倍数;根据各品类的流量占比选取部分商品作为热点数据进行压测,检查各环节对热点数据的处理是否合理;对于一些埋点和统计,需要能够清理这部分数据。目前主要是根据请求的一些固定特征,比如设备号、特殊标识等,上下游必须能够做到数据一致。清洁规则。4、单品页面未来的方向还有很大的优化空间,比如适应业务快速迭代的系统重构、jvm垃圾回收策略和堆内存分配大小调整、异步改造等。优化是在进行中,未来单品页面最重要的方向:动态配置:不同品类的产品可以根据单品页面的元素动态组成个性化的单品页面,从而实现完整的落地配置;细化:流量控制、自动降级等方面,可以根据用户特点,如用户级别、地域等,实施不同的策略;智能化:基于用户画像数据展示更个性化的推荐数据,为用户提供更有价值的信息。作者:陈宝安,2011年加入京东,目前主要负责手机京东核心业务(搜索、商品、购物车、结算、收银、我的京东)的后端研发).他带领团队奋战在一线多年,积累了丰富的大促准备经验,也见证了核心系统从每分钟几千单到几十万单的质变。【本文来自专栏作者张凯涛微信公众号(凯涛的博客)公众号id:kaitao-1234567】点此查看作者更多好文