写点什么

看苏宁易购的运营保障体系如何 hold 住 818 大促

2018 年 8 月 28 日

运营质量的好坏关系着用户的体验。在日常的业务运营过程中,商品无货、页面或券过期、商铺下架、视频无法播放等问题都严重影响用户体验。如果仅凭运营的人工监控和维护来保证服务质量,不仅效率低,而且效果也不佳。业务的需求是驱使技术革新的原动力。818 前夕,面向苏宁易购线上运营质量保障的先知平台正式上线。

先知平台的设计理念基于“As was foreseen”,正如预想的那样,线上运营过程的服务质量是完全可控制的。先知运营保障体系包括线上故障发现、应急响应、故障定位、快速恢复,形成完整闭环,能自动化帮助运营修复线上问题。

下面就来看一看先知平台背后的技术实现细节。

图 1. 基于先知的运营保障体系

基于 Selenium ChomeDriver 的性能监控

先知平台最基本的功能是模拟用户(带有真实用户会话信息)来对页面进行扫描(爬虫),在浏览和购物的过程中发现潜在的运营问题。我们将问题分为三类:业务、功能和性能。业务类问题包括商品无货、页面或券过期、商铺下架等;功能类问题包括数据埋点缺失、风控失效、推荐降级等用户无法直观感受,但会产生严重后果的问题;性能类问题包括页面 yslow 评分、状态码错误、接口响应超时等问题。

技术上,我们基于 Selenium ChomeDriver 实现对页面的扫描,它提供了一套用于 Web 应用程序的自动化爬虫工具。这里有几个技术实现细节值得分享:

  1. ChomeDriver 使用的是 Headless 模式。Headless Chrome 是 Chrome 浏览器的无界面形态,可以在不打开浏览器的前提下,使用所有 Chrome 支持的特性运行你的程序。相比于 UI 操作,Headless 模式大幅提高了我们的扫描效率和性能。
  2. 实现了针对页面性能数据的采集。一般的爬虫主要是针对功能逻辑的验证,很少覆盖页面和接口的加载性能。我们参考谷歌的 Chrome DevTools Protocol,开启 ChromeDriver 的 PERFORMANCE 日志,可以收集到页面交互过程中的页面(Page)性能和网络(Network)性能数据。
  3. 启用 ChromeDriverService。这完全是出于提高测试性能的考虑。我们知道每次创建一个 ChromeDriver,完成测试以后再释放掉这个对象,等下次来了一个新的测试,仍要再新建一个对象,如此反复。这相当于每次都打开浏览器,再关闭浏览器,再打开浏览器。这种实现方式并不利于高并发大规模的使用。我们希望如 Java 的池化设计思想一样,初始化生成多个持久化的浏览器对象,后面每次测试都用这些浏览器对象进行,这样会极大提升测试性能,避免了往复创建和关闭 Chrome 进程的过程。因此引入 ChromeDriverService,ChromeDriverService 是一个管理 ChromeDriver server 的的持久化实例。

下面是一个简单 demo:

复制代码
// 设置 Chromedriver 路径
System.setProperty(ChromeDriverService.CHROME_DRIVER_EXE_PROPERTY,
                   System.getProperty("user.dir") + "/drivers/chromedriver");
// 启用 ChromeDrvierService 持有浏览器进程
ChromeDriverService chromeDriverService = new ChromeDriverService.Builder()
                   .withVerbose(true)
                   .usingAnyFreePort()
                   .build();
// 启用 Headless 模式
ChromeOptions options = new ChromeOptions();
options.addArguments("--headless");
// 开启 PERFORMANCE 日志采集
DesiredCapabilities cap = DesiredCapabilities.chrome();
LoggingPreferences logPrefs = new LoggingPreferences();
logPrefs.enable(LogType.PERFORMANCE, Level.ALL);
cap.setCapability(CapabilityType.LOGGING_PREFS, logPrefs);
cap.setCapability(ChromeOptions.CAPABILITY, options);
driver = new ChromeDriver(chromeDriverService, cap);

动态编译引擎 DynamicEngine 实时加载监控脚本

在监控的过程中,不同的业务需要关注的指标往往不同,且随着促销活动的进行不断变化。比如,之前我们没有对商品售罄状态的监控,运营有这样诉求时,要求我们必须马上能在生产环境实现对商品状态的监控。为了做到监控脚本的热拔插,我们自己实现了动态脚本编译引擎 DynamicEngine,能够实时在生产环境增加监控模板,面对需求变化具备灵活的可扩展性。

要实现 DynamicEngine,基于 JavaCompiler 读取源码,编译诊断,输出 class。JavaClassObject 负责文件抽象,代表源代码或者编译后的 class。ClassFileManager 管理 JavaClassObject,负责 JavaClassObject 的创建和保存位置,根据 Java ClassLoader 的双亲委托模式,我们需要实现自己的 DynamicClassLoader,DynamicClassLoader 继承自 URLClassLoader,将生成的 class 动态加载到 JVM。

图 2. DynamicEngine 类依赖图

Quartz 实现定时任务调度

定时任务的实现基于 Java Quartz,Quartz 是目前最为成熟, 使用最广泛的 Java 任务调度框架。Quartz 运行时由 QuartzSchedulerThread 类作为主体,循环执行调度流程。JobStore 作为中间层,按照 quartz 的并发策略执行数据库操作,完成主要的调度逻辑。JobRunShellFactory 负责实例化 JobDetail 对象,将其放入线程池运行。LockHandler 负责获取 LOCKS 表中的数据库锁。

图 3. Java Quartz 任务调度交互图

先知的监控模式包括主动监控、被动监控和漫游监控三种。主动监控是运营在后台直接配置的监控任务。被动监控是与业务系统打通,提供公共接入 API,运营页面或者事件生成时自动构建监控任务。漫游监控的设计初衷借鉴了 Chaos Monkey 的思想,运营很难知道下一个出问题的是哪一个活动页面,既然如此,我们建立了从流量入口页开始的漫游任务,会不断爬取链接建立任务来发现问题。不同的监控模式的集群是隔离的,避免任务占用资源互相影响。

图 4. 先知平台的任务调度

先知智能运营的场景应用

前面我们所阐述的监控扫描、脚本执行和定时任务调度方案,虽然能帮助运营发现线上问题,但解决问题仍需要运营的人工干预。在某些情况下,运营并不能及时完成页面的修复和维护,需要自动化的运营方案。所以,先知不仅仅是一个针对运营的监控告警平台,它还能自动化修复线上问题。

智能运营的设计思想是,先知与推荐系统、泰坦系统(运营内容管理平台)打通。如下图所示,我们以促销商品售罄问题为例,当先知发现这个问题后,先判断这个商品坑位是否允许降级,如果允许,则调用推荐系统,根据用户信息推荐出与此款商品偏好类似的替代商品。在通知泰坦系统,将替代商品维护到这个坑位。这样既保证了线上热点坑位始终有货可卖,又满足了用户的购物偏好,保证了用户体验。

图 5. 先知智能运营的场景应用

总结    

目前,先知承担了苏宁易购所有线上运营页面和活动的服务保障工作,日监控任务 10 万余个,发现并解决问题 6400 余个,帮助运营迅速定位线上问题,平均缩短解决问题时间 30 分钟,显著提高了易购的线上服务质量。未来,苏宁易购将致力于把先知打造成为开放的一站式线上服务质量保障平台,大规模监控任务并发执行、海量数据分析、智慧运营服务化都将成为苏宁易购新的技术研究和攻关课题。

作者简介

朱羿全,南京航空航天大学硕士研究生毕业,苏宁易购消费者研发中心高级技术经理,主要负责易购各系统架构优化与大促保障工作。先后参与了易购整站 Https 改造、苏宁拼购架构改造、先知业务监控平台建设等工作。专注于打造高可靠、高性能、高并发服务系统的技术研究。

2018 年 8 月 28 日 18:14649

评论

发布
暂无评论
发现更多内容

《Python深度学习》第二版重磅来袭——(Keras之父亲自编写)

计算机与AI

《前端算法系列》数组去重

徐小夕

Java 面试 算法 前端

读写分离这个坑,你应该踩过吧?

楼下小黑哥

MySQL 主从同步 读写分离

数字经济跨越五个融合发展阶段,区块链正成为基础支撑结构

CECBC区块链专委会

数字经济

第六周-作业1

Mr_No爱学习

面试被问线程安全怎么保障,我的回答让面试官眼前一亮

996小迁

Java 架构 面试 多线程

百篇已过,又是一个新篇章,谈谈感受吧

良知犹存

代码人生

Bitmap为什么那么快?

Man

redis 中间件

架构词典:语言

lidaobing

架构 语言

Newbe.ObjectVisitor 0.4.4 发布,模型验证器上线

newbe36524

.net core ASP.NET Core dotnet

5种分布式事务方案与阿里的 Seata 中间件

Bruce Duan

分布式事务 seata

S型曲线不止关乎身材?|技术人应知的创新思维模型(2)

Alan

创新 思维模型

Redis 子进程开销监控和优化方式

码农架构

Redis开发与运维

Redis 持久化方式-RDB

码农架构

redis redis持久化

第六周-学习总结

Mr_No爱学习

话题讨论 | 作为地地道道的程序员半年内都没摸过代码是什么样的体验?

xcbeyond

话题讨论

基于有限状态机与消息队列的三方支付系统补单实践

Java架构师迁哥

谷燕西:不需要银行的银行业务

CECBC区块链专委会

移动互联网

Windows下MySQL无法启动万能解决方案

MySQL从删库到跑路

MySQL

国家计算机网络与信息安全管理中心官员:数字货币的风险仍需关注

CECBC区块链专委会

信息安全

算法训练营课程纲要

陈皓07

Spock单元测试框架实战指南四 - 异常测试

Java老k

Java 单元测试 spock

警察营救安徽望江县17岁女生跳河自尽过程中,现场看热闹的旁观者们在做什么?

wbliu85

排查指南 | 当 mPaaS 小程序提示“应用更新错误(1001)”时

蚂蚁集团移动开发平台 mPaaS

小程序 问题排查 mPaaS

2. Spring早期类型转换,基于PropertyEditor实现

YourBatman

Spring Framework 类型转换 PropertyEditor

拆解增长黑客之实战(二):留存与变现

懒杨杨

读书 增长 产品运营

第十一周作业

solike

「生产事故」MongoDB复合索引引发的灾难

Kerwin

数据库 mongodb

甲方日常 64

句子

工作 随笔杂谈 日常

报销发票抵扣工资的CTO,该不该? | 法庭上的CTO(5)

赵新龙

CTO 法庭上的CTO

生产环境压测建设历程之三 淘宝网2009年的痛

数列科技杨德华

演讲经验交流会|ArchSummit 上海站

演讲经验交流会|ArchSummit 上海站

看苏宁易购的运营保障体系如何hold住818大促-InfoQ