如何基于OceanBase构建应用和数据库的异地多活

摘要: OceanBase是一个通用的分布式的关系型数据库,有很多独特的特点。比如数据库的多租户、高可用、极致弹性伸缩能力。如果把OceanBase当作单库使用,就没有把OceanBase的分布式优势发挥到极致。前言OceanBase是一个通用的分布式的关系型数据库,有很多独特的特点。比如数据库的多租户、高可用、极致弹性伸缩能力。如果把OceanBase当作单库使用,就没有把OceanBase的分布式优势发挥到极致。本文主要分享一个基于分布式架构的应用把OceanBase数据库的分布式优势发挥到极致所需要了解的OceanBase基础,这也是理解蚂蚁金服的基于OceanBase构建的三地五中心异地多活架构的基础。分布式数据库开发相关问题好的性能首先是设计出来的,应用如果追求极致的性能,就需要关注OceanBase里数据的相关事情。如:数据如何分布?数据如何读写?存储容量瓶颈怎么办?访问性能瓶颈怎么办?数据库出故障时数据可用性和可靠性具体怎样?应用需要做什么特殊处理么?数据库扩展时应用需要迁移数据么?数据迁移的时候对应用有什么影响?这些问题对理解OceanBase的分布式特点很有帮助。后面我们逐步看看OceanBase是如何应对。OceanBase集群外观首先简介一下OceanBase集群的外观。OceanBase是以集群形式运行的,由一堆服务器组成。上图是「三副本」部署,机器会分为三组,每组一个区域(称为Zone),各个机器通过网络互相访问。没有光纤交换机、共享存储以及直连网线等。服务器通常建议CPU、内存和磁盘尽可能的大,磁盘建议用普通SSD盘。普通服务器的好处是便宜,劣势是可靠性和性能可能不如小型机那么高。也就是说OceanBase可以部署在一组可靠性和性能不是特别高的普通服务器上,却提供了高性能、高可用和高可靠、弹性伸缩等多项能力。以上是一个OceanBase集群的外观和能力,但是提供给业务的并不是这个集群的全部资源和能力,而是其子集,即租户(Tenant)。OceanBase多租户特性OceanBase定义了一些基本的资源规格(Resource unit config,如4CPU8Gmem500Gdisk等),然后选取某类资源规格创建一组资源池(Resource Pool),此时集群资源就有一部分被分配出去了。最后将这个资源池关联到一个新建租户,则租户就可以使用这个资源池的能力。OceanBase默认有个sys租户,管理整个集群。用户租户必须在sys租户内部创建。如下示例就是创建租户的过程。#sys租户登录方法$mysql -hxxx.xx.11.11 -uroot@sys#obdemo -P2883 -proot oceanbase -A#资源规格(UnitConfig)create resourceunit S0_uc max_cpu=2,max_memory=‘5G’,…资源单元(Unit)create resourcepool Pool_01 unit=‘S0_uc’,unit_num=2,…租户(Tenant)create tenant test_ins resource_pool_list= (‘Pool_01’),…OceanBase兼容了大部分MySQL连接协议和语法,租户的使用体验跟MySQL实例很像。研发可以在租户里创建数据库(Database)、表(Table)。还包括分区表等。OceanBase里描述数据的最小粒度是分区。普通的表(非分区表)就是一个分区,分区表则包含多个分区。租户的示意图如下。租户之间数据是绝对隔离,资源有一定程度隔离。研发可以将业务先垂直拆分为多个独立的子业务,分别使用不同的租户或者集群。OceanBase资源单元租户里并不知道数据具体在哪个机器上,也可以说没必要知道。只是租户的性能还取决于运维为租户规划的资源池分布情况,所以了解一下资源单元的分布特点对性能规划也是有意义的。资源池(Resource Pool)是由一组资源单元(Resource Unit)组成。资源单元数量默认跟Zone的数量一致或者是它的倍数(可以配置具体分布在哪些Zone以及每个Zone里的Unit数量)。如下图资源单元具备一定的资源能力,是数据的容器。租户拥有的资源单元规格和数量决定了这个租户最大性能。资源单元可以在同一个Zone的不同节点之间自由迁移,OceanBase借此来维持各个节点的资源利用率尽可能维持一个均衡状态。OceanBase拆分设计数据库拆分数据库拆分有两种。一是垂直拆分。即按业务模块拆分到不同的实例或库里。为了模块之间互不影响,拆分到不同的实例比较好。在OceanBase里实现时可以是拆分到同一个集群里不同租户或者不同集群里的租户都可以,取决于业务规模和数据库集群规模。垂直拆分很好理解,后面不再赘述。一是水平拆分。即按某个业务维度将数据拆分到多个分片。这些分片可以是在一个库或者不同库或者不同实例的不同库下。水平拆分实现又有两类常用的选择。如下:分库分表。将一个业务表拆分到N个相同结构的物理表中。中间件做业务表(逻辑表)到分表(物理表)的映射路由以及其他相关操作(如结果聚合计算)等。这个N个物理表可以在不同实例的不同分库中。分库的维度和分表的维度可以不一样,比较灵活。分区表。将一个物理表设计为分区表,拆分到N个分区。分区表的各个分区结构是数据库内部保证一致。OceanBase选择的是分区表的水平拆分方式,并且支持二级分区表(即有2个不同的拆分维度叠加使用)。水平拆分示意图如下:上图是分库分表和分区表同时结合使用。业务表order先经过中间件拆分为100个分表(存在10个分库里),每个分表在OceanBase内部又是一个分区表(100个分区)。分库分表的维度和分区表分区的维度都是一致的,根据用户ID。分库分表和分区各有利弊。分库分表的好处是各个分表的结构一致性是在中间件层保证,比较好控制,比较适合灰度变更(允许部分分表结构不一致,最终必须全部一致)。此外更大的好处是,分库分表是实现异地多活单元话架构的必不可少的条件。缺点是中间件的SQL支持范围有限。分区的好处是在数据库内部解决了拆分问题。针对分区表的SQL功能是数据库SQL引擎的本质工作,相关特性(全局索引、二级分区等)会持续开发完善。分区分库分表架构设计,需要确定机器数、实例数、分库数和分表数的拓扑,性能理论上限取决于主实例所处的机器节点数。此后要做扩展就要调整这四个元素的数目及其联系。这种扩展很可能涉及到分表数据的迁移,需要借助外部工具或产品实现。分区架构设计,研发确定分区策略和分区数,运维确定租户的资源单元数量,OceanBase确定资源单元(Unit)在哪些机器节点上以及分区(Partition)在哪些资源单元里。同一个分区不能跨节点存储。如下图。此后要做扩展就是调整资源单元的规格、数量。OceanBase在确定Unit里的分区的位置时会尽量让每个节点的负载维持均衡。这个负载的计算方式比较复杂,会综合考虑OB节点内部CPU、内存和空间利用率等。分区随意分布对应用性能很可能有负面影响。当业务上有联系的两个表的分区分布在不同的资源单元里(同时也分布在不同的节点里),这两个表的连接就难以避免跨节点请求数据,网络上的延时会影响这个连接的性能。注: t1(p0) 表示表t1的0号分区。每个分区在集群里数据实际有三份,即三副本(Replica)。图中忽略了Zone2和Zone3的细节。三副本之间的数据同步靠把Leader副本的事务日志同步到其他Follower副本中。Paxos协议会保障这个事务日志传输的可靠性(事务日志在一半以上成员里落盘,剩余成员最终也会落盘),同时还有个以分区为粒度的选举机制,保障Leader副本不可用的时候,能快速从现有两个Follower副本里选举出新的Leader副本,并且数据还绝对不丢。这里就体现了故障切换时两个重要指标:RPO=0, RTO<30s。Locality图5中t0和t1业务上是有联系的表(如主表和详情表),两者都是分区表,分区策略和分片数都相同,OceanBase提供了一个表属性“表分组”(TableGroup)。设置为同一个表分组的不同表的分区数一定一样,并且同号分区组成一个“分区分组”(PartitionGroup)。同一个分区分组的分区一定会分配在同一个资源单元(Unit)内部(也就是会在同一个节点内部),彼此的连接逻辑就避免了跨节点请求。另外一个效果是如果一个事务同时修改两个有业务关联的分区,使用分区分组也可以规避跨节点的分布式事务。这个表分组属性的设置就是OceanBase的Locality特性之一——影响相关分区的分布。实际上每个分区都有三副本(Replica, 本文例子),图5中省略了t0(p0)和t1(p0)的其他两个副本都分别会在同一个Unit里分配。不仅如此,每个分区的三副本里都会有leader副本默认提供读写服务。leader副本是选举出来的。t0(p0)和t1(p0)的leader副本也一定会在同一个Unit里(即在同一个Zone里)。这样才彻底的避免了连接的时候跨节点请求。OceanBase的Locality特性还可以指定租户/数据库/表的默认Zone,这样下面的表的leader副本会优先被选举为这个Zone里副本。如下面例子,数据库和表会继承租户的默认设置,当然也可以自己修改primary_zone或者locality属性覆盖上层设置。:create tenant obtrans0primary_zone=‘hz1’;create table item (…)locality = ‘F@hz1, F@hz2, F@hz3,R{all_server}@hz1, R{all_server}@hz2, R{all_server}@hz3’注:F表示全功能副本,R表示只读副本。设置primary_zone后单个租户的所有表的读写都集中到一个Zone里,该租户在其他zone里的Unit就没有读写压力。通常这样做是源于业务应用的要求。如应用的请求都是来自于这个Zone,为了规避应用跨Zone读写数据性能下降。不过primary_zone更大的意义在于当集群里有很多租户的时候,可以将不同业务租户的读写压力分摊到不同Zone的机器,这样集群整体资源利用率提升,所有应用的总体性能也得到提升。后面要介绍的异地多活架构就充分利用OceanBase这个特性,在数据库层面将拆分的表的业务读写点尽可能分散到所有Zone的所有机器上。除了表与表之间可能有联系,业务模块之间也可能有联系。一个业务过程可能会横跨多个业务模块,前面这些模块的数据被垂直拆分到多个租户里。OceanBase的Locality特性“租户分组”(TenantGroup)还可以设置不同租户之间的联系。如下租户交易订单和支付订单在业务上是先后发生。create tenantgroup tgtrade tenant_array=(‘obtrade0’, ‘obpay0’);租户分组的意义依然是为了在分布式架构下尽可能将一个业务流程内多次数据库请求都约束在同一个Zone或者Region(注:OceanBase将地域相邻的Zone定义为一个Region)里。OceanBase异地多活架构异地多活概念异地多活的概念一直都有,只是内涵不断变化。以双机房多活为例,应用通常都是无状态的,可以多地部署。数据库有状态,传统数据库只有主库可以提供读写,备库最多只能提供只读服务(如ORACLE的Active Dataguard):1. 应用双活,数据库A地读写,B地不可读写。这种只有应用多活,数据库是异地备份容灾(无并发)。2. 应用双活,数据库A地读写,B地只读。这种也是应用双活,数据库读写分离(实例级并发)。3. 应用双活,数据库双活,两地应用同时读写不同表。这种数据库双向同步,应用同时错开写不同的数据(表级并发)。4. 应用双活,数据库双活,两地应用同时读写相同表不同记录。这种数据库双向同步,应用同时错开写不同的数据(行级并发)。5. 应用双活,数据库双活,两地应用同时读写相同表相同记录。这种数据库双向同步,应用同时写相同的数据,最终会因为冲突一方事务回滚(行级并发写冲突)上面第1种情形,B地应用是跨地域远程读写数据库。两地距离较大的时候性能会很不好。2的B地应用是本地访问数据库。3,4,5三种情形两地数据库都提供读写服务,对应用而言是本地访问数据库,但到分布式数据库内部,其要读写的数据是否正好在本地就取决于业务和数据库的拆分设计。有这么一种情形,B地应用访问B地数据库实例,请求的数据的写入点恰好是A地,这样会走分布式数据库内部路由远程A地实例中拿到数据,性能上会有些下降,而业务可能不知道为什么。OceanBase水平拆分方案为了避免在分布式数据库OceanBase内部发生跨Zone请求,应用的请求流量的水平拆分规则和数据的水平拆分规则要保持一致并联动,就可以实现真正的应用向本地实例请求读写的数据恰好就是在本地实例种。这就是Locality的用途所在。首先业务架构层面能根据用户ID(uid)做拆分,将用户拆分为100分。x和y是用户直接相关的表,都根据uid拆分为100个分表,分布在5个不同的租户里。x[00-19]表示20个分表。每个租户的Leader分别分布在不同的Zone。uid:00-19表示 分到这20个分片的用户数据和用户流量。应用层面在某个环节能根据UID将用户请求转发到对应的机房(Zone),应用服务之间的请求信息都有这个UID信息,后面应用请求都在本机房流转,并且访问数据库时通过分库分表中间件(DBP)和OceanBase的反向代理(OBProxy)就路由到本机房的业务租户上。实际使用这个架构时,有几个隐含的前提,Zone1和Zone2是同城双机房,Zone3和Zone4是同城双机房,两个城市靠的比较近,Zone5 实际很远,所以一般不提供写入。为节省空间,Zone5里的副本放的是日志副本。应用异地多活架构上面要实现OceanBase在每个Zone的应用写入都是恰好是本地访问,关键点就是应用流量水平拆分规则跟数据水平拆分规则保持一致。而应用要维持这样一个规则,需要很多产品都要支持水平拆分等。如下图图中流量接入层的“负载均衡”环节负责调整用户流量到对应的机房(Zone),此后的应用之间的请求就都是本地访问。能使用这个解决方案的业务都是能按用户维度做水平拆分。有些业务的拆分维度跟用户维度是冲突的,或者有些业务的数据只支持集中写入等,不能做到上面这种多活,但也可以使用OceanBase,实现单点写入,多点读取的功能。OceanBase在异地容灾和多活架构方案中的价值就是支持水平拆分规则的定义、解决了多个机房间数据同步和一致性问题、始终具备高可用和弹性伸缩能力等。参考OceanBase负载均衡的魅力蚂蚁金服异地多活的微服务体系本文作者:mq4096阅读原文本文为云栖社区原创内容,未经允许不得转载。

January 9, 2019 · 1 min · jiezi

性能诊断利器 JProfiler 快速入门和最佳实践

背景性能诊断是软件工程师在日常工作中需要经常面对和解决的问题,在用户体验至上的今天,解决好应用的性能问题能带来非常大的收益。Java 作为最流行的编程语言之一,其应用性能诊断一直受到业界广泛关注。可能造成 Java 应用出现性能问题的因素非常多,例如线程控制、磁盘读写、数据库访问、网络I/O、垃圾收集等。想要了定位这些问题,一款优秀的性能诊断工具必不可少。本文将介绍 Java 性能诊断过程中的常用工具,并重点介绍其中的优秀代表 JProfiler 的基本原理和最佳实践(本文所做的调研基于jprofiler10.1.4)。Java 性能诊断工具简介在 Java 的世界里,有许多诊断工具可供选择,既包括像 jmap、jstat 这样的简单命令行工具,又包括 JVisualvm、JProfiler 等图形化综合诊断工具,同时还有 SkyWalking、ARMS 这样的针对分布式应用的性能监控系统。下面分别对其进行介绍。简单命令行工具JDK 内置了许多命令行工具,它们可用来获取目标 JVM 不同方面、不同层次的信息。jinfo - 用于实时查看和调整目标 JVM 的各项参数。jstack - 用于获取目标 Java 进程内的线程堆栈信息,可用来检测死锁、定位死循环等。jmap - 用于获取目标 Java 进程的内存相关信息,包括 Java 堆各区域的使用情况、堆中对象的统计信息、类加载信息等。jstat - 一款轻量级多功能监控工具,可用于获取目标 Java 进程的类加载、JIT 编译、垃圾收集、内存使用等信息。jcmd - 相比 jstat 功能更为全面的工具,可用于获取目标 Java 进程的性能统计、JFR、内存使用、垃圾收集、线程堆栈、JVM 运行时间等信息。图形化综合诊断工具使用上述命令行工具或组合能帮您获取目标 Java 应用性能相关的基础信息,但它们存在下列局限:无法获取方法级别的分析数据,如方法间的调用关系、各方法的调用次数和调用时间等(这对定位应用性能瓶颈至关重要)。要求用户登录到目标 Java 应用所在的宿主机上,使用起来不是很方便。分析数据通过终端输出,结果展示不够直观。下面介绍几款图形化的综合性能诊断工具。JVisualvmJVisualvm 是 JDK 内置的可视化性能诊断工具,它通过 JMX、jstatd、Attach API 等方式获取目标 JVM 的分析数据,包括 CPU 使用率、内存使用量、线程堆栈信息等。此外,它还能直观地展示 Java 堆中各对象的数量和大小、各 Java 方法的调用次数和执行时间等。JProfilerJProfiler 是由 ej-technologies 公司开发的一款 Java 应用性能诊断工具。它聚焦于四个重要主题上。方法调用 - 对方法调用的分析可以帮助您了解应用程序正在做什么,并找到提高其性能的方法。内存分配 - 通过分析堆上对象、引用链和垃圾收集能帮您修复内存泄漏问题,优化内存使用。线程和锁 - JProfiler 提供多种针对线程和锁的分析视图助您发现多线程问题。高级子系统 - 许多性能问题都发生在更高的语义级别上。例如,对于JDBC调用,您可能希望找出执行最慢的 SQL 语句。JProfiler 支持对这些子系统进行集成分析。分布式应用性能诊断如果只需要诊断单机 Java 应用的性能瓶颈,上面介绍的诊断工具就已经够用了。但随着现代系统架构逐渐从单体转变为分布式、微服务,单纯使用上述工具往往无法满足需求,这时就需要借助 Jaeger、ARMS、SkyWalking 这些分布式追踪系统提供的全链路追踪功能。分布式追踪系统种类繁多,但实现原理都大同小异,它们通过代码埋点的方式记录 tracing 信息,通过 SDK 或 agent 将记录的数据传输至中央处理系统,最后提供 query 接口对结果进行展示和分析,想了解更多分布式追踪系统的原理可参考文章开放分布式追踪(OpenTracing)入门与 Jaeger 实现。JProfiler 简介核心组件JProfiler 包含用于采集目标 JVM 分析数据的 JProfiler agent、用于可视化分析数据的 JProfiler UI、提供各种功能的命令行工具,它们之间的关系如下图所示。JProfiler agentJProfiler agent 是一个本地库,它可以在 JVM 启动时通过参数-agentpath:<path to native library>进行加载或者在程序运行时通过 JVM Attach 机制进行加载。Agent 被成功加载后,会设置 JVMTI 环境,监听虚拟机产生的事件,如类加载、线程创建等。例如,当它监听到类加载事件后,会给这些类注入用于执行度量操作的字节码。JProfiler UIJProfiler UI 是一个可独立部署的组件,它通过 socket 和 agent 建立连接。这意味着不论目标 JVM 运行在本地还是远端,JProfiler UI 和 agent 间的通信机制都是一样的。JProfiler UI 的主要功能是展示通过 agent 采集上来的分析数据,此外还可以通过它控制 agent 的采集行为,将快照保存至磁盘,展示保存的快照。命令行工具JProfiler 提供了一系列命令行工具以实现不同的功能。jpcontroller - 用于控制 agent 的采集行为。它通过 agent 注册的 JProfiler MBean 向 agent 传递命令。jpenable - 用于将 agent 加载到一个正在运行的 JVM 上。jpdump - 用于获取正在运行的 JVM 的堆快照。jpexport & jpcompare - 用于从保存的快照中提取数据并创建 HTML 报告。安装配置JProfiler 同时支持诊断本地和远程 Java 应用的性能。如果您需要实时采集并展示远程 JVM 的分析数据,需要完成以步骤:在本地安装 JProfiler UI。在远程宿主机上安装 JProfiler agent 并让其被目标 JVM 加载。配置 UI 到 agent 的连接。具体步骤可参考文档 Installing JProfiler 和 Profiling A JVM。最佳实践本章将以高性能写 LogHub 类库 Aliyun LOG Java Producer 为原型,带您了解如何使用 JProfiler 剖析它的性能。如果您的应用或者您在使用 producer 的过程中遇到了性能问题,也可以用类似的方式定位问题根因。如果您还不了解 producer 的功能,建议先阅读文章日志上云利器 - Aliyun LOG Java Producer。本章使用的样例代码参见 SamplePerformance.java。JProfiler 设置数据采集模式JProfier 提供两种数据采集模式 Sampling 和 Instrumentation。Sampling - 适合于不要求数据完全精确的场景。优点是对系统性能的影响较小,缺点是某些特性不支持(如方法级别的统计信息)。Instrumentation - 完整功能模式,统计信息也是精确的。缺点是如果需要分析的类比较多,对应用性能影响较大。为了降低影响,往往需要和 Filter 一起使用。由于我们需要获取方法级别的统计信息,这里选择了 Instrumentation 模式。同时配置了 Filter,让 agent 只记录位于 Java 包com.aliyun.openservices.aliyun.log.producer下的类和类com.aliyun.openservices.log.Client的 CPU 分析数据。应用启动模式通过为 JProfiler agent 指定不同的参数可以控制应用的启动模式。等待模式 - 只有在 Jprofiler GUI 和 agent 建立连接并完成分析配置设置后,应用才会真正启动。在这种模式下,您能够获取应用启动时期的分析数据。对应的命令为-agentpath:<path to native library>=port=8849。立即启动模式 - 应用会立即启动,Jprofiler GUI 会在需要时和 agent 建立连接并设置分析配置。这种模式相对灵活,但会丢失应用启动初期的分析数据。对应的命令为-agentpath:<path to native library>=port=8849,nowait。离线模式 - 通过触发器记录数据、保存快照供事后分析。对应的命令为-agentpath:<path to native library>=offline,id=xxx,config=/config.xml。因为是在测试环境,同时对应用启动初期的性能也比较关注,这里选择了默认的等待模式。使用 JProfiler 诊断性能在完成 JProfiler 的设置后,便可以对 Producer 的性能进行诊断。Overview在概览页我们可以清晰的看到内存使用量、垃圾收集活动、类加载数量、线程个数和状态、CPU 使用率等指标随时间变化的趋势。通过此图,我们可以作出如下基本判断:程序在运行过程中会产生大量对象,但这些对象生命周期极短,大部分都能被垃圾收集器及时回收,不会造成内存无限增长。加载类的数量在程序初始时增长较快,随后保持平稳,符合预期。在程序运行过程中,有大量线程处于阻塞状态,需要重点关注。在程序刚启动时,CPU 使用率较高,需要进一步探究其原因。CPU viewsCPU views 下的各个子视图展示了应用中各方法的执行次数、执行时间、调用关系等信息,能帮我们定位对应用性能影响最大的方法。Call TreeCall tree 通过树形图清晰地展现了方法间的层次调用关系。同时,JProfiler 将子方法按照它们的执行总时间由大到小排序,这能让您快速定位关键方法。对于 Producer 而言,方法SendProducerBatchTask.run()耗时最多,继续向下查看会发现该方法的主要时间消耗在了执行方法Client.PutLogs()上。Hot Spots如果您的应用方法很多,且很多子方法的执行时间比较接近,使用 hot spots 视图往往能助您更快地定位问题。该视图能根据方法的单独执行时间、总执行时间、平均执行时间、调用次数等属性对它们排序。其中,单独执行时间等于该方法的总执行时间减去所有子方法的总执行时间。在该视图下,可以看到Client.PutLogs(),LogGroup.toByteArray(),SamplePerformance$1.run()是单独执行时间耗时最多的三个方法。Call Graph找到了关键方法后,call graph 视图能为您呈现与该方法直接关联的所有方法。这有助于我们对症下药,制定合适的性能优化策略。这里,我们观察到方法Client.PutLogs()执行的主要时间花费在了对象序列化上,因此性能优化的关键是提供执行效率更高的序列化方法。Live memoryLive memory 下的各个子视图能让您掌握内存的具体分配和使用情况,助您判断是否存在内存泄漏问题。All ObjectsAll Objects 视图展示了当前堆中各种对象的数量和总大小。由图可知,程序在运行过程中构造出了大量 LogContent 对象。Allocation Call TreeAllocation Call Tree 以树形图的形式展示了各方法分配的内存大小。可以看到,SamplePerformance$1.run()和SendProducerBatchTask.run()是内存分配大户。Allocation Hot Spots如果方法比较多,您还可以通过 Allocation Hot Spots 视图快速找出分配对象最多的方法。Thread History线程历史记录视图直观地展示了各线程在不同时间点的状态。不同线程执行的任务不同,所展现的状态特征也不同。线程pool-1-thread-<M>会循环调用producer.send()方法异步发送数据,它们在程序刚启动时一直处于运行状态,但随后在大部分时间里处于阻塞状态。这是因为 producer 发送数据的速率低于数据的产生速率,且单个 producer 实例能缓存的数据大小有限。在程序运行初始,producer 有足够空间缓存待发送数据,所以pool-1-thread-<M>一直处于运行状态,这也就解释了为何程序在刚启动时 CPU 使用率较高。随着时间的推移,producer 的缓存被逐渐耗尽,pool-1-thread-<M>必须等到 producer “释放”出足够的空间才有机会继续运行,这也是为什么我们会观察到大量线程处于阻塞状态。aliyun-log-producer-0-mover负责将超时 batch 投递到发送线程池中。由于发送速率较快,batch 会因缓存的数据达到了上限被pool-1-thread-<M>直接投递到发送线程池中,因此 mover 线程在大部分时间里都处于等待状态。aliyun-log-producer-0-io-thread-<N>作为真正执行数据发送任务的线程有一部分时间花在了网络 I/O 状态。aliyun-log-producer-0-success-batch-handler用于处理发送成功的 batch。由于回调函数比较简单,执行时间短,它在大部分时间里都处于等待状态。aliyun-log-producer-0-failure-batch-handler用于处理发送失败的 batch。由于没有数据发送失败,它一直处于等待状态。通过上述分析可知,这些线程的状态特征都是符合预期的。Overhead Hot Spots Detected当程序运行结束后,JProfiler 会弹出一个对话框展示那些频繁被调用,但执行时间又很短的方法。在下次诊断时,您可以让 JProfiler agent 在分析过程中忽略掉这些方法以减轻对应用性能的影响。小结通过 JProfiler 的诊断可知应用不存在大的性能问题,也不存在内存泄漏。下一步的优化方向是提升对象的序列化效率。参考资料深入浅出JProfilerJprofiler Introduction本文作者:吴波bruce_wu阅读原文本文为云栖社区原创内容,未经允许不得转载。 ...

January 7, 2019 · 2 min · jiezi

到底什么成就了今天的人工智能?(上)

摘要: 人工智能发展迅速,可是到底什么成就了今天的人工智能呢?跟随我们一起来探索吧。维基百科对智能有如下定义:智能是一种能够感知或推断信息,并将其作为知识留存下来,自适应地用于某种环境或上下文的能力。*人工智能(Artificial Intelligence)虽然我们很难对人工智能做一个确切的解释,但可以从查尔斯巴贝奇的分析机讲起。它虽然没有任何特殊的“自适应”能力,但却非常灵活。遗憾的是,理论上虽然完美,但却没有得以实现。巴贝奇分析机早图灵机50年左右出现。从理论上讲,它能够将任何可计算的函数作为输入,并在完全机械的情况下产生输出。复杂性理论(complexity theory)由此得以发展,同时人们也意识到构建通用计算机其实相对简单。此外,算法的实现也越发多样。尽管还存在一些技术上的挑战,但在过去的70年中,相同价格可购买到的计算量大约每两年翻一番。也就是说,构建计算力强大的人工智能系统越发容易。然而,这受到了所提供或输入的数据,以及处理时间的限制。可以做如下思考:如果每台计算机的能力都受到数据和时间的限制,我们还能称之为智能计算机么?下面我们简单回顾一下人工智能的发展史。人类的智能主要包括归纳总结和逻辑演绎,对应着人工智能中的联结主义(如人工神经网络)和符号主义(如吴文俊方法)。符号主义认为智能是基于逻辑规则的符号操作;联结主义认为智能是由神经元构成的信息处理系统。其发展轨迹如下图所示:联结主义,即“橙色阵营”在一开始处于领先地位,得益于其与神经科学和人类大脑之间的关系。人类大脑被视为“强AI(Strong Artificial Intelligence)”和“通用人工智能(Artificial General Intelligence,AGI)”唯一的成功应用。然而,第一代神经网络在处理实际问题时屡屡受挫。因为神经网络多数是线性的,并且能力十分有限,深受外界质疑。与此同时,符号主义,即“蓝色阵营”利用严谨的数学理论创造出了更多有用的东西。随着手工知识的积累,输入或输出数据量急速增长,系统的性能无法适应需求,联结主义逐渐衰败。就好比法律,专家制定出再完备的规则都有可能相互冲突,此时便需要越来越多的“法官”来解决这些问题。这减缓了联结主义的发展。后来,“橙色阵营”获取了足够的标签数据和计算资源,能够在可接受的时间内对网络进行“训练”,世界各地的研究学者开始进行大量试验。尽管如此,联结主义仍花费了大量的时间使大众重新信任神经网络,开发人员也花了较长才适应了模糊逻辑和统计的概念。在对人工神经网络进行详细讨论前,本文将先介绍一些其它方法:决策树、概率模型、进化算法。决策树(Decision Tree)是最简单有效的算法之一。其“学习”是通过顺序地遍历数据的每个属性并找到对特定输出具有最大预测能力的属性来执行的。像随机森林这样的高级变体使用了更复杂的学习技术,并在同一个模型中组合多个树,它们的输出是通过“投票”得到的,这与人类的“直觉”类似。概率模型(Probabilistic models)是统计方法的代表。概率模型与神经网络常共享架构、学习/优化过程甚至符号。但是概率模型大多受概率逻辑(通常是贝叶斯)的约束,而神经网络则无此约束。进化算法(Evolutionary computation)最初是受到生物进化的启发,且以随机突变和适应度为主。由于修改通常是随机的,其限制噪声的效果突出。进化算法是一种引导式搜索,许多方面与退火过程类似。上述方法有一个共同点:它们从较差的策略开始,逐渐对其改善,以期在某种性能评估方法中取得更好的分数。如今,机器学习技术,尤其是深度学习正在主导人工智能的发展。与大多数使用1到2个中间抽象层(所谓的浅模型)机器学习方法不同,深度学习可能包含数百甚至数千个堆叠的可训练层。研究学者认为对这样的深度网络进行训练,需要全新的优化程序。事实证明,使用梯度下降的逆向传播(即链式法则)即可很好的进行训练,也可使用Adam或RMSProp。神经网络训练流程如下:1、 获取输入2、 计算输出3、 评估性能4、 调节参数5、 重复训练,至性能最优梯度下降法只需调整参数使误差最小。但该方法容易使网络陷入局部最优,而没有获得最优性能。然而,最新研究表明许多神经网络已经能够获取全局最优解。深度学习实现了训练的并行化,即分布式学习。能在同一时间跨多台机器训练相同的体系结构,同时实现梯度交换,加速超过1000倍。此外,经过训练的网络可以处理相似的任务,即迁移学习,这也是人工神经网络广泛流行的重要原因。例如,经过图像分类训练的网络可以用于其他计算机视觉任务,自然语言处理和其他领域。更重要的是,同一个网络还可以用来解决不同模式的问题。强化学习(Reinforcement Learning,RL)则将它们结合在了一起。RL的最初想法来自行为心理学,科研人员探究了在行为心理学中奖励如何影响学习和塑造动物的行为。RL并不需要出现正确的输入/输出对,也不需要精确校正次优化的行为。举个例子,我们并不需要教会机器人如何精确移动,只需根据它走多远或多快对其进行奖励,它会自己找出正确的路线。然而,这种训练模式在实践中也是最具挑战性的,即使是相对简单的任务,通常也需要付出大量的努力才能正确设置。在实际问题中,通常很难在环境中指定奖励,研究人员目前更多地关注内部奖励模型。与RL并行的是逆向强化学习(Inverse Reinforcement Learning):当完成复杂的任务时,强化学习的回报函数很难指定,我们希望有一种方法能够找到高效且可靠的回报函数,这种方法就是逆向强化学习。通用人工智能中一些框架来自于严格的数学理论,一些受神经元回路的启发,还有一些基于心理模型。本文将以HTM、AIXI、ACT-R和SOAR为例进行介绍。层级实时记忆算法 (Hierarchical Temporal Memory,HTM),HTM算法旨在模拟新大脑皮层的工作原理,将复杂的问题转化为模式匹配与预测。它强调对“神经元”进行分层级,以及信息模式的空间特性与时间特性。稀疏分布表示(Sparse Distributed Representation, SDR)是HTM算法中的一个重要概念。实际上,它只是拥有几千个元素的位数组。就像大脑中的信息总是通过亿万神经细胞中的小部分活跃细胞来表示一样,HTM使用稀疏分布表示语义相关的输入。HTM算法中的抑制(Inhibition)类似于批规范化和其他一些正则化技术,提升(Boosting)在机器学习中已经是一个相对较老的概念,层次结构(Hierarchical Structure)并没有真正的大脑皮层的结构灵活。HTM对物体间关系的重视程度低,甚至连稀疏分布表示也可以用普通神经网络构建。总体来说,HTM需要进行大量调整才能获取与其它机器学习算法相当的性能。接下来介绍AIXI,它是一个对通用人工智能的理论上的数学形式化表示。然而,它有一个显著的缺点——无法计算。事实上,许多机器学习算法均不能精确计算,只能做近似处理。AIXI表示如下:AIXI的核心是一个强化学习智能体,在诸多方面与Schmidhuber开发的Godel Machine类似。然而,它们都是AGI的描述性模型,复杂程度高,无法执行,但不可否认,它们都是人工智能研究人员的灵感源泉。相反,ACT-R,即理性思维的自适应控制系统 (AdaptiveControl of Thought—Rational),它不仅是一种理论,而且是一种用LISP编写的软件框架。ACT-R主要关注不同类型的内存,较少关注其中数据的转换。该理论试图理解人类如何获得和组织知识以及如何产生智力活动,其研究进展基于神经生物学研究成果并从中得以验证,且已成功地为许多不同认知现象建立起合理的模型。然而,它在实际应用中并未取得成功,最终只作为研究人员的工具。SOAR与ACT-R有着相似的根源和基本假设,但它更关注于实现AGI,而不是建立人类认知的模型。ACT-R和SOAR是人工智能符号主义的经典代表,在认知科学的发展中起到了重要作用,但是应用它们相比现代联结主义需要更多的配置和先验知识。此外,神经影像和其他用于心智研究的工具越发详细和准确,而且ACT-R和SOAR在某一定程度上过于僵化,无法保持相关性。本文作者:【方向】阅读原文本文为云栖社区原创内容,未经允许不得转载。

January 7, 2019 · 1 min · jiezi

使用jMeter构造逻辑上有依赖关系的一系列并发请求

相信前端开发工程师对CSRF(Cross-site request forgery)跨站请求伪造这个概念都非常熟悉,有的时候也简写成XSRF,是一种对网站的恶意利用。尽管听起来像跨站脚本(XSS),但它与XSS非常不同,XSS利用站点内的信任用户,而CSRF则通过伪装成受信任用户的请求来利用受信任的网站。CSRF攻击的防御方式有多种,最简单最易实现的一种思路就是在客户端向服务器发起的请求中放入攻击者无法伪造的信息,并且该信息没有存储于 cookie 之中。技术上来说,当客户端向服务器发起请求执行一些敏感操作之前(比如用HTTP post实现的转账,扣款等功能),服务器端随机产生一个token,返回给客户端。客户端接下来的操作,必须在HTTP请求中以参数的形式把这个服务器端颁发的token带上。同时服务器端在实现给客户端分配token的同时,也要加入一个token校验机制。如果请求中没有 token 或者 token 内容不正确,则认为可能是 CSRF 攻击而拒绝该请求。这个token我们一般称为CSRF token。讲了这么多,是为了引入本文想要讨论的话题。假设我想用jMeter测试一个OOdata服务创建Service Ticket的性能。因为创建功能不像读操作,执行之后会对系统产生持久化影响(Persistence side-effect), 因此服务器端的实现加入了CSRF token的校验。这就是说,如果我们直接用jMeter构造并发的HTTP post请求,是没有办法完成测试的,这些请求因为没有包含CSRF token,会被服务器端直接拒绝掉。根据前面描述的CSRF攻防原理,CSRF token是服务器端随机生成的,客户端无法用任何技术进行伪造,因为为了测试接口HTTP post操作进行Service Ticket的创建,我们必须构造一个它的前置HTTP GET请求,专门用于得到服务器返回的CSRF token,然后再构造真正用于性能测试的HTTP POST请求,把第一步GET请求获得的CSRF token附到POST请求的头部中去。本文介绍在jMeter里如何维护并配置这种具有依赖关系的一组请求。当然如果您不喜欢用jMeter,想自己写代码实现,也是可以的。可以参考我放在github上的Java代码实现。用jMeter的好处是不需要编程,通过简单的配置就能实现这个性能测试需求,一般没有开发背景的测试人员也能独立完成。First let us have a look how JMeter could archive the same without even one line of programming.My project in JMeter is displayed with the following hierarchy. I have configured with “Number of 5 threads” in my thread group, so once executed, the response time of these 5 threads are displayed in result table together with average response time.从下图能看出,因为拿CSRF token的HTTP GET在逻辑上必须先于实际需要测试性能的HTTP POST请求,这实际上构成了一个Transaction-事务,所以我使用jMeter里提供的Transaction Controller来管理。Some key points for this JMeter project creation(1) Since now one thread should cover both XSRF token fetch via HTTP get and Service request creation via HTTP post, so a transaction controller is necessary to include both request.(2) Create the first HTTP request to fetch XSRF token. The setting could be found below: adding a http header field with name asx-csrf-token and value as “fetch”:在HTTP GET请求的头部加上一个名为x-csrf-token的字段,值赋成fetch。这样服务器接到这个请求,就知道这是客户端发起的CSRF token请求,于是服务器响应这个请求,把创建好的随机CSRF token通过HTTP response头部字段的方式返回给客户端。下一个问题就是,服务器返回给客户端合法的CSRF token后,jMeter如何读取到这个token,并用于接下来的请求?幸运的是,jMeter提供了正则表达式提取式,可以让我们很方便地从HTTP响应结构中提取出token来。Create a Regular Expression Extractor to parse the XSRF token from response header and stored it to a variable named “jerrycsrftoken”.下图构造了一个jMeter正则表达式提取器,工作于HTTP响应的头部字段,解析出的token值存储于变量jerrycsrftoken中。Before you continue, please make sure that the XSRF token is correctly parsed from request header, which could be confirmed by printing it out in a debug sample:这个请求构造完之后,我们先试着运行一次,确保在变量jerrycsrftoken里确实看到解析好的CSRF token。(3) Create another HTTP request with type POST.这时万事俱备,我们可以开始构造真正要进行性能测试的HTTP post,即Service Ticket的创建请求了。请求的报文正文:Just paste the following text to the tab “Body Data”:–batch_1Content-Type: multipart/mixed; boundary=changeset_1–changeset_1Content-Type: application/httpContent-Transfer-Encoding: binaryPOST ServiceRequestCollection HTTP/1.1Content-Length: 5000Accept: application/jsonContent-Type: application/json{“ServicePriorityCode”: “2”,“Name”: {“content”: “Jerry Testing ticket creation via JMeter ${uuid} “},“ServiceRequestDescription”: [{“Text”: “Piston Rattling 1 - Generic OData Test Create”,“TypeCode”: “10004”},{“Text”: “Piston Rattling 2 - Generic OData Test Create”,“TypeCode”: “10007”}]}–changeset_1—-batch_1–In the body text I use a user-defined variable ${uuid} which we could create it in last step. And for this post request, use the XSRF token fetched from previous HTTP get request.前面说过,POST请求的头部需要加上合法的CSRF token,此处我们使用前面GET请求已经拿到的并且存储于变量jerrycsrftoken中的token值:我希望最后通过并发测试生成的Service Ticket的描述信息的后缀是1到100的随机正整数,因此我使用jMeter里自带的一个随机数发生器:(4) As the last step, create a user variable by using JMeter built-in function __Random, to create a random number between 1 ~ 100 as a fragment of created Service Request description.Now execute the Thread group, and the execution detail for these three HTTP request could be reviewed separately in tree view:试着运行一下,发现这个POST操作确实按照我们期望的那样,在HTTP头部字段里加上了正确合法的CSRF token:For example, the XSRF token is successfully fetched in the first request: rdPy7zNj_uKDYvQLgfQCFA==And used as one header field in second HTTP Post request as expected:And finally in UI we could find the created Service request with random number between 1 ~ 100 as postfix:在UI上观测到我构造的5个并发请求创建的Service Ticket,说明CSRF token在服务器端的校验成功,同时发现描述信息都带上了随机数,说明我的jMeter随机数生成器的用法也正确。希望本文对大家的工作有所帮助。要获取更多Jerry的原创文章,请关注公众号"汪子熙”: ...

January 1, 2019 · 2 min · jiezi

蚂蚁金服核心技术:百亿特征实时推荐算法揭秘

阿里妹导读:本文来自蚂蚁金服人工智能部认知计算组的基础算法团队,文章提出一整套创新算法与架构,通过对TensorFlow底层的弹性改造,解决了在线学习的弹性特征伸缩和稳定性问题,并以GroupLasso和特征在线频次过滤等自研算法优化了模型稀疏性,在支付宝核心推荐业务获得了uvctr的显著提升,并较大地提升了链路效率。0.综述在线学习(Online learning)由于能捕捉用户的动态行为,实现模型快速自适应,进而成为提升推荐系统性能的重要工具。然而它对链路和模型的稳定性,训练系统的性能都提出了很高的要求。但在基于原生TensorFlow,设计Online推荐算法时,我们发现三个核心问题:一些资讯推荐场景,需要大量长尾词汇作为特征,需使用featuremap对低频特征频次截断并连续性编码,但耗时且方法aggressive。使用流式数据后,无法预知特征规模,而是随训练逐渐增长。因此需预留特征空间训练几天后重启,否则会越界。模型稀疏性不佳,体积达到数十GB,导致上传和线上加载耗时长且不稳定。更重要的是,在线学习如火如荼,当流式特征和数据都被打通后,能按需增删特征,实现参数弹性伸缩的新一代训练平台成为大势所趋。为了解决这些问题,从2017年底至今,蚂蚁金服人工智能部的同学,充分考虑蚂蚁的业务场景和链路,对TensorFlow进行了弹性改造, 解决了以上三大痛点,简化并加速离线和在线学习任务。其核心能力如下:弹性特征伸缩体系,支持百亿参数训练。group_lasso优化器和频次过滤,提高模型稀疏性,明显提升线上效果。模型体积压缩90%,完善的特征管理和模型稳定性监控。在与业务线团队的共同努力下,目前已在支付宝首页的多个推荐场景全流量上线。其中某推荐位的个性化online learning桶最近一周相比线上多模型融合最优桶提升4.23% , 相比随机对照提升达34.67% 。 某个性化资讯推荐业务最近一周,相比DNN基准uv-ctr提升+0.77%,pv-ctr提升+4.78%,模型体积压缩90%,链路效率提升50%。1. 弹性改造及优势背景:在原生TensorFlow中,我们通过Variable来声明变量,若变量超过了单机承载的能力,可使用partitioned_variables来将参数分配到不同机器上。 但必须指定shape,声明后即不可改变,通过数组索引查找。由于推荐系统中大量使用稀疏特征,实践中一般采取embedding_lookup_sparse一类的方法在一个巨大的Dense Variable中查找向量并求和,来代替矩阵乘法。开源Tensorflow限定了Variable使用前必须声明维度大小,这带来了两个问题:1)需要预先计算特征到维度范围内的int值的映射表,这一步操作通常在ODPS上完成。因为需要扫描所有出现的特征并编号,计算非常缓慢;2)在online learning场景下,为了容纳新出现的特征,需要预留一部分维度空间,并在线上不断修改映射表,超过预留空间则需要重新启动在线任务。为了突破固定维度限制,实现特征的动态增加和删除,最朴素的优化想法是在TensorFlow底层实现模拟字典行为的Variable,并在此基础上重新实现Tensorflow上层API。由此我们进行了优化,在server新增了基于HashMap的HashVariable,其内存结构如下:在声明该变量时,只需增加一句,其他训练代码皆不需改动:每个特征都通过hash函数映射到一个2的64次方大小的空间内。当需要计算该特征时,PS会按需惰性创建并返回之。但其上层行为与原生TF一致。由于去掉了featuremap转ID的过程,我们内部形象地将其称为“去ID化”。在此之上我们实现了Group Lasso FTRL,频次过滤和模型压缩等一系列算法。备注:弹性特征带来一个显著的优势:只要用足够强的L1稀疏性约束,在单机上就能调试任意大规模的特征训练,带来很多方便。我们的hashmap实现是KV化的,key是特征,value是vector的首地址。离线训练优化经过这样的改造后,在离线批量学习上,带来了以下变化:在线训练优化online learning上,能带来如下变化:除了性能有明显的提升之外,其最大的优势是不需提前申请空间,训练可以无缝稳定运行。2. 特征动态增删技术弹性架构,主要目的就是特征优选,让模型自适应地选择最优特征,进而实现稀疏化,降低过拟合。本节介绍特征优选的两个核心技术:使用流式频次过滤, 对特征进入进行判定。使用Group Lasso优化器,对特征进行筛选和删除。2.1 Group Lasso 优化器稀疏化是算法追求的重要模型特性,从简单的L1正则化和Truncated Gradient[9], 再到讨论累积梯度平均值的RDA(Regularized Dual Averaging)[10], 再到目前常见的 FTRL[2] 。 然而它们都是针对广义线性模型优化问题提出的稀疏性优化算法,没有针对sparse DNN中的特征embedding层做特殊处理。把embedding参数向量当做普通参数进行稀疏化,并不能达到在线性模型中能达到的特征选择效果,进而无法有效地进行模型压缩。例如:当包含新特征的样本进入时,一个特征对应的一组参数(如embedding size为7,则参数数量为7)被激活,FTRL判定特征中的部分参数无效时,也不能安全地将该特征删除。如图:因此,在L1和L2正则的基础上,人们引入L21正则(group lasso)和L2正则(exclusive sparsity),分别表示如下:L21早在2011年已经引入,它最初目的是解决一组高度关联特征(如男女)应同时被保留或删除的问题,我们创新地扩展到embedding的表示上,以解决类似的问题。在L21中,由于内层L2正则将一个特征的所有参数施加相同的约束,能将整组参数清除或保留,由此决定embedding层中的某些特征对应的embedding向量是否完全删除,提升模型泛化性。因此称为group lasso。而L12则正好相反,它迫使每组参数中的非0参数数量一致但值又尽可能不同,但使输出神经元互相竞争输入神经元,进而使特征对目标更具区分性。对于DNN分类网络,底层表示要求有足够的泛化性和特征抽象能力,上层接近softmax层,需要更好的区分性。因此我们通常在最底层的embedding层使用group lasso。即如下的优化目标:直接将L21正则项惩罚加入loss,模型最终也能收敛,但并不能保证稀疏性。因此Group lasso优化器参考了FTRL,将梯度迭代分成两个半步,前半步按梯度下降,后半步微调实现稀疏性。通过调节L1正则项(即公式中的),能有效地控制模型稀疏性。Group lasso是弹性计算改造后,模型性能提升和压缩的关键。值得指出:在我们实现的优化器中,Variable,以及accum和linear两个slot也是KV存储。L12和L21正则相结合的方法也已经有论文讨论[8],但我们还未在业务上尝试出效果。由于篇幅限制,本节不打算详细介绍Group lasso的原理和推导2.2 流式频次过滤讨论完特征动态删除的方法后,我们再分析特征的准入策略。2.2.1 频次过滤的必要性在Google讨论FTRL的文章1中提到, 在高维数据中大部分特征都是非常稀疏的,在亿级别的样本中只出现几次。那么一个有趣的问题是,FTRL或Group FTRL优化器能否能删除(lasso)极低频特征?在RDA的优化公式中,满足以下条件的特征会被置0:若在t步之前,该特征只出现过几次,未出现的step的梯度为0,随着步数增大,满足上述条件变得越来越容易。由此RDA是可以直观处理极稀疏特征的。 但对于FTRL,要满足:其中,不仅和历史梯度有关,还与历史学习率和权重w有关。 因此FTRL虽然也能处理极稀疏特征,但并没有RDA那么aggressive(此处还待详细地分析其下界,Group FTRL与此类似)。由于FTRL在设计和推导时并未明确考虑极低频特征,虽然通过增大,确实能去除大量极低频特征,但由于约束太强,导致部分有效特征也被lasso,在离线实验中被证明严重影响性能。其次,对这些巨量极低频特征,保存历史信息的工程代价是很高昂的(增加几倍的参数空间和存储需求),如下图:因此我们提出,能否在实时数据流上模拟离线频次过滤,为特征提供准入门槛,在不降低模型性能的基础上,尽量去除极低频特征,进一步实现稀疏化?2.2.2 频次过滤的几种实现注意: 由于默认的embedding_lookup_sparse对特征执行了unique操作(特征归一化以简化计算),因此在PS端是不可能获取真实特征和label频次的。需要Python端对placeholder统计后,上传给server端指定的Variable,优化器通过slot获得该Variable后作出联合决策。最naive的思路是模拟离线频次过滤,对特征进行计数,只有达到一定阈值后再进入训练,但这样破坏了数据完整性:如总频次6,而阈值过滤为5,则该特征出现的前5次都被忽略了。为此我们提出了两种优化方案:基于泊松分布的特征频次估计在离线shuffle后的特征满足均匀分布,但对在线数据流,特征进入训练系统可看做泊松过程,符合泊松分布:其中n为当前出现的次数,t为当前的步数,为单位时间发生率,是泊松分布的主要参数,T为训练总步数。为特征最低门限(即最少在T时间内出现的次数)。因此我们能通过前t步的特征出现的次数n,将t时刻当做单位时间,则。 根据泊松分布,我们可以算出剩余时间内事件发生大于等于次的概率每次该特征出现时,都可按该概率做伯努利采样,特征在t步进入系统的概率用下式计算:通过真实线上数据仿真,它能接近离线频次过滤的效果,其是随每次特征进入时动态计算的。它的缺陷是:当t越小时,事件发生在t内的次数的variance越大,所以会以一定概率误加或丢弃特征。未来总的训练步数T在在线学习中是未知的。频次过滤与优化器相分离,导致不能获得优化器的统计信息。动态调L1正则方案在经典的FTRL实现中,L1正则对每个特征都是一致的。这导致了2.2.1 中提到的问题:过大的L1虽然过滤了极低频特征,但也影响的了模型的性能。参考各类优化器(如Adam)对learning_rate的改进,我们提出:通过[图片上传失败…(image-10f16c-1545974538974)]特征频次影响L1正则系数,使得不同频次的特征有不同的lasso效果。特征频次和基于MLE的参数估计的置信度相关,出现次数越低置信度越低。如果在纯频率统计基础上加入一个先验分布(正则项),当频率统计置信度越低的时候,越倾向于先验分布,相应的正则系数要更大。我们经过多个实验,给出了以下的经验公式:其中c是惩罚倍数,为特征最低门限,这两者皆为超参,是当前特征出现的频次。我们在线上环境,使用了动态调节L1正则的方案 。在uvctr不降甚至有些微提升的基础上,模型特征数比不使用频次过滤减少75%,进而从实验证明了频次过滤对稀疏化的正向性。它的缺点也很明显:特征频次和正则系数之间的映射关系缺少严谨证明。频次过滤作为特征管理的一部分,目前还少有相关论文研究,亟待我们继续探索。3.模型压缩和稳定性3.1 模型压缩在工程上,由于做了优化,如特征被优化器lasso后,只将其置0,并不会真正删除;在足够多步数后才删除。同时引入内存池,避免特征的反复创建和删除带来的不必要的性能损失。 这就导致在训练结束后,模型依然存在大量0向量。导出时要进一步做模型压缩。由于引入了HashPull和HashPush等非TF原生算子,需要将其裁剪后转换为原生TF的op。 我们将这些步骤统称图裁剪(GraphCut), 它使得线上inference引擎,不需要做任何改动即可兼容弹性改造。由于有效特征大大减少,打分速度相比原引擎提升50%以上。我们将图裁剪看做TF-graph的静态优化问题,分为3个步骤:第一遍遍历Graph,搜索可优化子结构和不兼容的op。第二遍遍历,记录节点上下游和元数据,裁剪关键op,并将Variable的非0值转存至Tensorflow原生的MutableDenseHashTable。本步骤将模型体积压缩90%。拼接新建节点,重建依赖关系,最后递归回溯上游节点,去除与inference无关的子图结构我们实现了完整简洁的图裁剪工具,在模型热导出时调用, 将模型从原先的8GB左右压缩到几百兆大小,同时保证模型打分一致。3.2 模型稳定性和监控online learning的稳定性非常重要。我们将线上真实效果,与实时模型生成的效果,进行了严密的监控,一旦样本偏差过多,就会触发报警。由于需捕捉时变的数据变化,因而不能用固定的离线数据集评估模型结果。我们使用阿里流式日志系统sls最新流入的数据作为评估样本,以滑动窗口先打分后再训练,既维持了不间断的训练,不浪费数据,同时尽可能高频地得到最新模型效果。我们对如下核心指标做了监控:样本监控: 正负比例,线上打分值和online-auc(即线上模型打分得到的auc),产出速率,消费速率。训练级监控: AUC, User-AUC(参考备注),loss, 模型打分均值(与样本的正负比例对齐),异常信息。特征级管理: 总特征规模,有效/0/删除特征规模,新增/插入/删除的速率。整体模型和调度:模型导出的时间,大小,打分分布是否正常,是否正常调度。业务指标:uvctr,pvctr(小时级更新,T+1报表)。线上与训练指标之间的对应关系如下表:通过http接口,每隔一段时间发送监控数据,出现异常会及时产生钉钉和邮件报警。下图是对9月20日到27号的监控,从第二张图表来看,模型能较好的适应当前数据流的打分分布。User-AUC:传统的AUC并不能完全描述uvctr,因为模型很可能学到了不同用户间的偏序关系,而非单个用户在不同offer下的点击偏序关系。为此,我们使用了User-AUC,它尽可能地模拟了线上uvctr的计算过程,在真实实验中,监控系统的uvctr小时报表,与实时模型输出的User-AUC高度一致。4. 工程实现和效果目前算法已经在支付宝首页的多个推荐位上线。推荐系统根据用户的历史点击,融合用户画像和兴趣,结合实时特征,预估用户CTR,进而提升系统整体点击率。我们以推荐位业务为例说明,其采用了经典的wide&deep的网络结构,其sparse部分包含百级别的group(见下段备注1)。 一天流入约百亿样本,label的join窗口为固定时长。由于负样本占大多数,上游链路对正负样本做了1:8的降采样(见下文备注2)。训练任务采用蚂蚁统一训练平台构建,并使用工作流进行定时调度,离线和在线任务的其他参数全部一致。Batchsize为512,每200步(即20万样本)评估结果,定时将模型通过图裁剪导出到线上系统。当任务失败时,调度系统会自动拉起,从checkpoint恢复。该推荐业务的online learning桶最近一周相比线上多模型融合最优桶提升4.23% , 相比随机对照提升达34.67% 。 另一资讯推荐业务其最近一周,相比DNN基准uv-ctr提升+0.77%,pv-ctr提升+4.78%。实验效果相比有较大的提升。备注1: group embedding是将相似emb特征分组,各自lookup求和后再concat,使得特征交叉在更高层进行。其设计是考虑到不同group的特征差异很大(如user和item),不应直接对位求和。备注2: inference打分仅做pointwise排序,采样虽改变数据分布但不改变偏序关系,因此并未在训练上做补偿。5. 未来工作弹性特征已经成为蚂蚁实时强化深度学习的核心要素。它只是第一步,在解决特征空间按需创建问题后,它会带来一个充满想象力的底层架构,众多技术都能在此基础上深挖: 在工程上,可继续从分钟级向秒级优化,进一步提升链路实时性并实现模型增量更新; 在算法上,我们正在探索如样本重要性采样,自动特征学习,在线线性规划与DNN的结合,实现优化器联合决策等技术。由于在线学习是个复杂的系统工程,我们在开发和调优时遇到了大量的困难,涉及样本回流,训练平台,模型打分,线上评估等一系列问题,尤其是稳定性,但基本都一一克服。为了保证线上结果稳定可信,我们在观察和优化两三个月后才发布这篇文章,希望和业界同仁一起交流探讨。本文作者为蚂蚁金服人工智能部认知计算组的基础算法团队,团队涉及图像、NLP、推荐算法和知识图谱等领域,拥有定损宝和理赔宝等核心业务。参考文献:[1] McMahan, Brendan. “Follow-the-regularized-leader and mirror descent: Equivalence theorems and l1 regularization.” Proceedings of the Fourteenth International Conference on Artificial Intelligence and Statistics. 2011.[2] McMahan, H. Brendan, et al. “Ad click prediction: a view from the trenches.” Proceedings of the 19th ACM SIGKDD international conference on Knowledge discovery and data mining. ACM, 2013.[3]Yuan, Ming, and Yi Lin. “Model selection and estimation in regression with grouped variables.” Journal of the Royal Statistical Society: Series B (Statistical Methodology) 68.1 (2006): 49-67.[4] Andrew, Galen, and Jianfeng Gao. “Scalable training of L 1-regularized log-linear models.” Proceedings of the 24th international conference on Machine learning. ACM, 2007.[5]Scardapane, Simone, et al. “Group sparse regularization for deep neural networks.” Neurocomputing 241 (2017): 81-89.[6] Yang, Haiqin, et al. “Online learning for group lasso.” Proceedings of the 27th International Conference on Machine Learning (ICML-10). 2010.[7]Zhou, Yang, Rong Jin, and Steven Chu–Hong Hoi. “Exclusive lasso for multi-task feature selection.” Proceedings of the Thirteenth International Conference on Artificial Intelligence and Statistics. 2010.[8] Yoon, Jaehong, and Sung Ju Hwang. “Combined group and exclusive sparsity for deep neural networks.” International Conference on Machine Learning. 2017.[9] Langford, L. Li, and T. Zhang. Sparse online learning via truncated gradient.JMLR, 10, 2009.[10]L. Xiao. Dual averaging method for regularized stochastic learning and online optimization. In NIPS, 2009.本文作者:墨眀阅读原文本文来自云栖社区合作伙伴“阿里技术”,如需转载请联系原作者。 ...

December 28, 2018 · 2 min · jiezi

首次公开!《阿里计算机视觉技术精选》揭秘前沿落地案例

当下计算机视觉技术无疑是AI浪潮中最火热的议题之一。视觉技术的渗透,既可以对传统商业进行改造使之看到新的商业机会,还可以创造全新的商业需求和市场。无论在电商、安防、娱乐,还是在工业、医疗、自动驾驶领域,计算机视觉技术都扮演着越发重要的角色。元旦假期即将来临,我们精心准备了这本《阿里巴巴机器智能计算机视觉技术精选》,收录了顶级会议 CVPR 2018 阿里论文,送给计划在假期“充电”的同学们,也希望能和更多学术界、工业界同仁一起探讨交流。下载地址:https://yq.aliyun.com/download/3237?utm_content=g_1000033518在这本干货精选集中,我们收录了多篇具有代表性的 CVPR 2018 论文。比如,拍立淘利用图像搜索和识别技术,帮助用户在移动端通过拍照就能找到相似商品;线下新零售领域,阿里用空间定位、货架商品SKU识别技术推动“人货场”数字化,并做进一步的商业分析;城市大脑项目中,阿里研发了大规模视频高效处理技术,帮助城市交通事故识别、人流轨迹判断、交通数据样本汇总。哪些核心技术值得一看?Spotlight论文《基于时间尺度选择的在线行为预测》讨论了视频中行为预测的一个非常重要的问题:怎么去选择一个好的时间维度窗口?论文提出了包含多个子网络的尺度选择网,比如包括时间序列建模的一维卷积子网络、尺度回归子网络以及行为预测子网络。在两个公开数据集上,尺度选择网的实验结果优于其他方法,并且准确率也接近使用Ground Truth尺度的结果。Spotlight论文《基于语境对比特征和门控多尺度融合的场景分割》致力于场景分割中的两大问题:场景图片中像素形式的多样化(例如:显著或者不显著、前景或者背景)和场景图片中物体大小的多样性。文章针对这两个问题分别提出了语境对比局部特征和门控多尺度融合方法。本文提出的模型在Pascal Context, SUN-RGBD和COCO Stuff 三个场景分割数据集上验证了性能,取得了目前最高的场景分割性能。对于跨模态检索而言,如何学到合适的特征表达非常关键。Spotlight论文《所见所想所找-基于生成模型的跨模态检索》提出了一种基于生成模型的跨模态检索方法,该方法可以学习跨模态数据的高层次特征相似性,以及目标模态上的局部相似性。本文通过大量的实验证明了所提出的方法可以准确地匹配图像和文本,并且在MSCOCO以及Flickr30K的数据集上都取得了state-of-the-art的效果。在论文《整体还是局部?应用Localized GAN进行图像内容编辑、半监督训练和解决mode collapse问题》中,作者建立了GAN和半监督机器学习中Laplace-Beltrami算子的联系,在用少量标注样本训练深度学习模型上取得了优异的性能。同时论文还展示了用Localized GAN (LGAN)对给定图像在局部坐标系下进行编辑修改,从而获得具有不同角度、姿态和风格的新图像;以及如何从流型切向量独立性的角度来解释和解决GAN的mode collapse问题。论文《处理多种退化类型的卷积超分辨率》针对现有基于CNN的单图超分(SISR)算法不能扩展到用单一模型解决多种不同的图像退化类型的问题,提出了一种维度拉伸策略,使得单个卷积超分辨率网络能够将SISR退化过程的两个关键因素(即模糊核和噪声水平)作为网络输入来解决这个问题。实验结果表明提出的卷积超分辨率网络可以快速、有效的处理多种图像退化类型,为SISR实际应用提供了一种高效、可扩展的解决方案。论文《于尺度空间变换的本征图像分解》将把图像分解为其本征的反射图像和光照图像看作是一个图像到图像的转换问题,并且将输入和输出在尺度空间进行分解。通过将输出图像(反射图像和光照图像)扩展到它们的拉普拉斯金字塔的各个成分,论文提出了一种多通道网络结构,可以在每个通道内并行地学习到一个图像到图像转换函数,这个函数通过一个具有跳过连接的卷积神经网络来表示。在MPI-Sintel数据集和MIT Intrinsic Images数据集上结果表明,新提出的模型在比之前最先进的技术上有了明显的进步。大多数现有的零样本学习(Zero-Shot Learning,ZSL)方法都存在强偏问题。在论文《基于直推式无偏嵌入的零样本学习》中,作者提出了一个简单而有效的方法,称为准完全监督学习(QFSL),来缓解此问题。假定标记的源图像和未标记的目标图像都可用于训练。在语义嵌入空间中,被标记的源图像被映射到由源类别指定的若干个嵌入点,并且未标记的目标图像被强制映射到由目标类别指定的其他点。在AwA2,CUB和SUN数据集上进行的实验表明,文章的方法在遵循广义ZSL设置的情况下比现有技术的方法优越。更为具体的实践信息,大家可以通过此本电子书,进一步了解。好的视觉技术不仅需要好的方法指引,还需要在实际的场景中形成数据闭环和不断打磨。未来的计算机视觉技术一定是理论探索和数据实践的共同推进。希望这本论文合集能抛砖引玉,给学术界和工业界带来一些输入,共同推进计算机视觉技术的发展。本文作者:元旦“充电包”阅读原文本文来自云栖社区合作伙伴“阿里技术”,如需转载请联系原作者。

December 27, 2018 · 1 min · jiezi

阿里重磅开源Blink:为什么我们等了这么久?

摘要: 阿里巴巴计算平台事业部研究员蒋晓伟深入分享Flink和Blink的关系以及未来发展。推荐阅读。12月20日,由阿里巴巴承办的 Flink Forward China 峰会在北京国家会议中心召开,来自阿里、华为、腾讯、美团点评、滴滴、字节跳动等公司的技术专家与参会者分享了各公司基于 Flink 的应用和实践经验。感兴趣的开发者可以看云栖社区的对于大会的主会+5场分论坛的直播与视频点播。会议进行中,看到AI前线对蒋晓伟的采访。正如许多开发者所关心的Flink和Blink的关系(云栖社区2016年文章:阿里蒋晓伟谈流计算和批处理引擎Blink,以及Flink和Spark的异同与优势),如今有了更新的方向。本篇AI前线的专访讲述的极为清晰。特别转载,共享。*今年,实时流计算技术开始步入主流,各大厂都在不遗余力地试用新的流计算框架,实时流计算引擎和 API 诸如 Spark Streaming、Kafka Streaming、Beam 和 Flink 持续火爆。阿里巴巴自 2015 年开始改进 Flink,并创建了内部分支 Blink,目前服务于阿里集团内部搜索、推荐、广告和蚂蚁等大量核心实时业务。在大会的主题演讲上,阿里巴巴集团副总裁周靖人宣布,阿里巴巴内部 Flink 版本 Blink 将于 2019 年 1 月正式开源! 阿里希望通过 Blink 开源进一步加深与 Flink 社区的联动,并推动国内更多中小型企业使Flink。Flink Forward China会上,AI 前线对阿里巴巴计算平台事业部研究员蒋晓伟(花名量仔)进行了独家专访,他与我们分享了关于下一代实时流计算引擎的看法,并针对 Blink 的重要新特性、开源后 Blink 与 Flink 之间的关系、Blink 后续规划等问题进行了解答。阿里巴巴与 Flink随着人工智能时代的降临和数据量的爆发,在典型的大数据业务场景下,数据业务最通用的做法是:选用批处理的技术处理全量数据,采用流式计算处理实时增量数据。在很多的业务场景之下,用户的业务逻辑在批处理和流处理之中往往是相同的。但是,用户用于批处理和流处理的两套计算引擎是不同的。因此,用户通常需要写两套代码。毫无疑问,这带来了一些额外的负担和成本。阿里巴巴的商品数据处理就经常需要面对增量和全量两套不同的业务流程问题,所以阿里巴巴就在想:能不能有一套统一的大数据引擎技术,用户只需要根据自己的业务逻辑开发一套代码。这样在各种不同的场景下,不管是全量数据还是增量数据,亦或者实时处理,一套方案即可全部支持,这就是阿里巴巴选择 Flink 的背景和初衷。彼时的 Flink 不管是规模还是稳定性尚未经历实践,成熟度有待商榷。阿里巴巴实时计算团队决定在阿里内部建立一个 Flink 分支 Blink,并对 Flink 进行大量的修改和完善,让其适应阿里巴巴这种超大规模的业务场景。简单地说,Blink 就是阿里巴巴开发的基于开源 Flink 的阿里巴巴内部版本。阿里巴巴基于 Flink 搭建的平台于 2016 年正式上线,并从阿里巴巴的搜索和推荐这两大场景开始实现。目前阿里巴巴所有的业务,包括阿里巴巴所有子公司都采用了基于 Flink 搭建的实时计算平台。目前,这套基于 Flink 搭建的实时计算平台不仅服务于阿里巴巴集团内部,而且通过阿里云的云产品 API 向整个开发者生态提供基于 Flink 的云产品支持。以下内容整理自 AI 前线对蒋晓伟的采访。开源的时机AI 前线:为什么选择现在将 Blink 开源?这其中有哪些考量?什么样的时机才是开源最合适的时机?蒋晓伟: 在我看来,有几个因素:第一个因素是,这几年我们一直试图把阿里对 Flink 的改进推回社区,但社区有自己的步伐,很多时候可能无法把我们的变更及时推回去。对于社区来说,需要达成共识,才能更好地保证开源项目的质量,但同时就会导致推入的速度慢一些。经过这几年积累,我们这边和社区之间的差距已经变得比较大了。Blink 有一些很好的新功能,比如批处理功能,在社区版本是没有的。在过去这段时间里,我们不断听到有人问,Blink 什么时候能开源、是不是能开源这样的呼声。我们有两种方法,一种就是慢慢地推回去再给用户用。但我们认为这样等下去对社区不是最好的。我们还是希望尽快把我们的代码拿出来,尽量让大家都能用起来。所以最近这半年,我们一直都在准备把代码整理好去进行开源。选择在这个时间点开源有几个好处:第一个好处是我们所开源的这些代码在阿里内部经过像双一十、双十二这样巨大流量的检验,让我们对它的质量有更大的信心,这是非常大的好处;第二个好处,Flink Forward 大会是第一次在中国举办,在这样一个场合开源表明了阿里对 Flink 社区坚定的支持,这是一个比较好的场合。主要是基于这些考虑。选 Blink 还是 Flink?这不会是一个问题AI 前线:开源的 Blink 版本会和阿里巴巴内部使用的 Blink 保持一致吗?蒋晓伟: 即将开源的是阿里巴巴双十二的上线版本,还会有一些小的改进。AI 前线:Blink 开源后,两个开源项目之间的关系会是怎样的?未来 Flink 和 Blink 也会由不同的团队各自维护吗?蒋晓伟: 开源的意思是,我们愿意把 Blink 的代码贡献出来,但这两个项目是一个项目。有一件事情需要澄清一下,我们将公开 Blink 的所有代码,让大家都可以看到,但与此同时,我们会跟社区一起努力,通过讨论决定 Blink 以什么样的方式进入 Flink 是最合适的。因为 Flink 是一个社区的项目,我们需要经过社区的同意才能以分支的形式进入 Flink,或者作为变更 Merge 到项目中。我想强调一下,我们作为社区的一员需要跟社区讨论才能决定这件事情。Blink 永远不会成为另外一个项目,如果后续进入 Apache 一定是成为 Flink 的一部分,我们没有任何兴趣另立旗帜,我们永远是 Flink 的一部分,也会坚定地支持 Flink。我们非常愿意把 Blink 的代码贡献给所有人,所以明年 1 月份我们会先将 Blink 的代码公开,但这期间我们也会和社区讨论,以什么样的形式进入 Flink 是最合适的、怎么贡献是社区最希望的方式。我们希望,在 Blink 开源之后,和社区一起努力,把 Blink 好的地方逐步推回 Flink,成为 Flink 的一部分,希望最终 Flink 和 Blink 变成一个东西,阿里巴巴和整个社区一起来维护。而不是把它分成两个东西,给用户选择的困难,这不是我们想要的。因此未来用户也不会面临已经部署了 Flink、是否要把 Flink 迁移到 Blink 的问题,企业选型时也不需要在 Flink 和 Blink 之间抉择,Blink 和 Flink 会是同一个项目。Blink 开源只有一个目的,就是希望 Flink 做得更好。Blink 改进了什么?AI 前线:能不能重点介绍一下即将开源的 Blink 版本有哪些比较重要的新技术特性?与 Flink 最新发布版本相比,阿里的 Blink 做了哪些方面的优化和改进?蒋晓伟: 阿里巴巴实时计算团队不仅对 Flink 在性能和稳定性上做出了很多改进和优化,同时在核心架构和功能上也进行了大量创新和改进。过去两年多,有很多更新已经推回给社区了,包括 Flink 新的分布式架构等。目前我们的 Blink 版本跟社区版本还有几点差异,第一个是稳定性方面,我们做了一些优化,在某些场景会比社区版本更加稳定,特别是在大规模场景。另外还有一个比较大的不一样是我们全新的 Flink SQL 技术栈,它在功能上,特别是在批处理的功能上比社区版本强大很多。它支持现在标准 SQL 几乎所有的语法和语义。另外,在性能上,无论是在流式 SQL 还是批 SQL,我们的版本在性能上都有很大的优势。特别是在批 SQL 的性能方面,当前 Blink 版本是社区版本性能的 10 倍以上,跟 Spark 相比,在 TPCDS 这样的场景 Blink 的性能也能达到 3 倍以上。如果用户对批处理或者对 SQL 有着比较强的需求,我们这个版本会用户可以得到很多好处。Blink 在阿里内部的应用AI 前线:请介绍一下 Blink 在阿里内部的使用情况。目前 Blink 在阿里的大数据架构中扮演什么样的角色?在阿里内部主要用于哪些业务和应用场景?蒋晓伟: 现在阿里的大数据平台上,所有的实时计算都已经在使用 Blink;同时,除了实时计算以外,在一些流批一体化的场景也会用 Blink 来做批处理;我们在机器学习场景也有一个探索,叫做 Alink,这个项目是对 Flink Machine Learning Library 的改进,其中实现了大量的算法,都是基于 Flink 做实时机器学习的算法,Alink 在很多场景已经被证明在规模上有很大的优势。同时,我们在图计算场景也有一些探索。AI 前线:目前阿里内部有多少部门在使用 Blink?蒋晓伟: 前段时间我们刚刚做过统计,阿里的技术部门大约有 70% 都在使用 Blink。Blink 一直是在用户的反馈之中成长起来的,对于内部用户反馈的数据倾斜、资源使用率、易用性方面的问题,Blink 都做了针对性的改进。现在 Blink 用的最多的场景主要还是实时计算方面,阿里还有一些业务现在相对比较新,还没有进入实时计算的领域,等这些业务进入实时计算领域时也会使用 Blink。在批处理方面,阿里内部也有一个自研的批处理引擎叫做 MaxCompute,MaxCompute 也会拥抱 Flink 生态,在语法和语义上做和 Flink 兼容的工作。未来,整个阿里的计算体系和平台都会融入同一个生态。后续规划AI 前线:接下来阿里对于 Blink 还有哪些规划?包括技术改进、落地应用、更新维护、社区等几个方面。蒋晓伟: 从技术上说,今天我们公布了 Flink 在批处理上的成果,接下来,我们会对技术持续投入,我们希望每几个月就能看到技术上有一个比较大的亮点。下一波亮点应该是机器学习场景。要把机器学习支持好,有一系列的工作要做,包括引擎的功能、性能和易用性。这些工作我们已经在内部的讨论和进行之中,接下来几个月,大家应该会看到一些成果。我们也在和社区讨论一些事情。除了机器学习之外,我们在图计算方面也有一些探索,包括对增量迭代更好的支持。做完这些之后,可以认为 Flink 作为大数据的计算引擎已经比较完备了。同时,我们也重点去做 Flink 的生态,包括 Flink 与其他系统之间的关系、易用性等。Flink 要真正做好,不仅需要它本身功能强大,还需要把整个生态做得非常强大。这部分我们甚至会跟一些 ISV 合作,看看是不是能够在 Flink 之上提供更好的解决方案,进一步降低用户的使用门槛。在社区方面,我们希望能够把把 Blink 完全融入 Flink 社区,一起做 Flink 社区的运营,让 Flink 真正在中国、乃至全世界大规模地使用起来。在应用方面,实时流计算其实有很多很有潜力的应用场景,但有一些可能大家不是非常熟悉,我们会对这些场景做一些推广。以实时机器学习为例,它往往能够给我们带来比一般的机器学习更大的效果提升。去年,实时强化学习给我们在搜索上带来了 20% 以上的提升。除此之外,在安全领域(比如实时的 Fraud Detection)、监控报警方面,还有 IoT 领域,实时流计算都有非常广泛的应用场景。这些 Flink 现在可能已经做了,但是大家还没有意识到,Flink 能够给大家带来这样的商业上的好处。AI 前线:Blink 开源之后,后续阿里在这基础上做的变更和更新会以什么样的方式推回社区版本?蒋晓伟: 我们理想的方式是,阿里内部的版本是社区的 Flink 版本加上一些定制化的插件,不需要对 Flink 本身做修改,而是对 Flink 做增加。比如跟阿里内部系统交互的部分跟社区是不适用的,就会保持在内部,我们希望这些修改不动 Flink 代码,而是用插件的方式加在 Flink 上面。最终的方式就是,对于所有公司都有用的修改会在 Flink 代码本身做修改,使所有使用 Flink 的公司都能从中获利,而对接阿里内部系统的部分就只在阿里内部使用。下一代实时流计算引擎之争AI 前线:先在很多人提到实时流计算引擎,都会拿 Spark 和 Flink 来做对比,您怎么看待下一代实时流计算引擎之争?未来实时流计算引擎最重要的发展方向是什么?蒋晓伟:Spark 和 Flink 一开始 share 了同一个梦想,他们都希望能够用同一个技术把流处理和批处理统一起来,但他们走了完全不一样的两条路,前者是用以批处理的技术为根本,并尝试在批处理之上支持流计算;后者则认为流计算技术是最基本的,在流计算的基础之上支持批处理。正因为这种架构上的不同,今后二者在能做的事情上会有一些细微的区别。比如在低延迟场景,Spark 基于微批处理的方式需要同步会有额外开销,因此无法在延迟上做到极致。在大数据处理的低延迟场景,Flink 已经有非常大的优势。经过我们的探索,Flink 在批处理上也有了比较大的突破,这些突破都会反馈回社区。当然,对于用户来说,多一个选择永远是好的,不同的技术可能带来不同的优势,用户可以根据自己业务场景的需求进行选择。未来,在大数据方向,机器学习正在逐渐从批处理、离线学习向实时处理、在线学习发展,而图计算领域同样的事情也在发生,比如实时反欺诈通常用图计算来做,而这些欺诈事件都是实时地、持续不断地发生,图计算也在变得实时化。但是 Flink 除了大数据领域以外,在应用和微服务的场景也有其独特的优势。应用和微服务场景对延迟的要求非常苛刻,会达到百毫秒甚至十毫秒级别,这样的延迟只有 Flink 的架构才能做到。我认为应用和微服务其实是非常大的领域,甚至可能比大数据更大,这是非常激动人心的机会。上面这些都是我们希望能够拓宽的应用领域。AI 前线:在技术方面,Spark 和 Flink 其实是各有千秋,但在生态和背后支持的公司上面,Flink 是偏弱的,那么后续在生态和企业支持这块,阿里会如何帮助 Flink?蒋晓伟: 这次阿里举办 Flink Forward China 就是想推广 Flink 生态的重要举动之一。除了 Flink Forward China 大会,我们还会不定期举办各种线下 Meetup,投入大量精力打造中文社区,包括将 Flink 的英文文档翻译成中文、打造 Flink 中文论坛等。在垂直领域,我们会去寻找一些合作伙伴,将 Flink 包装在一些解决方案中提供给用户使用。AI 前线:关于开源项目的中立性问题。阿里现在在大力地推动 Flink 开源项目的应用和社区的发展,但业界其他公司(尤其是与阿里在其他业务上可能有竞争的公司)在考虑是否采用 Flink 的时候可能还是会对社区的中立性存在一些疑虑,对于这一点,阿里是怎么考虑的?蒋晓伟: 阿里本身会投入非常大的力量推动 Flink 社区的发展和壮大,但我们也非常希望有更多企业、更多人加入社区,和阿里一起推动社区发展,这次阿里承办 Flink Forward China 峰会就是想借此机会让更多公司参与进来。光阿里一家是无法把 Flink 生态做起来的。我希望大家能够看到我们在做的事情,然后消除这样的疑虑。我们会用自己的行动表明,我们是真的希望把 Flink 的社区做大,在这件事情上,我们并不会有私心。本文作者:阿里云头条阅读原文本文为云栖社区原创内容,未经允许不得转载。 ...

December 21, 2018 · 2 min · jiezi

网易考拉在服务化改造方面的实践

导读:网易考拉(以下简称考拉)是网易旗下以跨境业务为主的综合型电商,自2015年1月9日上线公测后,业务保持了高速增长,这背后离不开其技术团队的支撑。微服务化是电商IT架构演化的必然趋势,网易考拉的服务架构演进也经历了从单体应用走向微服务化的整个过程,以下整理自网易考拉陶杨在近期Apache Dubbo Meetup上的分享,通过该文,您将了解到:考拉架构的演进过程考拉在服务化改造方面的实践考拉在解决注册中心性能瓶颈方面的实践考拉未来的规划考拉架构的演进过程考拉在2015年初上线的时候,线上只有七个工程,商品详情页、购物车下单页等都耦合在中间这个online的工程里面。在上线之初的时候,这种架构还是比较有优势的,因为当时考拉的开发人员也不是很多,把所有的功能都耦合在一个进程里面,利于集中开发、测试和上线,是一种比较高效和节省成本的方式。但是随着业务的不断发展,包括需求的逐步增多,开发团队的不断扩容,这时候,单体架构的一些劣势就逐渐的暴露出来了,例如开发效率低:功能之间的相互耦合,不同需求的不同分支也经常会修改同一块代码,导致合代码的过程非常痛苦,而且经常会出问题。再例如上线成本高:几乎所有的发布需求都会涉及到这些应用的上线,同时不断增长的业务需求,也会使得我们的代码越来越臃肿,造成维护困难、可用性差,功能之间相互耦合,都耦合在一个进程里面,导致一旦某一个业务需求涉及的代码或者资源出现问题,那么就会影响其他的业务。比如说我们曾经在online工程里面,因为优惠券兑换热点的问题,影响了核心的下单服务。这个架构在考拉运行的4到5个月的时间里,从开发到测试再到上线,大家都特别痛苦。所以我们就开始进行了服务化拆分的工作。这个是考拉现在的分布式服务架构。伴随着服务化的拆分,我们的组织架构也进行了很多调整,出现了商品中心、用户中心和订单中心等等。拆分其实是由业务驱动的,通过业务来进行一些横向拆分或者纵向拆分,同时,拆分也会面对一个拆分粒度的问题,比如怎么才算一个服务,或者说服务拆的过细,是不是会导致我们管理成本过高,又或者说是否会带来架构上的新问题。考拉的拆分由粗到细是一个逐步演进的过程。随着服务化的拆分,使得服务架构越来越复杂,随之而来产生了各种各样的公共技术,比如说服务治理、平台配置中心、分布式事务和分布式定时任务等等。考拉的服务化实践微服务框架在服务化中起到了很重要的作用,是服务化改造的基石,经过严格的技术选型流程后,我们选用了Dubbo来作为考拉服务改造的一个重要支柱。Dubbo可以解决服务化过程中服务的定义、服务的注册与发现、服务的调用和路由等问题,此外,Dubbo也具有一些服务治理的功能和服务监控的功能。下面我将介绍考拉基于Dubbo做的一些服务化实践。首先来说一下 熔断。在进行服务化拆分之后,应用中原有的本地调用就会变成远程调用,这样就引入了更多的复杂性。比如说服务A依赖于服务B,这个过程中可能会出现网络抖动、网络异常,或者说服务B变得不可用或者不好用时,也会影响到A的服务性能,甚至可能会使得服务A占满整个线程池,导致这个应用上其它的服务也受影响,从而引发更严重的雪崩效应。因此,服务之间有这样一种依赖关系之后,需要意识到服务的依赖其实是不稳定的。此时,需要通过采取一些服务治理的措施,例如熔断、降级、限流、隔离和超时等,来保障应用不被外部的异常拖垮。Dubbo提供了降级的特性,比如可以通过mock参数来配置一些服务的失败降级或者强制降级,但是Dubbo缺少自动熔断的特性,所以我们在Dubbo上引入了Hystrix。消费者在进行服务调用的时候会经过熔断器,当服务提供者出现异常的时候,比如暂时性的不可用,熔断器就会打开,对消费端进行调用短路,此时,消费端就不会再发起远程调用,而是直接走向降级逻辑。与此同时,消费端会持续的探测服务的可用性,一旦服务恢复,熔断器就会关闭,重新恢复调用。在Dubbo的服务治理平台上,可以对Hystrix上运行的各种动态参数进行动态的配置,包括是否允许自动熔断,是否要强制熔断,熔断的失败率和时间窗口等等。下面再说一下 限流。当用户的请求量,调用超过系统可承受的并发时系统QPS会降低、出现不可用甚至存在宕机的风险。这就需要一个机制来保护我们的系统,当预期并发超过系统可承受的范围时,进行快速失败、直接返回,以保护系统。Dubbo提供了一些基础的限流特性,例如可以通过信号量的配置来限制我们消费者的调用并发,或者限制提供者的执行并发。但是这些是远远不够的,考拉自研了限流框架NFC,并基于Dubbo filter 的形式,实现了对Dubbo的支持,同时也支持对URL等其他资源的限流。通过配置中心动态获取流控规则,对于资源的请求,比如Dubbo调用会经过流控客户端,进行处理并判断是否触发限流,一旦请求超出定义的阈值,就会快速失败。同时,这些限流的结果会上报到监控平台。上图中的页面就是考拉流控平台的一个监控页面,我们在页面上可以对每一个资源(URL、Dubbo接口)进行一个阈值的配置,并对限流进行准实时监控,包括流控比率、限流次数和当前的QPS等。限流框架除了实现基本的并发限流之外,也基于令牌桶和漏桶算法实现了QPS限流,并基于Redis实现了集群级别的限流。这些措施保障系统在高流量的情况下不会被打垮。考拉在监控服务方面的改造在服务化的过程中,系统变得越来越复杂,服务数量变得越来越多,此时需要引入更多维度的监控功能,帮助快速的去定位并解决系统中的各类问题。监控主要分为这四个方面,日志、Metrics、Trace和HealthCheck。在应用程序、操作系统运行的时候,都会产生各种各样的日志,通过日志平台对这些日志进行采集、分析和展示,并支持查询和操作。Metrics反映的是系统运行的基本状态,包括瞬时值或者聚合值,例如系统的CPU使用率、磁盘使用率,以及服务调用过程中的平均延时等。Trace是对服务调用链的一个监控,例如调用过程中的耗时分析、瓶颈分析、依赖分析和异常分析等。Healthcheck可以探测应用是否准备就绪,是否健康,或者是否还存活。接下来,围绕Dubbo来介绍一下考拉在监控方面的改造实践。第一个是服务监控。Dubbo提供了服务监控功能,支持定期上报服务监控数据,通过代码增强的方式,采集Dubbo调用数据,存储到时序数据库里面,将Dubbo的调用监控功能接入到考拉自己的监控平台。上图中的页面是对Dubbo提供者的服务监控,包括对服务接口、源集群等不同维度的监控,除了全局的调用监控,还包括不同维度的监控,例如监控项里的调用次数。有时候我们更关心慢请求的情况,所以会将响应时间分为多个范围,比如说从0到10毫秒,或是从10到50毫秒等,这样就可以看到在各个范围内请求的数量,从而更好地了解服务质量。同时,也可以通过各种报警规则,对报警进行定义,当服务调用出现异常时,通过邮件、短信和电话的形式通知相关人员。监控平台也会对异常堆栈进行采集,例如说这次服务调用的异常的原因,是超时还是线程满了的,可以在监控平台上直接看到。同时生成一些监控报表,帮助我们更好地了解服务的性能,推进开发去改进。第二个是Trace。我们参考了Dapper,自研了Trace平台,并通过代码增强的方式,实现了对Dubbo调用链路的采集。相关调用链参数如TarceID,SpanID 等是通过Dubbo的隐式传参来传递的。Trace可以了解在服务调用链路中的一个耗时分析和瓶颈分析等。Trace平台上可以展示一次服务调用,经历了哪些节点,最耗时的那个节点是在哪里,从而可以有针对性的去进行性能优化。Trace还可以进行依赖分析,这些依赖是否合理,能否通过一些业务手段或者其它手段去减少一些不合理的依赖。Trace对异常链路进行监控报警,及时的探测到系统异常并帮助我们快速的定位问题,同时和日志平台做了打通,通过TraceId可以很快的获取到关联的异常日志。第三个是健康检查。健康检查也是监控中很重要的一个方面,以更优雅的方式上线应用实例。我们和自动部署平台结合,实现应用的健康检查。服务启动的时候可以通过Readiness接口判断应用依赖的各种资源,包括数据库、消息队列等等是否已经准备就绪。只有健康检查成功的时候才会触发出注册操作。同时Agent也会在程序运行的过程中定时的检查服务的运行状态。同时,也通过这些接口实现更优雅的停机,仅依赖shutdownhook,在某些情况下不一定靠谱,比如会有shutdownhook执行先后顺序的问题。应用发布的时候,首先调用offline接口,将注册服务全部从注册中心反注册,这时不再有新的流量进来,等到一段时间后,再执行停机发布操作,可以实现更加优雅的停机。考拉在服务测试方面的改造下面来介绍一下考拉在服务测试方面的实践。服务测试分为接口测试、单链路压测、全链路压测和异常测试四个维度。接口测试通过接口测试,可以来验证对外提供的Dubbo服务是否正确,因此我们也有接口测试平台,帮助QA更好的进行接口测试,包括对接口的编辑(入参、出参),用例的编辑和测试场景的执行等,单链路压测单链路的压测,主要面对单个功能的压测,比如要上线一个重要功能或者比较重要的接口之前,必须通过性能测试的指标才可以上线。全链路压测考拉作为电商平台,在大促前都会做全链路压测,用以探测系统的性能瓶颈,和对系统容量的预估。例如,探测系统的各类服务的容量是否够,需要扩容多少,以及限流的阈值要定多少合适,都可以通过全链路压测来给出一些合理的值。异常测试对服务调用链路中的一些节点进行系统异常和服务异常的注入,也可以获取他们的强度依赖关系。比如一个非常重要的接口,可以从Trace获取的调用链路,然后对调用链的依赖的各个服务节点进行异常注入。通过接口的表现,系统就会判断这个接口的强度依赖关系,以改善这些不合理的强依赖关系。考拉在API网关方面的改造随着考拉服务化的发展,我们自研了API网关,API网关可以作为外部流量的统一接口,提供了包括路由转发、流控和日志监控等一些公共的功能。考拉的API网关是通过泛化调用的方式来调用后台Dubbo的服务的。Dubbo原生的泛化调用的性能比普通Api调用要差一些,所以我们也对泛化调用性能做了一些优化,也就是去掉了泛化调用在返回结果时的一次对象转换。最终压测的结果泛化的性能甚至比正常的调用性能还要好些。考拉在多语言方面的改造考拉在业务发展的过程中产生了不少多语言的需求,例如,我们的前端团队希望可以用Node应用调用Dubbo服务。对比了易用性,选用了开源的jsonrpc 方案,然后在后端的Dubbo服务上暴露了双协议,包括Dubbo协议和json rpc协议。但在实施的过程中,也遇到了一些小问题,比如说,对于Dubbo消费者来说,不管是什么样的协议提供者,都是invoker。通过一个负载均衡策略,选取一个invoker进行调用,这个时候就会导致原来的Java客户端选用一个jsonrpc协议的提供者。这样如果他们的API版本不一致,就有可能导致序列化异常,出现调用失败的情况。所以,我们对Dubbo的一些调用逻辑做了改造,例如在Java客户端的消费者进行调用的时候,除非显示的配置,否则默认只用Dubbo协议去调用。另外,考拉也为社区的jsonrpc扩展了隐式传参的功能,因为可以用Dubbo隐式传参的功能来传递一些全链路参数。考拉在解决注册中心性能瓶颈方面的实践注册中心瓶颈可能是大部分电商企业都会遇到的问题,考拉也不例外。我们现在线上的Dubbo服务实例大概有4000多个,但是在ZooKeeper中注册的节点有一百多万个,包括服务注册的URL和消费者订阅的URL。Dubbo应用发布时的惊群效应、重复通知和消费者拉取带来的瞬时流量一下就把ZooKeeper集群的网卡打满,ZooKeeper还有另外一个问题,他的强一致性模型导致CPU的利用率不高。就算扩容,也解决不了ZooKeeper写性能的问题,ZooKeeper写是不可扩展的,并且应用发布时有大量的请求排队,从而使得接口性能急剧下降,表现出来的现象就是应用启动十分缓慢。因此,在今年年初的时候就我们决定把ZooKeeper注册中心给替换掉,对比了现有的一些开源的注册中心,包括Consul、Eruka、etcd等,觉得他们并不适合Dubbo这种单进程多服务的注册模型,同时容量能否应对未来考拉的发展,也是一个问号。于是,我们决定自研注册中心,目前正在注册中心的迁移过程当中,采用的是双注册中心的迁移方案,即服务会同时注册ZooKeeper注册中心,还有新的注册中心,这样对原有的架构不会产生太大的影响。考拉新的注册中心改造方案和现在社区的差不多,比如说也做了一个注册数据的拆分,往注册中心注册的数据只包含IP, Port 等关键数据,其它的数据都写到了Redis里面,注册中心实现使用了去中心化的一个架构,包括使用最终一致性来换取我们接口性能的一个提升。后面如果接入Dubbo,会考虑使用Nacos而不是ZooKeeper作为注册中心。未来规划考拉最近也在进行第二机房的建设,通过两个机房独立部署相同的一套系统,以实现同城双活。针对双机房的场景,Dubbo会做一定的改造,例如同机房优先调用,类似于即将发布的Dubbo2.7.0中的路由特性。在Dubbo在服务注册的时候,读取系统环境变量的环境标或者机房标,再将这些机房标注册到注册中心,然后消费端会做一个优先级路由,优先进行同机房的服务调用。容器化也是我们在规划的一个方向。随着服务化进程的演进,服务数也变得越来越多,通过容器化、DevOps可以提升测试、部署和运维效率。Service Mesh在今年非常火,通过Service Mesh将服务框架的的能力比如注册发,路由和负载均衡,服务治理等下沉到Sidecar,使用独立进程的方式来运行。对于业务工程的一个解耦,帮助我们实现一个异构系统,对多语言支持,也可以解决中间件升级推动困难以及各种依赖的冲突,业务方也可以更好的关注于业务开发,这也会是未来探索的一个方向。本文作者:中间件小哥阅读原文本文为云栖社区原创内容,未经允许不得转载。

December 20, 2018 · 1 min · jiezi

支付宝客户端架构分析:自动化日志收集及分析

小蚂蚁说:《支付宝客户端架构解析》系列将从支付宝客户端的架构设计方案入手,细分拆解客户端在“容器化框架设计”、“网络优化”、“性能启动优化”、“自动化日志收集”、“RPC 组件设计”、“移动应用监控、诊断、定位”等具体实现,带领大家进一步了解支付宝在客户端架构上的迭代与优化历程。本节将结合禾兮在 OSChina 珠海站现场的分享《移动端分析方案在蚂蚁金服 mPaaS 中的实践》,介绍支付宝客户端自动化日志收集与分析的具体思路。内容将分成三个部分展开:支付宝客户端分析方案的探索;MAS 移动分析框架浅析;mPaaS 技术架构与助力。支付宝客户端分析方案的探索正如我们在《开篇 | 模块化与解耦式开发在蚂蚁金服 mPaaS 深度实践探讨》已经对支付宝的架构演变与开发团队规模发展做过介绍:截止目前,在研发上面,支付宝仅 Android、iOS 客户端开发人员近千人,客户端代码行数超过了数百万行,按业务划分的工程数也已近千个,每个工程都有独立的开发 owner 负责某一个具体的模块。虽然工程师团队及工程量越发庞大,支付宝依旧能够做到日发布的频率以确保业务快速迭代,同时在业务功能日益复杂的环境,保证 App 闪退率仅 0.01%。那么,在如此大体量的用户规模和研发团队下,支付宝又是如何确保用户使用过程中的用户体验呢?我们主要从以下两个维度衡量客户端用户体验:静态:指应用开发过程中,关注 App 本身的安装包大小、存储、涉及到的用户隐私权限、安全策略等,决定用户是否愿意安装并使用你的应用。动态:指应用发布上线后,用户在使用过程中,App 的启动速度,闪退、卡死卡顿等稳定性数据,网络请求,内存以及电量流量等用户实际的使用感受。启动应用是用户使用任何一款应用最必不可少的操作,从点击 App 图标到首页展示,整个启动过程的性能,严重影响着用户的体验。支付宝客户端作为一个超级 App,启动速度当然是我们关注的重要指标之一。支付宝对于应用启动过程中的优化,主要分为以下四个方面:框架治理:梳理启动流程并重构,遵守启动过程中按需加载原则。引用 Pipeline 机制,根据业务优先级规定业务初始化时机。制定统一的开发规范,尽量降低业务方流程对启动性能的影响。业务治理:按需加载,延时执行。线程治理:统一管理已有线程,并调整线程优先级。I/O 治理:关注主线程 I/O,优化合并频繁读写的 I/O 操作,尽量使用统一存储。技术突破:防止启动过程中的 UI 重刷操作。虚拟机优化,包括 JIT 关闭,降低 GC 次数。基础模块调优,分析主线程耗时操作并优化。另外,用户使用过程中 App 的内存、存储、电量及流量等消耗,也是重要的衡量指标。具体的优化点如下:内存:内存分析:memtrace hprof 线下内存分析,遍历对象,根据生命周期标记内存泄露,同时根据 object 创建引用确定业务归属。Native 内存:图像库切换到 native 层,4.x bitmap 像素数据放到 ashme 共享内存,降低 GC。内存优化:对象池复用,减小 bitmap 对内存占用,使用更小的图,尤其注意三方 H5 页面。存储:存储分析:查看应用存储大小。存储优化:使用共享库,业务定向优化,压缩存储等。流量:耗流量原因:分析各种网络请求。流量异常捕获:hook 所有网络请求,根据host聚合流量,超过阈值确定异常。流量优化:PC 底层协议优化,资源增量按需下载,同时通过切面信息调用方。电量:耗电原因:监控 CPU 使用率,各种 sensor、gps、weaklock、网络连接等耗电操作。耗电异常捕获:遍历线程,获取所有线程运行时间,与主线程比较确定异常。耗电优化:高性能 dump 线程栈优化,通过线程映射调用方,评估调用逻辑进行优化。针对以上每个优化点,支付宝都投入了大量精力进行研究和实践,有关启动性能优化的详细内容可以查阅文档《支付宝客户端架构解析:iOS 客户端启动性能优化初探》和《支付宝客户端架构解析:Android 客户端启动速度优化之「垃圾回收」》,其他优化点请持续关注“客户端架构解析”系列文章。基于这些对用户体验优化的内容,支付宝构建了一套完整的超级 App 线上运维体系,实时监控线上 App 发生的异常问题,针对这些问题,以最快的时间定位问题原因并找到对应的解决方案,最后通过动态热修复的技术及时修复线上问题,最终形成一个线上质量保障的闭环,保障应用运行的稳定性。MAS移动分析框架浅析接下来,详细介绍超级 App 运维体系中的移动监控框架具体是如何实现的。移动分析 MAS(Mobile Analysis Service)通过对移动客户端、H5、小程序、PC等多端埋点数据的采集与分析,实现产品核心指标监控,提供页面、设备、留存、性能等基础分析,并支持自定义事件分析、漏斗分析等高阶分析,帮助企业更好地完成业务监控、用户洞察与行为分析,指导产品迭代,精细化产品运营,辅助营销决策,加速业务商业化。主要分为以下四个阶段:整个移动分析的完整链路从左往右看,就是客户端通过调用埋点 SDK 的接口进行数据埋点,埋点 SDK 对日志进行格式化后,先写入客户端本地文件,满足日志上报触发条件后,将本地日志上报到日志服务器并清理本地日志文件以减少存储大小;日志服务器接收到客户端上报的日志后同步到计算平台,经过离线计算和实时计算后,将结果进行展示,用来监控、分析、搜索、推荐等。接下来我们将从移动分析框架的四个阶段,详细介绍数据分析的整个链路逻辑。数据采集根据采集数据时机、应用场景,最终用途的不同,我们把客户端采集的数据分为了以下几类。其中结合 mPaaS 模块化开发框架,报活埋点、押后台埋点、页面自动化埋点、性能埋点及 H5 埋点,由客户端 SDK 自动采集,无需开发者手动调用接口实现,开发者只需要关注自己的业务逻辑,在需要监控的逻辑除埋点统计。为了降低频繁上报日志对应用性能的影响,客户端采集到数据后,会预先保存在应用本地,通过以下三种方式同步到日志服务器:自动上报:满足一定条件后客户端埋点 SDK 自动上报,包括程序每次冷启动都会触发检查日志上报的逻辑。程序进入后台会立即触发上报。写日志时,某种类型的日志默认到达 40 条就触发上报。实时监控:对于比较重要的客户端日志,如异常、应用闪退日志等,可实时上报,产生一条上报一条,便于后台实时监控。动态控制:在自动上报的基础上,通过服务端下发的开关值,修改客户端日志写入和日志上报触发的条件。如在大流量并发的情况下,为减少日志服务器的压力,控制客户端只写入并上报异常或闪退日志,忽略行为日志的统计。数据计算上报到日志服务器的日志,会同步到计算平台进行计算,后台主要包含以下几个系统:mdap:日志采集网关,负责收集客户端埋点日志,收到日志后,直接传输至 JStorm 集群进行计算。JStorm:实时计算引擎,根据处理规则对日志进行实时解析并将需要的数据存储入库。SSDB: kv 数据存储层,底层使用 leveldb,支持单表十亿级记录。ZooKeeper:集群管理、组件间服务发现。数据应用计算平台计算出来的结果,可以为用户提供用户分析、事件分析、行为、性能等数据分析服务。基础分析:关注于 App 的通用分析,包括每日登录用户、新增用户、使用时长、用户留存、页面分析、访问路径等基础分析。高阶分析:用于 App 专注业务的特定分析需求,提供一种灵活的多维分析能力;提供热修复报告,帮助您了解 RPC、修复、回滚相关信息等。性能分析:提供闪退、卡死、卡顿的统计功能。当客户端发生性能问题后,移动分析服务提供实时查看性能分析的统计数据。日志管理:支持按关键字实时搜索查询日志,或通过服务端开关实时控制客户端日志上报逻辑。数据决策在上一步数据应用的基础上,可以与大数据、营销平台及推送平台结合,根据移动分析得到的埋点数据,通过大数据平台进行打标、圈人、用户画像及建模后,可以在营销平台上发起一次营销活动,指定活动的类型,活动算法,参与人群及活动奖品,通过消息推送、数据同步,动态发布等形式,触达到客户端,实现客户端拉新促活、活动推广及操作引导的目的。同时结合运营活动的场景需求,形成了一套完整的数字化运营体系,监控一次运营活动的参与人数、活动发放率、核销率等,观察活动的有效性。mPaaS 技术架构与助力上面介绍的支付宝内移动端分析方案的技术积累和架构实践,已经通过 mPaaS 移动开发平台作为蚂蚁金服金融科技的一部分对外开放。mPaaS(Mobile Platform As A Service),源于支付宝 App 的移动开发平台,为移动开发、测试、运营及运维提供云到端的一站式解决方案,能有效降低技术门槛、减少研发成本、提升开发效率,协助企业快速搭建稳定高质量的移动 App。在 mPaaS 移动开放平台上,我们将移动分析框架中的本地日志、埋点、自动化埋点、性能监控、Crash报告、诊断日志等模块,作为一个个独立的组件来进行输出。任何一个 App 都可以通过 mPaaS 插件,添加对应的组件,在当前应用中集成这些功能,只需要这样简单的操作,就可以让你的应用具有和支付宝一样强大的移动端分析监控能力。客户端集成了这些移动分析相关的组件后,用户在使用APP过程中会产生相应的日志,经过数据采集、数据上报、数据计算等处理后,计算的结果会同步到 mPaaS 移动分析的大盘上展示,包括应用的基础应用概况、性能稳定数据、流量走向等等,方便开发者实时监控 APP 的概况大盘和稳定性等,实时发现线上问题并修复。目前,mPaaS 移动开发平台已经服务了众多企业,包括蚂蚁金服内部的香港支付宝、网商银行、口碑商家等,同时还有大量的外部蚂蚁生态合作伙伴,包括12306、上海地铁、广州地铁、广发银行等。秉承着「给世界带来小而美的变化」的理念,我们通过 mPaaS 帮助 12306 这样的国民级 App 重构了客户端,使得大家可以用上一个好的体验的 App 进行出行购票,用 mPaaS 这样成熟的底层框架搭建一个 12306 仅需要 2-3 个月的时间。除了 12306 还有支付宝香港版,广发银行手机银行和发现精彩多个客户端,同样在短短几个月的时间内便完成了业务重构。蚂蚁金服ATEC城市峰会·上海2019年1月4日,一场金融科技的前沿探索之旅——蚂蚁金服ATEC科技大会即将起航,你准备好了吗?小蚂蚁为大家准备了满满了攻略福利,等你来拿!了解蚂蚁金服ATEC科技大会更多信息,记得持续关注小蚂蚁(官微:蚂蚁金服科技)蚂蚁金服金融科技官网:https://tech.antfin.com/artic…ATEC科技大会:蚂蚁金服ATEC(Ant Technology Exploration Conference)科技大会是蚂蚁金服在中国举办的最大的技术盛会,旨在向遍布全球的合作伙伴与技术专业人群分享新技术的发展趋势与落地实践,通过对先进的前沿技术探索与讨论,为世界带来平等的机会。ATEC大会一直在路上。过去一年,蚂蚁金服ATEC科技大会走过杭州、硅谷、新加坡、伦敦等全球金融科技中心城市,之后将会造访国内各个金融科技中心城市,与当地受众分享蚂蚁金服对金融科技最前沿的洞察。ATEC科技大会报名方式 & 福利:本次大会门票采用审核制。嘉宾填写个人信息进行报名,报名后3天之内收到报名审核成功的短信,即为报名成功。大会报名截止日期为2018年12月31日24时,额满即止。前50位报名嘉宾将会优先审核通过,先到先得哦~小蚂蚁还为大家准备了本账号读者的专属福利邀请码: SF2B3A 还等什么,赶紧点击下方报名链接,小蚂蚁期待你的到来ATEC报名链接:https://alipaytech.mikecrm.co… 本文作者:平生栗子阅读原文本文为云栖社区原创内容,未经允许不得转载。 ...

December 19, 2018 · 1 min · jiezi

内存性能的正确解读

一台服务器,不管是物理机还是虚拟机,必不可少的就是内存,内存的性能又是如何来衡量呢。1. 内存与缓存现在比较新的CPU一般都有三级缓存,L1 Cache(32KB-256KB),L2 Cache(128KB-2MB),L3 Cache(1M-32M)。缓存逐渐变大,CPU在取数据的时候,优先从缓存去取数据,取不到才去内存取数据。2. 内存与时延显然,越靠近CPU,取数据的速度越块,通过LMBench进行了读数延迟的测试。从上图可以看出:Intel(R) Xeon(R) Platinum 8163 CPU @ 2.50GHz 这款CPU的L1D Cache,L1I Cache为32KB,而L2 Cache为1M,L3为32M;在对应的Cache中,时延是稳定的;不同缓存的时延呈现指数级增长;所以我们在写业务代码的时候,如果想要更快地提高效率,那么使得计算更加贴近CPU则可以获取更好的性能。但是从上图也可以看出,内存的时延都是纳秒为单位,而实际业务中都是毫秒为单位,优化的重点应该是那些以毫秒为单位的运算,而内存时延优化这块则是长尾部分。3. 内存带宽内存时延与缓存其实可谓是紧密相关,不理解透彻了,则可能测的是缓存时延。同样测试内存带宽,如果不是正确的测试,则测的是缓存带宽了。为了了解内存带宽,有必要去了解下内存与CPU的架构,早期的CPU与内存的架构还需要经过北桥总线,现在CPU与内存直接已经不需要北桥,直接通过CPU的内存控制器(IMC)进行内存读取操作:那对应的内存带宽是怎样的呢?测试内存带宽有很多很多工具,linux下一般通过stream进行测试。简单介绍下stream的算法:stream算法的原理从上图可以看出非常简单:某个内存块之间的数据读取出来,经过简单的运算放入另一个内存块。那所谓的内存带宽:内存带宽=搬运的内存大小/耗时。通过整机合理的测试,可以测出来内存控制器的带宽。下图是某云产品的内存带宽数据:————————————————————-Function Best Rate MB/s Avg time Min time Max timeCopy: 128728.5 0.134157 0.133458 0.136076Scale: 128656.4 0.134349 0.133533 0.137638Add: 144763.0 0.178851 0.178014 0.181158Triad: 144779.8 0.178717 0.177993 0.180214————————————————————-内存带宽的重要性自然不言而喻,这意味着操作内存的最大数据吞吐量。但是正确合理的测试非常重要,有几个注意事项需要关注:内存数组大小的设置,必须要远大于L3 Cache的大小,否则就是测试缓存的吞吐性能;CPU数目很有关系,一般来说,一两个核的计算能力,是远远到不了内存带宽的,整机的CPU全部运行起来,才可以有效地测试内存带宽。当然跑单核的stream测试也有意义,可以测试内存的延时。4. 其他内存与NUMA的关系:开启NUMA,可以有效地提供内存的吞吐性能,降低内存时延。stream算法的编译方法选择:通过icc编译,可以有效地提供内存带宽性能分。原因是Intel优化了CPU的指令,通过指令向量化和指令Prefetch操作,加速了数据的读写操作以及指令操作。当然其他C代码都可以通过icc编译的方法,提供指令的效率。本文作者:ecs西邪阅读原文本文为云栖社区原创内容,未经允许不得转载。

December 13, 2018 · 1 min · jiezi

优秀工程师必备的三大思维,你拥有哪些?

阿里妹导读:不同岗位、不同职责的技术人对工程师思维的深度要求是不一样的,但从多维度去思考却应是每个技术人都应该具备的素养。本文整理自阿里巴巴高级技术专家至简在团队内部的个人分享,希望通过对工程师思维的分析和解读,让大家能正确对待那些在现实工作中看上去与本职岗位无关,却对团队效能影响极大的一些点和一些事。作者简介:至简,阿里巴巴高级技术专家,是集团Service Mesh方向的重要参与者和推动者。曾出版《专业嵌入式软件开发——全面走向高质高效编程》一书,坚信和倡导软件设计是软件质量之根本,并对软件开发的复杂性本质有着深刻的认识,对如何高质高效实施软件开发有着自己独到的见解和方法。在社会分工的背景下,软件行业的工程师群体被划分成了开发、测试、产品等诸多岗位,以协作的方式共同完成价值创造。高度依赖软件的互联网行业正以全新的方式改善着人们的生活,同时在改善的道路上对价值创造的效能提出了更高的要求,而背后是对个体与团队的协作效能有着更高的诉求。专人专岗的协作模式在进一步改善团队的协作效能时所面临的最大挑战在于“岗位墙”,即岗位间衔接不可避免会出现一些模糊地带,而这些模糊地带又很容易相互忽视,导致失去关注而很大程度地拉低了团队效能。比如,开发工程师会认为保证质量是测试工程师单方面的职责;开发工程师不关注用户体验而只需关注实现需求,等等。此外,这种协作模式也会固化个体的思维和心智模式,将个体的思维和心智框定在所处岗位之内,以致对于岗位之外的内容不能很好地理解,使得个体在整个协作活动中会缺乏同理心、系统性,从而影响工作幸福感。相信这些现实工作场景读者并不陌生:开发工程师对产品工程师所提出的用户体验方面的需求会认为过于吹毛求疵;产品工程师因不理解技术的实现原理而提出天马行空、不接地气的需求(我们在此不讨论创新这一特例);测试工程师因为不理解工程效率的内涵而将自己的工作变成了体力活;开发工程师不清楚自己对于软件质量的责任,而将那些本因自己做好的琐碎工作心安理得地交给测试工程师去做;辛辛苦苦所开发出来的功能,用户抱怨难用。这些问题发生的最终结果,一定是团队协作效能的低下。那么在没有找到比专人专岗更好的协作模式的情形下,我们该如何发挥个体的力量去改善团队的协作效能呢?改善的起点在于全面地梳理工程师思维,帮助工程师个体在职场和职业发展中建立起更为全面的思维和视野,以促使每个工程师在协作过程中能最大程度地发挥个体能力去推动团队协作效能的提升。我将工程师思维分解为产品、技术和工程三大思维。每个维度主要关注的内容通过几个关键字去表达,如下图所示。下面针对每种思维需要关注的每个词以图中从上至下的顺序去解释。由于解释是基于关键词去展开的,所以段落之间的衔接可能会显得生硬,还请读者见谅。产品思维产品思维的起源是用户(或客户)价值。用户价值是通过技术手段以产品或服务的形态去解决用户的痛点,或带去爽点。毫无疑问,工程师在日常工作中应时刻关注并理清自己的工作与用户(或客户)价值的联系,并且应该通过聚焦于用户价值去安排工作的优先级和分配自己的精力。当用户价值足够时,产品能否在市场中立足并真正收获收益,首先考验的是产品的用户体验。良好的用户体验一定是站在用户的角度,基于用户心智来塑造概念,由于概念存在理解和解释成本,所以塑造的概念应足够轻、少且易掌握。概念一旦塑造出来则概念间的关系也随之确定,这些关系基本上决定了产品与用户的交互流程。好的产品体现于“易用”二字,其极致在于迎合用户的本能反应并符合各种生活或专业常识。所有产品都存在演进的过程,所创造的用户价值也在被不断地挖掘与探索,那时不同的细化价值需要通过产品特性去区分和表达。特性也是产品差异化的一种体现,特性也间接地确定了软件实现层面的功能模块边界。作为开发工程师,也需要对产品特性有非常透彻的理解,并能将其很好地抽象并转化为软件实现层面的功能模块。特性需要考虑通过售卖license等形式进行开启或关闭去实现售卖,这一点对于2B的产品甚是必要。为了产品更好地演进,需要通过数据闭环的形式去检验创造用户价值的效果,让产品的开发、运营、营销工作做到有的放矢。在产品价值创造的道路上,最害怕的事莫过于只顾低头干做加法,做得多却无人关心收效。而我们通过数据化闭环的形式,不仅能让整个产品大团队聚焦于核心价值,还能帮助团队在探索用户价值的道路上理性地做减法。大多情形下,做减法远难于做加法。技术思维技术思维的源头是需求。需求可以分成市场需求、系统需求、特性需求等不同层次,回答的是技术层面“做什么”的问题。显然,清晰表达的需求以及对需求的精确理解才能确保将事做对。毋容置疑,需求一旦出现偏差所导致的浪费是非常严重的,也正因如此工程师对于需求的质量相当重视。需求一旦确立,会基于模块化的思想拆分成多个功能模块去降低实现的局部复杂度,最终将所有功能模块“拼接”在一起去实现整体需求。每个功能模块会安排给一个人或一个团队负责,由于功能模块是需求分解后的产物,容易导致工程师在实现的过程中只看到“树木”而忘记了“森林”。性能是工程师在实现一个功能模块时不得不关注的,特别是当功能模块被运用于高频、时效性敏感、算力有限的场合时性能将尤其被关注。在现实中有时会存在工程师乐于追求性能的极致去体现自己的技术实力,甚至出现过早追求性能而滑入过度设计的误区。毫无疑问,一个正规的团队,对于功能模块的开发工作多会以项目制、多个迭代的方式去完成交付。不少工程师这里会有一个误区,忘记了敏捷思想所倡导的“项目计划的目的是为了适应变化”,而是将“按时交付”当作是天职,各种赶工爬到终点时却毫不意外地看到了“一地鸡毛”的景象。在迈向第四次工业革命的道路上,人工智能、大数据、机器学习,Kubernetes、Istio、Knative、Go、Dart、Flutter等新技术不断冲击着工程师已掌握的技能。快速跟上技术的迭代步伐是每个有追求的工程师不断提升自己专业素养的表现之一。工程师的内心一定不缺乏对新技术的追求,憧憬自己所掌握的技术具有一定的先进性。工程思维工程思维的起点是流程。流程的背后是科学,以既定的步骤、阶段性的输入/输出去完成价值创造,通过过程控制确保最终结果让人满意。由于流程涉及每一个工程师的工作质量与效率,其含义不只在于定义、工具化、检查等内容,而是应基于工程师的日常工作习惯,将流程与工程师的工作环境无缝整合。“无缝”体现于流程中的概念与工程师群体已建立的专业常识相一致、没有增加毫无价值的负担,根本仍是确保易用性。机制的含义是通过对所需解决问题的分析,以一种模式去解决同类问题。机制应体现一定的系统性,而非“头痛治头,脚痛治脚”。系统性不是一开始就能被洞察到,可能在演进的过程中逐步发现和完善的,因而需要工程师在工作的过程中不时回顾并付诸实践去落实。对于工程师来说,机制是通过系统性的软件设计去达成的。可以说产品质量直接决定了工程师的工作和生活幸福感。一个质量不可靠的产品一定会给用户和工程师自己带去麻烦,甚至造成无法挽回的经济损失并造成负面的社会影响。对于工程师来说,那势必打乱个体的工作与生活节奏。为了让产品的质量做到可靠,单元测试、静态分析、动态分析等确保工程质量的手段应成为工程师的基本工作内容,通过将这些手段与CI(Continuous Integration)流程进行整合去持续构建起对软件产品的质量信心。在互联网行业,除了软件产品的质量得可靠外,风险可控是另一个不能忽视的内容。而风险可控是建立于系统性机制和质量可靠之上的。对于服务端软件来说愈是如此。风险往往出现于资源使用的极端场景,当从外部涌入的过多事务远超软件产品的处理能力时,需要有一定的机制让整个产品能相对平滑地应对,或是扩充资源、或是限制涌入事务的流量。软件所需的机器成本是比较容易忽视的话题,软件成本不只与软件性能相关,还与软件之间的依赖、技术方案等因素相连。当一个软件需要从公司的内部对外输出时,平时忽视对成本的关注就会暴露出成本问题。比如,为了运行某个软件需要数量庞大的计算资源,所导致的资金开销对于客户来讲很可能是无法接受的。至此,大致介绍完了自己所理解的工程师思维。延伸了解工程师思维的价值在于,工程师个体需要在工作中逐步建立起产品、技术和工程三大思维,以便用更为全面的视角去看待日常工作中所面临的困境和困惑。当站在单一的思维去看待所面临的问题时可能觉得不合理,但从三大思维层面去审视时所得到结论可能完全相反。从团队协作的角度,只有团队中有更多的个体从多维度去进行思考,才容易发现岗位间衔接的那些无人问津的灰色地带,进而通过补位、助攻去更大程度地发挥团队的效能。显然,不同岗位、不同职责的工程师对于这三大思维的深度要求是不一样的,但从多维度去思考却应是每个工程师都应该具备的素养。最后,我也给读者留下一些问题,同样期待您在留言区分享自己的思考。本文作者:至简阅读原文本文来自云栖社区合作伙伴“阿里技术”,如需转载请联系原作者。

December 13, 2018 · 1 min · jiezi

将神经网络训练成一个“放大镜”

摘要: 想不想将神经网络训练成一个“放大镜”?我们就训练了一个这样炫酷的神经网络,点击文章一起看下吧!当我们网购时,我们肯定希望有一个贴近现实的购物体验,也就是说能够全方位的看清楚产品的细节。而分辨率高的大图像能够对商品进行更加详细的介绍,这真的可以改变顾客的购物体验,让顾客有个特别棒的购物之旅。idealo.de是欧洲领先的比价网站,也是德国电子商务市场最大的门户网站之一,在此基础上,我们希望能够在此基础上为用户提供一个用户友好、有吸引力的购物平台。在这里,我们利用深度学习来评估数百万酒店图像的美学层次和技术质量,另外,那些没有任何信息的、特别难看的小的产品图像对我们来说是无效的,因此需要想办法解决。购物网站上并不是所有的商店都能为顾客提供高质量的图像,相反,商家提供的图像特别小、分辨率特别低、质量也很低。为了向用户展示高质量的高分辨率图像,我们基于2018年的论文《图像超分辨率的RDN网络》,训练了一个特别先进的卷积神经网络。我们的目标很简单:拍摄一些特别小的图像,然后就像使用放大镜一样,对图像进行放大,并且还要保持高分辨率。本文对实现这一目标做了详细介绍,另外,具体实现的细节,请查看GitHub。总概与大多数深度学习项目一样,我们的深度学习项目主要有四个步骤:1.回顾前人对该项目所做的贡献。2.实施一个或多个解决方案,然后比较预先训练的版本。3.获取数据,训练并测试模型。4.针对训练和验证结果对模型进行改进和优化。具体来说,本文主要有以下几方面的内容:1.介绍模型训练的配置,如何评估模型的性能2. 查看早期训练和测试结果,了解从哪方面进行改进。3.指出后续需要探索的方向。训练与以往“标准”的监督深度学习任务不同,我们这个“放大镜”深度学习模型输出的不仅仅是类标签或一个分数,而是一整幅图像。这就意味着训练过程以及评估会跟以往略有不同,我们要输出的是原始高分辨率图像,为了更好的对模型进行评估,我们需要一种测量缩放输出图像“质量”的方法,该方法更详细的优缺点将在后面进一步做详细阐释。损失函数损失函数是用来评估神经网络的性能究竟如何,这个有很多方法可以评估。这个问题的本质为大家留下了创造力空间,如有些聪明的人会用高级特征和对抗网络。对于第一次迭代,我们使用标准方法:网络的超分辨率(SR)输出和高分辨率输出(HR)之间的像素均方差(MSE)。评估我们用峰值信噪比(PSNR)来评估输出图像的质量,峰值信噪比是基于两个图像之间的像素均方差(MSE)。由于峰值信噪比是最常用的评估输出图像质量的方法,因此我们也使用这一评估标准,以便将本文模型与其他模型作比较。开始我们在p2.xlarge AWS EC2实例上进行训练,直到验证损失函数收敛,训练结束,这大概需要90个周期(一个周期24小时),然后使用Tensorboard跟踪训练数据集及验证数据集的损失函数和PSNR值。如上图所示,左上角为在每个周期结束时,反向传播到神经网络上的训练损失函数。右上角为跟踪泛化性能的非训练数据及的损失。左下角为训练数据集的PSNR值。右下角为验证数据集的PSNR值。结果输出的结果如下所示,我们先看看模型的输出结果,再考虑如何对该模型进行改进。左侧是验证数据集中的整个图像,中间是卷积神经网络的输出提取图像块,右侧是使用标准过程将中间输出提取图像块按比例放大后的输出,这里使用了GIMP的图像缩放功能![LR图像(左),重建SR(中),GIMP基线缩放(右)。](https://upload-images.jianshu…这个结果肯定不是特别完美:蝴蝶的天线周围有些没必要的噪声,蝴蝶的颈部和背部的毛发及翅膀上有些斑点轮廓,神经网络的输出图像(中)看起来要比GIMP基线输出图像(右)更加清晰。结果分析为了进一步理解模型有哪些优缺点,我们需要从验证数据集中提取具有高PSNR值的图像块和具有低能量度值的图像块。不出所料,性能最佳的图像块是具有较多平坦区域的图像块,而较为复杂的图像块难以准确再现。因此,我们重点关注这些较复杂的图像块,以便对结果进行训练和评估。同样的,我们也可以使用热图(heatmap)突出显示原始HR图像和神经网络输出SR图像之间的误差,颜色较暗的部分对应于较高的像素均方误差(较差的结果),颜色较浅的部分对应于较低的像素均方误差(或较好的结果)我们可以看到,具有多种模式的区域的误差会更大,但是看起来“更简单”的过渡区域则是相当黑暗的(例如云、天空),这是可以改进的,因为它与idealo的目录用例相关。浅谈深度学习任务中的非真实数据与常见的分类问题或输出为一个分值的监督式深度学习任务不同,我们用于评估神经网络输出的真实数据是原始HR图像。这既有好处,也有坏处。坏处:像Keras这样的当前较为流行的深度学习框架没有预先制定训练解决方案,比如生成器。实际上,它们通常依赖于从一维数组中获取训练和验证标签或文件,或者是直接从文件结构中派生出来的,这会涉及到一些额外的编码算法。好处:没有必要花太多时间来获得标签,给出一个HR图像池,我们可以对其进行简单的缩小,获得我们所需要的LR训练数据,并使用原始HR图像来评估损失函数通常来说,使用图像数据对神经网络进行训练时,需要从训练数据集中随机的选择多个图像来创建训练批次。然后将这些尺寸重新缩小到一个较小的尺寸,一般来说,大小约为100×100像素。我们随时使用随机变换对图像进行增强,并反馈到神经网络中。在这种情况下,没有必要向神经网络反馈整张图像,并且这也非常不可取。这是因为,我们不能将图像重新缩放到100×100的小像素点。毕竟,我们想要对图像进行放大。同时,我们也无法用较大尺寸的图像进行训练,比如大小为500×600像素的图像,因为处理这种大图像需要很长的时间。相反,我们可以从整个图像中提取一个非常小的随机色块,比如大小为16×16像素块,这样一来,我们就有了更多的数据点,因为每个图像都可以提供数百个不同的色块。我们之所以能够处理这种小色块,是因为我们不需要将一堆图像进行分类,比如:腿+尾巴+胡须+死老鼠=猫。因此,模型的末端就没有全连接层。我们只需要使用神经网络来构建这些模式的抽象表示,然后学习如何对其进行放大,除此以外,还要对块进行重新组合,使组合后的图像变得有意义。这种抽象表示由卷积层和放大层来完成,其中,卷积层是该网络中唯一的一种层类型。我们还要说明的是,全卷积结构使该网络的输入大小相互独立。也就是说,这意味着它与普通的分类卷积神经网络有所不同,你可以向完全卷积神经网络中输入任何大小的图像:无论输入图像原始大小是什么,网络都会输入一个输入图像大小2倍的图像。有关图像超分辨率的RDN网络更加详细的介绍,请查看文末链接。另一方面,我们还需要思考如何从图像中提取这些块。思路如下:从数据集中提取出n个随机图像,然后从每个图像中提取p个随机快。我们尝试了几种方法,如下图所示:首先,从一个均匀的网格中提出块,并创建一个完整的块数据集。在训练的时候,我们随机的提取其batch_size,并对其进行放大,反馈给网络。这种方法的缺点是需要静态的存储非常大的数据集,如果要用云服务器进行训练,这种方法其实并不理想:移动和提取数据集是一项相当耗时的操作,并且具有确定性定义的数据集可能并不是最佳数据集。另一种方法是随机选择batch_size大小的图像,并从中提取单个块。这种方法需要从磁盘中读取数据,这就大大降低了训练时间(我们设置的每个训练时间为15min-1h)。最后,我们将原始数据集中随机提取的单个图像块进行融合,并从中提取动态的batch_size块,这不仅能存储原始数据集,同时,也能保持较快的训练速度。拓展这是放大idealo网站产品目录的第一步,我们已经完成了。下面是我们将产品图像中低质量、低分辨率的图像进行放大,并输出。从上图中,我们可以看到,图像中较为平坦的地方会产生较为明显的噪声,文本也会略有失真。这就是我们计划要改进的地方。在下一步的探索中,我们将在自己的产品图像数据集上对神经网络进行训练。相关链接Github: Image Super ResolutionPaper: Residual Dense Network for Image Super-Resolution (Zhang et al. 2018)Dataset: DIVerse 2K resolution high quality images本文作者:【方向】阅读原文本文为云栖社区原创内容,未经允许不得转载。

December 10, 2018 · 1 min · jiezi

【Keras】减少过拟合的秘诀——Dropout正则化

摘要: Dropout正则化是最简单的神经网络正则化方法。阅读完本文,你就学会了在Keras框架中,如何将深度学习神经网络Dropout正则化添加到深度学习神经网络模型里。 Dropout正则化是最简单的神经网络正则化方法。其原理非常简单粗暴:任意丢弃神经网络层中的输入,该层可以是数据样本中的输入变量或来自先前层的激活。它能够模拟具有大量不同网络结构的神经网络,并且反过来使网络中的节点更具有鲁棒性。阅读完本文,你就学会了在Keras框架中,如何将深度学习神经网络Dropout正则化添加到深度学习神经网络模型里,具体内容如下:如何使用Keras API创建Dropout层;如何使用Keras API将Dropout正则化添加到MLP、CNN和RNN层;在现有模型中,如何使用Dropout正则化减少过拟合。Keras中的Dopout正则化在Keras深度学习框架中,我们可以使用Dopout正则化,其最简单的Dopout形式是Dropout核心层。在创建Dopout正则化时,可以将 dropout rate的设为某一固定值,当dropout rate=0.8时,实际上,保留概率为0.2。下面的例子中,dropout rate=0.5。layer = Dropout(0.5)Dropout层将Dropout层添加到模型的现有层和之前的输出层之间,神经网络将这些输出反馈到后续层中。用dense()方法指定两个全连接网络层:…model.append(Dense(32))model.append(Dense(32))…在这两层中间插入一个dropout层,这样一来,第一层的输出将对第二层实现Dropout正则化,后续层与此类似。现在,我们对第二层实现了Dropout正则化。…model.append(Dense(32))model.append(Dropout(0.5))model.append(Dense(32))…Dropout也可用于可见层,如神经网络的输入。在这种情况下,就要把Dropout层作为网络的第一层,并将input_shape参数添加到层中,来制定预期输入。…model.add(Dropout(0.5, input_shape=(2,)))…下面,我们来看看Dropout正则化如何与常见的网络类型一起使用。MLP Dropout正则化在两个全连接层之间添加Dropout正则化,代码如下所示:# example of dropout between fully connected layersfrom keras.layers import Densefrom keras.layers import Dropout…model.add(Dense(32))model.add(Dropout(0.5))model.add(Dense(1))…CNN Dropout正则化我们可以在卷积层和池化层后使用Dropout正则化。一般来说,Dropout仅在池化层后使用。# example of dropout for a CNNfrom keras.layers import Densefrom keras.layers import Conv2Dfrom keras.layers import MaxPooling2Dfrom keras.layers import Dropout…model.add(Conv2D(32, (3,3)))model.add(Conv2D(32, (3,3)))model.add(MaxPooling2D())model.add(Dropout(0.5))model.add(Dense(1))…在这种情况下,我们要将Dropout应用于特征图的每个单元中。在卷积神经网络中使用Dropout正则化的另一个方法是,将卷积层中的整个特征图都丢弃,然后在池化期间也不再使用。这种方法称为空间丢弃,即Spatial Dropout。“我们创建了一个新的Dropout正则化方法,我们将其称为Spatial Dropout。在这个方法中,我们将Dropout值扩展到整个特征映射中。”——《使用卷积神经网络有效的进行对象本地化,2015》在Keras中,通过SpatialDropout2D层提供Spatial Dropout正则化。# example of spatial dropout for a CNNfrom keras.layers import Densefrom keras.layers import Conv2Dfrom keras.layers import MaxPooling2Dfrom keras.layers import SpatialDropout2D…model.add(Conv2D(32, (3,3)))model.add(Conv2D(32, (3,3)))model.add(SpatialDropout2D(0.5))model.add(MaxPooling2D())model.add(Dense(1))…RNN Dropout正则化我们在LSTM循环层和全连接层之间使用Dropout正则化,代码如下所示:# example of dropout between LSTM and fully connected layersfrom keras.layers import Densefrom keras.layers import LSTMfrom keras.layers import Dropout…model.add(LSTM(32))model.add(Dropout(0.5))model.add(Dense(1))…在这里,将Dropout应用于LSTM层的32个输出中,这样,LSTM层就作为全连接层的输入。还有一种方法可以将Dropout与LSTM之类的循环层一起使用。LSTM可以将相同的Dropout掩码用于所有的输入中。这个方法也可用于跨样本时间步长的循环输入连接。这种使用递归模型进行Dropout正则化则称为变分循环神经网络(Variational RNN)。“变分循环神经网络在每个时间步长使用相同的Dropout掩码,包括循环层。这与在RNN中实现Dropout正则化一样,在每个时间步长丢弃相同的神经网络单元,并且随意的丢弃输入、输出和循环连接。这和现有的技术形成对比,在现有的技术中,不同的神经网络单元将在不同的时间步长被丢弃,并且不会对全连接层进行丢弃。”——《循环神经网络中Dropout的基础应用,2016》Keras通过循环层上的两个参数来支持变分神经网络(输入和循环输入样本时间步长的一致性丢弃),这称为 输入“Dropout”和循环输入的“recurrent_dropout”。# example of dropout between LSTM and fully connected layersfrom keras.layers import Densefrom keras.layers import LSTMfrom keras.layers import Dropout…model.add(LSTM(32))model.add(Dropout(0.5))model.add(Dense(1))…Dropout正则化案例在本节中,我们将演示如何使用Dropout正则化来减少MLP在简单二元分类问题上的过拟合。在这里,我们提供了一个在神经网络上应用Dropout正则化的模板,你也可以将其用于分类和回归问题。二元分类问题在这里,我们使用一个标准的二元分类问题,即定义两个二维同心圆,每个类为一个圆。每个观测值都有两个输入变量,它们具有相同的比例,类输出值为0或1。这个数据集就是 “圆”数据集。我们可以使用make_circles()方法生成观测结果。我们为数据添加噪声和随机数生成器,以防每次运行代码时使用相同的样本。# generate 2d classification datasetX, y = make_circles(n_samples=100, noise=0.1, random_state=1)我们可以用x和y坐标绘制一个数据集,并将观察到的颜色定义为类值。生成和绘制数据集的代码如下:# generate two circles datasetfrom sklearn.datasets import make_circlesfrom matplotlib import pyplotfrom pandas import DataFrame# generate 2d classification datasetX, y = make_circles(n_samples=100, noise=0.1, random_state=1)# scatter plot, dots colored by class valuedf = DataFrame(dict(x=X[:,0], y=X[:,1], label=y))colors = {0:‘red’, 1:‘blue’}fig, ax = pyplot.subplots()grouped = df.groupby(’label’)for key, group in grouped: group.plot(ax=ax, kind=‘scatter’, x=‘x’, y=‘y’, label=key, color=colors[key])pyplot.show()运行以上代码,会创建一个散点图,散点图展示每个类中观察到的同心圆形状。我们可以看到,因为噪声,圆圈并不明显。这是一个特别好的测试问题,因为类不可能用一条直线表示,比如它不是线性可微分的,在这种情况下,就需要使用非线性方法来解决,比如神经网络。在这里,我们只生成了100个样本,这对于神经网络来说,样本是相当少了。但是它提供了训练数据集的过拟合现象,并且在测试数据及上的误差更大:这是使用正则化的一个特别好的例子。除此之外,这个样本集中有噪声,这就使神经网络模型有机会学习不一致样本的各个方面。多层感知器的过拟合我们可以创建一个MLP模型来解决这个二元分类问题。该模型将具有一个隐藏层,它的节点比解决该问题所需节点要多得多,从而产生过拟合。另外,我们训练模型的时间也大大超过正常训练模型所需要的时间。在定义模型之前,我们将数据集拆分为训练集和测试集:30个训练数据来训练模型和70个测试数据来评估拟合模型性能。# generate 2d classification datasetX, y = make_circles(n_samples=100, noise=0.1, random_state=1)# split into train and testn_train = 30trainX, testX = X[:n_train, :], X[n_train:, :]trainy, testy = y[:n_train], y[n_train:]接下来,我们可以定义模型。在隐藏层中使用500个节点和矫正过得线性激活函数;在输出层中使用S型激活函数预测类的值(0或1)。该模型使用二元交叉熵损失函数进行优化,这个函数适用于二元分类问题和梯度下降到有效Adam问题。# define modelmodel = Sequential()model.add(Dense(500, input_dim=2, activation=‘relu’))model.add(Dense(1, activation=‘sigmoid’))model.compile(loss=‘binary_crossentropy’, optimizer=‘adam’, metrics=[‘accuracy’])将训练数据训练4000次,默认每次训练次数为32。 然后用测试数据集验证该模型性能,代码如下。# fit modelhistory = model.fit(trainX, trainy, validation_data=(testX, testy), epochs=4000, verbose=0)测试的方法如下。# evaluate the model_, train_acc = model.evaluate(trainX, trainy, verbose=0), test_acc = model.evaluate(testX, testy, verbose=0)print(‘Train: %.3f, Test: %.3f’ % (train_acc, test_acc))最后,在每次训练的时候绘制模型的性能。如果模型在训练数据集时的确是过拟合,那么我们训练集上的准确度线图更加准确,并且准确度随着模型学习训练数据集中的统计噪声而再次下降。# plot historypyplot.plot(history.history[‘acc’], label=‘train’)pyplot.plot(history.history[‘val_acc’], label=‘test’)pyplot.legend()pyplot.show()将以上所有代码组合起来,如下所示。# mlp overfit on the two circles datasetfrom sklearn.datasets import make_circlesfrom keras.layers import Densefrom keras.models import Sequentialfrom matplotlib import pyplot# generate 2d classification datasetX, y = make_circles(n_samples=100, noise=0.1, random_state=1)# split into train and testn_train = 30trainX, testX = X[:n_train, :], X[n_train:, :]trainy, testy = y[:n_train], y[n_train:]# define modelmodel = Sequential()model.add(Dense(500, input_dim=2, activation=‘relu’))model.add(Dense(1, activation=‘sigmoid’))model.compile(loss=‘binary_crossentropy’, optimizer=‘adam’, metrics=[‘accuracy’])# fit modelhistory = model.fit(trainX, trainy, validation_data=(testX, testy), epochs=4000, verbose=0)# evaluate the model, train_acc = model.evaluate(trainX, trainy, verbose=0), test_acc = model.evaluate(testX, testy, verbose=0)print(‘Train: %.3f, Test: %.3f’ % (train_acc, test_acc))# plot historypyplot.plot(history.history[‘acc’], label=‘train’)pyplot.plot(history.history[‘val_acc’], label=‘test’)pyplot.legend()pyplot.show()运行以上代码,我们可以看到模型在训练和测试数据集上的性能:模型在训练数据集上的性能优于测试数据集,这是过度拟合的一个可能标志。鉴于神经网络和训练算法的随机性,模型的测试结果可能会有所不同。由于该模型严重过拟合,该模型在同一数据集上运行的结果差异并不会很大。Train: 1.000, Test: 0.757下图为模型在训练和测试集上的精度图,我们可以看到过拟合模型的预期性能,其中测试精度增加到一定值以后,再次开始减小。使用Dropout正则化减少MLP过拟合我们使用Dropout正则化更新这个示例,即在隐藏层和输出层之间插入一个新的Dropout层来实现。在这里,指定Dropout rate=0.4。# define modelmodel = Sequential()model.add(Dense(500, input_dim=2, activation=‘relu’))model.add(Dropout(0.4))model.add(Dense(1, activation=‘sigmoid’))model.compile(loss=‘binary_crossentropy’, optimizer=‘adam’, metrics=[‘accuracy’])下面列出了隐藏层后添加了dropout层的完整更新示例。# mlp with dropout on the two circles datasetfrom sklearn.datasets import make_circlesfrom keras.models import Sequentialfrom keras.layers import Densefrom keras.layers import Dropoutfrom matplotlib import pyplot# generate 2d classification datasetX, y = make_circles(n_samples=100, noise=0.1, random_state=1)# split into train and testn_train = 30trainX, testX = X[:n_train, :], X[n_train:, :]trainy, testy = y[:n_train], y[n_train:]# define modelmodel = Sequential()model.add(Dense(500, input_dim=2, activation=‘relu’))model.add(Dropout(0.4))model.add(Dense(1, activation=‘sigmoid’))model.compile(loss=‘binary_crossentropy’, optimizer=‘adam’, metrics=[‘accuracy’])# fit modelhistory = model.fit(trainX, trainy, validation_data=(testX, testy), epochs=4000, verbose=0)# evaluate the model, train_acc = model.evaluate(trainX, trainy, verbose=0)_, test_acc = model.evaluate(testX, testy, verbose=0)print(‘Train: %.3f, Test: %.3f’ % (train_acc, test_acc))# plot historypyplot.plot(history.history[‘acc’], label=‘train’)pyplot.plot(history.history[‘val_acc’], label=‘test’)pyplot.legend()pyplot.show()运行以上代码,查看模型在训练和测试集上的性能。你所得到的结果可能会有所不同,在这种情况下,该模型具有较高的方差。在这里,我们可以看到,Dropout导致训练集的准确度有所下降,从100%降至96%,而测试集的准确度从75%提高到81%。Train: 0.967, Test: 0.814从这里我们可以看出,该模型已经不再适合训练数据集了。尽管使用Dropout正则化时会产生很多噪音,训练数据集和测试数据集的模型精度持续增加。在后续学习中,你可以进一步探索以下这些问题:1.输入Dropout。在输入变量上使用Dropout正则化,更新示例,并比较结果。2.权重约束。在隐藏层添加max-norm权重约束,更新示例,并比较结果。3.反复评估。更新示例,重复评估过拟合和Dropout模型,总结并比较平均结果。4.网格搜索率。创建Dropout概率的网格搜索,并报告Dropout rate和测试数据集准确度二者之间的关系。拓展阅读论文1.《使用卷积神经网络进行高效的对象本地化,2015》2.《递归神经网络中的理论Dropout应用,2016》博文1.基于Keras深度学习模型中的Dropout正则化2.如何使用LSTM网络的Dropout进行时间序列预测API1.Keras Regularizers API2.Keras Core Layers API3.Keras Convolutional Layers API4.Keras Recurrent Layers API5.sklearn.datasets.make_circles API总结阅读完本文,你已经了解了如何将深度学习正则化添加到深度学习神经网络模型的API中。具体来说,有以下几个内容:1.如何使用Keras API创建Dropout层。2.如何使用Keras API将Dropout正则化添加到MLP、CNN和RNN层。3.如何向现有模型中添加Dropout正则化,以此减少过拟合。本文作者:【方向】阅读原文本文为云栖社区原创内容,未经允许不得转载。 ...

December 10, 2018 · 3 min · jiezi

阿里云HBase全新发布X-Pack 赋能轻量级大数据平台

一、八年双十一,造就国内最大最专业HBase技术团队阿里巴巴集团早在2010开始研究并把HBase投入生产环境使用,从最初的淘宝历史交易记录,到蚂蚁安全风控数据存储。持续8年的投入,历经8年双十一锻炼。4个PMC,6个committer,造就了国内最大最专业的HBase技术团队,其中HBase内核中超过200+重要的feature是阿里贡献。集团内部超过万台的规模,单集群超过千台,全球领先。二、HBase技术团队重磅发布X-Pack,重新赋能轻量级大数据平台阿里云自从17年8月提供HBase云服务以来,到18年12月累计服务了上千大B客户,已经有上千个在线的集群。是阿里云增长最为快速的数据库服务,也是大B客户比例最高的云服务之一。并于6月6日全球第一个推出HBase 2.0,是HBase领域当之无愧的排头兵。为了满足客户对数据库更丰富业务处理需求、更易用、强大功能的需求,我们重磅发布 X-Pack :支持SQL、时序、时空、图、全文检索能力、及复杂分析。阿里云HBase从KV为主大数据数据库成功进化成“轻量级全托管大数据平台”数据库。全部能力计划12月底全部上线。三、深度解读 “ 轻量级全托管大数据平台 ”,云HBase能力再上新台阶通常一个大企业里面,数据和业务存在天然的多样性。真正称得上平台级的数据库,要至少要满足客户不同三个及以上层次的诉求,才能称的上平台级。阿里云HBase从成本最优化、运维便利性、业务敏捷度三个方面将HBase的能力全面提升一个高度,成就轻量级全托管大数据平台,云HBase能力再上新台阶。3.1 轻量级,满足CXO成本最优化的诉求1)起步成本低,整体成本低,扩展性强。云HBase针对企业不同的使用环境,不同的SLA诉求,云HBase一共提供3个版本,分别满足开发环境,在线业务,以及金融级业务的诉求。单节点版本,低廉的价格用于开发测试场景,集群版本,99.9%可用,满足企业在线业务诉求,支持最高5000万的QPS和10P的数据。还有支持金融级高可用的双活版本。所有版本都支持11个9的数据可靠性,无需担心数据丢失。2)支持冷存储,助你不改代码,1/3成本轻松搞定冷数据处理大数据场景下,存储成本占比往往是大头,把存储成本降下来,整体成本才能下降。一般随着业务的发展,HBase中存储的数据量会逐渐变大。在这些数据中,业务最关心的,最常访问的,往往是某些特定范围的数据,比如说最近7天的数据,业务对这类数据访问频次高,延迟要求高,即所谓的热数据。而其他的数据,一般访问量极少,性能要求不高, 但这类数据往往数据量大,即冷数据。如果能把冷热数据分离开,把热数据存储在性能更好的介质中,而把庞大的冷数据放到成本更低的介质中,从而实现把更多优质资源用来提高热数据的读写性能,同时节省存储成本的目的。阿里云HBase针对冷数据存储的场景,提供一种新的冷存储介质,其存储成本仅为高效云盘的1/3,写入性能与云盘相当,并能保证数据随时可读。冷存储的使用非常简单,用户可以在购买云HBase实例时选择冷存储作为一个附加的存储空间,并通过建表语句指定将冷数据存放在冷存储介质上面,从而降低存储成本,基本不用改代码就获得了低成本存储能力,助力企业降低整体成本。3.2 全托管,全面解放运维,为业务稳定保驾护航大数据时代,数据是企业最宝贵的资产,业务是企业赖以生存的基础。因此高可用和高可靠是最基本诉求。云HBase提供的全托管服务相比其他的半托管服务以及自建存在天然的优势。依托持续8年在内核和管控平台的研究,以及大量配套的监控工具、跨可用区,跨域容灾多活方案,云HBase提供目前业界最高的4个9的可用性(双集群),11个9的可靠性的高SLA的支持,满足众多企业客户对平台高可用、稳定性的诉求。云HBase服务定位为全托管服务,后台自动代维和保持服务稳定性,极大的降低了客户使用门槛,让无论是SME,还是巨头都能享受到HBase技术红利。选择云HBase就是选择了高可用、高可靠服务!3.3 全面能力提升,源头解决业务敏捷度,真正释放数据和业务的价值1)100%兼容原生接口和能力,开发简单,容易上手。云HBase百分百兼容开源接口,并提供一系列配套开发,数据搬迁,监控工具,全面帮助用户提高开发和管理效率。2)独家跨Region/AZ双活阿里云是云HBase首家推出跨Region/AZ双活,在一个集群出现故障的时候,迅速地将业务切换至另外一个集群从而避免故障。HBase主备之间数据的同步基于异步链路实现,遵循最终一致性协议,典型的主备同步延迟在200ms左右。满足金融、社交、电商、人工智能等关键领域对高可用的诉求。3)备份恢复量级提升百倍以上,数据库领域最大我们经常会听到“某某某DBA误操作把整张表删了”,“某某磁盘故障,造成数据库的某个库的数据全部损坏了”。这种由于外在和内在的原因造成的数据不可靠,最终会给用户带来毁灭性的灾难。所以一个企业级数据库,全量备份、全量恢复、增量备份、增量恢复,是基础能力。传统数据库备份恢复的能力都是TB级别,这在交易等场景下面是足够的,但是面向大数据场景就捉襟见肘了。云HBase通过垂直整合高压缩、内核级优化,分布式处理等能力,将备份恢复的量级成功推高百倍以上,做到百TB级别甚至更高,让客户大数据量下面也无后顾之忧。4)支持融合多模型和融合多负载、提供开箱即用的能力云HBase在KV的基础上,同时支持时序、时空、图、文档等多种数据模型,内置丰富处理能力,让业务开发效率提升百倍。在线能力的基础上,融合流处理、批处理、OLAP,OLTP、高速对象存储,全文检索等能力,提供客户融合业务开箱即用的能力。四、展望未来,持续优化服务,不负重托,成就客户历经近8年的技术沉淀,阿里巴巴大数据NoSQL数据库处理技术的精华沉淀在HBase上,后者成功支撑了成功支撑了阿里经济体中最大的NoSQL业务体量,是阿里大数据处理技术的核心组成部分,当前将这项技术应用到广大企业中,助力企业发现数据价值。短短1年间,就覆盖了社交、金融、政企、车联网、交通、物流、零售、电商等数十个个行业,帮单用户顶住千万级QPS的业务压力,以及百PB级数据高效存储和处理。本文作者:所在jason阅读原文本文为云栖社区原创内容,未经允许不得转载。

December 6, 2018 · 1 min · jiezi

做了2个多月的设计和编码,我梳理了Flutter动态化的方案对比及最佳实现

背景在端上为了提升App的灵活性, 快速解决万变的业务需求,开发者们探索了多种解决方案,如PhoneGap ,React Native ,Weex等,但在Flutter生态还没有好的解决方案。未来闲鱼都会基于Flutter 来跨端开发,如果突破发版周期,在不发版的情况下,完成业务需求,同时能兼容性能体验,无疑是更快的响应了业务需求。因此我们需要探索在Flutter生态下的动态化。方案选择借鉴Android 和Ios上的动态性方案,我们也思考了多种Flutter动态性方案。1.下载替换Flutter编译产物下载新的Flutter编译产物,替换 App 安装目录下的编译产物,来实现动态化,这在Android 端是可行的,但在Ios 端不可行。我们需要双端一体的解决方案,所以这不是最好选择。2.类似React Native 框架我们先来看看React Native 的架构React Native 要转为android(ios) 的原生组件,再进行渲染。用React Native的设计思路,把XML DSL转为Flutter 的原子widget组件,让Flutter 来渲染。技术上说是可行的,但这个成本很大,这会是一个庞大的工程,从投入产出比看,不是很好的选择3.页面动态组件框架由粗粒度的Widget组件动态拼装出页面,Native端已经有很多成熟的框架,如天猫的Tangram,淘宝的DinamicX,它在性能、动态性,开发周期上取得较好平衡。关键它能满足大部分的动态性需求,能解决问题。三种方案的比较图表如:根据实际动态性需求,从两端一致性,和性能,成本,动态性考虑,我们选择一个折中方案,页面动态组件的设计思路是一个不错的选择。页面动态组件框架在Flutter上使用粗力度的组件动态拼装来构建页面,需要一整套的前后端服务和工具。本文我们重点介绍前端界面渲染引擎过程。语法树的选择Native端的Tangram ,DinamicX等框架他们有个共同点,都是Xml或者Html 做为DSL。但是Flutter 是React Style语法。他自己的语法已经能很好的表达页面。无需要自定义的Xml 语法,自定义的逻辑表达式。用Flutter 源码做为DSL 能大大减轻开发,测试过程,不需要额外的工具支持。所以选择了Flutter 源码作为DSL,来实现动态化。如何解析DSLFlutter源码做为DSL,那我们需要对源码进行很好的解析和分析。Flutter analyzer给了我们一些思路,Flutter analyzer是一个代码风格检测工具。它使用package:analyzer来解析dart 源码,拿到ASTNode。看下Flutter analyze 源码结构,它使用了dart sdk 里面的 package:analyzerdart-sdk: analysis_server: analysis_server.dart handleRequest(Request request) analyzer: parseCompilationUnit() parseDartFile parseDirectives Flutter analyze 解析源码得到ASTNode过程。插件或者命令对analysis server发起请求,请求中带需要分析的文件path,和分析的类型,analysis_server经过使用 package:analyzer 获取 commilationUnit (ASTNode),再对astNode,经过computer分析,返回一个分析结果list。同样我们也可以把使用 package:analyzer 把源文件转换为commilationUnit (ASTNode),ASTNode是一个抽象语法树,抽象语法树(abstract syntax tree或者缩写为AST)是源代码的抽象语法结构的树状表现形式.所有利用抽象语法树能很好的解析dart 源码。解析渲染引擎下面重点介绍渲染模块架构图:1.源码解析过程1.AST树的结构如下面这段Flutter组件源码:import ‘package:flutter/material.dart’;class FollowedTopicCard extends StatelessWidget { @override Widget build(BuildContext context) { return new Container( padding: const EdgeInsets.fromLTRB(12.0, 8.0, 12.0, 0.0), child: new InkWell( child: new Center( child: const Text(‘Plugin example app’), ), onTap: () {}, ), ); }}它的AST结构:从AST结构看,他是有规律的.2.AST 到widget Node我们拿到了ASTNode,但ASTNode 和widget node tree 完全是两个不一样的概念,需要递归ASTNode 转化为 widget node tree.widget Node 需要的元素用Name 来记录是什么类型的widgetwidget的arguments放在 map里面widget 的literals 放在list 里面widget 的children 放在lsit 里面widget 的触发事件 函数map里面widget node 加fromjson ,tojson 方法可以在递归astNode tree 时候,识别InstanceCreationExpression来创建一个widget node。2.组件数据渲染框架sdk 中注册支持的组件,组件包括:a.原子组件:Flutter sdk 中的 Flutter 的widgetb.本地组件:本地写好到一个大颗粒的组件,卡片widget组件c.逻辑组件:本地包装了逻辑的widget组件d.动态组件:通过源码dsl动态渲染的widget具体代码如下: const Map<String, CreateDynamicApi> allWidget = <String, CreateDynamicApi>{ ‘Container’: wrapContainer, ………….} static Widget wrapContainer(Map<String, dynamic> pars) { return new Container( padding: pars[‘padding’], color: pars[‘color’], child: pars[‘child’], decoration: pars[‘decoration’], width: pars[‘width’], height: pars[‘height’], alignment: pars[‘alignment’] );}一般我们通过网络请求拿到的数据是一个map。比如源码中写了这么一个 ‘${data.urls[1]}‘AST 解析时候,拿到这么一个string,或者AST 表达式,通过解析它 ,肯定能从map 中拿到对应的值。3.逻辑和事件a.支持逻辑Flutter 概念万物都是widget ,可以把表达式,逻辑封装成一个自定义widget。如果在源码里面写了if else,变量等,会加重sdk解析的过程。所以把逻辑封装到widget中。这些逻辑widget,当作组件当成框架组件。b.支持事件把页面跳转,弹框,等服务,注册在sdk里面。约定使用者仅限sdk 的服务。4.规则和检测工具a.检测规则需要对源码的格式制定规则。比如不支持 直接写if else ,需要使用逻辑wiget组件来代替if else 语句。如果不制定规则,那ast Node 到widget node 的解析过程会很复杂。理论上都可以解析,只要解析sdk 够强大。制定规则,可以减轻sdk的解析逻辑。b.工具检测用工具来检测源码是否符合制定的规则,以保证所有的源码都能解析出来。性能和效果帧率大于50fps,体验上看比weex相同功能的页面更加流畅,Samsung galaxy s8上,感觉不出组件是通过动态渲染的.数据结构服务端请求到的数据,我们可以约定一种格式如下:class DataModel { Map<dynamic, dynamic> data; String type;}每个page 都是由组件组成的,每个组件的数据都是 DataModel来渲染。根据type 来找到对应的模版,模版+data,渲染出界面。动态模版管理模块我们把Widget Node Tree 转换为一个组件Json模版,它需要一套管理平台,来支持版本控制,动态下载,升级,回滚,更新等。框架的边界该框架是通过组件的组装,组件布局动态变更,页面布局动态变更来实现动态化。所以它适合运营变化较快的首页,详情,订单,我的等页面。一些复杂的逻辑需要封装在组件里面,把组件内置到框架中,当作本地组件。框架侧重于动态组件的组装,而引擎对于源码复杂的逻辑表达式的解析是弱化的。后续拓展1.和UI自动化的结合UI自动化 ,前面已经有文章介绍。UI自动化工具生成组件,再组件转为模版,动态下发,来快速解决运营需求。2.国际化的支持App在不同国家会有不同的功能,我们可以根据区域,来动态拼装我们的页面。3.千人千面根据不同的人群,来动态渲染不一样的界面。总结本文介绍动态化方案的渲染部分。该方案都在初探阶段,还有很多需要完善,后续会继续扩展和修改,等达到开源标准后,会考虑开源。动态方案是一个后端前端一体的方案,需要一整套工具配合,后续会有文章继续介绍整体的动态化方案。敬请关注闲鱼技术公共账号,也邀请您加入闲鱼一起探索有意思的技术。参考资料:Static Analysis:https://www.dartlang.org/guides/language/analysis-optionshttps://www.dartlang.org/tools/analyzerdart analyzer :https://pub.dartlang.org/packages/analyzerhttps://github.com/dart-lang/sdk/tree/master/pkg/analyzer_cli#dartanalyzerdartdevc:https://webdev.dartlang.org/tools/dartdevc本文作者:闲鱼技术-石磬阅读原文本文为云栖社区原创内容,未经允许不得转载。 ...

December 5, 2018 · 1 min · jiezi

深度学习Trick——用权重约束减轻深层网络过拟合|附(Keras)实现代码

摘要: 深度学习小技巧,约束权重以降低模型过拟合的可能,附keras实现代码。在深度学习中,批量归一化(batch normalization)以及对损失函数加一些正则项这两类方法,一般可以提升模型的性能。这两类方法基本上都属于权重约束,用于减少深度学习神经网络模型对训练数据的过拟合,并改善模型对新数据的性能。目前,存在多种类型的权重约束方法,例如最大化或单位向量归一化,有些方法也必须需要配置超参数。在本教程中,使用Keras API,用于向深度学习神经网络模型添加权重约束以减少过拟合。完成本教程后,您将了解:如何使用Keras API创建向量范数约束;如何使用Keras API为MLP、CNN和RNN层添加权重约束;如何通过向现有模型添加权重约束来减少过度拟合;下面,让我们开始吧。本教程分为三个部分:Keras中的权重约束;图层上的权重约束;权重约束案例研究;Keras中权重约束Keras API支持权重约束,且约束可以按每层指定。使用约束通常涉及在图层上为输入权重设置kernel_constraint参数,偏差权重设置为bias_constraint。通常,权重约束方法不涉及偏差权重。一组不同的向量规范在keras.constraints模块可以用作约束:最大范数(max_norm):强制权重等于或低于给定限制;非负规范(non_neg):强制权重为正数;单位范数(unit_norm):强制权重为1.0;Min-Max范数(min_max_norm):强制权重在一个范围之间;例如,可以导入和实例化约束:# import normfrom keras.constraints import max_norm# instantiate normnorm = max_norm(3.0)图层上的权重约束权重规范可用于Keras的大多数层,下面介绍一些常见的例子:MLP权重约束下面的示例是在全连接层上设置最大范数权重约束:# example of max norm on a dense layerfrom keras.layers import Densefrom keras.constraints import max_norm…model.add(Dense(32, kernel_constraint=max_norm(3), bias_constraint==max_norm(3)))…CNN权重约束下面的示例是在卷积层上设置最大范数权重约束:# example of max norm on a cnn layerfrom keras.layers import Conv2Dfrom keras.constraints import max_norm…model.add(Conv2D(32, (3,3), kernel_constraint=max_norm(3), bias_constraint==max_norm(3)))…RNN权重约束与其他图层类型不同,递归神经网络允许我们对输入权重和偏差以及循环输入权重设置权重约束。通过图层的recurrent_constraint参数设置递归权重的约束。下面的示例是在LSTM图层上设置最大范数权重约束:# example of max norm on an lstm layerfrom keras.layers import LSTMfrom keras.constraints import max_norm…model.add(LSTM(32, kernel_constraint=max_norm(3), recurrent_constraint=max_norm(3), bias_constraint==max_norm(3)))…基于以上的基本知识,下面进行实例实践。权重约束案例研究在本节中,将演示如何使用权重约束来减少MLP对简单二元分类问题的过拟合问题。此示例只是提供了一个模板,读者可以举一反三,将权重约束应用于自己的神经网络以进行分类和回归问题。二分类问题使用标准二进制分类问题来定义两个半圆观察,每个类一个半圆。其中,每个观测值都有两个输入变量,它们具有相同的比例,输出值分别为0或1,该数据集也被称为“ 月亮”数据集,这是由于绘制时,每个类中出现组成的形状类似于月亮。可以使用make_moons()函数生成观察结果,设置参数为添加噪声、随机关闭,以便每次运行代码时生成相同的样本。# generate 2d classification datasetX, y = make_moons(n_samples=100, noise=0.2, random_state=1)可以在图表上绘制两个变量x和y坐标,并将数据点所属的类别的颜色作为观察的颜色。下面列出生成数据集并绘制数据集的完整示例:# generate two moons datasetfrom sklearn.datasets import make_moonsfrom matplotlib import pyplotfrom pandas import DataFrame# generate 2d classification datasetX, y = make_moons(n_samples=100, noise=0.2, random_state=1)# scatter plot, dots colored by class valuedf = DataFrame(dict(x=X[:,0], y=X[:,1], label=y))colors = {0:‘red’, 1:‘blue’}fig, ax = pyplot.subplots()grouped = df.groupby(’label’)for key, group in grouped: group.plot(ax=ax, kind=‘scatter’, x=‘x’, y=‘y’, label=key, color=colors[key])pyplot.show()运行该示例会创建一个散点图,可以从图中看到,对应类别显示的图像类似于半圆形或月亮形状。上图的数据集表明它是一个很好的测试问题,因为不能用直线划分,需要非线性方法,比如神经网络来解决。只生成了100个样本,这对于神经网络而言较小,也提供了过拟合训练数据集的概率,并且在测试数据集上具有更高的误差。因此,也是应用正则化的一个好例子。此外,样本具有噪声,使模型有机会学习不一致的样本的各个方面。多层感知器过拟合在机器学习力,MLP模型可以解决这类二进制分类问题。MLP模型只具有一个隐藏层,但具有比解决该问题所需的节点更多的节点,从而提供过拟合的可能。在定义模型之前,需要将数据集拆分为训练集和测试集,按照3:7的比例将数据集划分为训练集和测试集。# generate 2d classification datasetX, y = make_moons(n_samples=100, noise=0.2, random_state=1)# split into train and testn_train = 30trainX, testX = X[:n_train, :], X[n_train:, :]trainy, testy = y[:n_train], y[n_train:]接下来,定义模型。隐藏层的节点数设置为500、激活函数为RELU,但在输出层中使用Sigmoid激活函数以预测输出类别为0或1。该模型使用二元交叉熵损失函数进行优化,这类激活函数适用于二元分类问题和Adam版本梯度下降方法。# define modelmodel = Sequential()model.add(Dense(500, input_dim=2, activation=‘relu’))model.add(Dense(1, activation=‘sigmoid’))model.compile(loss=‘binary_crossentropy’, optimizer=‘adam’, metrics=[‘accuracy’])然后,设置迭代次数为4,000次,默认批量训练样本数量为32。# fit modelhistory = model.fit(trainX, trainy, validation_data=(testX, testy), epochs=4000, verbose=0)这里将测试数据集作为验证数据集验证算法的性能:# evaluate the model_, train_acc = model.evaluate(trainX, trainy, verbose=0), test_acc = model.evaluate(testX, testy, verbose=0)print(‘Train: %.3f, Test: %.3f’ % (train_acc, test_acc))最后,绘制出模型每个时期在训练和测试集上性能。如果模型确实对训练数据集过拟合了,对应绘制的曲线将会看到,模型在训练集上的准确度继续增加,而测试集上的性能是先上升,之后下降。# plot historypyplot.plot(history.history[‘acc’], label=‘train’)pyplot.plot(history.history[‘val_acc’], label=‘test’)pyplot.legend()pyplot.show()将以上过程组合在一起,列出完整示例:# mlp overfit on the moons datasetfrom sklearn.datasets import make_moonsfrom keras.layers import Densefrom keras.models import Sequentialfrom matplotlib import pyplot# generate 2d classification datasetX, y = make_moons(n_samples=100, noise=0.2, random_state=1)# split into train and testn_train = 30trainX, testX = X[:n_train, :], X[n_train:, :]trainy, testy = y[:n_train], y[n_train:]# define modelmodel = Sequential()model.add(Dense(500, input_dim=2, activation=‘relu’))model.add(Dense(1, activation=‘sigmoid’))model.compile(loss=‘binary_crossentropy’, optimizer=‘adam’, metrics=[‘accuracy’])# fit modelhistory = model.fit(trainX, trainy, validation_data=(testX, testy), epochs=4000, verbose=0)# evaluate the model, train_acc = model.evaluate(trainX, trainy, verbose=0), test_acc = model.evaluate(testX, testy, verbose=0)print(‘Train: %.3f, Test: %.3f’ % (train_acc, test_acc))# plot historypyplot.plot(history.history[‘acc’], label=‘train’)pyplot.plot(history.history[‘val_acc’], label=‘test’)pyplot.legend()pyplot.show()运行该示例,给出模型在训练数据集和测试数据集上的性能。可以看到模型在训练数据集上的性能优于测试数据集,这是发生过拟合的标志。鉴于神经网络和训练算法的随机性,每次仿真的具体结果可能会有所不同。因为模型是过拟合的,所以通常不会期望在相同数据集上能够重复运行得到相同的精度。Train: 1.000, Test: 0.914创建一个图,显示训练和测试集上模型精度的线图。从图中可以看到模型过拟合时的预期形状,其中测试精度达到一个临界点后再次开始减小。具有权重约束的多层感知器过拟合为了和上面做对比,现在对MLP使用权重约束。目前,有一些不同的权重约束方法可供选择。本文选用一个简单且好用的约束——简单地标准化权重,使得其范数等于1.0,此约束具有强制所有传入权重变小的效果。在Keras中可以通过使用unit_norm来实现,并且将此约束添加到第一个隐藏层,如下所示:model.add(Dense(500, input_dim=2, activation=‘relu’, kernel_constraint=unit_norm()))此外,也可以通过使用min_max_norm并将min和maximum设置为1.0 来实现相同的结果,例如:model.add(Dense(500, input_dim=2, activation=‘relu’, kernel_constraint=min_max_norm(min_value=1.0, max_value=1.0)))但是无法通过最大范数约束获得相同的结果,因为它允许规范等于或低于指定的限制; 例如:model.add(Dense(500, input_dim=2, activation=‘relu’, kernel_constraint=max_norm(1.0)))下面列出具有单位规范约束的完整代码:# mlp overfit on the moons dataset with a unit norm constraintfrom sklearn.datasets import make_moonsfrom keras.layers import Densefrom keras.models import Sequentialfrom keras.constraints import unit_normfrom matplotlib import pyplot# generate 2d classification datasetX, y = make_moons(n_samples=100, noise=0.2, random_state=1)# split into train and testn_train = 30trainX, testX = X[:n_train, :], X[n_train:, :]trainy, testy = y[:n_train], y[n_train:]# define modelmodel = Sequential()model.add(Dense(500, input_dim=2, activation=‘relu’, kernel_constraint=unit_norm()))model.add(Dense(1, activation=‘sigmoid’))model.compile(loss=‘binary_crossentropy’, optimizer=‘adam’, metrics=[‘accuracy’])# fit modelhistory = model.fit(trainX, trainy, validation_data=(testX, testy), epochs=4000, verbose=0)# evaluate the model, train_acc = model.evaluate(trainX, trainy, verbose=0)_, test_acc = model.evaluate(testX, testy, verbose=0)print(‘Train: %.3f, Test: %.3f’ % (train_acc, test_acc))# plot historypyplot.plot(history.history[‘acc’], label=‘train’)pyplot.plot(history.history[‘val_acc’], label=‘test’)pyplot.legend()pyplot.show()运行该示例,给出模型在训练数据集和测试数据集上的性能。从下图可以看到,对权重进行严格约束确实提高了模型在验证集上的性能,并且不会影响训练集的性能。Train: 1.000, Test: 0.943从训练和测试精度曲线图来看,模型已经在训练数据集上不再过拟合了,且模型在训练和测试数据集的精度保持在一个稳定的水平。扩展本节列出了一些读者可能希望探索扩展的教程:报告权重标准:更新示例以计算网络权重的大小,并证明使用约束后,确实使得幅度更小;约束输出层:更新示例以将约束添加到模型的输出层并比较结果;约束偏置:更新示例以向偏差权重添加约束并比较结果;反复评估:更新示例以多次拟合和评估模型,并报告模型性能的均值和标准差;进一步阅读如果想进一步深入了解,下面提供一些有关该主题的其它资源:博客机器学习中矢量规范简介(Gentle Introduction to Vector Norms in Machine Learning)APIKeras Constraints APIKeras constraints.pyKerasCore Layers APIKeras Convolutional Layers APIKeras Recurrent Layers APIsklearn.datasets.make_moons API本文作者:【方向】阅读原文本文为云栖社区原创内容,未经允许不得转载。 ...

November 30, 2018 · 2 min · jiezi

这一年多来,阿里Blink测试体系如何从0走向成熟?

引言Apache Flink是面向数据流处理和批处理的分布式开源计算框架,2016年阿里巴巴引入Flink框架,改造为Blink。2017年,阿里整合了所有流计算产品,决定以Blink引擎为基础,打造一款全球领先的实时计算引擎。当年双11,Blink支持了二十多个事业部/群,同时运行了上千个实时计算job,每秒处理的日志数峰值达到惊人的4.7亿。因此Blink的可靠性和稳定性保障变得极其重要,搜索事业部的质量团队为此专门成立了Blink测试小组,通过一年多的努力,建立了从代码质量到持续集成再到预发测试的全面的测试体系,帮助Blink的质量取得大幅提高。Blink测试平台介绍Blink测试团队为Blink质量量身打造Blink测试平台,内容如下图所示:Blink测试平台包含了三个测试阶段: 代码质量校验阶段,主要进行静态代码扫描、单元测试和基于minicluster的测试;集成测试阶段,主要是进行功能测试、性能测试和带有破坏性的稳定性测试;而预发测试阶段,主要是利用用户的job进行仿真测试,并在版本发布之前做最后的版本兼容性测试。平台选取部分测试集合纳入到precommit的验证中,可尽早发现代码中问题,而大规模的功能、性能、稳定性测试,通常作为dailybuild的集合。另外,Blink测试平台建立了较为完善的质量度量体系,除去对代码覆盖率的统计及变化的分析,还可一键生成测试报告,并对不同版本的质量进行横向对比。代码质量校验阶段代码质量校验阶段是整个Blink质量保障的基础。主要包含单元测试,利用aone提供的"集团代码规约扫描"工具对代码进行规范扫描,单机运行的基于minicluster的集成测试,只有这三个阶段都测试通过后才允许Blink代码提交到项目git。功能测试Blink功能测试框架使用defender,该框架是由pytest[1]改造而来,很好地支持了BlinkSql测试的特性,并支持第三方插件的引入。在测试集群中可以端到端的对某一场景进行精准测试。具体流程如下图所示,支持IDE和Jenkins两种触发模式,yarn_job、yarn_session和local三种case运行调度模式。执行结束后通过web页面或邮件的形式对结果进行展示,并对运行结果进行持久化。具有如下优势:1、case的统一调度与精细化管理:现在Blink在defender上有12个场景4000多个case,可以每天定时进行dailyrun,如果某一类别的case出现问题可单独执行,并可在页面上显示详情。2、case的三种运行模式满足了不同场景的测试需求:其中yarn_session模式对一个模块中存在sqlCase的场景较为适用,可大大减少与Yarn交互的时间。3、case灵活配置:不仅可以支持系统配置,对每个case集所需资源(slot,memory等)或集群其他配置的不同进行单独配置。4、一个case可同时支持批和流两种运行类型。5、client类型灵活扩展:可对现有数据存储和服务进行集成和扩展。现已支持多类型data store读写服务,yarn_session的启动,Blink job交互等。性能测试Blink作为实时大数据处理引擎,其对单位时间内的数据处理能力和数据处理的实时性提出了非常严苛的要求。因此,性能测试是整个Blink测试中非常重要的一环,是衡量Blink新版本能否发布的核心标准之一。Blink的性能测试主要包含Operator性能测试、SQL性能测试和runtime性能测试:Operator指构成SQL语义的一个原子操作,例如Sum,Aggregate等,是一个不能再分割的算子。Operator的性能测试主要用于监控单个算子在整个开发过程中的性能变化,以保证局部处理的优化和提高。目前,Operator的测试分成两个部分:单个算子的性能测试和算子组合的性能测试。Operator测试以Daily Run的方式反馈性能的变化。SQL性能测试主要用于监控版本开发过程中单个SQL的性能变化。TPCH和TPCDS是业界SQL标准性能测试集,分别有22和103个测试用例。测试平台将其引入到Blink性能测试中,以更全面地衡量Blink的性能变化。Runtime性能测试主要为了保障runtime层面性能不回退,主要包含端到端性能测试和模块性能测试。端到端性能测试首先根据梳理出测试场景,关注各场景job在指定数据量下的job运行时间,模块性能测试主要包含网络层性能测试,调度层性能测试,failover性能测试等,更关注在特定场景下job的处理时间。性能测试未来规划是将E2E性能测试、模块级别性能测试和参数调整整体联动起来,使其能够更好协助开发定位性能问题root cause和查看参数调优效果。稳定性测试对于支持高并发、多节点,集群物理环境复杂的分布式系统来说,类似磁盘打满、网络延迟等物理节点的异常很难避免。Blink作为一个高可用的分布式系统,必然要做到在异常情况下也能保证系统的稳定运行及数据的正常产出。“避免失败的最好方法就是不断地失败”,因此,在Blink任务运行期间将可能发生的异常模拟出来,就能够验证Blink的稳定性。我们把异常场景分为两类:一类是"黑猴子",该类场景与运行环境相关,包括机器重启、网络异常、磁盘异常、cpu异常等,这部分异常主要用shell命令来模拟;另一类异常是"白猴子",此类场景与Blink job相关,包括rpc消息超时,task异常,heart beat消息超时等,主要通过byteman[2]软件注入的方式来实现。在稳定性测试中,monkey作为调度会随机选取上述异常场景进行组合,以模拟线上可能出现的所有异常场景。考虑到Blink支持任务failover的特性和稳定性测试的自动运行,我们把稳定性测试设定为一轮轮的迭代循环,每一轮迭代都包含释放出monkey,提交任务,等待job恢复,校验四个阶段,校验主要包含checkpoint,container及slot资源等是否符合预期,校验失败就报警,校验成功后通过后进入下一轮迭代,以验证任务在长时间运行下的任务稳定性。稳定性测试架构分为四层:组件层主要包含测试Blink job,monkeys和dumper;action层包含job启动,状态校验,输出校验等;执行层包含service,monkey操作等,monkey操作时会根据ssh到具体机器,执行monkey操作;最上层是WebUI。详情如下图所示:预发测试Blink预发测试阶段主要通过克隆线上的真实任务和数据来进行复杂业务逻辑和大数据量的测试。因此,Blink 预发测试是对代码质量校验和集成测试的补充以及整个测试流程的完善,是Blink版本发布的最后一道关卡。Blink预发测试主要分为两个部分:仿真测试和兼容性测试。仿真测试仿真测试对Blink的功能、性能和稳定性等基础测试指标进行进一步地衡量,并将开发中的版本与当前的线上版本进行横向比较。因此,仿真测试能够尽早发现各种功能、性能退化和稳定性问题,从而提高上线版本的质量。仿真测试主要分为环境克隆,环境适配和测试运行三个阶段:环境克隆环境克隆是实现整个仿真测试的基础,包括线上任务的挑选、克隆和测试数据的采样。Blink的线上任务分散在多个不同的工程中,数量较多。虽然,每一个线上任务都有其内在的业务逻辑,但是,不同的任务可以根据其主要的处理逻辑进行归类,例如,以Agg操作为主的任务集合,以Sum操作为主的任务集合等,因此,Blink仿真测试需要对线上任务进行甄别,挑选出其中最具有代表性的任务。仿真测试的测试数据集是当前线上任务输入数据的采样,仅在数据规模上有差异,并且,可以根据测试需求的不同进行动态地调节,从而实现对测试目标的精确衡量。环境适配环境适配是仿真测试过程中的初始化阶段,主要进行测试用例的修改,使其能够正常运行。该过程主要包括两个步骤:更改测试数据输入源和测试结果输出地址和更新任务的资源配置。测试运行测试运行是仿真测试流程中的实际执行模块,包括测试用例的运行和结果反馈两个部分。Blink仿真测试包括功能测试、性能测试和稳定性测试等模块,不同的测试模块具有不同的衡量标准和反馈方式。这些测试模块的测试结果与代码质量校验和集成测试的结果一起构成Blink测试的结果集。性能测试和功能测试以仿真任务和采样数据作为输入,对比和分析任务在不同执行引擎上的执行过程和产出。其中,性能测试重点考察执行过程中不同执行引擎对资源的利用率、吞吐量等性能指标。功能测试则将执行的最终结果进行对比。需要特别指出的是,在功能测试中,线上版本的运行结果被假定为真,即当线上版本的执行结果与开发版本的执行结果不同时,认为开发版本的执行存在错误,需要修复开发中引入的错误。稳定性测试重点关注仿真测试任务在线上克隆环境、大数据量和长时间运行条件下的稳定性。其以Blink开发版本作为唯一的执行引擎,通过收集执行过程中的资源利用情况、吞吐量、failover等指标来进行度量。兼容性测试Blink兼容性测试主要用于发现Blink新、旧版本之间的兼容性问题,从而为线上任务升级Blink执行引擎的版本提供依据。目前,兼容性测试主要分为静态检查和动态运行两个阶段,其中,静态检查是整个兼容性测试的基础。静态检查静态检查主要用于分析线上任务在不同执行引擎下生成执行计划的不同,包括两个方面的内容:新的执行引擎生成执行计划的正确性及生成执行计划的时间长短。新、旧版本的执行引擎生成的执行计划是否兼容。在静态检查中,若新的执行引擎不能正确地生成执行计划,或者生成执行计划的时间超出预期,都可以认为静态检查失败,Blink新版本中存在异常或者缺陷,需要查找原因。当新版本能够正确地生成执行计划时,若新、旧版本的执行引擎生成的执行计划不兼容,那么,需要将对比结果反馈给开发人员以判断该执行计划的更改是否符合预期;若执行计划兼容或者执行计划的更改符合预期,则可以直接进行运行时测试。动态运行测试Blink动态运行测试利用仿真测试中的功能测试模块来进行任务的运行,是升级Blink新版本之前的最后一轮测试。若任务能够正常启动且测试结果符合预期,则认为该任务可以自动升级,反之,则需要人工介入进行手动升级。展望通过一年多的努力,Blink整体质量已经有很大幅度的提高,Blink的测试方法和工具也越来越成熟,Blink回馈社区之际,我们会逐步将测试工具一起输出,回馈更多的社区开发测试者,与此同时,随着Blink用户群的壮大,Blink业务开发者对于业务任务的质量保证需要日渐高涨,Blink测试团队未来会提供更多质量保证和开发效率工具,进一步提升Blink开发者工程效率。本文作者:溶月阅读原文本文来自云栖社区合作伙伴“阿里技术”,如需转载请联系原作者。

November 23, 2018 · 1 min · jiezi