BT

如何利用碎片时间提升技术认知与能力? 点击获取答案

阿里Goldeneye业务监控平台之架构演进,如何实时处理100T+/天的日志量?

| 作者 许琦 关注 0 他的粉丝 , 马国强 关注 0 他的粉丝 发布于 2017年4月11日. 估计阅读时间: 31 分钟 | QCon上海2018 关注大数据平台技术选型、搭建、系统迁移和优化的经验。

本文源自2月16日『高效开发运维』微信群的在线分享《Goldeneye 智能监控》,分享者为阿里巴巴开发专家马国强和许琦先生,转载请在文章开头注明来自『高效开发运维』公众号。加群学习请关注『高效开发运维』公众号,并点击菜单中的“加群学习”或直接回复“加群”。

一、黄金眼业务背景

淘宝天猫等业务线上每天会存在的超大流量,这些流量就是阿里宝贵的数据资源。阿里妈妈线上每天会产生超大规模的流量,这些流量数据就是阿里宝贵的资源。在大流量上任何的服务器波动,故障都会造成巨大的经济损失。然而故障总是会出现,如何快速的定位问题,及早发送报警给开发同学,是解决这类问题高效、快速的途径。黄金眼业务需求也是为了解决这个问题从而孕育而生,黄金眼业务方面大致经历了以下几个发展阶段:

  • 第一阶段:黄金眼只服务于单个业务线,主要针对大盘核心数据进行监控,监控的粒度从原始的小时级别提升到5分钟级。实时计算取代离线计算成为监控报警的核心计算框架。
  • 第二阶段:黄金眼开始在阿里妈妈崭露头角,逐步覆盖内部核心业务线,并得到一直好评。此阶段针对多个核心业务的大盘数据、细粒度数据进行监控,同时也逐步深入到引擎内部的指标进行故障定位预警,取得了很好的效果。
  • 第三阶段:黄金眼在阿里妈妈内部覆盖90%以上的监控需求,同时将外部BU的需求也逐步接入到系统中。面对每个场景纷繁的需求,更细粒度的监控维度,黄金眼也逐步走向自动化,智能化的道路。

目前的黄金眼覆盖监控报警、数据可视化、预测服务、故障定位、数据分析、算法A/B Test等功能。在黄金眼的核心计算框架上不断提高内部性能,深挖各种数据模型,逐步完善黄金眼的技术深度和应用广度。

二、黄金眼架构演进

黄金眼为阿里妈妈业务保驾护航已久,这里以最初的版本为起点来阐述黄金眼架构的变迁。架构和业务是均衡发展的,业务的规模驱动着架构的演进,架构的变迁能够为业务灵活扩展提供稳定的支撑。

下文中所讲的三种架构版本的演进过程,是我们保持业务发展、系统性能和工作效率之间平衡的过程。反推这个过程,新的架构也适合之前的业务规模和场景,然而衡量一个架构的优劣不是兼容了历史,而是能预见未来。所以,我们在保持业务和技术均衡的基础上,结合对未来业务潜在的需求的思考,才产生了每一次架构的改进和升级。这些是黄金眼每位成员的集体智慧,供大家参考学习。

应用:构建在整个黄金眼之上,对外部用户提供各种有针对性的服务,包括监控报警服务,预测服务,故障定位服务,算法A/B test服务等。

实时计算:黄金眼中95%以上的业务线指标数据都是通过实时计算得到的,需要监控报警的数据更是全部由实时计算storm平台解析,处理,汇聚之后写入分布式存储当中,供给前台展现报警。

存储: HBase集群在整个黄金眼中是集数据存储、展现的数据中心,所有的实时计算结果数据、阈值数据、其他时间序列的数据都要汇总到HBase存储当中

离线计算:离线计算部分主要处理的是离线的数据表,用于每天的日报,周报,反作弊数据统计,也是之前比较传统的统计报警模式。离线计算一般是以天为单位,可以优化到小时级别,但仍然存在报警晚等问题。

1、Goldeneye架构 V1版本——storm模式

这一阶段的业务特点就是野蛮生长,业务每天都会迸发出新的玩法,线上流量也在逐步突破历史最高。当线上出现问题需要排除查的时候,对几十亿级别的流量的线上系统故障维持1小时,损失是不可估量的。而业务还大部分依赖于离线计算,即使优化到小时级别,也很难减少损失。因此我们改变之前依靠离线报表进行监控报警的方式,引入storm实时计算引擎开发我们的监控报警任务。根据原始的storm语义,结合当时的大盘数据sum的需求,我们设计了第一版黄金眼实时计算的架构。对于每一个独立的业务线都定制一个独立的storm任务,每个实时任务的框架图如下所示:

Spout阶段

该阶段主要和消息中间件进行通信,读取对应的实时日志消息,维护读取的时间戳保证数据的exactly once。阿里内部使用的Time Tunnel作为实时的中间件,功能类似开源的kafka。根据大盘监控的统计需求,组合对应的key(例如广告位+时间戳进行组合)、value(例如pv数量)信息,发送给下游的bolt。

Count Bolt 阶段

使用filed grouping方式,相同的key在同一个bolt中处理。在count bolt内部,先进行初步的内存聚合,然后根据批量batch的条目数或者batch时间触发emit发送给下一级的write bolt。

Write bolt阶段

write bolt阶段有两种模式,根绝数据量的情况选择Put 模式或increment模式。put模式采用先get在put的方式对数据进行更新,increment模式直接发送给HBase,让HBase内部的region server进行累计。

通过这一版本的改造,我们的计算周期从小时级别缩短到秒级别,报警周期缩短到5分钟报警。在报警策略方面,我们也摆脱了人工拍定阈值的方式,采用同环比阈值报警,提高了报警的准确性。

Goldeneye V1的优势很明显,每个业务线单独开发逻辑,部署任务,业务逻辑清晰。不足也是比较明显,需要开发同学对storm编程比较熟悉。进行双11、双12等大促活动时,需要针对各自的业务进行逻辑的调整,资源扩容等工作。而且每个业务都需要重复开发外围的TT/HBase代码,抽象封装可以大大减少重复代码量。大盘需求得到满足,而更细粒度的监控需求需要定制开发,定制开发难度大、周期长。

2、Goldeneye架构 V2版本——ARM框架

黄金眼大盘监控的效果很好,于是其他业务线也找到了各自的技术团队,生产了一台给自己业务线使用的Goldeneye V1。那个时期各业务线终于过上了美好而又和谐的生活。(直到机器老化了,业务线同学觉得自己维护起来很费劲,而且业务整合的时候跨业务线数据不能打通,这就是V2架构的背景)。

技术方面,用户重复计算这些场景,对于storm的理解不够深入、实时任务性能不够,所以也急需要我们改善用户的编程习惯和编程体验。让用户只关注业务逻辑本身就可以。于是我们开始着手抽象实时计算框架了。我们在storm的原语上抽象了ARM(Alimama Realtime Model)是广告实时框架的简称,它是包含输入、输出、存储以及实时计算框架的组件集合。

ARM提供如下组件:

  • 输入输出:输入输出包括TT,HDFS,ODPS及MetaQ/Swift等。通过配置实例化组件,API访问。
  • 存储:支持对LDB,MDB,HBase的访问,通过配置实例化组件,通过API访问。
  • mapmerge:mapmerge框架抽象出map-merge计算框架,帮助用户实现KV流的实时计算。

Mapper阶段

用户只需要关心日志解析的代码,无需在关心与外部TT/HBase的链接配置等操作。核心代码就是将一条原始的raw log,解析成对应的结构。其中一条日志可以输出多条组合向后发送。</KEY,VALUE></KEY,VALUE>

Merger阶段

用户只需要关心真正的内存count 逻辑,关心用户代码即可,不需关心外部存储的配置等信息,在需要输出的时候直接调用write(key,value)即可。

在V2版本用户只需要关心解析包和业务的聚合逻辑,已经不需要在关心外围设备,以及集群相关的配置信息了,这样大大解放了用户的生产力,使得各个业务线可以在ARM平台上快速构建实时监控任务。不足之处是每个业务独立的存储结构,每次都需要独立开发一条web展示系统,同时考虑到大部分的需求是Sum,分布式sum操作可以进一步抽象,而且我们在实践中又发现了类似join、TopN等需要抽象的实时语义,需要进一步的完善。

3、Goldeneye架构 V3版本——ARM算子层

这一阶段的业务特点就是黄金眼在阿里妈妈内部已经覆盖了所有的核心业务线。对于其他业务线的需求,需要给非技术同学提供更易用性的接入,为外部引流部门提供高性能的解决方案,为已经在系统上运行的部门提供快速、可配置的聚合逻辑。

颠覆之前的开发模式,真正走向平台化,在完整兼顾阿里妈妈内部需求的同时给集团内部的其他部门提供平台化服务。ARM算子层在ARM框架mapper/merger接口之上,封装了实时sum、实时join等多种计算模型。

Source阶段

和goldeneye V2 mapper的相同之处在于,用户只需要关心具体的解析逻辑。和goldeney V2 mapper不同的是,之前用户会把数据转换为结构,例如key=a,key=b,key= c,需要对下游发送3条数据,而在新版本中用户仅需要发送一条的流</KEY1,KEY2,KEY3,VALUE></KEY,VALUE>

aggregator阶段

在这个阶段相比goldeneye V2有了本质的提高。用户不需要关心cache buffer等代码的配置,只需要在配置文件中书写类SQL的配置就可以。ARM算子层会把这个SQL语句转换成对应的执行计划,映射到具体的计算模型上。例如,

经过这几个版本的迭代,ARM框架已经很趋于成熟,在storm平台之上,构建一套完整的分布式计算sum,分布式join,topn ,unique等功能。同时随着框架的引进我们也接入了更多的业务,覆盖了阿里妈妈90%以上的业务线,同时我们还对外在阿里集团内部和多个部门合作共建,努力推广黄金眼监控系统。我们的优势其实很明显,我们在监控上做到准确无误,用户的接入效率也提高了10倍以上,而且用户在后期的监控需求变更上也非常方便,易于维护。经过算子层的抽象,用户只需要关心解析内容和简单的SQL配置就可以完成实时聚合了,这大大提高了使用的易用性,接入效率提高10倍以上。同时在这个阶段我们对后台的算子层也进行了深入的优化,在性能生也有很大的提高,峰值流量QPS可以覆盖300W/s,完美的度过了2016年双11的流量高峰,以及外部媒体流量引入的高峰。技术优化点在接下来详细阐述。

三、黄金眼计算存储技术难点

伴随着阿里妈妈业务的发展,日志数据量也在逐步增加。黄金眼系统实时处理的日均处理日志量超过100T,峰值的QPS逐步提高。同时单条日志中需要解析的核心指标也在增加,使得一条日志会转变为多条需要统计的消息,进一步造成消息量的膨胀。内部对于监控需求也越来越细化,由原来简单的大盘粒度(时间维度)一维聚合统计,变化到多维聚合统计。这进一步促使黄金眼实时计算的计算量激增。面对这么大的输入流量和这么复杂的计算场景,我们在计算存储上做了以下方面的优化。

1、实时计算如何支撑巨大的流量压力

在内部系统中,我们观察到某个任务内部出现300W/s的高峰QPS的现象,因此我们采取以下几点方式逐步泄洪,将流量高峰平稳度过。

提升拓扑处理效率——流量分层

在离线计算中常常会有数据倾斜的情况,在实时计算中也会出现同样的情况。为了解决数据倾斜,我们在实时计算的count阶段采用了了多种防止倾斜的办法。

我们在设计聚合算子是采用了2级计算模式: 2级模式的第一级采用shuffle的模式,平均分配到第一级的shuffle aggregator(SA)。在shuffle Aggregator(SA)内部中完成对group by key的内存聚合。聚合之后的key的数量已经降了n个数量级。然后再根据group by的key进行filed group分发到 group by Aggregator(GBA)保证key的分发是均匀的。

在group by Aggregator(GBA)内部我们通过多个线程对数据进行读写,同时增加read cache和write batch进一步提高效率。

这样就解决了数据倾斜的问题,同时通过key的数量在内存逐步聚合,保证流量在逐级递减,使得黄金眼系统应对300W/s的流量得以实现。

提高后端读写效率——剔除无效读写

在线上系统运行过程中,我们观察到后端存储压力过大,为减少对存储访问压力我们做了一些优化工作。通过观察半结构化的日志数据,我们发现在source parse阶段处理输出的日志字段非常稀疏,这与业务访问特点有关。前端采集的日志会包含全部指标,但并不是全部指标都会有值被更新,单条日志中实际需要更新的内容只占一少部分,所以我们在cache中增加了对空值和0值的判断,去掉了大量无用读写存储的操作。

提升网络传输效率——消息压缩

面对海量的实时日志,我们首先考虑将数据处理的数据量进行了缩减。Storm是一个基于消息的实时计算引擎,在spout/bolt之间传输都需要进行序列化,反序列化。我们采用了Google的ProtoBuffer方式进行序列化,将一条日志中的需要统计处理的核心字段保留并进行传输。对于核心的数据的字段我们尽量避免String类型,而是改为对应的数值类型定义,例如timestamp=1435051454如果用string存储要10个字节,用fix32只用4个字节。根据字段的实际值把每个字段都设置了最合适的类型,这么调整一下后,实测ProtoBuffer序列化后的大小相对于之前减少了30%以上,效果明显。虽然输入的数据没有变化,但是经过瘦身后的消息在传输和计算的过程中节省了大量的网络带宽,为实时计算能力的提高打下了坚实的基础。

2、复杂应用场景如何保持schema通用性

存储系统的易用性将直接影响到上层应用使用,以及数据处理的流程,如何设计通用的存储系统是分布式系统中重要的一个环节,核心的思路是存储schema保持清晰简明。底层设计的越通用,上层才能构建出丰富的应用。黄金眼经历了三次schema结构的演变,是去繁从简的过程。下面介绍这三次schema的变化。 

(1)第一版设计:业务驱动

第一版设计是每个业务按月建表,由程序定时触发按月建表,每张表的schema大致如下:

使用过程中发现metric存在数据倾斜问题,造成HBase的写region过程存在热点影响查询性能。这里的优化点是新建表的region范围按照上个月的region分布来创建,可以缓解写热点造成的影响。

(2)第二版设计:解决热点问题

第二版设计对第一版做了稍微改动,主要是为了解决热点问题,表的schema设计如下:

稳定运行了一段时间后,我们也在思考如何可以让黄金眼更高效的接入业务,于是我在存储层面重新设计时间序列框架theia,Theia是基于HBase存储时间序列数据的应用,提供多种metric数据采集方式,处理,存储,报警及展示功能的整体解决方案,黄金眼主要使用了theia的存储功能。

(3)第三版设计:通用schema

第三版我们重新梳理了黄金眼的业务场景,以及对存储的访问模式,结合业务特点重新设计了HBase的schema,取消了按月建表,所有业务可以共用同一份表,表存储分为meta表和data表,表结构大致如下:  

meta表

data表

由于theia支持long、bytes、pb格式的value类型,所以qualifier中会标明value类型。第三版的设计参考的opentsdb的设计,同时避免了热点问题以及查询性能不稳定等问题。同时所有业务线使用同一份表,通过namespace区分业务线,简化了数据处理和访问的复杂度,同时也减少了运维成本。

3、一致性问题填坑——多线程get/put不一致

一致性问题一直是分布式系统中遇到的让人头疼的问题,在黄金眼中最终数据写入存储是通过类似HBase的Increment操作完成的,但由于使用HBase的Increment操作性能上较差需要堆大量存储资源,所以经过对比我们最终采用了get/put的方式来做累加操作。在黄金眼使用的初期,我们观察到监控的曲线图上曲线经常出现毛刺现象,如下所示:

通过与离线数据进行对比发现不一致情况确实存在。分析原因得知数据经过mapper处理过后会shuffle到merger的不同writerQueue中,由于hash规则使得相同的key被随机分配到了不同的Writer Queue中,key在更新过程中需要从本地缓存或者HBase中获取数据的最新状态,导致相同key的更新操作会随机出现在多个writer Queue中。找到问题原因后我们调整了数据处理方式,保证相同key的状态更新由同一个writer 处理,最终解决了数据不一致的问题。

经过上述的几点优化后,系统的整体性能得到了大幅提升。同时随着系统的稳定运行,我们还在探索新的计算框架,在storm原语之上构建sum/join等实时算子会带有一定的局限性,我们目前也在调研Flink相关的计算平台,统一实时、离线的变成框架,同时进一步提高我们的系统效率,为业务提供更优质的服务。

四、未来发展趋势

随着黄金眼系统的逐步完善平台化是大势所趋,我们已经完成了初步的平台化工作,后续还回进一步在自动化,智能化方向深挖。

1、自动化   

1) 数据自动接入

未来的数据是自动接入的,每一个核心的实时数据回有一个监控报警的开关,用户只需要打开这个开关就可以自动的配置到黄金眼的监控平台中,节省开发量,用户只需要关心维度即可。尽管在V3的状态下用户已经可以只需要关注日志的parse和书写对应的sql就可以完成对应的实时sum了,对开发同学已经很简便了,但对很多运营同学提出了更高的的要求。而且运行同学的监控需求是非常普遍的,经常需要关注某几个id下的流量变化,所以如何让他们快速的使用我们的黄金眼系统便成为一个挑战,而且我们的接入效率基本也在开发测试2-3天左右,如果更加快速的开发,提高接入效率了,能否将接入效率提高到1天以内接入。    我们参考了开源的可视化的做法,后续将会逐步退出基于web拖拽方式的自动接入系统,方便所有用户的接入。 目前已经针对V3版本实现了Web的自动化配置接入(半自动),后续会逐步优化用户的使用习惯,实现完全的自动化接入。

2) 实时任务自动发布

当用户的任务自动配置完成后,只需要点击“自动发布”功能即可发布到对应的jstorm集群上,实现一键的任务起停,彻底改变我们目前依赖start/stop脚本手工起停任务的方式。完全的把我们的PE同学解放出来。

3) 指标自动展示

用户在自动接入阶段已经配置好了所有的维度,指标等信息,这些信息会被记录到mysql中,用于后面自动展示。用户只需要配置对应的中文名称,具体含义,即可展示,做到即配即用。同时对于用户统计的val1,val2等指标我们定义为直接指标,而用户可以在系统内部方便的定义间接指标例如val3=val1+val2,val4=val1/val2,做到灵活可用。

4) 指标自动报警

随着阈值模型的进一步完善,后续会逐步的开发自动报警功能。用户数据自动展示到页面后,只需要拖拽2根线选定作为报警的上限和下限,同时选择报警的方式是动态阈值或者是变点检测等预测算法产出阈值即可,后台会根据用户的选择直接配置生成报警规则,做到自动报警目前我们已经走在自动化,平台化的大路上。

2017年初我们已经初步完成了第一版的设计,用户可以在我们的web页面上实现自动配置、半自动发布、自动展示、自动报警等功能,后续还会持续在交互设计上进行优化,为用户提供更好、更准确的监控服务。

2、智能化

1) 智能调整参数

每天的流量高峰,流量低谷会出现在不同时段,基本上测试好一定的配置参数可以很好的应对。但是如果经历季度的变化、出现大促等流量升高等情况都需要我们对拓扑的参数进行调整。所以后续会采集每天的流量QPS变化数据,根据QPS变化数据的预警值调整拓扑的配置参数,进行流量自适应。

2) 智能算法模型

监控报警,阈值预测是我们黄金眼平台的核心功能,实时计算和存储系统为它提供了非常好的平台支撑。未来我们会在架构上不断的优化智能算法模型,不断挖掘计算存储的能力,为业务的快速发展保驾护航。

QA互动

Q1:除了类似Kafka之外,黄金眼中有采用开源的模块吗?会有哪些自研的技术模块开源吗?

A1:TimeTunnel类似Kafka系统做日志收集,开源的模块有JStorm,HBase,Zookeeper,暂时没有开源计划。

Q2:课件上有提到平台在报警策略方面摆脱了人工设定阈值的方式,而是采用同环比阈值报警,这部分实现能否再详细描述下

A2:这在上次马小鹏的分享中已经介绍过了,主要是采用动态阈值监测技术,具体细节可以看上次分享的内容。《阿里Goldeneye四个环节落地智能监控:预测、检测、报警及定位

Q3 指标的配置对于运维来说比较繁琐,特别是监控很多业务的时候。课件上说有采用到SQL配置的方式,能否再详细描述,还有什么途径可以减少配置工作量?

A3: 我们使用SQL主要是为了提高用户接入监控的效率。当用户输入SQL语句时,我们ARM框架会解析出对应的输入,过滤条件,group by 维度,sum指标等信息,映射到底层的数据流上进行实时聚合。我们后续会通过程序将用户的所有监控维度进行一维、多维组合,采用WEB选取的方式供用户选择。

Q4: Goldeneye如何保证exactly once语义?为什么选择storm?是否有考虑阿里内部其他部门采用的flink?

A4:黄金眼的exactly once是通过jstorm保证的,我们开启了ACK机制。另外我们为了防止脏数据进入系统会对输入的执行timestamp记录下来,遇到宕机等问题是会从历史的timestamp读取数据。选择storm是因为我们关注计算的实时性,在核心业务指标监控上,我们可以自由的控制计算的实效,保证报警的及时准确。目前正在调研flink相关的技术内容

Q5 流式计算中有可能数据有late data的问题,例如部分节点日志上传慢,对于监控来说,会导致数据不完整,报警不准确;goleden eye如何检测数据点的完整性?

A5: 分布式的日志采集会存在late data问题。我们在实时统计的时候采用的是日志内部的ts而不是log server采集的时间,所以late data数据会聚合加到正确的ts维度上,不会出现错误。我们是流使计算数据是一直流入系统的,所以不存在检验完整性的问题。

Q6:系统能否做到有报警后,系统能主动解决大部分问题,而不用人工去解决问题。如果可以,是用什么手段

A6: 黄金眼会根据动态阈值监测技术发现风险点,但目前线上遇到的故障都是业务问题,涉及系统多原因复杂,无法自动完成恢复。多是联系业务人员定位问题

Q7:几千个监控指标,上千Server,请教一个问题:如何分析系统宕机前后的监控指标,找出root cause,同时钻取到日志?

A7: 黄金眼的定位是在业务大盘数据监控,多维度指标数据监控,算法A/Btest等方向,我们的指标还是以业务指标为主。宕机的root cause可以通过机器本身的CPU,内存,流量,网络,磁盘等因素排查定位。钻取日志可以通过关键词查询,但需要在对相应日志进行收集和索引。

Q8:多个业务产生报警事件,很可能是同一个告警来源产生的, 平台如何智能识别归类这些告警,避免告警泛滥导致狼来了效应。

A8: 快速定位到告警源头需要对告警进行全链路tracing ,记录告警的时间戳,打通trace通路。同时建立报警规约规则,例如机器故障报警,线上模块报警,流量报警等,避免规约后误报。

Q9:请问老师,对于黄金眼这么大的数据处理量,是否采用了分布式的方式?是如何实现的?还有就是对于以后的server端的扩展是否有完整的技术方案?

A9: 我们的系统是采用分布式的方式,日志通过TimeTunnel收集,JStorm 拓扑任务订阅并消费日志,统计聚合结果会存储在HBase中提供给应用使用。这套技术方案好处之一就是可以水平扩展,我们在迎接双11流量高峰时会提前进行扩容以应对大流量对系统的冲击。

Q10: 日志的收集是否需要嵌入到业务代码,部署上线能做到1-3天?

A10: 我们的业务会统一生成一份实时日志,被time tunnel收集。多个应用会订阅这些公共日志。部署上线根据业务的上线情况决定。

Q11:黄金眼用的哪个开源的展现图表?grafana?监控信息是从日志里分析出来的?客户端

A11: 我们是使用highchart开发的监控图表,grafana是一套很不错的系统,如果是单独部署的话推荐使用。监控信息是从日志里解析出来进行实时处理、存储、报警的。

Q12:storm对metrics聚合粒度是多大,一分钟?以及存储的粒度

A12:storm对metrics聚合粒度是可配置的,根据业务需求可以配置成5分钟或者1分钟甚至更小的时间。存储就是按照对应的聚合时间存储相应的dim/metric数据。

作者介绍

马国强,资深研发工程师,阿里妈妈全景业务监控(黄金眼)核心研发。2012年中科院计算所硕士毕业,毕业后进入人人网从事广告平台的实时系统、人人网离线计算平台的研发和运维工作。2014年加入阿里妈妈从事实时计算框架、大规模数据处理等基础架构研发。在分布式计算、实时计算方面有丰富实践经验,目前致力于阿里妈妈全景业务监控(黄金眼)的计算框架设计与优化。

许琦,资深研发工程师,2014年4月加入阿里从妈妈基础服务部门,从事广告数据存储平台研发与性能优化相关工作,2012年在新浪数据库平台部门负责NoSQL数据服务平台研发及存储性能优化。


感谢木环对本文的审校。

给InfoQ中文站投稿或者参与内容翻译工作,请邮件至editors@cn.infoq.com。也欢迎大家通过新浪微博(@InfoQ@丁晓昀),微信(微信号:InfoQChina)关注我们。

评价本文

专业度
风格

您好,朋友!

您需要 注册一个InfoQ账号 或者 才能进行评论。在您完成注册后还需要进行一些设置。

获得来自InfoQ的更多体验。

告诉我们您的想法

允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p

当有人回复此评论时请E-mail通知我
社区评论

允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p

当有人回复此评论时请E-mail通知我

允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p

当有人回复此评论时请E-mail通知我

讨论

登陆InfoQ,与你最关心的话题互动。


找回密码....

Follow

关注你最喜爱的话题和作者

快速浏览网站内你所感兴趣话题的精选内容。

Like

内容自由定制

选择想要阅读的主题和喜爱的作者定制自己的新闻源。

Notifications

获取更新

设置通知机制以获取内容更新对您而言是否重要

BT