苏宁零售云 App 稳定保障实践
1. 背景
苏宁零售云目标T4-T6级市场的业务,定位更靠谱的智慧零售解决方案和零售服务集成商,实战式跨界赋能。苏宁易购TO C的经验丰富,相关的方案很完善,但是零售云TO B相关业务启动后,业务增长迅速,App相关的稳定保障方案缺失。
2. 零售云业务的特殊性
零售云主要是TO B的业务,目标T4-T6级市场的加盟店,授权店,跟TO C业务相比,有以下有个不同点:
1)用户量不多,但是每个用户强依赖零售云相关App。
2)每笔订单金额巨大。
3)需要系统稳定。
零售云的每个用户都是一家门店的一个角色人员(老板,店长,收银员…),每家门店每天的进销存都依赖零售云配套App(零售云,零售云店员,零售云管家)。零售云App提供进货服务,零售云店员提供销售服务,零售云管家提供库存管理,报表查询等服务。可以看出,一个用户使用出现问题,就会影响到一家门店的日常销售,导致不能正常销售,每一家门店每天都付着店面租金和人员酬劳,不能营业的后果非常严重。
3. 前期快速迭代满足业务遇到的问题
1)系统问题需要门店上报给运营,运营再同步给研发负责人,问题的流程较长响应比较慢。
2)研发需要跟门店人员确认操作过程,甚至借用登录账号,体验不好。
3)App到数量的灰度发布,不能精确试点,一旦出错,影响范围较大。
4. App稳定保障思路
系统稳定的三个特点:可监控,可灰度,可回溯。对于App来说,一旦新包发出去后,想回溯就不太现实了,办法无非是提示更新或者热更新,所以我们主要针对前面两点来实现。
4.1 可监控
在监控上我们做了两个方面的工作:
1)云迹性能监控,类似友盟或者Buggly的性能统计,包括崩溃,卡顿,日活等等;
2)云迹实时日志统计分析。
4.2 可灰度
1)实现到店铺层面的灰度更新
下面我们来展开讲讲这两点的实现方式。
5. 到人的请求监控(可监控)
类似友盟或者Buggly的性能统计,我相信大部分App也都接入了,这边不做解释了,不管TO B还是TO C业务都一样。
正是基于上面的性能统计,我们得知,零售云App的使用用户,60%左右是在WIFI环境下。上面也解释了TO B业务对系统的强依赖性,但是对于流量消耗的敏感度却不高。基于前提条件,我们决定把客户端所有的网络请求数据和业务错误轨迹都记录在云迹平台,并且配置错误告警。这样做的好处有两个:1)通过短信和邮件告警,可以快速知道错误。2)通过实时日志埋点可以知道每个用户的行为和操作轨迹,方便快速定位错误。流程图如下所示:
5.1异常告警
我们根据自己的需求,配置搜索条件,告警触发条件,并以短信和邮件的方式通知给对应的负责人。如下图所示:
当有异常触发告警条件时,对应负责人会短信和邮件收到告警通知,第一时间发现问题。
5.2日志查询
1.当收到告警后,对应负责人需要登录到云迹实时日志分析平台 1) 选择对应的系统名 2) 选择日志类型 3)选择查询时间 4) 通过kibana查询语法,即可查询到该条件下的日志。
2.我们随便点开一条日志,可以看到详细的用户信息。
根据上图日志内容可以快速获取如下关键信息:
1)app版本
2)手机版本,手机型号
3)业务信息(请求地址,请求参数,返回参数,堆栈信息)
4)账号
通过上面信息可以快速定位到某个时间点下错误的请求。
3.某个用户轨迹
很多时候,某些错误是在用户特定操作下才会触发,这个时候,需要知道用户的操作轨迹,我们可以通过kibana查询语法,筛选出某个用户的所有日志,根据请求时间可以很方便的知道,用户的整个操作轨迹。如图所示,该用户最近三小时的操作行为都可以查到。
得到用户的行为轨迹,很多错误场景,研发可以自己模拟,不需要再远程咨询门店用户,方便高效定位问题。
6. 到店的移动App灰度发布(可灰度)
TO C的场景一般是用户量的灰度,比如一次灰度10000个用户,但是对于TO B却不适合,比如一次灰度100个用户,可能覆盖到100家店铺,一旦出问题这100家店铺正常销售受到影响,而且统计哪些店铺受到影响也很困难。针对零售云特殊的情况,我们制定了特殊的灰度发布流程。每个app在苏宁升级平台(MPCS)上面配置两个appid,一个为正式版本包,一个为灰度版本包,客户端根据分销前台返回的appId(0/1),区分取正式包还是灰度包的appid,进行版本更新请求。灰度期间,通过分销前台配置店铺白名单,在白名单文件中的店铺下的用户提示升级到最新版本,其他用户无影响。在灰度成功后,分销前台关闭灰度开关,进行全量升级。流程图如下所示:
灰度期间只有白名单用户才调用灰度包更新接口,其他用户调用正式包升级接口。逐步增加灰度的店铺,10个-\u0026gt;20个-\u0026gt;50个-\u0026gt;100个-\u0026gt;全量,期间注意观察云迹异常。
7. 避免的生产问题
通过上面的稳定保障,我们避免了不少生产问题,这边举两个例子:
1)四月份的一个下午,突然收到很多告警,打开云迹实时日志查到一个小时内报大量的请求超时,而且集中在某个区域,通过这些关键信息,最后定位是运营商网络的问题,当天就快速修复,对于用户来说对于整个修复过程无感知。
2)云迹告警商品详情页接口会偶尔失败,通过云迹查询到日志信息发现,商品详情页需要传的店铺编码,某些时候客户端传的是空,但是review客户端相关模块代码,确认每次都是传了店铺编码,这个时候就需要模拟用户的操作轨迹。通过查询该用户所有操作日志,分析出失败接口前面几分钟的操作行为得知,在四级页停留了很长时间后登陆失效,再次登陆后店铺编码为空,知道具体错误后,就可以在下个版本修复避免生产问题。
8. 目标展望
为了保障零售云App的稳定,我们其实还做了很多工作,这里不一一列举了,当然我们还有很多的提升空间,未来我们会不断优化监控和灰度方案,加强数据收集和分析,保障零售云App的稳定。再稳定的系统也不能保证百分之百不出问题,所以在应对可能出现的问题时,我们必须要在第一时间发现问题,快速响应解决问题。
作者简介
曹银飞,苏宁易购IT总部Android技术专家,拥有多年Android研发和管理经验。曾就职于联创,腾讯等大型互联网公司,现负责苏宁易购Android开发部产品研发与技术管理工作,在Android项目架构设计,性能优化,团队管理上有多年的实战经验。现致力于打造苏宁智慧零售相关App,希望将苏宁的零售技术能力发挥到极致。
相关文章:

小酌重构系列[8]——提取接口
前言 世间唯一“不变”的是“变化”本身,这句话同样适用于软件设计和开发。在软件系统中,模块(类、方法)应该依赖于抽象,而不应该依赖于实现。 当需求发生“变化”时,如果模块(类、方法…
多线程并发编程需要注意虚假唤醒Spurious wakeup
虚假唤醒 Spurious wakeup 如果等待线程在没有通知被调用的情况下唤醒,则称为Spurious wakeup。 解决方案就是: 使用while条件判断,更好的方案是避免使用wait这种低级的API,而是使用高级的并发工具。 因为这些高级的并发工具都是经过无数…

高中计算机个人总结怎么写,毕业生自我总结范文
毕业生自我总结范文1时光飞逝,三年忙碌而充实的大学生活在一片有序的繁忙中将要过去了,回首过去三年,内心感慨万千。我是20xx年春参加电大机械班的学习,回顾这三年的电大学习之路,饱含了汗水和收获。总结是一面镜子&am…

python - 字符串的格式化输出
# -*- coding:utf-8 -*-project: jiaxyauthor: Jimmyfile: study_2_str.pyide: PyCharm Community Editiontime: 2018-11-01 15:12blog: https://www.cnblogs.com/gotesting/# 字符串s #空字符串# 1:字符串拼接# 1.1:字符串与字符串的拼接用 连接s_1 hellos_2 worlds_3 5…
一个冷僻的知识点try直接返回finally里的设置null其实无效
先看引用类型的代码: import java.util.HashMap; import java.util.Map;public class trycatchefinally {public static void main(String[] args) {System.out.println(getMap().get("KEY"));}public static Map<String, String> getMap() {Map&l…

身份证工具类
2019独角兽企业重金招聘Python工程师标准>>> 身份证工具类 package com.pqs.common.tools;import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; import java.util.HashMap; import java.util…

目前常用的服务器端网络操作系统有,目前常用的服务器端网络操作系统是()。...
在一台IP地址为192.168.1.1的Windows Server 2008 R2计算机上安装活动目录,建立一个森林根域test.com,保留默认的域功能级别,同时使该计算机成为域test.com的首台域控制器并承担着DNS服务器和全局编录服务器的角色。 操作步骤ÿ…

如何处理用代码创建SD Sales order时遇到的错误消息KI 180
2019独角兽企业重金招聘Python工程师标准>>> 错误消息KI 180:You must enter a company code for transaction Create sales document 代码: REPORT zcreate_so.DATA: ls_header TYPE bapisdhd1,ls_headerx TYPE bapisdhd1x,lt_bapiret2 LIKE bapiret2 OCCURS …
Flink 基本原理与生产实践分享【入门必读,概念清晰】
Flink 基本原理与生产实践分享【入门必读,概念清晰】 https://zh.wikipedia.org/zh-hans/Apache_Flink Apache Flink是由Apache软件基金会开发的开源流处理框架,其核心是用Java和Scala编写的分布式流数据流引擎。Flink以数据并行和流水线方式执行任意流…

数据库模型设计——主键的设计
在数据库设计时,主要就是对实体和关系的设计,实体表现出来就是表,关系表现出来就是外键。而对于一个表,由两部分组成:主键和属性。主键的简单定义就是表中为每一行数据的唯一标识。其实更准确的说法,每一行…

jsp ajax动态添加数据,jquery Ajax实现Select动态添加数据
jquery Ajax实现Select动态添加数据,具体内容如下1.背景最近在工作中,遇到了一个关于select的问题。一般情况下,select下拉框中的数据都是固定的或者直接在jsp中读取列表值显示。但是,这次要实现select与别的选项框联动࿰…

Spring Boot(十一)Redis集成从Docker安装到分布式Session共享
2019独角兽企业重金招聘Python工程师标准>>> 一、简介 Redis是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API,Redis也是技术领域使用最为广泛的存储中间件,它是「…
Java线上问题排障:Linux内核bug引发JVM死锁导致线程假死
Java本质上还是离不开操作系统,一来Java源码是用C/C实现的,二来java进程还是需要依附于操作系统和硬件资源,有时候一些问题是操作系统级别导致的,下面的整个事件是源自一则真实的线上案例。 过程: JVM死锁导致线程不可…

从AdventureWorks学习数据库建模——保留历史数据
在业务需求中,经常需要我们在系统中能够记录历史信息,能够查看到历史变动情况,这时我们可以通过增加开始结束时间字段来记录数据的历史版本。对数据的历史记录主要分为:关系、属性历史,实体历史和变更历史。 关系、属性…

因特网的域名服务器系统的好处,dns域名服务器的作用是什么
大家好,我是智能客服时间君,上述问题将由我为大家进行解答。dns是域名系统 (Domain Name System) 的缩写,该系统用于命名组织到域层次结构中的计算机和网络服务。DNS 命名用于Internet等TCP/IP网络中,通过用户友好的名称查找计算机…

Openssl私建CA
构建私有CA: 在确定配置为CA的服务上生成一个自签证书,并为CA提供所需要的目录及文件即可;步骤: (1) 生成私钥;[rootcentos7 ~]# (umask 077; openssl genrsa -out /etc/pki/CA/private/cakey.pem 4096)Generating RSA priva…
不同版本浏览器前端标准兼容性对照表以及CORS解决跨域和CSRF安全问题解决方案
CORS也已经成为主流的跨域解决方案,不过CORF也会引发CSRF,本文先分享第三方的一个前端工具箱全面展示那些浏览器版本支持CORS,由于各家浏览器厂商因为各自原因在不同的版本里支持的标准不同,这个工具小而美,可以清晰的…

arm服务器获取文件路径中文,ssh 访问远程服务器文件路径
ssh 访问远程服务器文件路径 内容精选换一换在IntelliJ上选择“项目”,找到“.idea”文件夹,单击右键选择“新建>文件”, 输入文件名“settings.json”生成settings.json文件。如图1所示。复制以下代码至新创建的settings.json文件中&…

[Win7]如何还原[.bat]文件关联
2019独角兽企业重金招聘Python工程师标准>>> 此文已迁移到微信公众号:灰灰的Rom笔记,公众号ID:SXF-Rom。 灰灰的Rom笔记 转载于:https://my.oschina.net/shawnxia/blog/672371

Android Monkey使用
Monkey 是什么? Android SDK自带的压力测试工具,也是一个命令行工具。它向系统发送伪随机的用户事件流(如按键输入,触摸屏输入,手势输入等),实现对正在开发的应用程序进行压力测试。 ࿰…
Flink在美团的应用与实践听课笔记
本文系《Flink在美团的应用与实践》的听课笔记 原始视频视频资源已经在优酷公开:2018.8.11 Flink China Meetup北京站-Flink在美团的应用与实践 作者:刘迪珊美团 1.现状和背景 实时平台架构 最底层是数据缓存层,可以看到美团测的所有日志类…

[LeetCode]题解(python):150-Evaluate Reverse Polish Notation
题目来源: https://leetcode.com/problems/evaluate-reverse-polish-notation/ 题意分析: 给定一个数组,用这个数组来表示加减乘除,例如 ["2", "1", "", "3", "*"] -> ((2 …

微软苹果服务器宕机,苹果服务器宕机,iPhone用户别做这两项操作,微软特斯拉也中招...
原标题:苹果服务器宕机,iPhone用户别做这两项操作,微软特斯拉也中招虽然苹果一直都以安全来标榜自己,而事实上也确实如此。IOS封闭的环境,相对与安卓这个开放的环境确实要更加安全一些。苹果可以很好的抵御外来的风险&…

索尼发布无人机相机专利,支持眼部对焦
无人机将采用可折叠式设计,无需使用手机就能操控。 目前消费级无人机的行业霸主自然是大疆无疑,前段时间推出的Mavic 2再次让我们领略了大疆无人机的实力。不过近日,索尼在日本公布了其首个无人机相机专利技术,似乎在向大疆发起挑…

你需要知道的高性能并发框架Disruptor原理
Disruptor的小史 现在要是不知道Disruptor真的已经很outer了,Disruptor是英国外汇交易公司LMAX开发的一款开源的高性能队列,LMAX Disruptor是一个高性能的线程间消息传递库,它源于LMAX对并发性,性能和非阻塞算法的研究࿰…

c++11 多线程 1c++ concurrency in action
一、并行、多线程 1、计算机中的并行有两种方式:任务切换、利用多处理器多核。 纯粹的任务切换: 纯粹的多处理器多核: 任务切换与多处理器多核结合: 实际应用中是“任务切换与多处理器多核结合”方式,首先现在硬件偏移…

芯片刀片服务器,使用“刀片服务器”其实不难
刀片服务器已经轰轰烈烈地吵了将近两年的时间,市场上的刀片服务器产品也越来越多,所使用的芯片种类也逐渐发展为intel、amd、power等几种,支持的平台也包括了unix和ia架构。2005年底,hp还推出了基于安腾2平台的bl60p产品ÿ…

Prometheus 对比 Zabbix
公司要上监控,Prometheus 是最热门的监控解决方案,作为喜新厌旧的程序员,我当然是选择跟风了,但上级更倾向于 Zabbix,那没办法,只能好好对比一番,给出几个靠谱的理由了。 但稍稍深入一点&#x…

好理解的Java内存虚假共享(False Sharing)性能损耗以及解决方案
虚假共享(False Sharing)也有人翻译为伪共享 参考 https://en.wikipedia.org/wiki/False_sharing 在计算机科学中,虚假共享是一种性能降低的使用模式,它可能出现在具有由高速缓存机制管理的最小资源块大小的分布式一致高速缓存的系统中。当系统参与者将…

delphi xe 文件服务器,DelphiXE7中创建WebService(服务端+客户端)
相关资料:http://www.2ccc.com/news/Html/?1507.htmlhttp://www.dfwlt.com/forum.php?modviewthread&tid922DelphiXE7新建WebService具体操作:1.打开“DelphiXE7”->“File”->“New”->“Other”2.“New Items”->“Delph…