为快节奏的业务运营进行无意义的 ReactNative 升级
一、背景
满帮集团移动团队2018年初开始尝试ReactNative,经过近三年的发展,目前已经承载了大部分的核心业务场景,涉及16+的业务模块、200+页面,日均PV数据在千万级。核心业务使用ReactNative开发后,我们脱离了APP发版的限制,统一使用动态发版。相比于APP发版,动态发版频率提高了很多,一周最低两版,有时一周甚至会发5个版本。
2018年上线ReactNative时,用的是当时比较新的0.51版本。在后续的版本中,Facebook官方引入了诸多新的特性,比如Hooks、Hermes引擎等等。我们继续使用0.51版本,这些新特性都无法使用,而且社区中很多基于更新版本ReactNative的第三方库业务也无法使用。因此,在使用0.51版本3年之后,我们决定升级到目前较新的0.62版本。
二、0.62 主要改进
2.1 性能提升
相比于0.51版本,0.62最大的改进是,android上使用了Hermes作为JS执行引擎,在启动速度、内存占用、JS运行效率上都有非常大的提升。
2.2 稳定性提升
从0.51版本到0.62版本,修复了大量功能性和稳定性bug,比如Native 部分的SDK的健壮性得到了很大的加强,例如Android中 ReactHostView,在 show() 和 hide() 的安全性都进行了加强。又如ViewManager 部分, 不合法时直接进行了异常处理。
2.3 社区生态
ReactNative生态主要分为两部分:
2.3.1、React 本身语言特性。
**0.51** 使用的是 React 16.0, **0.6x**使用的是 16.11.+, 中间新增了很多令人兴奋的新特性,例如 **16.2.0** 的 [Context](https://reactjs.org/docs/context.html) 、 **16.8.0** 的 [Hooks](https://reactjs.org/docs/hooks-intro.html) , 这些无疑是开发的利器!
2.3.2、围绕ReactNative、React 开发的 第三方库
社区的第三方库往往两年一个周期提高 React 的依赖版本,例如比较有名到导航库 :
React-Navigation , 并且增加很多实用的新特性, 例如 ReactNative 内部路由栈开始支持页面间的激活、回到后台等特性。 这在我们日常开发中非常实用。
2.4 性能摸底
以上是Facebook官方给出的改进内容,其中性能上有较大的优化,为了对此次提升的性能有更加量化的认知,我们做了一次全面的性能测试。
2.5 Android端****性能
0.6x开始,Android端引入了Hermes引擎,带来了很大的性能提升。相比于JSC,Hermes最大的改进是支持直接运行JS代码预编译的产物,因此冷启动性能上有很大提升,同时内存占用也有一定下降,但是包体积增大了一些。
为了了解清楚性能提升数据,我们在Android端对JSC和Hermes进行了性能对比测试。
测试设备VIVOX21RAM:6G**。**
2.5.1****冷启动耗时数据
从下图可以看出,Hermes+HBC的冷启动耗时相较于JSC+JS下降了50%以上。因此我们决定使用Hermes+HBC的方案。
2.5.2 包体大小数据:
从下图可以看出,HBC二进制包的压缩比明显不如Jsbundle, 体积几乎是后者的两倍, 但是这一点可以通过后续的拆包, 端上转化HBC 等手段规避。
2.5.3 代码指令处理速度
面对大量运算以及解析的时候, JSC 性能衰退特别严重,而Hermes则相对平稳, Hermes 和 JSC 耗时比基本在 1/6左右, 出色的处理速度对帧率、 动画流畅度都有很大的提升!
2.5.4 内存****占用
测试设备VIVOX21RAM:6G
从下图测算出来的数据可以得出两条结论:
1、ReactNative 0.62 内存表现明显优于 ReactNative 0.51,这得益于Hermes的加载机制,不会把整个文件一次性load进内存解析。
2、ReactNative 0.62 的内存抖动较平缓, 这得益于 Hermes执行的产物是二进制, 而非JS代码,不需要二次转码。
整体操作流程,涉及 4 个 ReactInstanceManager 和 5个页面, 节省了 56 M 内存空间,收益确实可观。
2.6iOS端****性能
从0.51升级到 0.62后,IOS端的JS引擎依然只有JSC。但是在Jsbundle之外,支持了RAM格式, 采用RAM 以及 inline方案,冷启动速度和内存都可以得到很大的改善。但是考虑到我们后续要做基座拆分,因此没有使用RAM格式,IOS端依然使用JSC+Jsbundle的方案。因此,IOS端在内存、冷启动、指令执行速度上并没有太大提升。不过最近一个 ReactNative版本 0.64 ,官方在IOS上也开始支持 Hemers。
从性能数据上看,Android端性能有非常大的提升。升级后也能使用hooks等React的最新特性,提升开发效率,因此我们决定升级到0.62版本。
三、如何执行一次无感知升级
3.1 挑战和风险
3.1.1 多部门合作协作
如前所述,ReactNative承载了满帮大部分的核心业务场景,涉及16+业务模块,200+页面,50+开发人员。满帮集团的业务在高速发展期,各种业务运营活动的开展都以天为单位计时。业务多、人员多、迭代节奏快、稳定性要求高。 需要统筹多个测试、开发团队以及发版团队等多条线的工作。
3.1.2 SDK升级与高频率发版并行
为了满足快节奏的业务迭代,我们每周最低发布最低两次动态版本(最高一周能发布5次)。我们要求技术改造不能影响业务迭代(包括APP版本迭代和动态版本迭代),任何业务需求不能因为技术改造而延期。因此我们需要 0.51 发版工作和 0.62升级工作同步进行, 而且要互不干扰。
3.1.3 降低升级成本
快节奏高频率的发版下,SDK升级不能给业务需求的开发、测试带来过多的负担,需要把对业务开发、测试的影响尽可能的降低。本次升级作为跨越3年的大版本升级,涉及到非常多的 Release Note,我们需要尽力从底层兼容这些差异性,从而尽可能得降低开发人员修改面以及降级测试人员的回归力度,近而降低各方面的成本。
3.1.4 保证线上稳定
满帮集团核心的两款APP日均UV在500万级别,对APP体验的要求又非常严苛,异常率上升万分之一,都会导致客户投诉率提升,稳定性保障是升级方案的重中之重。但是,无论我们方案做得多完美,谁也不能保证不会有意外状况发生。因此我们需要在第一时间感知到线上异常,降低影响并及时修复。
本次ReactNative SDK升级,就像是给一辆以120码高速行驶的重型卡车更换轮胎,稍有不慎就会翻车。
3.2 升级方案原则
3.2.1 低风险
主要主要包括两点:
1. 业务风险低:不影响业务需求的迭代。
2. 稳定性风险低:不影响线上的稳定性,异常率要控制在极低的水平。
3.2.1.1 发布方案设计
为了满足上面两个条件,我们决定采用分批次、灰度的方式发布上线。
分批就是把线上用户分成多个批次,一个批次上线完成后再进行其他批次的。满帮有四款APP:运满满司机端、货车帮司机端、运满满货主端、货车帮货主端,我们结合业务特性分析后,采用的方案是两个司机端第一批上,两个货主端第二批上。
灰度放量现在业内用的非常普遍了,这里不再解释含义,下文中会详细说明灰度方案的细节。
3.2.1.2 告警和回退方案设计
真正做到低风险,我们还需要把线上问题扼杀在摇篮, 我们需要告警机制。 升级前的满帮ReactNative已经有告警机制,因此我们只需要把 0.62 拆分出一个统计维度单独计算, 因为前期灰度的量少,如果和原先的告警机制复用就很难触发告警条件。
遇到线上顽疾短时间内无法解决的我们还需要有降级方案,能够短时间内把线上的 0.62 切换到 0.51, 待问题解决后再切回 0.62.。
3.2.2 低成本:
这里的低成本是指对业务开发、测试的影响尽可能的降低。降低代码修改量、修改难度,从而降低开发投入的人力成本;降低影响范围,从而缩小测试回归范围、降低回归力度,从而节省测试投入的人力成本。
3.2.2.1 一套代码
为了降低风险,我们采用的是多批次灰度放量的形式发布上线,整个上线周期会持续很长一段时间,在上线期间,各个业务模块都在不断的迭代开发新的需求。也就是说,存量的业务代码和新需求的业务代码,都要兼容两个版本的SDK。要兼容两个版本的SDK,最简单的方案是维护两套代码,分别适配两个版本的SDK,但是这样需要写两遍代码,对业务开发来说是非常沉重的负担。为了避免这种负担,我们提出了一套代码适配两个版本SDK的方案。
3.2.2.2 开发环境切换
一套代码适配两个版本SDK,代码当然要放在一个分支上。在开发业务需求时需要分别在两个版本SDK环境上运行代码,我们提供了环境切换脚本,可以使用一行命令切换到不同的ReactNative环境上。比如:司机端在线上已经进行灰度放量了,货主端还没有开始放量,对于需要同时在司机&货主两端运行的代码,开发人员可以通过脚本切换到不同的环境进行开发, 如下图:
3.2.2.3 代码修改扫描
为了进一步降低开发人员的适配成本,我们开发了专门的脚本工具,可以扫描出所有需要修改的地方,并给出具体的修改方法。
采用如上的方案,我们做到了升级风险完全可控(通过多批次灰度升级控制稳定性),又把开发人员的适配成本将到了最低(通过一套代码适配两个版本的SDK和脚本扫描修改内容)。
四、技术准备
4.1 API changes梳理
升级之前,需要先梳理两个版本SDK之间的API差异,对0.51到0.62的所有修改有全面的认识。API change分为两种:
- breaking change
- 非breaking change 我们的方法是暴力阅读了0.51~0.62所有版本的Release Note,整理出了所有breaking changes,并给每个breaking change制定专门的适配方案。例如AsyncStorage,51版本的AsyncStorage用法是xxx,0.62版本的用法是yyy,所以0.51版本的代码和0.62版本的代码互相不兼容。 我们的适配方案是统一采用我们自己封装的Bridge[MBBridge.app.storage]
//npm install --save @react-native-community/asyncstorage
不建议使用
// import AsyncStorage from '@react-native-async-storage/async-storage';
// 建议修改为Bridge形式
// 根据KEY获取VALUE
MBBridge.app.storage.getItem({ key: BootPageModalKey.KEY_IS_SHOW_BOOTPAGEMODAL }).then(res => {
if (this.isGuidanceSwitch(res?.data?.text)) {
retuReactNative null
}
})
// 存储<KEY,VALUE>
MBBridge.app.storage.setItem({ key: Constant.StorageKey.Common.RefeReactNativeame, text: commonStore.refeReactNativeame })
4.2 代码适配方案
公司业务迭代节奏是一周三版甚至更多, 且主要使用的是ReactNative技术栈, 因此如果在如此快节奏的开发节奏下还要同步两套代码(0.51 && 0.62) , 那成本就太高了。因此我们觉得采用一套代码能够同时适配 0.51 和 0.62的方案**:**对于所有不兼容的API,封装一层适配层,屏蔽底层差异。如下图所示:
例如导航库的适配思路如下:
修改前:
这就是我们的业务层
import { StackNavigator } from "native-navigation"
const RootStack = StackNavigator(...)
export default class xxxx extends Component<any, any> {
render() {
retuReactNative (
<RootStack screenProps={this.props} />
)
}
}
修改后:
ReactNative**-lib-protocal** 就是我们的协议层
import { createStackNavigatorCompat, createAppContainerCompat } from "@ymm/ReactNative-lib-protocal"
const RootStack = createStackNavigatorCompat(...)
export default class StickerPageRouter extends Component<any, any> {
render() {
const App = createAppContainerCompat(RootStack)
retuReactNative (
<App screenProps={this.props} />
)
}
}
下面是0.62 的协议实现层:
import { NavigationActions } from 'react-navigation';
export default class StackActionsCompat {
static reset(resetAction: any){
retuReactNative NavigationActions.reset(resetAction)
}
static push(pushAction: any) {
retuReactNative NavigationActions.push(pushAction)
}
static pop(popAction: any) {
retuReactNative NavigationActions.pop(popAction)
}
static popToPop() {
retuReactNative NavigationActions.popToTop()
}
}
这样业务开发同学就可以实现一套代码跑在两个ReactNative版本上, 节省维护两套代码的成本。
4.3 脚本工具
这里的工具包括三个:
1、 API检查工具(支持本地 && CI/CD);
2、代码工程环境切换工具;
3、运行环境检查工具。
4.3.1API检查工具
API检查工具是为了检查那些在 0.51环境能运行而在 0.62上不再兼容的API,为了解决这个问题, 我们针对两个版本众多变动点抽象出API检测的规则。 检查工具使用 Python脚本编写,开发同学既可以在本地检查(直接运行python脚本或者运行npm命令) 也可以在Jekins打包时启用该检查, 检查效果如下:
正在检查:
检查异常:
检查通过:
4.3.2 环境切换工具
工程环境切换工具则是为了方便开发同学能够方便得切换0.51和 0.62 的协议实现层 和 **配置文件(package.json、metro.config.js 等) ,**这块可以用 Shell 或者 Python 实现。
这个工具保证了业务开发同学能够在一个分支上进行开发,而不用把关注点放在 0.51 和 0.62 的APi差异和配置差异上。
4.3.3 环境检查工具
运行环境检查工具则是为在测试环境检查 ReactNative SDK 环境和 Bundle产物不匹配的情况,例如 0.51 原生SDK加载了 0.62 的 Bundle/HBC, 或者0.62 原生SDK加载了 0.51 的Bundle 包,从而避免不必要的麻烦以及沟通成本:
五、发布方案
下图是我们升级计划的一个简图, 整个流程以角色为纬度,划分为四条主线: 开发人员、测试人员、APP版本、 动态版本。 每一条主线对应的时间轴在关键时间点都有详细的**Action。**例如:对于业务开发人员(第一条线)来说, 需要在 2020-12-18 日把适配的业务代码合入 dynamic-1231 主发布分支,随后 0.51、0.62 公用一套代码直至整个升级流程结束。
5.1、分批升级
如前所述,我们采用的是分批升级的方案,司机端APP第一批上线,货主端APP第二批上线。
Android端为了这次升级,对 ReactNative 的环境进行了插件化。为了尽可能的控制风险,第一批次Android司机端上线是通过插件动态发布的形式进行的:0.62版本的SDK和HBC的产物同时通过动态升级的方式下发到端上。动态发布的方式可以非常灵活的控制灰度节奏:为了确保稳定性,我们可以把灰度时间拉的足够长。而且,我们的动态升级平台支持线上实时回滚。
我们基于稳定性的角度出发,决定Android端通过动态升级的方式上线。但是保证稳定性的同时,也不能影响业务需求上线,0.62版本的SDK和HBC产物在线上灰度发布的同时,也会基于0.51版本的SDK和jsbundle产物同步做业务需求的发布。也就是说:0.51 和 0.62 环境需要在较长时间的在线上并行存在。
整个灰度过程中比较重要的一点是线上环境的功能同步问题:0.51 和 0.62 的产物会分别以各自的节奏发布到线上,不能相互干扰,但是同时又都必须包含所有的业务需求。
例如:0.51 每 2 天一个版本, 而 0.62 灰度周期是 10天, 因此需要保证用户无论使用的是 0.62 还是 0.51 都需要包含最新的功能, 我们的策略如下:
如上图所示,0.51和 0.62的发布是两条平行的线, 0.62 的版本号在设计上要大于 0.51的版本号**(保证了0.62 的产物永远不会被 0.51 的产物覆盖)**,每一次 0.51业务包的发布都会同步发布一个 0.62的业务包,因此可以保证以下两点:
1、线上用户使用的功能始终是最新的;
2、0.62产物始终按照自己的节奏灰度, 不会被0.51的产物覆盖。
待0.62灰度全量之后, 线上不会再发布 0.51 的业务包,线上升级切换完成!
5.2、CI/CD
由于0.51和 0.62的业务 Bundle需要较长时间的在线上并行存在, 以及两个版本的环境、产物也会存在不兼容的情况。 因此除了有测试阶段的环境检测手段之外, 还需要在CI/CD阶段插入我们的一系列校验流程:
- 环境切换;
- 把检查兼容API的python脚本集成到构建过程中;
- 根据产物类型来生成版本号规则: 0.51版本号规则 :5.91.xxx.yy
0.62版本号规则:5.91.1xxx.yyyy
- 针对Android的hbc产物生成额外的map并上传ftp。
5.3、数据准备
这里主要是埋点,用来和0.51版本的数据区分开,我们期望线上 0.62 版本产生的数据能准确得反应升级的真实情况(访问占比、稳定性), 同时我们也为 0.62 的数据单独配置了告警策略:
指标/平台 | Android | IOS |
---|---|---|
容器访问 | .scenario("enterPage") .params("is62", true) |
scenario:@"enterPage" extraDic:@{@"is62":@(true),} |
异常统计 | .scenario("jserror") .params("is62", true) |
scenario:@"jserror" extraDic:@{@"is62":@(true),} |
引擎创建耗时 | .scenario("engine_cost") .params("is62", true) |
scenario:@"engine_cost" extraDic:@{@"is62":@(true),} |
冷启动耗时 | .scenario("cold_lunch") .params("is62", true) |
scenario:@"cold_lunch" extraDic:@{@"is62":@(true),} |
六 线上验证
项目上线以后,我们所要做的就是及时跟进线上数据, 验证前期实验室数据, 以及关注监控数据, 及时调整方案。
6.1 每日报表输出
在62升级包灰度期间,每日会有报表输出, 包括每个模块的DAU、PV、JS异常用户数、JS异常率、SDK异常用户数以及SDK异常率等, 开发和测试同学可以从整体了解线上运行的状况。我们也提前制定了预案,异常率达到一定阀值时就停止灰度。
6.2 性能数据输出
以Android端的性能数据为例,最终我们从线上采集到的性能数据如下,和我们线下测量的数据基本吻合:
指标 | 业务 | 包大小 | 冷启动时长 | 热启动时长 | 内存占用 |
---|---|---|---|---|---|
升级前 | 发货页 | 5.2M | 2115ms | 48ms | 30M |
审核 | 2.4M | 1155ms | 41ms | 25M | |
... | ... | ... | ... | ... | |
升级后 | 发货页 | 7.1M | 748ms | 49ms | 21M |
审核 | 3.8M | 552ms | 43ms | 16M | |
... | ... | ... | ... | ... | |
提升 | 45% | 约64% | 无变化 | 约30% |
1、包大小
Android端采用的是Hermes+HBC的方案,打包输出的产物从字符串格式的**.jsbundle变为二进制包.hbc**, 包体积因此增长了 45% 以上。这是以空间换时间的一个优化(JIT 变为 AOT)。
2、冷启动
采用Hermes+HBC的方案后,指令运行速度大大提升,冷启动时长时减少了约64% ,启动速度提升了近三倍,基本符合我们之前的测试和预期。
3、热启动
我们做了引擎复用机制,引擎创建一次后,会驻留内存,因此第二次启动就是热启动了。热启动的过程相较于冷启动,没有JS代码加载、初始化执行等耗时操作。因此、热启动时长几乎没有改善,这也基本符合我们之前的测试和预期。
4、内存占用
Hermes引擎执行HBC,省掉了JS代码解释的过程,因此冷启动单页面运行时内存减少了 30%以上。
6.3 后续批次
第一批次的升级工作基本告一段落, 在这中间会沉淀不少最佳实践:上线计划、容错方案、测试计划、性能分析 等,第二批次货主端的升级工作仅需要在这基础上做微调整, 上线风险和整体计划会流畅很多。
司机端第一批次对稳定性做了基本的验证,我们可以确定风险整体可控。因此,货主端第二批次上线时,直接采用了跟随APP发版的方式上线。
IOS端没有插件化机制,因此两个批次都是采用跟随APP发版的方式上线,使用AppStore默认的7天灰度。
七、结束
至此, 整个升级工作告一段落。 从一开始技术预研、性能摸底、方案指定、升级测试再到最后的线上验证 ,每一个环节都必不可少,整个流程对我们跨端团队的启发不仅在技术上,同时也在沟通和任务管理上,我们是技术人员、管理人员、风控人员、产品人员。在最后,通过线上数据的分析,我们也会不断调整我们的升级策略和细节参数, 同时也是验证实验室猜想的过程。 整个过程并不能保证一帆风顺,但是只要每一个步骤都有相对靠谱的Plan B,以及团队成员的紧密合作, 升级工作并不会像想象中那般艰难。
作者简介
王超,现为满帮大前端团队架构师,目前负责满帮ReactNative平台建设。
推荐阅读
-
为快节奏的业务运营进行无意义的 ReactNative 升级
-
openEuler郑州用户组成立!openEuler与hyperfusion携手共建河南地区用户生态 - 开幕致辞 超融合操作系统业务总经理、openEuler委员会成员蒋振华先生为本次活动致辞。 在本次活动的致辞中,他提到,作为openEuler社区早期的成员,超融合见证了openEuler从成立到在各行业商业落地,再到跨越生态拐点的过程,感谢openEuler提供了一个全产业链共同创新的平台,共同推动创新技术的商业落地。 同时,本次活动得到了郑州市郑东新区大数据管理局、郑州中原科技城投资服务局的大力支持。 郑东新区大数据管理局曹光远 在活动致辞中表示,openEuler的应用和*应用设施的深度优化,为郑东新区数字化转型提供了安全、可靠、高性能的技术基础;郑州中原科技城招商服务局王林表示,郑东新区欢迎所有openEuler生态相关企业扎根当地,围绕openEuler社区共同发展,形成合力。 openEuler社区及运维功能介绍 openEuler技术委员会委员胡峰 openEuler技术委员会委员胡峰先生在本次活动中介绍了openEuler社区目前发展的整体情况,并重点从技术层面介绍了openEuler的运维功能。 openEuler 晚会 胡峰先生介绍智能运维工具 A-Ops 和 openEuler gala、 阿波罗 Apollo、智能漏洞管理解决方案等新功能,以及涵盖各种运维场景的精品运维组件。在*交流环节,许多用户就目前使用的 openEuler 在*交流环节,许多用户就自己在使用openEuler过程中遇到的一些问题与胡峰先生进行了进一步的交流。 软硬结合,构建多样化算力操作系统 Hyperfusion 基于 openEuler 的基础上,结合自身软硬件技术积累,推出了富讯服务器操作系统 FusionOS FusionOS. FusionOS 首席架构师张海亮 分享了 FusionOS FusionOS首席架构师张海亮分享了FusionOS的软硬件协同优势、卓越的性能和可靠性,以及FusionOS在金融、运营商、*、互联网等行业的实践案例,引起了众多用户的兴趣,分享结束后,不少参会者就FusionOS的特点向讲师提问并进行了交流。
-
纯干货分享 | 研发效能提升——敏捷需求篇-而敏捷需求是提升效能的方式中不可或缺的模块之一。 云智慧的敏捷教练——Iris Xu近期在公司做了一场分享,主题为「敏捷需求挖掘和组织方法,交付更高业务价值的产品」。Iris具有丰富的团队敏捷转型实施经验,完成了企业多个团队从传统模式到敏捷转型的落地和实施,积淀了很多的经验。 这次分享主要包含以下2个部分: 第一部分是用户影响地图 第二部分是事件驱动的业务分析Event driven business analysis(以下简称EDBA) 用户影响地图,是一种从业务目标到产品需求映射的需求挖掘和组织的方法。 在软件开发过程中可能会遇到一些问题,比如大家使用不同的业务语言、技术语言,造成角色间的沟通阻碍,还会导致一些问题,比如需求误解、需求传递错误等;这会直接导致产品的功能需求和要实现的业务目标不是映射关系。 但在交付期间,研发人员必须要将这些需求实现交付,他们实则并不清楚这些功能需求产生的原因是什么、要解决客户的哪些痛点。研发人员往往只是拿到了解决方案,需要把它实现,但没有和业务侧一起去思考解决方案是否正确,能否真正的帮助客户解决问题。而用户影响地图通常是能够连接业务目标和产品功能的一种手段。 我们在每次迭代里加入的假设,也就是功能需求。首先把它先实现,再逐步去验证我们每一个小目标是否已经实现,再看下一个目标要是什么。那影响地图就是在这个过程中帮我们不断地去梳理目标和功能之间的关系。 我们在软件开发中可能存在的一些问题 针对这些问题,我们如何避免?先简单介绍做敏捷转型的常规思路: 先做团队级的敏捷,首先把产品、开发、测试人员,还有一些更后端的人员比如交互运维的同学放在一起,组成一个特训团队做交付。这个团队要包含交付过程中所涉及的所有角色。 接着业务敏捷要打通整个业务环节和研发侧的一个交付。上图中可以看到在敏捷中需求是分层管理的,第一层是业务需求,在这个层级是以用户目标和业务目标作为输入进行规划,同时需要去考虑客户的诉求。业务人员通过获取到的业务需求,进一步的和团队一起将其分解为产品需求。所以业务需求其实是我们真正去发布和运营的单元,它可以被独立发布到我们的生产环境上。我们的产品需求其实就是产品的具体功能,它是我们集成和测试的对象,也就是我们最终去部署到系统上的一个基本单元。产品需求再到了我们的开发团队,映射到迭代计划会上要把它分解为相应的技术任务,包括我们平时所说的比如一些前端的开发、后端的开发、测试都是相应的技术任务。所以业务敏捷要达到的目标是需要去持续顺畅高质量的交付业务价值。 将这几个点串起来,形成金字塔结构。最上层我们会把业务目标放在整个金字塔的塔尖。这个业务目标是通过用户的目标以及北极星指标确立的。确认业务目标后再去梳理相应的业务流程,最后生产。另外产品需求包含了操作流程和业务规则,具需求交付时间、工程时间以及我们的一些质量标准的要求。 谈到用户影响的地图,在敏捷江湖上其实有一个传说,大家都有一个说法叫做敏捷需求的“任督二脉”。用户影响地图其实就是任脉,在黑客马拉松上用过的用户故事地图其实叫督脉。所以说用户影响地图是在用户故事地图之前,先帮我们去梳理出我们要做哪些东西。当我们真正识别出我们要实现的业务活动之后,用户故事地图才去梳理我们整个的业务工作流,以及每个工作流节点下所要包含的具体功能和用户故事。所以说用户影响地图需要解决的问题,我们包括以下这些: 首先是范围蔓延,我们在整张地图上,功能和对应的业务目标是要去有一个映射的。这就避免了一些在我们比如有很多干系人参与的会议上,那大家都有不同想法些立场,会提出很多需求(正确以及错误的需求)。这个时候我们会依据目标去看这些需求是否真的是会影响我们的目标。 这里提到的错误需求,比如是利益相关的人提出的、客户认为产品应该有的、某个产品经理需求分析师认为可以有的....但是这些功能在用户影响地图中匹配不到对应目标的话,就需要降低优先级或弃掉。另外,通常我们去制定解决方案的时候,会考虑较完美的实现,导致解决方案括很多的功能。这个时候关键目标至关重要,会帮助我们梳理筛选、确定优先级。 看一下用户影响到地图概貌 总共分为一个三层的结构: 第一层why,你的业务目标哪个是最重要的,为什么?涉及到的角色有哪些? 第二层how ,怎样产生影响?影响用户角色什么样的行为? (不需要去列出所有的影响,基于业务目标) 第三层what,最关键的是在梳理需求时不需一次把所有细节想全,这通常团队中经常遇到的问题。 我们用这个例子来看一下 这是一个客服中心的影响地图,业务目标是 3个月内不增加客服人数的前提下能支持1.5倍的用户数。此业务目标设定是符合 smart 原则的,specific非常的具体,miserable 是可以衡量的,action reoriented是面向活动的, real list 也是很实际的。 量化的目标会指引我们接下来的行动,梳理一个业务目标,尽量去量化,比如 :我们通过打造一条什么样的流水线,能够提高整个部署的效率,时间是原来的 1/2 。这样才是一个能量化的有意义的目标。 回到这幅图, how 层级识别出来的内容,客服角色:想要对它施加的影响,把客户引导到论坛上,帮助客户更容易的跟踪问题,更快速的去定位问题。初级用户:方论坛上找到问题。高级用户:在论坛上回答问题。通过我们这些用户角色,进行活动,完成在不增加客户客服人数的前提下支持更多的用户数量。 最后一个层级,才是我们日常接触比较多的真正的功能的特性和需求,比如引导到客户到论坛上,其实这个产品就需要有一个常见问题的论坛的链接。这个层次需要我们团队进一步地在交付,在每个迭代之前做进一步的梳理,细化成相应的用户故事。 这个是云智慧团队中,自己做的影响地图的范例,可以看下整个的层级结构。序号表示优先级。 那我们用户影响地图可以总结为:
-
对话NGC蔡岩:从机制创新到价值沉淀,解析DeFi产品开发逻辑 |链捕手 - 真正的DeFi产品首先要有足够的安全性和稳定性,如果能在此基础上有一些功能创新,那就非常好了。像 Uniswap 这样逐渐成为 DeFi 基础架构的产品,可遇而不可求。 链式捕手:固定利率协议之前关注度比较高,但观察下来发现,大部分协议还是类似于传统金融CDO(抵押债务凭证)的玩法,风险系数很高,您如何理解这块业务的价值和风险? 蔡岩:确实有些定息协议类似CDO玩法,背后绑定一个债券,但并不是所有的定息协议都是这样的玩法,像这种CDO玩法的主要代表项目是88mph,背后绑定的是Aave、Compoud这样的借贷协议,在此基础上做定息和浮息债券;像APWine,背后同样是Aave,它会发行期货收益代币来锁定你的收益;Notional本身是做借贷市场的,在此基础上做定息协议。 非 CDO 的玩法,比如 Horizon,更像是一个利率撮合器,背后需要用户通过拍卖产生更合适的目标收益率;像 Saffron、BarnBridge 等是通过风险分级来定义不同的收益率。总的来说,创新还是挺多的。 价值层面是创新和想象力,因为在传统金融领域,比如银行做固定收益证券,或者评级机构给风险分级,这些业务都非常大,利润也很丰厚。而 DeFi 的对口业务给了类似业务很大的想象空间。尤其是固定利率协议的成熟产品不多,尝试各种微创新是很有意义的。 风险程度还是要具体到不同的玩法,比如,在 Aave、Compoud 等借贷协议的固定利率协议背后,如果这些借贷协议受到攻击,与之绑定的固定利率协议也会受损。 同样,如果自己做借贷市场,可能更需要更强的开发能力。再有,如果该程序的机制或参数设计不当,同样会导致协议运行不稳定,并可能造成大量用户清盘。 总的来说,风险在于固定利率协议的设计,这是一个非常复杂的过程,需要不断地尝试和出错。 链式捕捉器:刚刚提到背后是Aave/Compound的固定费率协议风险较大,您认为Aave最大的不确定性和创新点分在哪里? 蔡岩:其实爱钱进一直被认为是走在行业前列的项目,他们的迭代速度非常快,比如率先尝试闪贷、推出新的经济激励模式、推出目前业内首个安全模块、尝试L2解决方案等等。 而在主要的借贷业务上,他们又十分谨慎,比如在抵押率、清算系数等风险参数的设计上相对于其他借贷协议较为保守,并不会存在为了吸引更多借贷资金而降低风险的要求。 与许多 DeFi 项目一样,即使 Aave 进行了多次审计,也无法保证不存在漏洞。前段时间,Aave 刚进入 V2 阶段时,白帽黑客就指出了某个漏洞。 之前的创新点可能是闪电借贷,这是当时业内独一无二的新产品功能,也为 Aave 带来了不少收益。当然,也有人批评闪电贷只能方便黑客实现资金效益的最大化,但工具本身并没有错,未来闪电贷肯定会有更多的应用场景。 其次是安全模块的设计,这有点像项目本身的储备金库,保障项目的安全性,这也是爱维开创的先河。说实话,目前大多数项目都没有做到代币模式的良性或正向运营,也做不到像Aave一样的安全模块,这是一个不小的门槛。 Chaincatcher从某种程度上来说,挖矿模式是DeFi财富效应的根本支撑,但Aave的CEO却说挖矿机制带来的动力是不可持续的,您怎么看这个观点? 蔡岩:"挖矿机制 "不可能失效,因为它是一种激励机制,或者说是项目冷启动的一种方式。但流动性开采亚博体育手机客户端不会一直高涨。比如去年11月的流行性挖矿高APY持续了一两个月就崩盘了,导致DeFi市场大幅回调。 Aave、Uniswap、Synthetix等项目真正爆发进入市值前15名也是在今年2月,我更倾向于这是头部DeFi长期价值的体现。虽然大家都喜欢抢高APY的矿机,但我个人很少参与挖矿,所以我并不觉得流动性挖矿是DeFi的基本面支撑。
-
澎湃新闻对话腾讯丁珂:从 "治已病 "到 "治未病",企业需快速构建 "安全免疫力"--丁珂指出,对企业而言,安全不是成本而是生命线 丁珂指出,对企业而言,安全不是成本而是生命线,也是商业 "硬币 "的另一面。在数字智能化的新阶段,发展驱动安全建设已成为普遍共识,企业需要转变安全思维,从被动建设到主动防御,构建一套新的安全范式和框架,以更加积极、主动的安全观来提升数字安全免疫力,以 "治未病 "的理念取代 "治已病",前置安全,快速构建 "安全免疫力"。对 "已病",前置预判,及时应对处置安全风险,才能维护品牌价值,保障健康发展。 与此同时,安全建设还普遍存在 "不知道往哪投、怎么投 "的痛点。对此,腾讯安全提出,企业可以按照数字安全免疫模型的框架进行安全全局部署,重点在业务安全、数据安全、安全运维管理、边界安全、终端安全、应用开发安全等薄弱环节的关键领域注入 "免疫增强针"。 今年进入公众视野的AIGC还在产业化、产品化的过程中,但大量攻击者已经利用它生成攻击脚本、钓鱼邮件,甚至伪造身份进行诈骗。"人工智能本身是否安全,会不会让网络更不安全? 腾讯安全研究认为,AIGC的风险主要集中在 "无法解释 "和 "无法追踪 "的特点上,但这在技术上是能够找到应对方法的。丁珂谈到,AIGC作为生产力的巨大提升,确实会带来更复杂的攻防态势和更大的防御难度。但任何新技术都要经历这样的周期。而法律法规也会随着技术的演进而不断更新,使新技术的发展更加规范和健全。 丁珂认为,随着我国网络安全法律法规体系的不断完善,合规性将给企业推进网络安全带来很大的推动力,并很直观地展现在需求端。未来,伴随着数据要素市场的建立或企业对数据价值的挖掘,也将带动数据安全市场的快速增长。 对于腾讯安全的商业逻辑和运营,丁珂表示,不谋求建立竞争壁垒,而是期望与生态共同发展,腾讯安全希望通过能力开放,实现安全与业务相伴的生态模式。 谈到未来,丁磊表示,安全领域已经进入加速发展期,在蓝海中会持续关注很多新的业务领域,希望孵化出新的商业模式,腾讯安全团队也会持续关注并抓住机会做好产品。 以下为采访实录(在不改变原意的基础上略有删减): 冲浪新闻:当前,以人工智能、大数据等新技术为驱动的第四次工业革命正向纵深推进,给人类生产生活带来深刻变革。而互联网作为新技术的载体,面临的安全挑战不仅数量越来越多,形式也越来越复杂。从互联网安全从业者的角度,腾讯观察到近年来国内外网络安全形势发生了哪些变化?这些变化呈现出怎样的趋势?