互联网架构技术周刊

架构原理 1、浅谈几种常用负载均衡架构 文章概括了负载均衡技术分类、作用位置和负载均衡算法,以及每种技术的优缺点。 2、古典、SOA、传统、K8S、ServiceMesh 近几年微服务的思想和架构演化的速度非常快,经常是每年都有一个新的思想产生,从传统微服务思想起,近两年结合K8S和容器,SpringCloud、ServiceMesh、Severless思想层出不穷,从物理机部署起,云化方向加速发展,本文对这种演化的过程和原因进行了简单的概括。 3、互联网架构:屡试不爽的架构三马车 作者理解的微服务、消息队列和定时任务的最佳实践。 4、10种常见的软件架构模式 文章总结了软件架构设计的十种常见模式和应用场景。 架构设计 1、10个有关RESTful API良好设计的最佳实践 国内做服务间交互主要使用RPC,而国外的实践上使用RESTful的方式也比较多,RESTful仍然有他的市场,简单易描述。 2、掌握它才说明你真正懂Elasticsearch 搜索和推荐系统的核心是检索引擎,Elasticsearch基于Lucene,隐藏其复杂性,并提供简单易用的Restful API接口、Java API接口。所以理解ES的关键在于理解Lucene的基本原理。 架构实践 1、从零开始搭建创业公司大后台技术栈 创业公司最重要的资产是清晰的业务和需求、强大的运营能力,技术在创业初期并不是核心。

May 24, 2019 · 1 min · jiezi

对话亲历者鲁肃我在支付宝拧螺丝的日子

对话亲历者:他是支付宝技术平台的奠基人之一,但是他总说“这还不是我心中最完美的架构”;他行事低调但却有着“此时此地,非我莫属”的豪气;他曾无数次充当救火大队长,但自评只是“没有掉队的那个人”。在2009-2019 互联网技术十年发展的波澜壮阔中,他是亲历者之一。 查看视频,点击此处:▵7分52秒,听支付宝技术人鲁肃讲故事 他叫程立,花名鲁肃,蚂蚁金服首席技术官。2005 年加入支付宝,是支付宝技术平台的奠基人之一,在支付宝与蚂蚁金服期间,主持支付宝各代技术架构的规划与基础技术平台的建设。2018 年,程立开始担任蚂蚁金服国际事业群首席运营官。 今天我们的主题是“十年”:希望能站在互联网技术发展的时间线上梳理出来几个重要的时间节点,如果用“2009 年到 2019 年是互联网技术 __ 的十年”来造句,希望听听您的讲述! 鲁肃:过去十年,面向整个数字时代的关键技术一个接一个的出现,从被人们接受,到开始步入应用。2009-2010 年是云计算,2011-2012 年是移动,2013-2014 年是大数据,2015-2016 年是人工智能,2017-2018 年是区块链。在蚂蚁金服,我们把区块链、AI、安全、IoT、计算这几大关键技术称为”BASIC“。这五个关键词在过去的十年里面接踵而至,而且得到了所有人的理解。所以我觉得回首来看的话,过去十年是技术革命非常关键的十年:一次技术革命去改变一个真正的行业,完成所有技术的准备。 您提到“革命”这个词,是不是可以这么说:过去十年是互联网技术革命的十年,是互联网技术改变所有人生活的十年? 鲁肃:我们认为过去十年技术正在改变,但是你说它已经完成这个改变了吗?它才刚开始。 听说您小时候一直想做一个数学家,然后某一天忽然发现自己应该做一个程序员? 鲁肃:我读书读到硕士都是以做数学家作为梦想。读博士之后,我的导师他是一个做实践、做工程的老师,所以在他的熏陶下,他让我解决很多工程的问题。那个时候我做了一个选择:不是完全根据自己的兴趣去做一件事情,而是结合自己的兴趣和擅长。那时候我基本上就把注意力转到工程上了。 说到做工程的精神,其实小时候我印象比较深的就是我的父亲每个周末到实验室加班,就把我带到实验室。他会让我看非常大的激光器,一个激光器像一个房子一样大,要把它上面一个盖子盖上,要把螺丝拧上,拧上之后要严丝合缝,确保没有任何漏气。我就是负责拧螺丝的。一圈有几十个螺丝,要一个一个去拧,而且你不能够一次把一个螺丝拧死,要一圈一圈拧。那时候我爸说我拧螺丝拧的特别好。 我的父亲是个物理学家,他做了很多拧螺丝的事情。我读硕士期间做数学研究,数学必须非常缜密,从提出一个定理,到证明它对不对,可能过程很长。我们现在做一个大的系统,写一个没有 bug 的程序,也是很相似的。所以说,我做了很多”拧螺丝“的事情。 您之前介绍过支付宝开发初期的一次重要转折,您经历过非常重要的一夜。可以再跟我们分享一下吗? 鲁肃:2004 年,当时淘宝要改造。这个项目是当时整个阿里巴巴最重要的一个项目,要用新的架构做面向未来的淘宝网。2005 年我加入支付宝以后,很自然的想要向团队证明自己。当时我的主管特别信任我,任命我做当时非常重要项目的主架构师。 这是我第一个做的项目,所以一开始做项目架构师的时候,我把我能想到的最好的架构、当时我懂的和我不懂的技术全部用上去。我想既然是这么重要的一个项目,它应该用最好的技术、最好的架构来做。 当项目进行到一个半月的时候,功能差不多开发到一半,有一天晚上加班以后一起吃饭。当时一个同事坐在我的边上,对着我主管说:你们设计的那个架构可能有问题,项目开发到现在,我们在里面加很多功能越来越难了,越来越容易出错。当时我的主管跟他说,鲁肃是这个项目的架构师,这个项目的技术他说了算,不要再有任何的怀疑,这个事就过去了。 那天晚上回去之后,我仔细想了想,认为他说的这个问题确实存在。而且,在这么重要的一个项目里面用了这么多新的技术,这是一件真正可靠的事情吗?差不多在凌晨一两点的时候,我开始正视这个问题:我认为这个架构确实是有问题。不但有同事说的问题,而且我们不应该用从未经过验证的技术去支持这么重要的一个系统。 所以接下来我也需要做决定:现在怎么办? 在凌晨三四点的时候,我决定要用新的架构。我快速搭了一个原型,用我最擅长的、最有把握的技术,做了一个演示系统。 早上八点到公司,我第一时间和主管说:马上叫齐项目组,我们开个重要的会议。会上我就说,之前这个架构有问题,我建议我们项目要改架构,改成一个更朴实的架构,用更可信赖的技术支撑,我根据这个架构做了一个 demo。会议开的非常高效,最后的结果是:第一,所有人支持用新的架构。第二,所有人会把他们自己之前的工作移到这个新的架构。这个会开完之后我特别感动。大家快速用新的架构完成了这个项目,在五月份把支付宝推到线上。 这个事情影响了我做架构的风格:我会偏实用主义,能够确保每个系统上线一定是最成功的方式。现在回想 2005 年如果当时做错一个决策的话,我的职业生涯也许可能是完全不同的道路,这个项目极大的可能会失败,对支付宝会有什么样的影响也不好说。这个事情也改变了我做决策的风格:做任何决策之前,先把“我”抛开。 感觉您和支付宝是互相成就的关系。至少,您是一个做好准备的人? 鲁肃:应该说是支付宝成就了我。整个支付宝发展的过程中发生过非常多重要的事情,我只在个别事件中起到关键作用。 我只是支付宝发展的过程中没有掉队的人。我觉得支付宝的发展永远比我想象的快,必须全力以赴才能够不掉队,你永远保持你的胜任和担当,其实这就是你的成长。 我觉得是一种担当。从加入支付宝第一天起,我就感觉支付宝这个系统扛在我的肩膀上了。那时候系统非常的原始,特别在早期一两年,基本上三天两头出问题,而且很多时候出现在夜里,任何的问题都是你的问题。这个责任感早期建立起来,一直到后来都没有改变。 您有座右铭吗? 鲁肃:我自己本人其实并没有什么座右铭,但是阿里巴巴有很多土话,这些土话对我的影响非常大。有一句话土话叫“此时此刻,非我莫属”,这个我觉得体现出整个阿里担当的精神,这种精神我个人觉得在我身上是有的,第一时间我会站出来。 在支付宝的发展当中还有没有其他印象深刻的事情? 鲁肃:2010 年,我印象是 1 月份开年会。当时支付宝的总裁讲完话之后,整个晚会的会场就黑了,突然一个声音响起,是我们一个客户的声音,客户在电话里面报怨我们的服务怎么不好,有什么问题。 那个时候我觉得特别震撼:那是我第一次听到一个真正的客户的声音!而且提出我们产品的问题。这些问题过去我们都知道,但我们不觉得它对客户有那么大的影响,但是那个时候听了这个,触动非常大。 然后灯亮了,马云先生走到台上说了一句话:“支付宝你做的太烂了,非常烂!” 这是阿里的风格,非常直接。说完,然后彭蕾上台说:“我会成为支付宝新的总裁。” 我印象她做了一篇演讲,她说:“我是一个女人,我有三个特点:第一个特点是爱做梦,第二个特点是小心眼,第三个特点是不讲理。”然后跟我们提了目标。当时用户在线支付要从支付宝网站跳到银行的网站上,这个成功率只有不到 70%。她说我要求大家把今年支付的成功率从 70% 做到 90% 以上。你们技术人员不要跟我讲做不到,我是不讲理的,你们一定要做到这个事。 年会开完,那年我们全公司就一个目标,就是怎么把这个数据从 70% 做到 90%,而不是非常宏大的做一个业务战略架构。在这个目标的驱动下,我们做了一个非常重要的创新:现在每天支付用的快捷支付,就是那时候创新出来的。由于快捷支付的出现,把它从 70% 不到变成 95% 以上,让移动支付成为可能。 ...

May 23, 2019 · 1 min · jiezi

阿里技术男的成长史越想证明自己死得越快……

摘要: 要不要折腾一下?2008年5月的一天钱磊对新婚的妻子说,想去杭州发展,那里有个公司叫阿里巴巴……在上海工作8年后,身为部门经理的钱磊,管理着一家ERP公司的百十来号员工,“再往上爬就是老板和他儿子了……从这个领域的技术角度来讲算是做到了顶。”05年,钱磊就开始关注一家名字奇怪,做事也奇怪的公司。 要不要折腾一下?2008年5月的一天钱磊对新婚的妻子说,想去杭州发展,那里有个公司叫阿里巴巴…… 不扒层皮,你怎么知道自己是谁?告别上海的家和妻子,钱磊拖着行李箱独自来了杭州。 豪情万丈地入职,不料压根没有“蜜月期”……“刚来的那两周,时时刻刻觉得自己是不是要背着包回上海了……”钱磊并不回避刚入职时的囧境。“不舒服,压力大。在原来的公司里,我就是拍板的人,来了以后发现其它人都挺厉害的。端着架子放不下,总想着自己好歹也是在业内干了八九年的人,在这里被刚毕业一两年的工程师挑战……” 像他这样外地来杭的人,一般入职后就开始着手找房子,钱磊则是在宾馆里住了整整两周。 “那段经历对我来说还是蛮宝贵的,不是有句阿里土话嘛,当你觉得不舒服的时候,就是成长的时候。一个人四平八稳时,很难获得成长。” 主管搭了半条命,我学到了两个字“担当”“硬”着陆半个月后,扒了层“皮”的钱磊又被主管砸了块“石头”。 他们要用技术的手段彻底解决业务问题——为阿里巴巴最早的“产品后台”B2B的CRM做系统重构。这就好比开着汽车换引擎,百年老宅动地基…… “最重要的一个责任落在了我身上,研发框架。当时业务给我们的时间只有两个月。我用了两周时间搭框架、做论证。对于一个入职不久的新人来讲,挑战非常大。” 这种打仗的感觉,让钱磊渐渐忘记了自己是谁,业务在奔跑,系统延迟一天上线,影响就越大。每天几百人依靠这个系统工作。 “……我的主管被业务方总经理请去喝了两个小时的茶,他是把半条命都搭上了。做不好,没有退路。为了系统上线,当时还停了两天业务,对公司来说每一分钟都是损失。” 系统上线后虽然又经历了多次调试,但这是一次技术对业务的引领,而不是以往那样跟在后面打配合。因为框架的通用性还不错。直到现在,这套CRM还在使用。 把业务风险和技术风险搭在一起,并不是一个最好的选择,但却是当时唯一的选择。“我从主管身上学到了两个字‘担当’,这是一个管理者的气质。”  离开场景和业务的修炼都是伪命题接手用户权限中心的技术团队后,钱磊开始实打实地接触客户。在这几年里,他从偏技术的架构,转为偏业务的架构。“离业务太远,做出来的东西不是场景驱动,后续会有较多的问题。架构师别把自己修炼成仙了,给公司留下的却是与业务无关的垃圾。” 当时B2B的ICBU遇到了用户权益打包的问题,底层需要一个产品化的解决方案,“原来每年销售做完规划以后,技术同学都要算,会花掉多少人力去做一个新的产品配置。每次都靠研发同学冲到代码里面写一大堆。我们做了权益包功能后,只花几个小时就能配置好了。权益的产品化解决了ICBU的一个大问题。这又是一次技术引领业务的实例。 越想证明自己 死得越快两年前,钱磊调到共享平台,做会员和安全。他们团队从技术和产品端入手,解决了移动端与PC端会员整体链路兼容的问题。降低了一半与帐户相关的客服电话量。“现在帐户相关的客服量在7%左右,我们的目标是三年后降到0。” 从中间件到信息平台,再到共享平台,钱磊接的摊子越来越大,2015年,入职的第7年,他获得了一次提名晋升P10(研究员)的机会。 “面试的时候,自我感觉还不错,毕竟这几年也做了几件拿得出手的东西……”一个月后,钱磊却得知了自己晋升失败的消息。 “心里肯定有波动啊。”提起两年前的那次晋升面试,钱磊坦白:“我当时还请了两天假,出去放空了一下。想明白了几件事,第一,这几年我在阿里巴巴学到的东西是不是已经远远超出过去?第二,公司给予的平台和空间是不是足够我成长?第三,我为业务创造最大化的价值了吗?当我连续问了自己几个问题后,一下子就看透了。证明自己没什么大意思,给业务和用户创造价值才是最踏实的。越想证明自己的人,死得越快。” 善于总结才能获得加速度钱磊觉得自己这九年来做得最正确的事,就是坚持总结和反思。“我几乎每个月都会给自己留出做总结的时候,这个月自己和团队做了什么事,还有哪些提升空间。一定要趁热打铁记录下来,反思能让我保持头脑的清晰。 我觉得一个不善于总结的人,就是在吃老本,吃惯性,吃你的智商和知识。反思就是获得加速度的那个点。这是工作多年来,让我最受益的一个习惯。” 技术人千万别陷在技术的圈子里钱磊在自己的内网签名里写着“知行合一”四个字。身为技术男,在业务相关的书之外,他独爱王阳明和南怀瑾,“王阳明的知行合一,是我的座右铭,倾听内心的声音,力量强大。南怀瑾的《庄子》我读了好几遍,佩服他为人的格局。我觉得技术同学特别需要打开思路,千万不要局限在技术这个圈子里。要有自己丰富的阅历,去看很多东西,触类旁通,在某些时候形成链接,对你的技术思考、业务思考都有帮助。” 好奇心与三个Why带了七八年团队,最多的时候钱磊一年要参加50多场面试,有招聘新人的,也有晋升的。他选人用人会特别看重对方的心态: “我觉得心态非常重要,我们面试人的时候,一定要去看他的进取心和好奇心。我觉得这两者是面向未来的能力。 我会问三个Why:为什么这样做?这样做背后有什么问题和思考?你的业务价值支撑点是什么?我对技术同学的要求是:至少你自己做的事儿,如果到‘P7’这个级别,一定是问不倒的,一定经得起我问三个‘为什么’。如果你经不起问的话,我认为你做这个事要么是需求驱动,要么你就是一个吃瓜群众。我非常在意一个人的独立思考能力。” 一个计较KPI的主管肯定会带出一个计较KPI的团队 钱磊说自己的管理之道就是四个字“言传身教”,“首先,要做好自己,不要对别人要求很高,对自己要求很低。再有,你是业务驱动、客户价值驱动,还是KPI驱动?一个天天计较自己KPI的人,肯定带不出一个不计较KPI的团队。 我们团队的KPI很简单,就是回归到业务场景。我的KPI已经连续几年都是以客服量为衡量点。你这个产品怎么样,上了多少功能,都不是最主要的因素,关键是你最终解决了客户的什么问题。客户用脚来投票。我会带着团队的D(业务负责人)一起review团队的KPI。  人生没有白走的路2017年7月,钱磊通过“绿色通道”(免试)晋升为P10(研究员),既在意料之中,又在意料之外。尽管不做要求,他还是准备了一个简单的PPT,那是写给自己的9年总结。 钱磊的办公桌面一如典型的技术男那样简单。桌上摆着他5岁女儿的照片。问起他印象最深刻的一个瞬间,他不加思索地回答:“2015年双11,连续熬了两个通宵后,11月13日的凌晨,我走到园区一号楼取车,眼前的夜空很美,身后是灯火通明的楼宇。就是一种很幸福的感觉。我,在这里,和大家在一起。我们和这家公司,挺伟大的……” 这就是一个阿里技术男的成长史。哪有那么多成长快乐,每一步都不是白走的路。你怎样选择和对待人生,人生就怎么样待你。 本文作者: 访谈橙阅读原文 本文来自云栖社区合作伙伴“阿里味儿”,如需转载请联系原作者。

May 23, 2019 · 1 min · jiezi

蚂蚁金服面对亿级并发场景的组件体系设计

作者:吕丹(凝睇),2011 年加入支付宝,先后负责了支付宝 Wap、alipass 卡券、SYNC 数据同步等项目,并参与了多次双十一、双十二、春节红包大促活动,在客户端基础服务方面有一定的项目实践经验与积累。目前负责蚂蚁金服移动开发平台 mPaaS 服务端组件体系优化与架构设计。5 月 6 日,InfoQ 主办的 QCon 2019 全球软件开发大会在北京举行。蚂蚁金服技术专家吕丹(凝睇)在大会上做了《蚂蚁金服面对亿级并发场景的组件体系设计》的分享,我们根据演讲整理如下: 今天,我主要想和大家分享一下移动领域基础组件体系,内容大致可以分为四大块,第一块是标准移动研发所需的基础服务体系,第二块是支撑亿级并发的核心组件“移动接入”的架构演进过程,第三块是双十一、双十二、新春红包这种大促活动的的应付方法,最后一块是目前已经对外输出的基础服务产品。 0. 移动研发基础服务体系 首先介绍一下支付宝客户端的演进过程。之前,支付宝客户端的主要功能是转账、订单支付、交易查询等等,更像是一个工具类的 APP,在需要付钱的时候才会掏出来,用完了就放回去了。2013 年,蚂蚁金服 all in 无线之后,加入了很多服务,例如余额宝、卡券、探索发现等,基本是把支付宝网站上的功能都尽量迁移到客户端,支付宝也逐渐演化成一个平台级别的客户端。之后,随着移动互联网的快速发展,公司内部孵化出了更多的 APP,其他行业也在移动互联网圈内铺开了大量的业务,为了提升用户量、用户粘性,APP 之间也开始进行了大量的业务融合,超级 APP 也因此而诞生,APP 开始朝着生态化的模式发展。 截止到目前为止,支付宝客户端的年活跃用户数超过 8 亿,在大促场景下,同时在线量超过 3 亿,并发请求超过 1 亿,同时上线的用户数超过百万每秒。 而在这些数据的背后一定需要一套庞大、复杂、完整的支撑体系来支持支付宝的运作,移动研发基础服务体系就是其中的重要组成部分。 按照研发过程,我们把移动研发基础服务体系分成四大块:APP 研发阶段,主要包括 App 框架、基础组件、云端服务和研发工具;App 测试阶段 ,主要包括研发协作平台和真机测试平台,其中研发协作平台包含版本管理、迭代管理、安装包编译、构建和打包的能力,而真机测试主要是代替人工服务,减少人工消耗,提升测试效率; App 运维阶段 ,主要包括智能发布、日志回溯、应急管理和动态配置;App 运营阶段,主要包括舆情反馈、实时分析、离线计算和智能营销。 1. 蚂蚁移动接入架构演进 今天的主题为支撑亿级并发下的基础服务,而在亿级并发下移动接入又是最核心、最重要的一个环节。移动接入并不是单个系统,而是一整套组件的总称,包括:Spanner+ 连接管理、API 网关、PUSH 通知和 SYNC 数据同步,它是所有移动业务的流量入口,需要维持客户端的状态,支持进行统一的管控,同时还需要进行部分的业务数据处理。 其实,一开始并没有移动接入这个说法,与支付宝客户端的演进过程类似,后端移动接入也是逐步迭代演进的。最开始,各个业务服务都是自己提供 API 或者直接暴露能力给客户端,没有统一的架构,没有统一的模型,也没有统一的管控。 为了解决这个问题,在 all in 阶段我们引申出了一个 API 网关,由它来做集中式管理,同时添加了 PUSH 推送的能力。因为公司内部有很多 APP,我们希望这些能力能够复用,所以在架构上,我们支持多 APP 同构,客户端会提供多个 SDK,可以随时进行集成。 ...

May 21, 2019 · 2 min · jiezi

Angular-架构设计

引言Alice测试上线,发现包体积太大,加载太慢。决定启用懒加载与预加载加速加载速度。 整三天,课也没去上。改得时候特别痛苦,哭了,为什么没有早点发现惰性加载这个东西。 星期一,重新设计前台架构,重构前台代码。 星期二,分模块加载,启用惰性加载与预加载。 星期三,修改单元测试,添加provide。 星期四,写PPT。 星期五,.NET考试。 重构前台之后,觉得自己当前设计的架构很合理,遂分享出来,供大家学习交流。 架构理论架构理论主要参考外国老哥的一篇文章,Angular (2+): Core vs Shared Modules CoreModule:核心模块,只被AppModule引用,保证全局单例。 ShareModule:共享模块,被各业务模块引用,存储各模块必备的组件、管道以及模板。 实践CoreModule核心Module,全局只导入一次。 称之为核心,因为没有它应用跑不起来。 核心模块存放拦截器和服务,不过与正常的有些区别。 拦截器 @Injectable()export class YunzhiInterceptor implements HttpInterceptor {}@NgModule({ imports: [ NgZorroAntdModule, RouterModule ], providers: [ {provide: HTTP_INTERCEPTORS, useClass: YunzhiInterceptor, multi: true} ]})export class CoreModule {}服务 @Injectable({ providedIn: CoreModule})export class CollegeService {}现在不往root里注入了,因为发现有的时候写root有人会搞不清楚模块的层级关系,然后就懵圈了。 为了规避这种问题,直接注入到核心模块中,防止有人误解。 norm其实是想起一个规范的英文的,但是spec却被测试给用了,所以就去百度翻译了个放这了。 这个包主要是存储数据规范的。 entity存储实体,对应后台实体。 target存储自定义的规范对象,历史的教训告诉我们,如果把所有都放到实体包里,这很糟糕。 page这个是向小程序抄来的,小组件可以复用,大组件就需要单建目录了,都放一起看着混乱。 分模块加载,每个功能一个单独的模块,模块职责划分清晰。 @NgModule({ declarations: [ SetupComponent ], imports: [ SetupRouteModule, ShareModule ]})export class SetupModule {}模块中就这几行,什么废话都不要写,就声明本模块的组件,并导入本模块的路由和Share模块。其他的都不要写,第三方的导入交给ShareModule去处理。本模块只负责业务,不负责代码。 ...

May 18, 2019 · 1 min · jiezi

印度版的大众点评如何将-Food-Feed-业务从-Redis-迁移到-Cassandra

Zomato 是一家食品订购、外卖及餐馆发现平台,被称为印度版的“大众点评”。目前,该公司的业务覆盖全球24个国家(主要是印度,东南亚和中东市场)。本文将介绍该公司的 Food Feed 业务是如何从 Redis 迁移到 Cassandra 的。 Food Feed 是 Zomato 社交场景中不可或缺的一部分,因为它可以让我们的用户参与其中并与朋友的餐厅评论和图片保持同步,甚至可以通过这个获取餐厅提供的优惠和折扣。开始我们选择 Redis 作为消息 Feed 流的存储引擎,因为在当时的用户场景这是最好的选择。但是随着业务的发展,我们需要更高的可用性和负载支持,而 Redis 不能很好的满足这个需求。虽然我们可以通过丢失一些数据来避免系统的中断,但这不是我们想做的事情。为了确保我们的系统具有高可用性,我们不得不放弃 Redis,而选择 Cassandra 作为其替代品。 Cassandra 非常适合这个用例,因为它是分布式的,就有高可用性等。并且 Cassandra 也可以用于存储时间序列数据 - 这实际上就是我们的Feed 流。在做出这一重大改变之前,我们确实有一些 Cassandra 的使用经验,但对于像 Feed 这样重要的东西来说肯定是不够的。我们必须弄清楚如何顺利的从 Redis 过渡到 Cassandra,并像在 Redis 上那样有效地运行 Feed,并且没有停机时间。 我们开始花时间在 Cassandra 上,在前两周深入探索其配置并调整它以满足我们的要求。接下来,在最终确定 Feed 的架构之前,我们明确了一下两个情况: Feed 流信息一般只用于读取而基本上不会修改。使用 Redis 的时候,我们可以同时读取上百个 keys 而不必担心读取延迟,但是对于Cassandra 而言,连接延迟可能是读取请求过程中一个相当重要的部分。schema 需要足够灵活,以便将来允许 Feed 中新类型的数据。鉴于我们不断迭代并致力于丰富产品体验,因此在 Feed 中添加元素和功能几乎是不可避免的。我们花了几天时间用于收集了我们项目的数据模式以及各种用户案例,然后开始使用2个数据中心,每个数据中心有3个节点。 我们从 Redis 中迁移大概 6000万条记录到 Cassandra 中用于测试其性能。由于是测试阶段,我们只将一部分流量切入到 Cassandra ,并准备了两个版本的代码,分别写入到 Cassandra 和 Redis 。架构图如下 ...

May 15, 2019 · 1 min · jiezi

现代IM系统中的消息系统架构-架构篇

前言 IM全称是『Instant Messaging』,中文名是即时通讯。在这个高度信息化的移动互联网时代,生活中IM类产品已经成为必备品,比较有名的如钉钉、微信、QQ等以IM为核心功能的产品。当然目前微信已经成长为一个生态型产品,但其核心功能还是IM。还有一些非以IM系统为核心的应用,最典型的如一些在线游戏、社交应用,IM也是其重要的功能模块。可以说,IM系统已经是任何一个带有社交属性的应用需要具备的基础功能,网络上对于这类系统的设计与实现的讨论也越来越多。 IM系统在互联网初期即存在,其基础技术架构在这十几年的发展中更新迭代多次,从早期的CS、P2P架构,到现在后台已经演变为一个复杂的分布式系统,涉及移动端、网络通信、协议、安全、存储和搜索等技术的方方面面。IM系统中最核心的部分是消息系统,消息系统中最核心的功能是消息的同步、存储和检索: 消息的同步:将消息完整的、快速的从发送方传递到接收方,就是消息的同步。消息同步系统最重要的衡量指标就是消息传递的实时性、完整性以及能支撑的消息规模。从功能上来说,一般至少要支持在线和离线推送,高级的IM系统还支持『多端同步』。消息的存储:消息存储即消息的持久化保存,传统消息系统通常只能支持消息在接收端的本地存储,数据基本不具备可靠性。现代消息系统能支持消息在服务端的在线存储,功能上对应的就是『消息漫游』,消息漫游的好处是可以实现账号在任意端登陆查看所有历史消息。消息的检索:消息一般是文本,所以支持全文检索也是必备的能力之一。传统消息系统通常来说也是只能支持消息的本地检索,基于本地存储的消息数据来构建。而现在消息系统在能支持消息的在线存储后,也具备了消息的『在线检索』能力。本篇文章内容主要涉及IM系统中的消息系统架构,会介绍一种基于阿里云表格存储Tablestore的Timeline模型构建的消息系统。基于Tablestore Timeline构建的现代消息系统,能够同时支持消息系统的众多高级特性,包括『多端同步』、『消息漫游』和『在线检索』。在性能和规模上,能够做到全量消息云端存储和索引,百万TPS写入以及毫秒级延迟的消息同步和检索能力。 之后我们会继续发表两篇文章,来更详细介绍Tablestore Timeline模型概念及使用: 模型篇:详细介绍Tablestore Timeline模型的基本概念和基础数据结构,并结合IM系统进行基本的建模。实现篇:会基于Tablestore Timeline实现一个具备『多端同步』、『消息漫游』和『在线检索』这些高级功能的简易IM系统,并共享我们的源代码。传统架构 vs 现代架构 传统架构下,消息是先同步后存储。对于在线的用户,消息会直接实时同步到在线的接收方,消息同步成功后,并不会在服务端持久化。而对于离线的用户或者消息无法实时同步成功时,消息会持久化到离线库,当接收方重新连接后,会从离线库拉取所有未读消息。当离线库中的消息成功同步到接收方后,消息会从离线库中删除。传统的消息系统,服务端的主要工作是维护发送方和接收方的连接状态,并提供在线消息同步和离线消息缓存的能力,保证消息一定能够从发送方传递到接收方。服务端不会对消息进行持久化,所以也无法支持消息漫游。消息的持久化存储及索引同样只能在接收端本地实现,数据可靠性极低。 现代架构下,消息是先存储后同步。先存储后同步的好处是,如果接收方确认接收到了消息,那这条消息一定是已经在云端保存了。并且消息会有两个库来保存,一个是消息存储库,用于全量保存所有会话的消息,主要用于支持消息漫游。另一个是消息同步库,主要用于接收方的多端同步。消息从发送方发出后,经过服务端转发,服务端会先将消息保存到消息存储库,后保存到消息同步库。完成消息的持久化保存后,对于在线的接收方,会直接选择在线推送。但在线推送并不是一个必须路径,只是一个更优的消息传递路径。对于在线推送失败或者离线的接收方,会有另外一个统一的消息同步方式。接收方会主动的向服务端拉取所有未同步消息,但接收方何时来同步以及会在哪些端来同步消息对服务端来说是未知的,所以要求服务端必须保存所有需要同步到接收方的消息,这是消息同步库的主要作用。对于新的同步设备,会有消息漫游的需求,这是消息存储库的主要作用,在消息存储库中,可以拉取任意会话的全量历史消息。消息检索的实现依赖于对消息存储库内消息的索引,通常是一个近实时(NRT,near real time)的索引构建过程,这个索引同样是在线的。 以上就是传统架构和现代架构的一个简单的对比,现代架构上整个消息的同步、存储和索引流程,并没有变复杂太多。现代架构的实现本质上是把传统架构内本地存储和索引都搬到云上,最大挑战是需要集中管理全量消息的存储和索引,带来的好处是能实现多端同步、消息漫游以及在线检索。可以看到现代架构中最核心的就是两个消息库『消息同步库』和『消息存储库』,以及对『消息存储库』的『消息索引』的实现,接下来我们逐步拆解这几个核心的设计和实现。 基础模型 在深入讲解消息系统的设计和实现之前,需要对消息系统内的几个基本概念和基础模型有一个理解。网上分析的很多的不同类型的消息系统实现,实现差异上主要在消息同步和存储的方案上,在消息的数据模型上其实有很大的共性。围绕数据同步模型的讨论主要在『读扩散』、『写扩散』和『混合模式』这三种方案,目前还没有更多的选择。而对于数据模型的抽象,还没有一个标准的定义。 本章节会介绍下表格存储Tablestore提出的Timeline模型,这是一个对消息系统内消息模型的一个抽象,能简化和更好的让开发者理解消息系统内的消息同步和存储模型,基于此模型我们会再深入探讨消息的同步和存储的选择和实现。 Timeline模型 Timeline是一个对消息抽象的逻辑模型,该模型会帮助我们简化对消息同步和存储模型的理解,而消息同步库和存储库的设计和实现也是围绕Timeline的特性和需求来展开。 如图是Timeline模型的一个抽象表述,Timeline可以简单理解为是一个消息队列,但这个消息队列有如下特性: 每条消息对应一个顺序ID:每个消息拥有一个唯一的顺序ID(SequenceId),队列消息按SequenceId排序。新消息写入能自动分配递增的顺序ID,保证永远插入队尾:Timeline中是根据同步位点也就是顺序ID来同步消息,所以需要保证新写入的消息数据的顺序ID绝对不能比已同步的消息的顺序ID还小,否则会导致数据漏同步,所以需要支持对新写入的数据自动分配比当前已存储的所有消息的顺序ID更大的顺序ID。新消息写入也能自定义顺序ID,满足自定义排序需求:上面提到的自动分配顺序ID,主要是为了满足消息同步的需求,消息同步要求消息是根据『已同步』或是『已写入』的顺序来排序。而消息的存储,通常要求消息能根据会话顺序来排序,会话顺序通常由端的会话来决定,而不是服务端的同步顺序来定,这是两种顺序要求。支持根据顺序ID的随机定位:可根据SequenceId随机定位到Timeline中的某个位置,从这个位置开始正序或逆序的读取消息,也可支持读取指定顺序ID的某条消息。支持对消息的自定义索引:消息体内数据根据业务不同会包含不同的字段,Timeline需要支持对不同字段的自定义索引,来支持对消息内容的全文索引,或者是任意字段的灵活条件组合查询。消息同步可以基于Timeline很简单的实现,图中的例子中,消息发送方是A,消息接收方是B,同时B存在多个接收端,分别是B1、B2和B3。A向B发送消息,消息需要同步到B的多个端,待同步的消息通过一个Timeline来进行交换。A向B发送的所有消息,都会保存在这个Timeline中,B的每个接收端都是独立的从这个Timeline中拉取消息。每个接收端同步完毕后,都会在本地记录下最新同步到的消息的SequenceId,即最新的一个位点,作为下次消息同步的起始位点。服务端不会保存各个端的同步状态,各个端均可以在任意时间从任意点开始拉取消息。 消息存储也是基于Timeline实现,和消息同步唯一的区别是,消息存储要求服务端能够对Timeline内的所有数据进行持久化,并且消息采用会话顺序来保存,需要自定义顺序ID。 消息检索基于Timeline提供的消息索引来实现,能支持比较灵活的多字段索引,根据业务的不同可有自由度较高的定制。 消息存储模型 如图是基于Timeline的消息存储模型,消息存储要求每个会话都对应一个独立的Timeline。如图例子所示,A与B/C/D/E/F均发生了会话,每个会话对应一个独立的Timeline,每个Timeline内存有这个会话中的所有消息,消息根据会话顺序排序,服务端会对每个Timeline进行持久化存储,也就拥有了消息漫游的能力。 消息同步模型 消息同步模型会比消息存储模型稍复杂一些,消息的同步一般有读扩散(也叫拉模式)和写扩散(也叫推模式)两种不同的方式,分别对应不同的Timeline物理模型。 如图是读扩散和写扩散两种不同同步模式下对应的不同的Timeline模型,按图中的示例,A作为消息接收者,其与B/C/D/E/F发生了会话,每个会话中的新的消息都需要同步到A的某个端,看下读扩散和写扩散两种模式下消息如何做同步。 读扩散:消息存储模型中,每个会话的Timeline中保存了这个会话的全量消息。读扩散的消息同步模式下,每个会话中产生的新的消息,只需要写一次到其用于存储的Timeline中,接收端从这个Timeline中拉取新的消息。优点是消息只需要写一次,相比写扩散的模式,能够大大降低消息写入次数,特别是在群消息这种场景下。但其缺点也比较明显,接收端去同步消息的逻辑会相对复杂和低效。接收端需要对每个会话都拉取一次才能获取全部消息,读被大大的放大,并且会产生很多无效的读,因为并不是每个会话都会有新消息产生。写扩散:写扩散的消息同步模式,需要有一个额外的Timeline来专门用于消息同步,通常是每个接收端都会拥有一个独立的同步Timeline(或者叫收件箱),用于存放需要向这个接收端同步的所有消息。每个会话中的消息,会产生多次写,除了写入用于消息存储的会话Timeline,还需要写入需要同步到的接收端的同步Timeline。在个人与个人的会话中,消息会被额外写两次,除了写入这个会话的存储Timeline,还需要写入参与这个会话的两个接收者的同步Timeline。而在群这个场景下,写入会被更加的放大,如果这个群拥有N个参与者,那每条消息都需要额外的写N次。写扩散同步模式的优点是,在接收端消息同步逻辑会非常简单,只需要从其同步Timeline中读取一次即可,大大降低了消息同步所需的读的压力。其缺点就是消息写入会被放大,特别是针对群这种场景。Timeline模型不会对选择读扩散还是写扩散做约束,而是能同时支持两种模式,因为本质上两种模式的逻辑数据模型并无差别,只是消息数据是用一个Timeline来支持多端读还是复制到多个Timeline来支持多端读的问题。针对IM这种应用场景,消息系统通常会选择写扩散这种消息同步模式。IM场景下,一条消息只会产生一次,但是会被读取多次,是典型的读多写少的场景,消息的读写比例大概是10:1。若使用读扩散同步模式,整个系统的读写比例会被放大到100:1。一个优化的好的系统,必须从设计上去平衡这种读写压力,避免读或写任意一维触碰到天花板。所以IM系统这类场景下,通常会应用写扩散这种同步模式,来平衡读和写,将100:1的读写比例平衡到30:30。当然写扩散这种同步模式,还需要处理一些极端场景,例如万人大群。针对这种极端写扩散的场景,会退化到使用读扩散。一个简单的IM系统,通常会在产品层面限制这种大群的存在,而对于一个高级的IM系统,会采用读写扩散混合的同步模式,来满足这类产品的需求。采用混合模式,会根据数据的不同类型和不同的读写负载,来决定用写扩散还是读扩散。 典型架构设计 如图是一个典型的消息系统架构,架构中包含几个重要组件: 端:作为消息的发送和接收端,通过连接消息服务器来发送和接收消息。消息服务器:一组无状态的服务器,可水平扩展,处理消息的发送和接收请求,连接后端消息系统。消息队列:新写入消息的缓冲队列,消息系统的前置消息存储,用于削峰填谷以及异步消费。消息处理:一组无状态的消费处理服务器,用于异步消费消息队列中的消息数据,处理消息的持久化和写扩散同步。消息存储和索引库:持久化存储消息,每个会话对应一个Timeline进行消息存储,存储的消息建立索引来实现消息检索。消息同步库:写扩散形式同步消息,每个用户的收件箱对应一个Timeline,同步库内消息不需要永久保存,通常对消息设定一个生命周期。新消息会由端发出,通常消息体中会携带消息ID(用于去重)、逻辑时间戳(用于排序)、消息类型(控制消息、图片消息或者文本消息等)、消息体等内容。消息会先写入消息队列,作为底层存储的一个临时缓冲区。消息队列中的消息会由消息处理服务器消费,可以允许乱序消费。消息处理服务器对消息先存储后同步,先写入发件箱Timeline(存储库),后写扩散至各个接收端的收件箱(同步库)。消息数据写入存储库后,会被近实时的构建索引,索引包括文本消息的全文索引以及多字段索引(发送方、消息类型等)。对于在线的设备,可以由消息服务器主动推送至在线设备端。对于离线设备,登录后会主动向服务端同步消息。每个设备会在本地保留有最新一条消息的顺序ID,向服务端同步该顺序ID后的所有消息。 总结 本篇文章主要介绍了现代IM系统中消息系统所需要具备的能力,对比了传统架构和现代架构。为方便接下来的深入探讨,介绍了表格存储Tablestore推出的Timeline模型,以及在IM系统中消息存储和消息同步模型的基本概念和策略,最后介绍了一个典型的架构**本人13年Java开发经验及产品研发经验,BAT背景,曾在多家知名企业担任技术总监、企业方案选型首席顾问,先后从事内核开发、大型Java系统架构设计和物联网系统架构设计开发,精通复杂业务技术方案选型、架构、核心难点攻关,对于java语言及项目有非常深入的理解和丰富的实操经验,热爱前沿技术,乐于进行技术分享与技术探讨。本人13年Java开发经验及产品研发经验,BAT背景,曾在多家知名企业担任技术总监、企业方案选型首席顾问,先后从事内核开发、大型Java系统架构设计和物联网系统架构设计开发,精通复杂业务技术方案选型、架构、核心难点攻关,对于java语言及项目有非常深入的理解和丰富的实操经验,热爱前沿技术,乐于进行技术分享与技术探讨**

May 15, 2019 · 1 min · jiezi

如何实现724小时灵活发布阿里技术团队这么做

阿里妹导读:研发效能分为两块,一是用技术的更新来提升效率;二是提高整个技术生态中的协同效率,激发技术活力。阿里巴巴技术团队在此基础上要实现的终极目标是打造7*24小时灵活发布的通道,以及提供更快的业务代码迭代能力。今天,阿里巴巴高级测试开发专家傲野为你带来关于研发效能的一些思考,希望对你有启发。7*24小时发布窗口的实现其实并不简单,受限于很多因素。我简单地进行了分解。 一、系统先从最基础的开始说,当一个创业团队只有几个人,一两个系统的情况下,是可以不考虑研发效率这回事的。因为不存在系统间的依赖,系统内的依赖也完全在一个可控的范围内,本地起一个 Tomcat 或 Apache 就能开发、调试。另外再加上团队成员之间的高频交流,基本上可以实现随时随地,想发就发的要求。 当业务逐渐复杂,开发人数扩展到10几个人时。提效的第一步是理清系统内的依赖关系,并促进角色的专业化。这也是大家所熟知的MVC,通过对视图、模型、控制器的分离,对系统内的逻辑进行分层。把复杂的代码逻辑下沉到Model层,而视图层交由更专业的前端来负责。 当然,在系统内部仍然有一些扩展的空间,比如模块化,为不同的业务划分bundle等。但仍然没有突破本身的瓶颈,而且单一的系统也很难突破机器的特性。 二、架构当技术团队已经达到几十个上百人的规模,当业务已经无法通过单一的应用来进行水平扩展时。分布式的架构是解决问题的有效手段。在07年时,阿里集团就在推进SOA化,无论是淘宝还是支付宝,原来的单一应用不断被拆分出来,也在此时,承载服务化中枢的消息等中间件蓬勃发展。 这种方式实现了系统之间的解藕,激活了技术人员的生产力,同时增大了系统的弹性,实现了服务能力的低成本水平扩展。但因为复杂的调用关系,对于某一个贯穿多个应用的项目来说,无疑增加了集成的成本和质量的风险。 同时,如果对应用规模不加以规划和控制的话,会导致应用数的不断扩张,从而影响到整体的开发维护成本。 三、配置管理在5 - 10年前,阿里是有一个专门的岗位叫SCM的,负责技术团队内的代码管理,配置项管理和应用部署。特别是在服务化初期,开发人员的coding生产力被极度释放,应用数出现一个井喷,对配置管理的需求不断增强,并最终促使了配置管理的变革。 在讲配置管理前,先讲讲代码分支管理机制。这也是很多研发模式变革的起点。在此,笔者先表达自己的观点:没有对与错(先进与落后)的代码分支管理机制,只有适不适合自己团队当下以及未来发展的管理模式。 先从大的层面上来说,我们当前所讨论的都是为了解决并行开发的问题,即有多个项目或团队对于同一系列应用进行功能开发。如果仅仅是串行开发,是基本不用太考虑代码管理策略。 1、分支开发、主干发布。核心理念是使用固定的主干作为集成分支。使用分支进行开发,在合并到主干分支后生命周期终止。当然除此之外,还有紧急发布分支等。 2、分支开发、分支发布。发布成功后执行写基线操作,确保主干的及时更新和稳定。同时分支发布的方式不依赖于大集成,保持很强的灵活性。 体现在项目上的流程为: 3、其他模式:主干开发、分支分布等。由于我们并不常用,所以略过。 平台化的支持:早期配管的人肉化,也造成了代码集成和部署的效率很低。不同角色之间的协同靠人来完成。因此在那个背景下,还需要一个配套的PMO组织来保障。在这样一个历史背景下,Aone(对外版本是云效)也孕育而生,从平台化的角度来解决研发过程的协同、构建、集成和测试几个复杂的过程。为了更清楚的了解那个时期的痛点,我找了2009年左右的Aone的蓝图,可以管中窥豹(这个时期我并没有亲自经历过,只是针对于当时的前辈做了些访谈和收集了一些资料)。我猜想也正因为这条道路面向未来解决问题造就了现在的Aone平台。 四、测试当一个技术团队小,负责应用少以及业务的用户群体少时,是完全可以不用测试的。只有当业务发展到一定阶段,用户对于质量的容忍程度越来越低时,才引入专业的测试角色。其次,在软件离线交付阶段,由于软件的召回成本很高,所以对于测试是不遗余力的,但随着在线交付时代的深入,测试团队是否能够快速的实现软件质量的评测反馈,成为一个非常关键的问题。而也决定着,在打通上述各个环节后,7*24小时软件持续交付通道是否能够真正实现。 在讲之前,我们再回顾一下上个章节。Aone平台实现了开发代码、配置、应用部署的在线化,现在只剩下最后的一环:测试。从2010年以来,B2B的测试团队就希望可以把分层自动化平台跟Aone研发协作平台绑定在一起,通过系统调用的方式来实现一个测试的快速验证机制,并最终实现回归测试过程中的无人值守。 这个意义非常重大。应用的服务化后,技术的风险实际上是收敛的,大家都可以面向服务来进行开发,实现高内聚、构耦合。并且应用的发布也更加灵活了。但对于测试来说,却是极大的挑战。 1、测试的层次增加了。 2、测试的轮次变多了。每次集成,每次发布就有可能是一次完整的测试回归。 就如Aone的推进间接取替了SCM这个角色一样。研发平台的快速发展和业务7*24小时发布的诉求,也开始冲击测试在代码集成后的快速反馈能力。这是一个挑战,也是一个机会。否则,前期释放出来的所有生产力,最后全都被卡在了测试这最后一个环节,而且没有办法拆解(每拆解出来一个,测试工作量就增加一倍)。只能通过不断叠加集成的应用量来提高集成测试的效率。 经过1688测试团队几代同学的努力,现在我们在这个方面总算有了些成绩。我们已经通过分层自动化体系实现了60%以上发布测试的无人值守,并且全年拦截故障在数百个级别(含页面、UI等)。 它的实现逻辑如下: 五、文化至此,真正所谓的7*24小时业务的持续交付通道已经完全打造出来。我们再回顾一下。 1、应用内的架构分层,前端、后端、测试各应其职,通过专业化的力量激发了一轮生产力。 2、服务化的架构,让技术人员可以面向服务来进行业务的开发,实现了架构上的高内聚低耦合。进一步释放大规模技术团队的活力。 3、研发平台的搭建,提供了持续交付管道,实现了开发、测试过程的快速、准确传递。 4、依托于研发平台,实现了环境的自动化部署,应用监控,代码检查。扫除了研发过程的基建设施。让技术人员聚焦于代码的生产。 5、测试自动化验证体系,减少系统集成风险,提高集成的频率。最终实现了代码的快速上线。 本文作者: 施翔阅读原文 本文来自云栖社区合作伙伴“阿里技术”,如需转载请联系原作者。

May 15, 2019 · 1 min · jiezi

架构整洁之道-看这一篇就够了

阿里妹导读:程序的世界飞速发展,今天所掌握的技能可能明年就过时了,但有些知识历久弥新,掌握了它们,你在程序的海洋中就不会迷路,架构思想就是这样的知识。本文是《架构整洁之道》的读书心得,作者将书中内容拆解后再组织,不仅加入了个人的独到见解,而且用一张详细的知识脉络图帮助大家了解整本书的精华。如果你读过这本书,可以将本文当做一次思想交流,如果你还没看过这本书,更要阅读这篇文章,相信你会得到不同于以往的启发。 本篇文章我们将从软件系统的价值出发,首先认识架构工作的价值和目标, 接下来依次了解架构设计的基础、指导思想(设计原则)、组件拆分的方法和粒度、组件之间依赖设计、组件边界多种解耦方式以及取舍、降低组件之间通信成本的方法,从而最终指导我们做出正确的架构决策和架构设计。 一、软件系统的价值架构是软件系统的一部分,所以要明白架构的价值,首先要明确软件系统的价值。软件系统的价值有两方面,行为价值和架构价值。 行为价值是软件的核心价值,包括需求的实现,以及可用性保障(功能性 bug 、性能、稳定性)。这几乎占据了我们90%的工作内容,支撑业务先赢是我们工程师的首要责任。如果业务是明确的、稳定的,架构的价值就可以忽略不计,但业务通常是不明确的、飞速发展的,这时架构就无比重要,因为架构的价值就是让我们的软件(Software)更软(Soft)。可以从两方面理解: 当需求变更时,所需的软件变更必须简单方便。变更实施的难度应该和变更的范畴(scope)成等比,而与变更的具体形状(shape)无关。当我们只关注行为价值,不关注架构价值时,会发生什么事情?这是书中记录的一个真实案例,随着版本迭代,工程师团队的规模持续增长,但总代码行数却趋于稳定,相对应的,每行代码的变更成本升高、工程师的生产效率降低。从老板的视角,就是公司的成本增长迅猛,如果营收跟不上就要开始赔钱啦。 可见架构价值重要性,接下来从著名的紧急重要矩阵出发,看我们如何处理好行为价值和架构价值的关系。 重要紧急矩阵中,做事的顺序是这样的:1.重要且紧急 > 2.重要不紧急 > 3.不重要但紧急 > 4.不重要且不紧急。实现行为价值的需求通常是 PD 提出的,都比较紧急,但并不总是特别重要;架构价值的工作内容,通常是开发同学提出的,都很重要但基本不是很紧急,短期内不做也死不了。所以行为价值的事情落在1和3(重要且紧急、不重要但紧急),而架构价值落在2(重要不紧急)。我们开发同学,在低头敲代码之前,一定要把杂糅在一起的1和3分开,把我们架构工作插进去。 二、架构工作的目标前面讲解了架构价值,追求架构价值就是架构工作的目标,说白了,就是用最少的人力成本满足构建和维护该系统的需求,再细致一些,就是支撑软件系统的全生命周期,让系统便于理解、易于修改、方便维护、轻松部署。对于生命周期里的每个环节,优秀的架构都有不同的追求: 开发阶段:组件不要使用大量复杂的脚手架;不同团队负责不同的组件,避免不必要的协作。部署阶段:部署工作不要依赖成堆的脚本和配置文件;组件越多部署工作越繁重,而部署工作本身是没有价值的,做的越少越好,所以要减少组件数量。运行阶段:架构设计要考虑到不同的吞吐量、不同的响应时长要求;架构应起到揭示系统运行的作用:用例、功能、行为设置应该都是对开发者可见的一级实体,以类、函数或模块的形式占据明显位置,命名能清晰地描述对应的功能。维护阶段:减少探秘成本和风险。探秘成本是对现有软件系统的挖掘工作,确定新功能或修复问题的最佳位置和方式。风险是做改动时,可能衍生出新的问题。三、编程范式其实所谓架构就是限制,限制源码放在哪里、限制依赖、限制通信的方式,但这些限制比较上层。编程范式是最基础的限制,它限制我们的控制流和数据流:结构化编程限制了控制权的直接转移,面向对象编程限制了控制权的间接转移,函数式编程限制了赋值,相信你看到这里一定一脸懵逼,啥叫控制权的直接转移,啥叫控制权的间接转移,不要着急,后边详细讲解。 这三个编程范式最近的一个也有半个世纪的历史了,半个世纪以来没有提出新的编程范式,以后可能也不会了。因为编程范式的意义在于限制,限制了控制权转移限制了数据赋值,其他也没啥可限制的了。很有意思的是,这三个编程范式提出的时间顺序可能与大家的直觉相反,从前到后的顺序为:函数式编程(1936年)、面向对象编程(1966年)、结构化编程(1968年)。 1.结构化编程 结构化编程证明了人们可以用顺序结构、分支结构、循环结构这三种结构构造出任何程序,并限制了 goto 的使用。遵守结构化编程,工程师就可以像数学家一样对自己的程序进行推理证明,用代码将一些已证明可用的结构串联起来,只要自行证明这些额外代码是确定的,就可以推导出整个程序的正确性。 前面提到结构化编程对控制权的直接转移进行了限制,其实就是限制了 goto 语句。什么叫做控制权的直接转移?就是函数调用或者 goto 语句,代码在原来的流程里不继续执行了,转而去执行别的代码,并且你指明了执行什么代码。为什么要限制 goto 语句?因为 goto 语句的一些用法会导致某个模块无法被递归拆分成更小的、可证明的单元。而采用分解法将大型问题拆分正是结构化编程的核心价值。 其实遵守结构化编程,工程师们也无法像数学家那样证明自己的程序是正确的,只能像物理学家一样,说自己的程序暂时没被证伪(没被找到bug)。数学公式和物理公式的最大区别,就是数学公式可被证明,而物理公式无法被证明,只要目前的实验数据没把它证伪,我们就认为它是正确的。程序也是一样,所有的 test case 都通过了,没发现问题,我们就认为这段程序是正确的。 2.面向对象编程 面向对象编程包括封装、继承和多态,从架构的角度,这里只关注多态。多态让我们更方便、安全地通过函数调用的方式进行组件间通信,它也是依赖反转(让依赖与控制流方向相反)的基础。 在非面向对象的编程语言中,我们如何在互相解耦的组件间实现函数调用?答案是函数指针。比如采用C语言编写的操作系统中,定义了如下的结构体来解耦具体的IO设备, IO 设备的驱动程序只需要把函数指针指到自己的实现就可以了。 struct FILE { void (*open)(char* name, int mode); void (*close)(); int (*read)(); void (*write)(char); void (*seek)(long index, int mode);}这种通过函数指针进行组件间通信的方式非常脆弱,工程师必须严格按照约定初始化函数指针,并严格地按照约定来调用这些指针,只要一个人没有遵守约定,整个程序都会产生极其难以跟踪和消除的 Bug。所以面向对象编程限制了函数指针的使用,通过接口-实现、抽象类-继承等多态的方式来替代。 前面提到面向对象编程对控制权的间接转移进行了限制,其实就是限制了函数指针的使用。什么叫做控制权的间接转移?就是代码在原来的流程里不继续执行了,转而去执行别的代码,但具体执行了啥代码你也不知道,你只调了个函数指针或者接口。 ...

May 14, 2019 · 1 min · jiezi

阿里开发者招聘节-面试题15如何看待异构计算在整个云计算中的位置和作用

摘要: 阿里巴巴资深技术专家们结合多年的工作、面试经验总结提炼而成的笔试真题这一次将陆续放出(面试题答案将在专辑分享结束后统一汇总分享)。并通过这些笔试真题开放阿里巴巴工作机会,让更多的开发者加入到阿里这个大平台。为帮助开发者们提升面试技能、有机会入职阿里,云栖社区特别制作了这个专辑——阿里巴巴资深技术专家们结合多年的工作、面试经验总结提炼而成的面试真题这一次将陆续放出(面试题官方参考答案将在专辑结束后统一汇总分享,点此进入答题并围观他人答案)。并通过这些笔试真题开放阿里巴巴工作机会,让更多的开发者加入到阿里这个大平台。 这一次,不仅是知识的收获,还将间接地与技术大牛们做了直观的沟通,了解他们的出题思路与考察要点,并加以消化吸收,这对自己技术能力本身就是一种极大的提升。走上编程之路,不断丰富自己方能与世接轨,努力做最优秀的自己。 5月10,我们给开发者的第15道面试题。 15.如何看待异构计算在整个云计算中的位置和作用?阿里巴巴出题专家:隐达 FPGA异构计算资深专家,2007年即作为芯片架构师,成功开发两款规模分别超过3500万门的ASIC芯片,达到了当时最先进的45nm工艺的极限。在FPGA/ASIC以及硬件设计领域有超过20年的工作经验,对于超大规模FPGA设计开发、ASIC开发与原型验证以及FPGA在数据中心中的加速价值有着深刻的理解和丰富的经验。 招聘职位:阿里云-GPU虚拟化研发高级专家 本文作者:山哥在这里阅读原文 本文为云栖社区原创内容,未经允许不得转载。

May 13, 2019 · 1 min · jiezi

十五年了蚂蚁为何执着攻坚这两个技术堡垒

阿里妹导读:近日,蚂蚁金服副CTO 胡喜应邀做了《蚂蚁金服十五年技术架构演进之路》的演讲,分享蚂蚁金服对金融科技未来的判断,并首次对外公开蚂蚁金服技术人才培训体系以及 BASIC College 项目。主要观点:蚂蚁金服过去十五年,通过技术重塑了支付和微贷业务。Blockchain (区块链)、ArtificialIntelligence(人工智能)、Security(安全)、 IoT(物联网)和 Cloud computing(云计算),这五大 BASIC 技术仍会是金融科技的基石。BASIC 里最基础的能力是计算能力,只有不断提升计算能力,才能适应未来应用场景的千变万化。金融交易技术的核心是金融分布式中间件,关键是分布式数据库的能力。对数据不丢失,业务不停机是金融级高可用的极致追求,同时,更要具备主动发现风险和自我恢复的能力。金融级分布式系统,最终将走向云原生化。现有的中间件能力将通过 service mesh 形式下沉至基础设施。安全可信的执行环境是金融级系统的底线,安全容器将成为金融行业的强需求。金融级数据智能未来的趋势是 Big Data Base,我们需要开放式的计算架构,从统一存储规范,可插拔的引擎组件,融合计算引擎,到统一的智能 SQL,数据处理与人工智能系统将会进一步融合,最终形成开放智能计算架构的最佳实践。多样化的计算,如流、图、机器学习经常并存于业务场景中,蚂蚁金服联合 Berkeley 大学推进的新一代计算引擎 Ray,着力于打造一个多模,融合的金融级计算引擎,帮助业务以简单的函数式编程实现多样化的分布式计算功能。蚂蚁金服最新开源的SQLFlow,抽象出端到端从数据到模型的研发过程,配合底层的引擎及自动优化,我们希望让人工智能应用像 SQL一样简单。以下是蚂蚁金服副CTO胡喜的分享内容全文:蚂蚁金服过去十五年,通过技术重塑了支付服务小微贷款服务。我们认为 Blockchain (区块链)、Artificial intelligence(人工智能)、Security(安全)、 IoT(物联网)和 Cloud computing(云计算),这五大 BASIC 技术仍会是金融科创新发展的基石。 但是,在 BASIC 技术中最基础的能力是计算能力,只有不断提升计算能力,才能适应未来应用场景的千变万化。对蚂蚁来说,要解决两个最关键的计算问题,一个是在线交易支付的问题,另外就是解决金融级数据智能的问题,狭义来讲就是 OLTP 和 OLAP 的问题。 1、金融级云原生,让交易支付更简单讲到金融在线交易,肯定要讲到“双十一”。因为“双十一”是整个中国 IT 届技术驱动力的盛世,蚂蚁在“双十一”的发展过程当中,可以看到金融支付几乎每年都是三倍的增长,到今天,整个系统具备百万级每秒的伸缩支付能力。 背后到底怎么做的?有些技术能力就跟跳水项目的规定动作一样,一定要具备这些能力。比如怎么做分布式、微服务,消息队列的问题。具体到蚂蚁,更重要的是解决分布式事务的问题,怎么做高可用,怎么做一致性,数据不能有任何丢失,不能有任何偏差,到最后怎么能够完成金融级的分布式中间件,到现在为止,我们可以看到一点,在高可用,一致性方面我们已经做到在任何情况下的数据最终一致,保证每一笔支付扣款的资金安全。并且我们去年对整体内部的中间件进行了开源,SOFAStack 是我们这么多年沉淀在金融级的最佳实践,我们期待这些实践能够帮助到更多人,从最近开源的数据来看,有 23000 的 Star,100 多个同学来参与贡献,欢迎大家更多地去试用。 刚刚讲中间件是能够在跟数据库无关前提的情况下,能够把整个金融交易做好,这是我们基本的要求,但金融交易技术中最关键的是分布式数据库能力。2009 年,蚂蚁启动自主研发数据库 OceanBase,这是一个非常偏向于高可用,一致性分布式的数据库,通过 Paxos 算法解决内部一致性的问题,到今天为止,蚂蚁整个数据库全部跑在 OceanBase 之上。 我常常会说什么才是核心技术?有些人说,核心技术只要投入人就可以做好,其实不是这么回事,核心技术不仅仅是有人有资源,还需要时间的积累,是需要天时地利人和,还需要公司、整个业务的支持,才能发展到今天,做技术还是需要一点技术情怀,蚂蚁就是一直这样坚持下去,十年左右的时间坚持开发自己的数据库,从零开始写第一行代码,到现在为止,OceanBase 数据库集群最大处理峰值是 4200 万次 / 秒,单集群最大的节点超过 1000 台,最大存储容量超过 2PB,单表最大的行数是超过 3200 亿行,并且在少数副本故障的情况下,能够做到 RPO=0,RTO<30 秒,这个是我们对于数据库层面上所做一些努力。 ...

May 13, 2019 · 2 min · jiezi

Apache-Cassandra-在-Facebook-的应用

摘要: 在 Instagram (Instagram是Facebook公司旗下一款免费提供在线图片及视频分享的社交应用软件,于2010年10月发布。)上,我们拥有世界上最大的 Apache Cassandra 数据库部署。谁说 Facebook 弃用 Cassandra?相反 Facebook 拥有全世界最大的单个 Cassandra 集群部署,而且他们对 Cassandra 做了很多性能优化,包括 Cassandra on RocksDB 以提升 Cassandra 的响应时间。 在 Instagram (Instagram是Facebook公司旗下一款免费提供在线图片及视频分享的社交应用软件,于2010年10月发布。)上,我们拥有世界上最大的 Apache Cassandra 数据库部署。我们在 2012 年开始使用 Cassandra 取代 Redis ,在生产环境中支撑欺诈检测,Feed 和 Direct inbox 等产品。起初我们在 AWS 环境中运行了 Cassandra 集群,但是当 Instagram 架构发生变化时,我们将 Cassandra 集群迁移到Facebook 的基础架构中。我们对 Cassandra 的可靠性和可用性有了非常好的体验,但是在读取数据延迟方面我们觉得他需要改进。 去年 Instagram 的 Cassandra 团队开始着手这个项目,以显着减少 Cassandra 的读取延迟,我们称之为 Rocksandra。 在这篇文章中,我将描述该项目的动机,我们克服的挑战以及内部和公共云环境中的性能指标。 动机在 Instagram 上,我们大量使用 Apache Cassandra 作为通用键值存储服务。Instagram 的大多数 Cassandra 请求都是在线的,因此为了向数亿 Instagram 用户提供可靠且响应迅速的用户体验,我们有很高的 SLA 要求。 ...

May 9, 2019 · 2 min · jiezi

现代IM系统中的消息系统架构-模型篇

前言在架构篇中我们介绍了现代IM消息系统的架构,介绍了Timeline的抽象模型以及基于Timeline模型构建的一个支持『消息漫游』、『多端同步』和『消息检索』多种高级功能的消息系统的典型架构。架构篇中为了简化读者对Tablestore Timeline模型的理解,概要性的对Timeline的基本逻辑模型做了介绍,以及对消息系统中消息的多种同步模式、存储和索引的基本概念做了一个科普。 本篇文章是对架构篇的一个补充,会对Tablestore的Timeline模型做一个非常详尽的解读,让读者能够深入到实现层面了解Timeline的基本功能以及核心组件。最后我们还是会基于IM消息系统这个场景,来看如何基于Tablestore Timeline实现IM场景下消息同步、存储和索引等基本功能。 Timeline模型Timeline模型以『简单』为设计目标,核心模块构成比较清晰明了,主要包括: Store:Timeline存储库,类似数据库的表的概念。Identifier:用于区分Timeline的唯一标识。Meta:用于描述Timeline的元数据,元数据描述采用free-schema结构,可自由包含任意列。Queue:一个Timeline内所有Message存储在Queue内。Message:Timeline内传递的消息体,也是一个free-schema的结构,可自由包含任意列。Index:包含Meta Index和Message Index,可对Meta或Message内的任意列自定义索引,提供灵活的多条件组合查询和搜索。Timeline Store Timeline Store是Timeline的存储库,对应于数据库内表的概念。上图是Timeline Store的结构图,Store内会存储所有的Timeline数据。Timeline是一个面向海量消息的数据模型,同时用于消息存储库和同步库,需要满足多种要求: 支撑海量数据存储:对于消息存储库来说,如果需要消息永久存储,则随着时间的积累,数据规模会越来越大,需要存储库能应对长时间积累的海量消息数据存储,需要能达到PB级容量。低存储成本:消息数据的冷热区分是很明显的,大部分查询都会集中在热数据,所以对于冷数据需要有一个比较低成本的存储方式,否则随着时间的积累数据量不断膨胀,存储成本会非常大。数据生命周期管理:不管是对于消息数据的存储还是同步,数据都需要定义生命周期。存储库是用于在线存储消息数据本身,通常需要设定一个较长周期的保存时间。而同步库是用于写扩散模式的在线或离线推送,通常设定一个较短的保存时间。极高的写入吞吐:各类场景下的消息系统,除了类似微博、头条这种类型的Feeds流系统,像绝大部分即时通讯或朋友圈这类消息场景,通常是采用写扩散的消息同步模式,写扩散要求底层存储具备极高的写入吞吐能力,以应对消息洪峰。低延迟的读:消息系统通常是应用在在线场景,所以对于查询要求低延迟。Tablestore Timeline的底层是基于LSM存储引擎的分布式数据库,LSM的最大优势就是对写入非常友好,天然适合消息写扩散的模式。同时对查询也做了极大优化,例如热数据进缓存、bloom filter等等。数据表采用Range Partition的分区模式,能提供水平扩展的服务能力,以及能自动探测并处理热点分区的负载均衡策略。为了满足同步库和存储库对存储的不同要求,也提供了一些灵活的自定义配置,主要包括: Time to live(数据生命周期):可自定义数据生命周期,例如永久保存,或者保存N天。Storage type(存储类型):自定义存储类型,对存储库来说,HDD是最好的选择,对同步库来说,SSD是最好的选择。Timeline Module Timeline Store内能存储海量的Timeline,单个Timeline的详细结构图如上,可以看到Timeline主要包含了三大部分: Timeline Meta:元数据部分,用于描述Timeline,包括:Identifier:用于唯一标识Timeline,可包含多个字段。 Meta:用于描述Timeline的元数据,可包含任意个数任意类型的字段。Meta Index:元数据索引,可对元数据内任意属性列建索引,支持多字段条件组合查询和检索。Timeline Queue:用于存储和同步消息的队列,队列中元素由两部分组成:Sequence Id:顺序ID,队列中用于定位Message的位点信息,在队列中顺序ID保持递增。 Message:队列中承载消息的实体,包含了消息的完整内容。Timeline Data:Timeline的数据部分就是Message,Message主要包含:Message:消息实体,其内部也可以包含任意数量任意类型字段。 Message Index:消息数据索引,可对消息实体内任意列做索引,支持多字段条件组合查询和检索。IM消息系统建模 以一个简易版IM系统为例,来看如何基于Tablestore Timeline模型建模。按照上图中的例子,存在A、B、C三个用户,A与B发生单聊,A与C发生单聊,以及A、B、C组成一个群聊,来看下在这个场景下消息同步、存储以及读写流程分别如何基于Tablestore Timeline建模。 消息同步模型 消息同步选择写扩散模型,能完全利用Tablestore Timeline的优势,以及针对IM消息场景读多写少的特性,通过写扩散来平衡读写,均衡整个系统的资源。写扩散模型下,每个接收消息的个体均拥有一个收件箱,所有需要同步至该个体的消息需要投递到其收件箱内。图上例子中,A、B、C三个用户分别拥有收件箱,每个用户不同的设备端,均从同一个收件箱内拉取新消息。 消息同步库 收件箱存储在同步库内,同步库中每个收件箱对应一个Timeline。根据图上的例子,总共存在3个Timeline作为收件箱。每个消息接收端保存有本地最新拉取的消息的SequenceID,每次拉取新消息均是从该SequenceID开始拉取消息。对同步库的查询会比较频繁,通常是对最新消息的查询,所以要求热数据尽量缓存在内存中,能提供高并发低延迟的查询。所以对同步库的配置,一般是需要SSD存储。消息如果已经同步到了所有的终端,则代表收件箱内的该消息已经被消费完毕,理论上可以清理。但设计上来说不做主动清理,而是给数据定义一个较短的生命周期来自动过期,一般定义为一周或者两周。数据过期之后,如果仍要同步拉取新消息,则需要退化到读扩散的模式,从存储库中拉取消息。 消息存储库 消息存储库中保存有每个会话的消息,每个会话的发件箱对应一个Timeline。发件箱内的消息支持按会话维度拉取消息,例如浏览某个会话内的历史消息则通过读取发件箱完成。一般来说,新消息通过在线推送或者查询同步库可投递到各个接收端,所以对存储库的查询会相对来说较少。而存储库用于长期存储消息,例如永久存储,相对同步库来说数据量会较大。所以存储库的选择一般是HDD,数据生命周期根据消息需要保存的时间来定,通常是一个较长的时间。 消息索引库 消息索引库依附于存储库,使用了Timeline的Message Index,可以对存储库内的消息进行索引,例如对文本内容的全文索引、收件人、发件人以及发送时间的索引等,能支持全文检索等高级查询和搜索。 总结本篇文章主要对Tablestore Timeline模型进行了详解,介绍了Timeline各模块包括Store、Meta、Queue、Data和Index等,最后以一个简单的IM场景举例如何基于Timeline来建模。在下一篇实现篇中,会直接基于Tablestore Timeline来实现一个简易版的支持单聊、群聊、元数据管理以及消息检索的IM系统,敬请期待。 本文作者:木洛阅读原文 本文为云栖社区原创内容,未经允许不得转载。

May 8, 2019 · 1 min · jiezi

洞见数据库前沿-集结阿里云数据库最强阵容-DTCC-2019-八大亮点抢先看

摘要: 作为DTCC的老朋友和全球领先的云计算厂商,阿里云数据库团队受邀参加本次技术盛会,不仅将派出重量级嘉宾阵容,还会为广大数据库业内人士和行业用户奉上8场精彩议题。下面小编就为大家提前梳理了8大亮点,并附上阿里云议题全集,精彩一网打尽。2019年5月8日-5月10日,由国内知名IT技术社区主办的数据库技术交流盛会——DTCC 2019将在北京新云南皇冠假日大酒店召开。数据风云,十年变迁,DTCC见证并铭记了国内数据库技术的关键成长历程。作为DTCC的老朋友和全球领先的云计算厂商,阿里云数据库团队受邀参加本次技术盛会,不仅将派出重量级嘉宾阵容,还会为广大数据库业内人士和行业用户奉上8场精彩议题,精彩不容错过。 本次DTCC大会云集多位阿里云数据库顶级大咖,将为您带来最具价值的技术交流和探讨,干货满满。由阿里巴巴集团副总裁、达摩院数据库首席科学家、阿里云智能事业群数据库产品事业部总负责 李飞飞博士领衔,Google第一代分布式SQL系统Tenzing核心人物、阿里云OLAP产品分析引擎负责人林亮,数据库内核团队资深技术专家何登成等核心团队成员将依次亮相,分别就云原生数据库、新一代自研分析型数据库、分布式数据库、时序数据库、图数据库等最in的技术话题,展开深入讨论,分享最佳实战经验。同时,李飞飞博士还将作为DTCC大会的专家顾问,把握数据技术的主题内容与方向。 洞见前沿技术趋势,见证阿里云数据库成长历程。在这场数据库领域从业人士难得的年度盛会和交流平台上,阿里云技术大牛们将带来怎样的饕餮盛宴? 下面小编就为大家提前梳理了8大亮点,并附上阿里云议题全集,精彩一网打尽。期待与您共聚一堂,共话行业未来! 温馨提示不在北京?到不了现场?没关系,我们为您准备了议题直播,欢迎点击下面的直播链接,尽情围观!5月9日-5月17日,每天下午15:00敬请锁定云栖社区直播,关注这场数据库技术干货的大咖SHOW 点击直播链接,预约观看就可领取阿里云数据库超值代金券!数量有限,先到先得哦! 亮点1:阿里云云原生数据库——我们不一样作为基础软件之一,数据库一直是企业IT系统的核心。随着云计算的到来及相关技术的不断成熟,推动了数据库行业的快速发展,传统数据库铁打的防线也正在被撕裂。 在云计算时代,云原生数据库开始崛起,通过弹性扩展、按量付费等特性获得了大量企业用户的青睐,挑战 Oracle 等传统数据库厂商的位置。在2018年,Gartner发布的数据库魔力象限中,云数据库厂商的表现极为抢眼,作为国内云计算行业的佼佼者,阿里云数据库更是跻身“远见者”象限。 为了满足弹性扩展、弹性计算、以及按需按量付费等云上应用需求,云原生数据库需要利用软硬件一体化设计,基于新兴的 RDMA、NVM 等高速硬件,研发全用户态的 IO 与网络协议栈以提供极低的延迟。 同时探索新的体系架构例如通过 shared-storage 来实现 shared-everything 和存储计算分离,提供一写多读的扩展能力。在某些高并发、对水平拓展有强需求的应用场景下,云原生数据库同时也需要探索基于 shared-nothing 的分布式架构来提供分布式数据库能力来处理分布式 SQL 查询和分布式事务处理。金融级高可用、异地多活等技术挑战也是云原生数据库所必须提供的关键能力。 演讲主题:《云时代数据库的演进》演讲嘉宾:李飞飞(花名:飞刀),阿里巴巴集团副总裁,达摩院首席数据科学家,阿里云智能事业群数据库产品事业部负责人 议题简介:阿里巴巴数据库团队自主研发的存储引擎 X-Engine 充分利用数据的冷热特性以及计算机系统结构的分层内存体系,通过冷热数据分离存储技术,提升写性能的同时降低成本。基于对以上技术挑战的不断探索和实践,阿里巴巴数据库团推出了云原生数据库 POLARDB 和其分布式版本 POLARDB-X,经受了2018年阿里巴巴双十一的交易峰值挑战并在阿里云上取得了商业化的成功。 本次分享将基于阿里云数据库近期在 VLDB,SIGMOD 上的论文内容,结合核心系统设计原理,介绍云原生数据库技术的挑战和发展趋势。 演讲时间:5月8日11:05-11:45主会场场次:主场1——数据架构 十年变迁直播时间:5月9日 15:00-16:00直播链接:https://yq.aliyun.com/live/1043?utm_content=g_1000056249亮点2:数据库内核研究,深度解码阿里数据库实现演讲主题:《POLARDB-X架构和技术演进》演讲嘉宾:何登成(花名:圭多),阿里云智能数据库产品事业部资深技术专家,DTCC的老朋友。从2005年开始一直坚守在数据库内核研发领域,先后在神州通用、网易和阿里从事数据库内核产品研发工作,目前带领团队打造阿里新一代分布式数据库POLARDB-X。 议题简介:作为阿里自研的新一代分布式数据库,POLARDB-X支撑了阿里巴巴90%以上的在线数据库应用。从AliSQL到POLARDB-X,经历了怎样的思考?在过去的一年,POLARDB-X在技术上有了哪些演进?希望能在DTCC的舞台上,跟朋友们进行深度的分享和交流。 演讲时间:5月8日16:20-17:10专场场次:数据库内核技术直播时间:5月9日 16:00-17:00直播链接:https://yq.aliyun.com/live/1045?utm_content=g_1000056250亮点3:海量数据毫秒级分析背后的架构挑战以及工程实践演讲主题:《超大规模实时数仓架构挑战与实践解析》 演讲嘉宾:林亮(花名:意博),阿里云智能数据库产品事业部研究员,曾就职Google十多年,在超大规模SQL Engine和规模存储引擎上经验丰富。目前在负责阿里云PB级分析型数据库AnalyticDB架构工作。 议题简介:数据分析领域目前正在朝着在线化方向演进,数据业务在海量数据实时写入、高并发分析、稳定性、灵活性上挑战巨大。分析型数据库AnalyticDB是阿里巴巴自主研发的超大规模PB级实时数据仓库, 近2年在上述挑战背后的技术领域稳扎稳打,做了大量的难点突破和技术创新,本次演讲深入分析AnalyticDB海量数据毫秒级分析背后的架构挑战以及工程实践。 演讲时间:5月9日09:40-10:20主会场场次:主场2——数据架构 十年变迁直播时间:5月10日 15:00-16:00直播链接:https://yq.aliyun.com/live/1047?utm_content=g_1000056251亮点4:教你解锁时序时空数据库的种种黑科技演讲主题:《阿里云TSDB: 拥抱物联网的新一代时序时空数据库》演讲嘉宾:伊翼(花名:老滚)。阿里云智能数据库产品事业部技术专家,从事TSDB核心引擎的研发工作。 议题简介:阿里云TSDB是阿里自研的一种高性能,低成本,稳定可靠的在线时序时空数据库产品。该产品统一了阿里巴巴集团90%以上的APM数据和事件型数据的存储和计算,并在广泛应用于外部的物联网,工业制造,电力,化工以及IT运维等行业。本演讲将介绍该时序时空数据库的种种黑科技:・提供千万级并发读写・双十一写入TPS达到6000万/秒・十倍以上压缩比低成本存储・PB级时序时空数据秒级聚合・每天百亿时间线的集群规模等等 演讲时间:5月8日15:50-16:30专场场次:NoSQL技术与实践直播时间:5月13日 15:00-16:00直播链接:https://yq.aliyun.com/live/1044?utm_content=g_1000056252亮点5:把握数据库发展趋势 DBA应如何避免“踩坑”?进行云时代以后,IT行业各工种的职责都在发生变化,云数据库使得日常DBA管理实现更多的自动化,大大提高日常管理效率,同时也对于企业整体投资产出可以更快获得成效。对于DBA职位的而言,当前是一个转变期,不少企业从业务开始之初就直接使用云计算。 演讲主题:《如何构建云时代DBA的知识体系》演讲嘉宾:萧少聪(花名:铁庵),阿里云智能数据库产品事业部高级产品专家,PostgreSQL中国社区常委 议题简介:如何构建云时代DBA的知识体系?通过本次演讲,希望能够协助行业中已有的DBA转型及新就业进入DBA的技术人员对云DBA加深了解,让大家在转型过程少走弯路。 云数据库 vs 传统数据库管理模式对比;云DBA知识体系构成:基础、云主机、云数据库、智能化管理;直接使用云数据库与在云主机中自建数据库的管理差异;如何成长为一名优秀的云DBA。演讲时间:5月8日11:05-11:45专场场次:云时代的数据库(上)**直播时间:5月14日15:00-16:00直播链接:https://yq.aliyun.com/live/1046?utm_content=g_1000056253亮点6:关于数据库灾备,你想知道的都在这里演讲主题:《云时代数据库迁移 & 容灾技术新进展与应用》 演讲嘉宾:付大超(花名:千震),2012年加入阿里巴巴,目前负责DTS&DBS团队和研发,在阿里云提供迁移、同步和容灾的服务,支持阿里巴巴、蚂蚁、阿里云等异地多活单元化架构,曾负责阿里全球最大的HBase集群的开发和维护工作,曾先后工作于IBM、Cisco。 议题简介:迁移&容灾是数据库的强需求,传统的迁移&容灾技术已经发展多年,随着云时代的来临,在迁移&容灾的使用场景、网络、技术都有很大的变化,如何在云时代下更简单的实现数据库的迁移&容灾,云厂商如何通过新的技术实现弯道超车,本次topic主要分享阿里云在此领域的技术新进展和应用。 演讲时间:5月9日17:10-18:00专场场次:云时代数据库(下)直播时间:5月15日15:00-16:00直播链接:https://yq.aliyun.com/live/1048?utm_content=g_1000056254亮点7:NoSQL——如何拥有居家必备的企业级能力当整个世界由IT走向DT时代,数据库领域也发生了重大变化,NoSQL已成为企业应用常态 演讲主题:《NoSQL数据库最新技术发展趋势》 演讲嘉宾:朱洁(花名:所在),阿里云智能数据库产品事业部高级产品专家,当前为阿里云数据库NoSQL数据库产品Leader。10+数据库/大数据研发管理经验,专注于数据库/大数据服务平台建设、规划和实践应用,著有畅销书《大数据架构详解:从数据获取到深度学习》。 议题简介:企业IT系统面临层出不穷的新业务,安全,成本等诸多挑战。阿里云NoSQL数据库通过与企业业务深度结合,快速创新,提供最新的技术帮助企业用户迎接挑战,获得金融、社交、直播等众多大客户的信任。 本次演讲重点介绍阿里云NoSQL数据库在全球分布式,多模,弹性,HTAP,cloudNative,图,时序,时空等众多最新领域的创新和技术实践。 演讲时间:5月10日 09:40-10:20专场场次:分布式数据库实践(下)直播时间:5月16日15:00-16:00直播链接:https://yq.aliyun.com/live/1049?utm_content=g_1000056255亮点8:前沿技术应用——图数据库知多少?数据库从业者必看演讲主题:《探索互联数据的奥秘——图数据库GDB》 演讲嘉宾:王炎(花名:夜炎),阿里云智能数据库产品事业部高级技术专家。在分布式系统、存储领域以及NoSQL系统研发领域经验丰富。18年加入阿里巴巴集团,现在阿里负责图数据库系统相关研发工作。 ...

May 8, 2019 · 1 min · jiezi

后端好书阅读与推荐续七

后端好书阅读与推荐系列文章: 后端好书阅读与推荐后端好书阅读与推荐(续)后端好书阅读与推荐(续二)后端好书阅读与推荐(续三)后端好书阅读与推荐(续四)后端好书阅读与推荐(续五)后端好书阅读与推荐(续六)后端好书阅读与推荐(续七) Spring微服务实战Spring微服务实战 (豆瓣): https://book.douban.com/subje... Spring体系用来做微服务在当下可谓是风头正劲,这本书就用一个实例来手把手教我们实现微服务。实战系列的口碑一直不错,这本也不例外,看完就可以对微服务的概念有一个完整的理解,并且想上手也有路可寻。 亮点: 编码就像艺术,是一种创造性活动。构建分布式应用就像指挥一个管弦乐队演奏音乐,是一件令人惊奇的事情微服务是一个小的、松耦合的分布式服务,分解和分离大型复杂应用程序的功能,使它们独立,这样负责每个功能的团队都拥有自己的代码库和基础设施,技术不限,能灵活地独立开发部署,职责分离,降低团队协作成本。随着云的普及,微服务单元的增减(每个服务单元都是完整的)变得非常容易,使得整个应用更具弹性伸缩能力。Spring勇于自我革新,当初出场取代了沉重的J2EE,后面的Spring Boot使用简单注解去掉了自己原本繁重的配置,后来的Spring Cloud更是为分布式服务提供了一套完整的解决方案,所以Spring体系是我们构建微服务的绝佳选择微服务构建的一个关键是划分,而划分的一个关键是粒度,这个没有绝对标准,但是有几个原则:开始可以让服务设计范围大一些,后续可以重构至更小的服务;重点关注服务之间如何交互;随着对问题域的理解变化,服务的职责也要变化(演化思维)。需要注意微服务的几个坏味道(太粗;太细):职责过多,跨表超过5个,URL太长,测试用例太多;数量巨大、彼此依赖严重、成为简单的curd、只在一个表操作等微服务没有标准,但是作者提出了12种最佳实践:独立代码库、显式依赖、配置存储、后端可切换、构建发布运行必须完整、进程无状态、端口命令行制定、横向扩展并发、可down可up、环境一致、日志流式处理、管理脚本化。微服务的生命周期:装配、引导、发现、服务和监控、关闭少量程序可以使用低层级文件(YAML、json、XML)来存储配置,将其与代码分开,但是到了数百单元(每个单元可能有多个实例)时就不行了。手动管理既慢又复杂还可能配置漂移,这时应该引入配置管理工具(etcd、eureka、consul、zookeeper、spring cloud config等),服务启动时通过环境变量注入配置或者从集中式存储中获取服务发现提供了快速水平伸缩的能力,且当服务不健康时可以快速删除,还能取代传统的手动管理负载均衡。主要涉及服务注册、客户端服务地址查找、信息共享、健康监测4个方面一般大家关注高可用都是某个组件彻底不可用(容易检测)的情况,但是一个性能不佳而没有完全垮掉(不易检测)的服务也可以彻底拖垮整个应用,因此也需要保护这些不佳服务,避免连锁效应,导致彻底不可用。一般有客户端负载均衡(Ribbon)、断路器、后备、舱壁(Hystrix)等四个弹性模式来实现保护缓冲区AOP的思想帮我们分离关注点,那么要在微服务中实现靠啥?答案就是网关(比如Zuul,核心就是反向代理)了,我们可以在网关中实现验证授权、数据搜集与日志等关注点,但是要注意,避免网关成为单点要注意使其轻量且无状态(无状态就可以很容易扩展,而服务发现必须有状态,所以要扩展还要用Gossip等协议来同步状态数据,保障一致性和可用性)安全注意事项:都要使用HTTPSSSL、所有服务都要经过网关、将服务划分为公共API和私有API、封锁不必要的端口来限制微服务的攻击面微服务不是单体,其好处是灵活,代价就是解决问题时难以定位,所以需要追踪并聚合日志,最终定位问题。spring cloud 给每一个事务开启之前注入关联ID(一般由网关完成),每个服务都可以传播关联ID并将其添加进日志中,这些日志被统一发送到日志聚合点中,就可以供我们统一检索了,常见实现有ELK、Splunk等。光能检索还不够,一张直观的事务流图抵过1万条日志,Sleuth和ZipKin一起可以实现该功能微服务强调灵活迅速,所以一个成熟的构建与部署管道(引入CI/CD)必不可少:提交代码、自动构建(钩子实现)、构建期间进行单元测试与集成测试后获得一个jar(自包含tomcat)、用jar构建并提交机器镜像、在新环境中拉取机器镜像并进行平台测试后启动镜像、每个新环境都要重复前面一个步骤书很厚,所以很多具体工具可以跳过,尝试几个即可,将来使用的时候知道这本书里有就行了。 持续交付持续交付 (豆瓣): https://book.douban.com/subje... 微服务离不开CI/CD,而CI/CD核心就是几点:自动化、连续、小范围、快速、可靠。我们通过这本书来了解CI/CD,也看看持续交付是如何解决“Last Mile”问题,让软件交付不再令人紧张,成为一件简单平常的事情。 亮点: 从决定修改到结果上线的时间为周期时间,CI/CD技术能让周期从传统手段的周月单位变成小时甚至分钟级别(产品快速落地,降低机会成本),发布过程可靠可重复(减少错误与人力资源),核心技术就是部署流水线(一个应用从构建、部署、测试到发布这整个过程的自动化实现,过程中需要的所有东西包括需求、源码、配置、脚本、文档、运行环境等都要纳入VCS的管理,但是结果性的东西比如二进制镜像就不用,因为它可以随时构建得到,作者罗列了一些相应的工具)提出了一些反模式,让我们避免:手工部署软件(复杂 不可重复和审计 易出错)、开发完成之后才向类生产环境部署(不确定性很大 发布有风险)、生产环境手工配置管理(不能完全掌握 不可重复)。同时也提出了一些应该遵循的正面原则持续集成的前提是版本控制、自动化构建、团队共识,需要做到频繁提交、自动化测试、保持构建和测试过程较短、管理开发工作区、构建失败之后修复成功之前不能提交新代码、提交之前自己运行测试、提交测试通过之后再继续工作、时刻准备回滚(回滚之前要有一个修复时间)、为自己的问题负责、测试驱动等等持续集成能提高团队对复杂系统的自信心与控制力,其主要关注是开发团队,并不能解决软件部署、交付过程的低效,所以需要一个端到端的自动化构建、部署、测试和发布流程,也就是部署流水线(关注的是软件从CVS到用户手中这个过程),它有一些相关实践:只生成一次二进制包、不同环境统一部署、对部署进行冒烟测试、向生产环境的副本部署、每次变更都要立即在流水线中传递、只要有环节失败停止整个流水线。CI/CD的关键都是记录变更,为尽早发现问题提供信息,消除低效环节部署流水线的几个要点:构建与部署脚本化(配置初始化数据、基础设施、中间件等)、提交阶段快速反馈与及时修复、自动化验收测试(验收测试是验证客户的期待,单元测试是验证开发人员的期待)、注意非功能测试(主要指性能)、部署与发布要有策略并且可重复执行(文本化)且可回滚(不同版本文件不删除,用符号链接到当前版本)作者说无论项目大小都应使用CI/CD,这个我感觉有点偏激了,所谓磨刀不误砍柴工,前提是这个柴要么很多,要么很大,如果只是几根细柴,有那个磨刀的功夫柴都砍完了。但是实际工作中这么小的项目应该很少,所以大多数项目我们还是都还是应该搭建部署流水线,用上CI/CD。书很厚,其实好多地方可以跳过,你只需要看标题就能抓住主旨而无需多看。PS:可以先看看这本持续集成。 敏捷革命敏捷革命:提升个人创造力与企业效率的全新协作模式 (豆瓣): https://book.douban.com/subje... CI/CD 实际上正是敏捷开发的最佳实践,有了前面的铺垫,我们可以通过这本书我们来真正了解敏捷开发的全貌。 亮点: 2005年之前,大多数软件开发项目都是采用“瀑布法”:整个项目被划分为多个阶段,每个阶段都要经过严格的评审,以期为客户或软件使用者提供完美的产品(甘特图表现),每一阶段的工作做得足够好时才允许进入下一阶段。这种工作方式看似完美,实际全凭想象和猜测、华而不实,往往导致开发进度缓慢,常常超出预算,且现实和规划差异巨大,Scrum(敏捷开发流程)的出现就是解决这个问题的(不凭猜测,而是PDCA:计划、执行、检查、行动)任何项目的管理都需要实现两个目标:可控性与可预测性管理层的职责在于制定战略目标,团队的工作则是决定如何完成目标。无论任何人,只要不在现场,都不可能及时跟上事态变化的步调,所以团队要有自主决策权,此外一个团队需要包含完成一个项目的所有技能,同时要小而精(7人左右)。团队成员之间不要互相指责,而是尽量改善制度“冲刺”(一般以星期为周期)可以让团队成员集中精力快速做出成果并得到反馈,“每日立会”(15分钟以内)能让成员清楚地知道冲刺进度如何。Scrum的核心就是节奏确定懂项目、懂市场、懂顾客的产品负责人,拟定待办事项清单并检测两遍,重要的事情优先做这本书细看的话真的很洗脑,看完感觉自己迫不及待地想要冲进一家公司试试Scrum了。 DevOps实践指南DevOps实践指南 (豆瓣): https://book.douban.com/subje... DevOps是软件开发、运维和质量保证三个部门之间的沟通、协作和集成所采用的流程、方法和体系的一个集合(所以也要基于CI/CD,前4本书可以看做一个连续的专题,核心都是敏捷)。它取代了传统开发、测试、运维职责大分离的思想,填平了部门之间的鸿沟,让大家更有效的工作。我们可以通过这本书来对DevOps有一个全面的了解。 亮点: 开发部通常负责对市场变化做出响应,以最快的速度将新功能或者变更上线。而运维部则要以提供稳定、可靠和安全的服务为已任,让任何人都很难甚至无法引入可能会危害生产环境的变更。这种配置方式让开发部门和IT运维部门的目标和动因之间存在“根本的、长期的冲突”——公司对不同部门的考核和激励不同,这种冲突造成了一种恶性循环,阻碍了公司全局目标的实现。DevOps能够提高公司业绩,实现开发、QA、IT运维、信息安全等各职能技术角色的目标,同时改善人们的境遇DevOps是精益、约束理论、丰田生产系统、柔性工程、学习型组织、康威定律等知识体系的集大成者DevOps“三步工作法”:流动、反馈、持续学习与实验,并阐述了DevOps实施需遵守的原则与最佳实践(流动:它加速了从开发、运维到交付给客户的正向流程;反馈:它使组织构建安全可靠的工作体系,并获得反馈;持续学习与实验:它打造出一种高度信任的文化,并将改进和创新融入日常工作中)为了能识别工作在哪里流动、排队或停滞,需要将工作尽可能地可视化,如在看板或Sprint计划板上,使用纸质或电子卡片将各项工作展示出来,通过这种方式,不仅能将工作内容可视化,还能有效地管理工作,加速其从左至右的流动,还可以通过卡片从在看板上创建到移动至“完成”这一列,度量出工作的前置时间。此外,看板还能控制在制品数量(队列长度)文中关于小批量和大批量的差异,我以前在博客中也提到过。如此看来,两种方式各有优劣,关键看能分配的资源是什么?更追求总体效率还是效果出现的等待时间?对返工的要求是什么?再来决定使用方法第一步描述的原则,使得工作能够在价值流中从左向右快速地流动。第二步描述的原则,使得在从右向左的每个阶段中能够快速、持续地获得工作反馈。快速发现问题、群策群力解决问题,可以避免把问题带入下游环节,避免修复成本指数增加。根据精益原则,我们最重要的客户是我们的下游(不一定是最终付费用户),为他们而优化我们的工作,在源头保障质量。第三步描述的原则可以持续提升个人技能,进而转化为团队的财富......感觉历史的天平总是左右摇摆,一开始职责混乱、一个人干所有的事,后来职责分离、分工明确,现在又提倡填平鸿沟、部门融合。随着时代的发展,适用于时代的技术也总是不停变更,要想不被淘汰就得终身学习呀。 Web容量规划的艺术Web容量规划的艺术 (豆瓣): https://book.douban.com/subje... 容量规划(很早就有了,如道路规划、电力运营)是一门省钱的艺术,保证用合理的资源来实现最大化需求,通过这本书我们来敲开容量规划在互联网世界中实际运用的大门。 亮点: 容量规划整个过程:首先要明确定义响应时间、可供消耗容量以及峰值驱动处理等明确指标来定义总体负载和容量需求,然后了解当前基础设施的负荷特征,预测需要的资源来达到这种性能,然后如何管理资源,最后不断迭代,最终目标介于“没有买足够资源”和“浪费太多资源”之间有几个方法:预测系统何时失败、用统计图表(比数字更直观)呈现问题、性能调优与容量规划要同步进行、搜集数据驱动未来的规划测量是规划的前提,要有坚实的数据支撑而不是猜测,有许多工具可以测量,他们应该可以随着时间记录和保存数据、自定义度量、比较指标、导入和导出指标,当然测量工具本身要轻量,尽量对资源本身影响较小。如果说测量是对已有情况的了解,那么估计就是根据数据趋势预测未来。预测部分靠直觉,部分靠数学。我们可以做曲线拟合,注意到趋势和变更,并进行迭代和校准(看来基于机器学习或者说AI的运维是未来啊)文章除了基于传统模式的容量规划,还涉及到了基于虚拟化和云计算的模式,所以我们学习也要注意趋势和变化。 领域驱动设计领域驱动设计 (豆瓣): https://book.douban.com/subje... 构建程序之前,我们都要对业务进行梳理和理解,然后是领域划分与建模等一系列重要步骤,最后才是编码实现,这就是一本讲解这些步骤的好书。而且本书会告诉你,设计和实现可以交错进行和演化,来达到最优。还提出了专业术语,你在和别人交流时可以使用。我在读到假同源这个词语时真是犹如醍醐灌顶,因为之前开发项目就有过:同一个对象,这个模块改吧改吧,那个模块改吧改吧,最后导致对两个模块而言,这个对象都不完全属于它,要修改都得小心翼翼怕影响对方,本书告诉我,遇上假同源,要么重新理解和建模,统一该对象表示,要么果断分开这两个模块,用两个对象分别服务这两个模块。 亮点: 模型是一种简化,是对现实的解释,把与解决问题密切相关的方面抽象出来,而忽略无关的细节(所以需要我们消化和提炼已有知识,包括深层次探索)。用户应用软件的问题区域就是软件的领域(有形的如机票系统,无形的如会计系统)。成功的项目有一个共同特征:都有一个丰富的领域模型,这个模型在迭代设计过程中不断演变(我们要持续学习),与实现绑定,成为项目不可分割的一部分很多因素可能会导致项目偏离轨道,但真正决定软件复杂性的是设计方法。当复杂性失去控制时,开发人员就无法很好地理解软件,因此无法轻易、安全地更改和扩展它,而好的设计则可以为开发复杂特性创造更多机会。一些设计因素是技术上的,很多技术人员都能轻易注意到并改进,但是很多程序主要的复杂性并不在技术上,而是来自领域本身、用户的活动或业务,这部分往往被许多人忽略要避免不设计和过度设计(极限编程)模型、设计的核心、实现互相影响和关联;模型是团队所有人员沟通的中枢,使得开发人员和领域专家无需翻译就能沟通,高效简洁;模型是浓缩的知识技术人才更愿意从事精细的框架工作,试图用技术来解决领域问题,把学习领域知识和领域建模的工作留给别人去做。软件核心的复杂性需要我们直接去面对和解决,如果不这样做,则可能导致工作重点的偏离——软件的初衷以及核心就是为了解决领域问题对于比较重要的业务规则(这个知识点需要我们自己去理解)比如货船超订110%,应该单独抽象成1个实体(具体就可以是1个方法),而不是简单的用一个guard clause来实现,这样既能明确这个知识点本身,又利于代码的扩展性。当然,把不重要的细节也单独抽象就是典型的过度设计了以文本为主,简洁的小图为辅(大而全的图反而失去了解释能力)来阐释模型最好。文档是代码和口头交流的补充,为团队提供稳定和共享的交流。只用代码做文档容易使人陷入细节,不能把控全局,所以应该文档和代码互补,文档不再重复阐述代码能表现的内容而是着重核心元素,阐明设计意图,文档还要注意和代码保持同步不脱节(不再适用的文档要进行历史归档),不然就失去了意义。模型与实现也要同步,通过模型驱动设计MDD实现,保证模型既利于实现,也利于前期的分析要想创建出能处理复杂任务的程序,需要做到关注点分离,使设计中的每个部分都得到单独的关注,行业普遍采用分层架构,分层的价值在于每一层都只代表程序中的某一特定方面,每个方面的设计都更具内聚性,更容易解释。分层设计大都是“用户层界面-应用层-领域层-基础设施层”这种四层架构的变体,其中领域层是软件的核心,将其分离才是MDD的关键,也是领域驱动设计DDD的前提。领域层与应用层的区分关键在于领域层包含实际业务规则(如转账操作),而应用层是为了实现业务的辅助功能(如导入转账文本记录)DDD适用于大型项目,小项目用“Smart UI”更合适,还有其他的架构模式都有自己的使用场景和局限领域中用来表示某种具有连续性和标识(比如银行账户)的事物是ENTITY,用于描述某种状态的属性是VALUE OBJECT(不可变,无标识,比如数字3,尽量设计为不可变,便于复制和共享),动作或操作最好用SERVICE来表示(在大型系统中,中等粒度、无状态的SERVICE更容易被复用),对象之间的关联可以通过限定条件进行简化,MODULE是一种更粗粒度的建模和设计单元(提供了两种观察模型的方式,一是可以在MODULE中查看细节,而不会被整个模型淹没,二是观察MODULE之间的关系,而不考虑其内部细节)。领域模型中的每个概念都应该在实现元素中反映出来由于汽车的装配和驾驶永远不会同时发生,因此将这两种功能合并到同一个机制中是毫无价值的。同理,装配复杂的复合对象的工作也最好与对象要执行的工作分开。应该将创建复杂对象(比如依赖其他对象B的对象A就是复杂对象,不要直接在A构造函数中调用B的构造函数)的实例和AGGREGATE(一组相关对象的集合,比如车辆与发动机)的职责转移给单独的对象:FACTORY初始模型通常都是基于对领域的浅显认知而构建的,不够成熟也不够深入,通过重构(不仅是一般的代码细节的重构,还有领域的重构,后者通常风险很高,但是回报也很高,需要在前者的不断积累下寻找突破)最终开发出能够捕捉到领域深层含义的模型,这也是管理项目的规模和复杂性的要素,加上柔性设计(软件易于修改)就能让项目稳步发展。持续重构渐渐被认为是一种“最佳实践”,但大部分项目团队仍然对它抱有很大的戒心。人们虽然看到了修改代码会有风险,还要花费开发时间,但却不容易看到维持一个拙劣设计也有风险,而且迁就这种设计也要付出代价代码除了要能准确得到结果外,还要能显式的表达出领域的规则,易于理解和预测修改代码的影响。所以有一些原则:揭示意图的接口,能避免用户去研究它的实现(失去了封装的价值);无副作用的函数,安全地预见函数的作用,避免组合爆炸;断言可以帮助展示和理解副作用技术角度的设计模式中的一些也适用于领域设计,比如Strategy和Composite模式,把设计模式用作领域模式的唯一要求是这些模式能够描述关于概念领域的一些事情,而不仅是作为解决技术问题的技术解决方案大型系统的模型很复杂,需要注意三个要素:上下文(不要强制在大型系统中统一模型,可以在不同的上下文使用不同的模型(注意重复概念和假同源),划定好边界即可)、精炼和大型结构,才能操纵和理解这个模型......DDD我们可能都用过,但是很可能没把它当成一项正经学问,都是大概过一下需求,稍微捋一捋逻辑然后就开始编码了,实际上,在我们这个过程我们已经经历了ddd,看完本书以后希望能把这个过程正规化,流程化,高效化。 Go语言实战Go语言实战 (豆瓣): https://book.douban.com/subje... 上本书给我们讲了go的基础知识和原理,这本书就带领我们用go的各种库和工具进行实战。 亮点: 计算机一直在演化,但是编程语言并没有以同样的速度演化。现在的高性能服务器拥有 64 核、128 核,甚至更多核。但是我们依旧在使用为单核设计的技术在编程。Go语言对传统的面向对象开发进行了重新思考,并且提供了更高效的复用代码的手段。Go语言还让用户能更高效地利用昂贵服务器上的所有核心,而且它编译大型项目的速度也很快经验,如果需要声明初始为零值的变量,应该使用 var 关键字声明变量;如果提供确切的非零值初始化变量或者使用函数返回值创建变量,应该使用简化变量声明运算符 :=go vet工具不能让开发者避免严重的逻辑错误,或者避免编写充满小错的代码。不过可以很好地捕获一部分常见错误。每次对代码先执行 go vet 再将其签入源代码库是一个很好的习惯;在保存文件或者提交到代码库前执行 go fmt可以统一代码风格go在函数之间传递变量时,总是以值的方式传递的。函数间传递数组可能涉及大量数据拷贝,最好传递数组的指针,就只用拷贝8字节的指针而非拷贝数组本身。相反,与切片关联的数据包含在底层数组里,不属于切片本身,所函数间直接传递切片没有性能影响,映射也是;在创建切片时设置切片的容量和长度一样,就可以强制让新切片的第一个 append 操作创建新的底层数组,与原有的底层数组分离,可以安全地进行修改而不影响原切片,同时也保持了为切片申请新的底层数组的代码简洁性关键字 func 和函数名之间的参数被称作接收者,将函数与接收者的类型绑在一起。如果一个函数有接收者,这个函数就被称为方法。值接收者使用值的拷贝副本来调用方法,而指针接受者使用实际值来调用方法。Go语言会调整传入的参数,无论是指针接受者还是值接受者都可以接受指针或者值两种类型,说是方便开发,但我觉得这反而是一个不必要的歧义,比如到了接口的方法集中,如果使用指针接收者来实现一个接口,那么只有指向那个类型的指针才能够实现对应的接口。如果使用值接收者来实现一个接口,那么那个类型的值和指针都能够实现对应的接口,主要原因是编译器并不是总能自动获得一个值的地址通过嵌入类型,与内部类型相关的标识符会提升到外部类型上。这些被提升的标识符就像直接声明在外部类型里的标识符一样,也是外部类型的一部分,可以无缝实现对象组合,需要注意嵌入类型不需要声明字段。如 ...

May 7, 2019 · 1 min · jiezi

工程开发

更不知道起什么名字。我想归纳下一个通用系统(不考虑功能)的目标和实现方法,如果本人公司涉及到的会详细讲一下,也供架构设计搭建参考。本篇是个整体,其中涉及内容会分篇 目标: ——高性能 ——高可用 ——可扩展 ——成本(运维,研发效率,测试效率,物理成本与其他分不开暂不考虑) ——安全一个系统设计什么样子完全由目标决定,可以从原来的单机应用服务器扩展到分布式服务(包含CDN服务器集群,反向代理服务器集群,分布式微服务集群,通用数据代理集群,分布式缓存集群,分布式文件服务器,分布式数据库服务器等)举个例子一个简单的通用系统逻辑架构如下: 高性能单机高性能多进程,单进程多线程每个独立线程处理网络IO模式:异步、同步(actor,reactor,preactor)网路IO:阻塞、非阻塞(select,poll,epoll)见:xx actor,epoll集群高性能:1.缓存本地数据缓存:在存储中讲,略分布式数据缓存:在存储中讲,略CDN:见xx2.扩展服务器,任务分配器(负载均衡)需要关注分配器选型(硬件F5,软件LVS,nginx)、分配器与服务器之间连接管理,建立,检测,中断后处理、分配算法负载均衡整体上方案1)可负载均衡位置和方案 DNS负载均衡不需开发,DNS会自动就近访问。缓存更新不及时,扩展性差,分配策略简单无法感觉服务器状态,见:xx硬件 还具备防火墙,DDos等功能。扩展差。贵。4层LVS 见:xx7层 nginx 见:xx代码中 配置,服务发现等 见:在微服务中xx2)负载均衡算法 HASH 源地址hash目标地址hashsession id hash,用户id hash 适用于临时保存的场景轮询平分加权轮询负载最低优先(比如CPU负载,连接数,IO使用,网卡等,LVS可以以连接数来判断,其他因为收集负载负载应用场景没有轮询多)性能最优类(响应时间,收集,采样,统计周期)3.任务拆分 简单的系统更容易做到高性能,同时提高扩展性,在扩展性中说3.通信公司入网部署 见:xx长连接 见:xx网络协议 网络基础 见:xxtcp 见:xxhttp 见:xxthrift 见:xx高可用(稳定性建设)计算高可用1.部署,可以1主多备或多主多备。主备(单活):冷备(主从),温被(业务系统一直启动,但不对外提供服务)集群(多活):对称集群(负载均衡),非对称集群,任务分配器2.任务分配器分配算法更复杂,需要有角色状态能力,若多主还需要考虑尽量同一用户落入单机房,当然也可以简单的人工切换。高可用状态决策 1.一个决策者,多个上报者2.2个机器协商3.民主决策,=》脑裂 当集群连接中断,解决办法投票节点数必须超过系统总节点一半,当可用少于一半时系统不可用任务管理:某台服务器失败,是否要以及如何重新分配到新的服务器执行3.异地多活(活不是备) 异地同城异区,解决机房级别故障,可以通过搭建告诉网络,和同一个机房一样设计跨城异地,网络抖动时,延时会很高,数据不一致,支付宝等金融系统对余额这类数据不会做跨城异地,应对极端灾难场景跨国多活:不同地区不能相互访问,或几秒以上延时无感知的只读服务原则保证核心业务的异地多活,保证核心业务数据最终一致性减少异地多活机房的距离,搭建高速网络只保证绝大部分用户的异地多活。挂公告,事后补偿等挑选核心业务:访问量大的,核心功能,产生大量收入业务数据带存储异地多活比较难,见:xx。全局唯一ID,该生成ID方案也要异地多活,idc生成个方案:xx分类:数据量,唯一性,实时性,可丢失性,可恢复性。根据不同数据设计不同同步方案,避免少量数据异常导致整体业务不可用采取多种手段同步数据,除了存储系统等自带的同步功能,消息队列方式,二次读取,回源读取,重新生成数据等异常处理多通道同步数据同步+接口访问(用两种不同的网络连接,一个公网一个内网,优先同步+本地,不行就走接口,多机房需要路由规则记录数据来源,访问来源机器),日志记录(服务器上,本地独立系统存储,日志异地保存),用户补偿接口级故障,保证核心业务和绝大部分用户(bug等内存耗尽等,第三方系统大量请求或响应慢,攻击,促销等) 降级,降级系统,权限管理,批量操作等熔断:当a依赖B,B响应慢,A不再请求B。调用层统一采样+统计,设置阈值限流,基于请求限流,基于资源限流,排队,kafka等消息队列。排队模块,调度模块,服务模块存储高可用存储的东西涉及较多,独立见xx可扩展常见拆分方案:1.面向流程(UI,业务,数据,存储) 分层架构 保证各层之间的差异足够清晰,边界明显,本质就是隔离关注点,要保证层与层之间的依赖是稳定的,B/S,C/S MVC(逻辑都在M,C只是转发)/MVP(逻辑在P,M是数据),逻辑分层(自顶向下依赖比如端=》框架=》库=》内核),建议层层不能被跨越,两两依赖,否则时间久会乱比如sdk和common。缺点是冗余和每次都要经过所有层2.面向服务 SOA微服务 需要快速交付,轻量级,服务粒度细。small,lightweight,automated服务划分太细,服务间关系复杂;数量太多,团队效率下降,平均3人一个;调用链路长,性能下降;调用链路长,问题定位论难;一定要有自动化的测试,部署,监控保障;服务路由,故障隔离,注册和发现等服务治理。基于业务逻辑拆分。稳定和变化拆分,稳定服务力度可以粗一些。核心和非核心拆分,只对核心业务做高可用等。基于性能拆分,瓶颈单独部署。详见:xx(rpc,服务发现) 3.面向功能:微内核(插件化架构) 插件管理,注册,加载时机。插件连接(OSGI,消息模式,依赖注入spring,分布式协议rpc等)。插件通信(核心模块实现)比如OSGI,Eclipse的Equinox。service层(bundle注册),lifecycle(管理bundle的安装更新启动停止卸载),bundle规则引擎架构(开源drools), 成本研发效率框架。不同语言和层面的服务关注点不同,讲下thrift和PHP两篇,见xx环境。容器很方便(见xx)。线下容器环境,压测(见xx)物理机环境,线上预览环境,分级线上环境,仿真环境(见xx)问题定位。见xx测试自动化故障注入 todo全链路压测。见xx流量回放。见xx运维涉及配置下发,资源隔离调度,上线,监控等。见xx运营灰度:见xx运营系统安全todo

May 7, 2019 · 1 min · jiezi

架构整洁之道二两个价值的故事

每个软件系统都提供两个价值给利益相关者:表现和结构。软件开发者应的确保这两个价值尽量高负责。然而很不幸,程序员很多只关心其中一个而忽略另一个,甚至更不幸,他们可能关注的不是这两个价值,留下没有价值的系统 表现软件的第一个价值是他的表现,程序员被雇佣来帮利益相关者让服务器来挣钱或省钱,实现这个的方式是依照功能规范或写需求文档,来写代码实现这些需求。当程序出问题时,程序员修bug。很多程序员相信这就是他们工作的全部,他们就是为了实现功能和修bug而工作,但这是错误的。 架构第二个价值必须和软件这个词一起处理--一个由soft和ware组成的复合词。ware意味着产品,soft就是第二价值--”架构“的所在的地方软件具有柔软的特性,他打算用一种简单的方法改变机器的行为。为了达到目的,软件必须柔软,能够很轻松地改变,当利益相关者想要改一个需求,改变就需要简单并且可以轻松实现,改需求的困难应该仅仅是改变的范围,不是改变的形态。范围和形态都能驱动软件开发成本上升,但是两者是不同的。这就是成本不随需求改变的比例上升的原因,这也是开发一年比一年更便宜的原因。来自利益相关者的观点,开发者仅仅只提供了一些形态上的粗略改变,来自开发者的观点,老板的需求越来越难。问题当然是系统的架构,架构不好,后面的需求将会越来越难适合现在的架构 更大的价值功能或架构,谁能提供更大的价值,谁在软件开发中更重要,或者谁在添加需求中更能轻松修改系统。如果你问业务经理,他们可能觉得功能更重要,轮流问开发者,很多人也赞同这观点,但是这是错误的,我能用一个极端的逻辑工具测试他是错的。如果你给我一个能运行,但不可能改变的系统,改需求就不能运行,这个系统将无用。如果给我一个不能运行,但能够轻松修改的系统,我可以让他适应需求,然后运行起来。这个系统就有用了你可能觉得这个例子不能让人信服,毕竟没有不能改变的项目,然而有些系统基本不可能改变,因为改变的成本超过了改变的好处。 为架构而战为了实现架构这一责任,我们需要加入战斗,我也许该用奋斗这个词。坦白地说,基本上都是这样说的。开发团队必须为能让公司发展最好的东西而奋斗。管理团队,市场团队,销售团队,运维团队也是如此。都要奋斗。有效率的开发团队迎面奋斗。记住,作为一个开发者,你就是利益相关者,你需要维护的软件里有你的利益。这是你任务的一部分,责任的一部分,也是为什么你被雇佣的主要原因如果你是架构师,这个挑战将会是双倍难度。架构的主要责任是系统的结构,,而不是开发功能,架构师创造一个允许快速开发,修改,扩展功能的架构。记住,如果架构来晚了,系统将变得更难维护,修改对于部分或者整个系统最终将变得不可能。如果上述情况发生,那说明软件开发团队没有为必要的东西付出足够的努力。

May 2, 2019 · 1 min · jiezi

基于腾讯云CVM自建高可用Redis实践

本文来源 | 云+社区专栏文章作者 | 万守兵,腾讯云资深架构师。8年以上大型互联网公司运维工作经验,腾讯云资深迁云架构师,一直从事大型互联网服务端架构设计和优化工作。个人专注于云计算、k8s和 DevOps领域。 导读:在企业实际生产环境中为了能够给业务上层应用提供高可靠、低延迟、低数据损失的Redis缓存服务,本文通过对目前主流的几种redis高可用方案进行对比分析,并基于腾讯云CVM和HAVIP等基础产品进行搭建、配置、测试、总结,供大家参考。 01环境说明 1.需求与目标 本文将通过对目前主流的几种redis高可用方案进行对比分析,并基于腾讯云CVM和HAVIP等基础产品进行搭建、配置、测试、总结。 2.软件版本 redis用3.2.8版本,keepalived用1.2.19版本。 3.基本环境 采用同一网络内的三台主机(可以是物理主机、虚拟机或docker容器),要求三台主机之间都能相互访问。我这里使用腾讯云上3台CVM,每台CVM上开启一个redis-server、redis-sentinel和keepalived服务,redis-server端口为6379,redis-sentinel的端口为26379(我这里用默认端口,生产环境中可以修改默认端口),3台CVM上都安装keepalived服务。 02几种redis高可用方案说明 1.一般的主从复制方案 由于redis目前只支持主从复制备份(不支持主主复制),当主redis挂了,从redis只能提供读服务,无法提供写服务。所以,还得想办法,当主redis挂了,让从redis升级成为主redis。 优点:(1)实现了对master数据的备份,一旦master出现故障,slave节点可以提升为新的master,顶替旧的master继续提供服务 (2)实现读扩展。使用主从复制架构, 一般都是为了实现读扩展。Master主要实现写功能, Slave实现读的功能 缺点:(1)一旦主节点宕机,从节点晋升成主节点,同时需要修改应用方的主节点地址,还需要命令所有从节点去复制新的主节点,整个过程需要人工干预,此时需要经过如下操作(假设提升Slave1为Master): 在Slave1上执slaveof no one命令提升Slave1为新的Master节点在Slave1上配置为可写,这是因为大多数情况下,都将slave配置只读告诉Client端(也就是连接Redis的程序)新的Master节点的连接地址配置Slave2从新的Master进行数据复制 (2)主节点的写能力受到单机的限制 (3)主节点的存储能力受到单机的限制 2.sentinel高可用方案 客户端程序(如PHP程序)连接redis时需要ip和port,但redis-server进行故障转移时,主redis是变化的,所以ip地址也是变化的。客户端程序如何感知当前主redis的ip地址和端口呢?redis-sentinel提供了接口,请求任何一个sentinel,发送SENTINEL get-master-addr-by-name <master name>就能得到当前主redis的ip和port。需要注意的是,Redis Sentinel 端口和 Redis 主节点均需要开放访问权限。如果前端业务使用 Java,有 JedisSentinelPool 可以复用;如果前端业务使用 PHP,可以在 phpredis 的基础上做二次封装。 优点:(1)redis sentinel带有自动故障转移功能(failover),当一个主redis不能提供服务时,redis sentinel可以将一个从redis升级为主redis,并对其他从redis进行配置,让它们使用新的主redis进行复制备份; (2)服务探测故障及时; (3)DBA 维护成本低。 缺点:(1)对应用有入侵性:客户端每次连接redis前,先向sentinel发送请求,获得主redis的ip和port,然后用返回的ip和port连接redis。每次操作redis至少需要发送两次连接请求,第一次请求sentinel,第二次请求redis; (2)Sentinel服务器和Redis节点需要开放访问权限。 3.redis-sentinel+VIP方案+自定义脚本方案 底层是Redis Sentinel 集群,代理着 Redis 主从,Web端通过VIP提供服务。在部署Redis主从的时候,需要将虚拟IP绑定到当前的Redis 节点。当主节点发生故障,比如机器故障、Redis节点故障或者网络不可达,Sentinel 集群会调用 client-reconfig-script 配置的脚本,将VIP漂移到新的主节点上。 比如:当前redis系统中主redis的ip地址是172.16.2.4,那么VIP(172.16.2.250)指向172.16.2.4,客户端程序用VIP(172.16.2.250)地址连接redis,实际上连接的就是当前主redis,这样就避免了向sentinel发送请求。 优点:(1)脚本自定义,架构可控; (2)对应用透明,当主redis宕机,进行故障转移时,192.168.56.102这台服务器上的redis提升为主,这时VIP(172.16.2.4)指向192.168.56.102,这样客户端程序不需要修改任何代码,连接的是192.168.56.102这台主redis; (3)秒级切换,在 5s 内完成整个切换操作. ...

April 30, 2019 · 4 min · jiezi

阿里开发者招聘节-面试题0607-MySQL的数据如何恢复到任意时间点

摘要: 阿里巴巴资深技术专家们结合多年的工作、面试经验总结提炼而成的笔试真题这一次将陆续放出(面试题答案将在专辑分享结束后统一汇总分享)。并通过这些笔试真题开放阿里巴巴工作机会,让更多的开发者加入到阿里这个大平台。为帮助开发者们提升面试技能、有机会入职阿里,云栖社区特别制作了这个专辑——阿里巴巴资深技术专家们结合多年的工作、面试经验总结提炼而成的面试真题这一次将陆续放出(面试题官方参考答案将在专辑结束后统一汇总分享,点此进入答题并围观他人答案)。并通过这些笔试真题开放阿里巴巴工作机会,让更多的开发者加入到阿里这个大平台。 这一次,不仅是知识的收获,还将间接地与技术大牛们做了直观的沟通,了解他们的出题思路与考察要点,并加以消化吸收,这对自己技术能力本身就是一种极大的提升。走上编程之路,不断丰富自己方能与世接轨,努力做最优秀的自己。 4月28日,我们给开发者的第6~7道面试题。 06. 从innodb的索引结构分析,为什么索引的key长度不能太长07. MySQL的数据如何恢复到任意时间点阿里巴巴出题专家:近秋 阿里云数据库产品技术部技术专家,有6年的行业从业经验。2016年加入阿里云,目前负责最流行的开源数据库MySQL在阿里云的商业化的工作。 招聘职位:阿里云数据库技术专家点击进入聚能聊答题,并围观大家的回答! 本文作者:山哥在这里阅读原文 本文为云栖社区原创内容,未经允许不得转载。

April 30, 2019 · 1 min · jiezi

35条建议让你对Java-代码性能优化彻底理解

代码优化,一个很重要的课题。可能有些人觉得没用,一些细小的地方有什么好修改的,改与不改对于代码的运行效率有什么影响呢?这个问题我是这么考虑的,就像大海里面的鲸鱼一样,它吃一条小虾米有用吗?没用,但是,吃的小虾米一多之后,鲸鱼就被喂饱了。 代码优化也是一样,如果项目着眼于尽快无BUG上线,那么此时可以抓大放小,代码的细节可以不精打细磨;但是如果有足够的时间开发、维护代码,这时候就必须考虑每个可以优化的细节了,一个一个细小的优化点累积起来,对于代码的运行效率绝对是有提升的。 代码优化的目标是 减小代码的体积提高代码运行的效率代码优化细节 1、尽量指定类、方法的final修饰符带有final修饰符的类是不可派生的。在Java核心API中,有许多应用final的例子,例如java.lang.String,整个类都是final的。为类指定final修饰符可以让类不可以被继承,为方法指定final修饰符可以让方法不可以被重写。如果指定了一个类为final,则该类所有的方法都是final的。Java编译器会寻找机会内联所有的final方法,内联对于提升Java运行效率作用重大,具体参见Java运行期优化。此举能够使性能平均提高50%。 2、尽量重用对象特别是String对象的使用,出现字符串连接时应该使用StringBuilder/StringBuffer代替。由于Java虚拟机不仅要花时间生成对象,以后可能还需要花时间对这些对象进行垃圾回收和处理,因此,生成过多的对象将会给程序的性能带来很大的影响。 3、尽可能使用局部变量调用方法时传递的参数以及在调用中创建的临时变量都保存在栈中速度较快,其他变量,如静态变量、实例变量等,都在堆中创建,速度较慢。另外,栈中创建的变量,随着方法的运行结束,这些内容就没了,不需要额外的垃圾回收。 4、及时关闭流Java编程过程中,进行数据库连接、I/O流操作时务必小心,在使用完毕后,及时关闭以释放资源。因为对这些大对象的操作会造成系统大的开销,稍有不慎,将会导致严重的后果。 5、尽量减少对变量的重复计算明确一个概念,对方法的调用,即使方法中只有一句语句,也是有消耗的,包括创建栈帧、调用方法时保护现场、调用方法完毕时恢复现场等。所以例如下面的操作: for (int i = 0; i < list.size(); i++){...}建议替换为: for (int i = 0, int length = list.size(); i < length; i++){...}这样,在list.size()很大的时候,就减少了很多的消耗 6、尽量采用懒加载的策略,即在需要的时候才创建例如: String str = "aaa";if (i == 1){list.add(str);}建议替换为: if (i == 1){String str = "aaa";list.add(str);}慎用异常 异常对性能不利。抛出异常首先要创建一个新的对象,Throwable接口的构造函数调用名为fillInStackTrace()的本地同步方法,fillInStackTrace()方法检查堆栈,收集调用跟踪信息。只要有异常被抛出,Java虚拟机就必须调整调用堆栈,因为在处理过程中创建了一个新的对象。异常只能用于错误处理,不应该用来控制程序流程。 8、不要在循环中使用try…catch…,应该把其放在最外层除非不得已。如果毫无理由地这么写了,只要你的领导资深一点、有强迫症一点,八成就要骂你为什么写出这种垃圾代码来了。 9、如果能估计到待添加的内容长度,为底层以数组方式实现的集合、工具类指定初始长度比如ArrayList、LinkedLlist、StringBuilder、StringBuffer、HashMap、HashSet等等,以StringBuilder为例: (1)StringBuilder() // 默认分配16个字符的空间(2)StringBuilder(int size) // 默认分配size个字符的空间(3)StringBuilder(String str) // 默认分配16个字符+str.length()个字符空间可以通过类(这里指的不仅仅是上面的StringBuilder)的来设定它的初始化容量,这样可以明显地提升性能。比如StringBuilder吧,length表示当前的StringBuilder能保持的字符数量。因为当StringBuilder达到最大容量的时候,它会将自身容量增加到当前的2倍再加2,无论何时只要StringBuilder达到它的最大容量,它就不得不创建一个新的字符数组然后将旧的字符数组内容拷贝到新字符数组中—-这是十分耗费性能的一个操作。试想,如果能预估到字符数组中大概要存放5000个字符而不指定长度,最接近5000的2次幂是4096,每次扩容加的2不管,那么: (1)在4096 的基础上,再申请8194个大小的字符数组,加起来相当于一次申请了12290个大小的字符数组,如果一开始能指定5000个大小的字符数组,就节省了一倍以上的空间; (2)把原来的4096个字符拷贝到新的的字符数组中去。 这样,既浪费内存空间又降低代码运行效率。所以,给底层以数组实现的集合、工具类设置一个合理的初始化容量是错不了的,这会带来立竿见影的效果。但是,注意,像HashMap这种是以数组+链表实现的集合,别把初始大小和你估计的大小设置得一样,因为一个table上只连接一个对象的可能性几乎为0。初始大小建议设置为2的N次幂,如果能估计到有2000个元素,设置成new HashMap(128)、new HashMap(256)都可以。 10、当复制大量数据时,使用System.arraycopy()命令11、乘法和除法使用移位操作例如: for (val = 0; val < 100000; val += 5){a = val * 8;b = val / 2;}用移位操作可以极大地提高性能,因为在计算机底层,对位的操作是最方便、最快的,因此建议修改为: ...

April 29, 2019 · 3 min · jiezi

阿里开发者招聘节-面试题05-关于epoll和select的区别哪些说法是正确的

摘要: 阿里巴巴资深技术专家们结合多年的工作、面试经验总结提炼而成的笔试真题这一次将陆续放出(面试题答案将在专辑分享结束后统一汇总分享)。并通过这些笔试真题开放阿里巴巴工作机会,让更多的开发者加入到阿里这个大平台。为帮助开发者们提升面试技能、有机会入职阿里,云栖社区特别制作了这个专辑——阿里巴巴资深技术专家们结合多年的工作、面试经验总结提炼而成的面试真题这一次将陆续放出(面试题官方参考答案将在专辑结束后统一汇总分享,点此进入答题并围观他人答案)。并通过这些笔试真题开放阿里巴巴工作机会,让更多的开发者加入到阿里这个大平台。 这一次,不仅是知识的收获,还将间接地与技术大牛们做了直观的沟通,了解他们的出题思路与考察要点,并加以消化吸收,这对自己技术能力本身就是一种极大的提升。走上编程之路,不断丰富自己方能与世接轨,努力做最优秀的自己。 4月26日,我们给开发者的第5道面试题。 关于epoll和select的区别,哪些说法是正确的?(多选)A. epoll和select都是I/O多路复用的技术,都可以实现同时监听多个I/O事件的状态
B. epoll相比select效率更高,主要是基于其操作系统支持的I/O事件通知机制,而select是基于轮询机制
C. epoll支持水平触发和边沿触发两种模式
D. select能并行支持I/O比较小,且无法修改 阿里巴巴出题专家:寈峰 阿里技术专家,阿里巴巴百年技术大学讲师,Apache RocketMQ Committer,Linux OpenMessaging Advisory Board Member,具有多年分布式消息系统等中间件架构设计及研发经验,对云计算及分布式系统架构有深刻理解。目前负责Apache RocketMQ的研发及社区生态。 招聘职位:阿里云中间件技术专家 本文作者:山哥在这里阅读原文 本文为云栖社区原创内容,未经允许不得转载。

April 28, 2019 · 1 min · jiezi

云原生的新思考为什么容器已经无处不在了

4月24日,中国信息通信研究院主办的首届云原生产业大会在北京举行,在《云原生数字引领未来》的主题演讲中,阿里云容器服务总监易立表示:“云原生不但可以很好的支持互联网应用,也在深刻影响着新的计算架构、新的智能数据应用。以容器、服务网格、微服务、Serverless为代表的云原生技术,带来一种全新的方式来构建应用。”本文根据易立演讲内容整理而成。 拥抱云原生技术,解耦系统复杂度如今,大多数企业开始全面拥抱云计算,在All-in-Cloud全面到来的时代,三个重要转变:基础设施的云化、核心技术的互联网化、业务的数据化和智能化。在各行各业中,都有很多业务应用从诞生之初就生长在云端,各个企业也因此越来越像互联网公司,而技术能力被视为不可或缺的核心竞争力。在2019阿里云峰会·北京站上,阿里云智能总裁张建锋在谈及‘核心技术的互联网化’时,也提到了大力投资云原生。 为什么要拥抱云原生?一方面,云计算已经重塑了软件的整个生命周期,从架构设计到开发,再到构建、交付和运维等所有环节;另一方面,企业IT架构也随之发生巨大变化,而业务又深度依赖IT能力。这带来了一定程度的复杂性和挑战性。 正如人类社会发展伴随着技术革命与社会大分工一样,云原生技术的出现解耦了很多复杂性,这是IT技术的进步。 首先,Docker实现了应用与运行环境的解耦,众多业务应用负载都可以被容器化,而且应用容器化满足了敏捷、可迁移、标准化的诉求;其次,Kubernetes的出现让资源编排调度与底层基础设施解耦,应用和资源的管控也开始得心应手,容器编排实现资源编排、高效调度;随后,Istio为代表的服务网格技术解耦了服务实现与服务治理能力。此外,阿里云还提供了Open API、SDK等丰富的开发工具,实现第三方被集成,为云的生态伙伴提供广阔的可能性。这样的技术分层推动了社会分工,极大促进了技术和业务创新。 在阿里云看来,云原生首先可以支持互联网规模应用,可以更加快速地创新、和低成本试错;其次,屏蔽了底层基础架构的差异和复杂性;同时,服务网格、无服务计算等新的计算范型的不断涌现,给整体IT架构能力带来了极致弹性,从而更好地服务于业务。用户可以基于阿里云容器服务构建面向领域的云原生框架,如面向机器学习的Kubeflow,和面向无服务器的Knative等等。 方兴未艾,容器应用的新思考容器已经无处不在了, 作为容器服务的提供者,我们认为容器技术会继续发展,被应用于“新的计算形态”,“新的应用负载”和“新的物理边界”,在此将相关观察和新思考分享给大家。 1 新的计算形态:云原生的Serverless Runtime已来 云原生技术理念,是使企业用户及开发者只关注应用开发,无需关注基础设施及基础服务。与之相似的Serverless计算,将应用服务资源化并以API接口的方式提供出来,使用者只需从客户端发起调用请求即可,更重要的是,pay as you go 能够真正为用户节省成本。 Serverless Runtime 分为面向基础架构容器的实现,面向应用服务封装的实现,和事件驱动面向函数计算的实现。 云原生Serverless Runtime形态包含多种方式。业界各个厂商也相应地设计出了不同服务解决方案: 面向函数的Function as a Service(FaaS) - 比如AWS Lambda,阿里云的函数计算,提供了事件驱动的编程方式,用户只需提供函数实现响应触发实践,开发效率很高。阿里云函数计算按照调用量计费,可以根据业务流量平滑调整计算资源,在典型场景下,会有10%~90%的成本下降。客户码隆科技做模型预测,利用函数计算降低了40%的计算成本。面向应用 - 比如Google App Engine、新发布的Cloud Run和阿里云EDAS Serverless,用户只需提供应用实现而平台负责应用弹性、自动化运维,这主要面向互联网类型应用。相比于FaaS,面向应用的Serverless形态无需改造现有应用,阿里云EDAS Serverless为流行的开源微服务框架提供了无服务器应用托管平台,支持Spring Cloud,Apache Dubbo,或者阿里云HSF框架。面向容器 – 比如AWS fargate,或者是阿里云的Serverless Kubernetes 应用的载体是容器镜像,灵活性很好,配合调度系统可以支持各种类型应用,而无需管理底层基础架构。针对容器化应用,阿里云在去年5月推出了Serverless Kubernetes容器服务,无需节点管理和容量规划,按应用所需资源付费,弹性扩容。针对阿里云基础能力优化,安全,高效。极大降低了管理Kubernetes集群的。Serverless Kubernetes的底层是构建在阿里云针对容器优化的轻量虚拟化弹性容器实例之上,提供了轻量、高效、安全的容器应用执行环境。Serverless Kubernetes无需修改即可部署容器类型应用。 2 新的应用负载:容器正被用于越来越多类型应用 最早容器被认为不适合传统的已有应用,但是现在状况已大为改观。容器已经开启了对Windows生态的支持,新发布的1.14版本中Kubernetes 的Pod,Service,应用编排,CNI 网络等绝大多数核心能力都已经在 Windows 节点上得到了支持。当今Windows系统依然占有60%的份额,比如企业的ERP软件、基于ASP的应用、大量的Windows的数据库等,这些传统的基于虚拟化的应用,都可以在代码不用重写的情况下实现容器化。 基于容器技术构建的新架构,会催生新的应用业务价值。云原生AI是非常重要的应用场景,快速搭建AI环境,高效利用底层资源,无缝配合深度学习的全生命周期。对于AI工程,云原生系统可以在四个维度上为提效: 优化异构资源调度弹性、高效、细粒度(支持GPU共享)简化异构资源管理复杂性,提升可观测性和使用效率可移植、可组装、可重现的AI流程以深度学习分布式训练为例,通过阿里云容器服务可以获得三重加强。资源优化:统一调度CPU/GPU等异构资源,使用VPC/RDMA网络加速;性能提升:GPU 64卡P100,加速比提升90%,相比原生Tensorflow有45%提升;算法优化:MPI代替gRPC通信、ring-allreduce环形通信、计算和通信重叠、梯度融合等。 还有其他高性能计算的场景,以基因数据处理为例,阿里云某用户在5小时内完成WGS 100GB数据处理,支持5000+步骤的复杂流程, 90秒实现500节点扩容充分发挥容器极致弹性。 3 新的物理边界:云-边-端,容器不止运行在IDC服务器中 容器最被熟知的基础环境是数据中心,在业务流量高峰与低谷之时,凭借容器极致弹性可以实现应用与资源伸缩,有效地保证高利用率与高性价比。 随着5G和物联网时代的到来,传统云计算中心集中存储、计算的模式已经无法满足终端设备对于时效、容量、算力的需求。将云计算的能力下沉到边缘侧、设备侧,并通过中心进行统一交付、运维、管控,将是云计算的重要发展趋势。以Kubernetes为基础的云原生技术,在任何基础设施上提供与云一致的功能和体验,实现云-边-端一体化的应用分发, 支持不同系统架构和网络状况下,应用的分发和生命周期管理,并且针对边缘及设备进行如访问协议、同步机制、安全机制的种种优化。 如前所述,应用容器化实现了标准化的可移植性,促成了敏捷弹性的云原生应用架构。不仅大大简化了多云/混合云的部署,而且优化成本,同时提供更多的选择,比如满足安全合规的要求、提升业务敏捷性、提升地域覆盖性等等。 容器可以适用于多种基础环境,比如数据中心、边缘云、和多云/混合云,使得开发者关注回归到应用本身。 写在最后云原生时代,是开发者最好的时代。 云原生不但可以很好的支持互联网应用,也在深刻影响着新的计算架构、新的智能数据应用。以容器、服务网格、微服务、Serverless为代表的云原生技术,带来一种全新的方式来构建应用。此外,云原生也在拓展云计算的边界,一方面是多云、混合云推动无边界云计算,一方面云边端的协同。 ...

April 26, 2019 · 1 min · jiezi

阿里开发者招聘节-面试题01如何实现一个高效的单向链表逆序输出

摘要: 阿里巴巴资深技术专家们结合多年的工作、面试经验总结提炼而成的笔试真题这一次将陆续放出(面试题答案将在专辑分享结束后统一汇总分享)。并通过这些笔试真题开放阿里巴巴工作机会,让更多的开发者加入到阿里这个大平台。面试,如同玩一场饥饿游戏:既要对环境了然于胸,又要对自身心知肚明。发现一个好工作不容易,但成功应聘又会面临一系列的挑战。 为帮助开发者们提升面试技能、有机会入职阿里,云栖社区特别制作了这个专辑——阿里巴巴资深技术专家们结合多年的工作、面试经验总结提炼而成的面试真题这一次将陆续放出(面试题官方参考答案将在专辑结束后统一汇总分享,点此进入答题并围观他人答案)。并通过这些笔试真题开放阿里巴巴工作机会,让更多的开发者加入到阿里这个大平台。 这一次,不仅是知识的收获,还将间接地与技术大牛们做了直观的沟通,了解他们的出题思路与考察要点,并加以消化吸收,这对自己技术能力本身就是一种极大的提升。走上编程之路,不断丰富自己方能与世接轨,努力做最优秀的自己。 4月24日,我们给开发者的第1道面试题。 如何实现一个高效的单向链表逆序输出?阿里巴巴出题专家:游亮 阿里云弹性人工智能负责人
,带领团队研发了同时支持Tensorflow、MXNET、PyTorch、Caffe的Perseus加速框架,曾获得Dawnbench推理世界竞赛的性能第一和成本最低双料冠军。曾任阿里云弹性高性能计算、超级计算集群技术架构师,获得过多项专利,拥有10年以上AI技术研发和高性能优化经验。精通针对CPU、GPU、MIC等微架构的计算性能优化以及网络、存储等系统性能优化。曾在英特尔SSG部门工作,并获得过英特尔中国最高成就奖(ICA)。
当人工智能遇上云计算,未来不可限量,欢迎加入阿里云弹性人工智能团队。 招聘职位:阿里云-GPU虚拟化研发高级专家 点击进入聚能聊答题,并围观大家的回答! 更多面试真题陆续放出,敬请期待! 本文作者:山哥在这里阅读原文 本文为云栖社区原创内容,未经允许不得转载。

April 25, 2019 · 1 min · jiezi

阿里云POLARDB如何助力轻松筹打造5亿用户信赖的大病筹款平台

轻松筹首创了“大病救助”模式,帮助了众多病患在第一时间解決了医疗资金等问题,为了从源头解决了医疗资金问题。而在轻松筹这样全球5.5亿用户信赖的大病筹款平台的背后,是日益增长的各种数据。面对这样数据量所造成的巨大挑战,阿里云POLARDB是如何帮助轻松筹践行“善DNA”的呢?本文就为大家分享。 关于轻松筹2014年9月,轻松筹成立。“轻松筹”作为公司旗下的首要产品,“善DNA”可谓贯穿了整个发展历程。轻松筹将目标聚焦在公众健康保障领域,各功能板块都与百姓的健康息息相关。由轻松筹首创的“大病救助”模式帮助众多病患在第一时间解決了医疗资金等问题。 为了从源头解决医疗资金问题,轻松筹于2016年4月推出了“轻松互助”业务,其目的在于抱团抵抗大病风险,一人患病,众人均推救助金。并与多家保险公司达成合作,推出多款会员定制的保险产品,至此,轻松筹“全民健康保障体系”正式建成。 目前,轻松筹在自主研发的“区块链”技术的加持下,再一次开创了行业先河。“阳光链”将大病救助、公益机构及互助行动的捐赠记录、资金流向公开透明,为公益事业及大病救助的发展指明了新方向。历时4年,轻松筹体系(包含大病救助、轻松互助、轻松e保、轻松公益、轻松健康)在全球183个国家和地区的用户总数超过5.5亿、筹款总额超过255亿元。 轻松筹的“大病救助”场景由轻松筹首创的“大病救助”模式,通过社交强关系为大病患者提供高效便捷的筹款渠道,目前已经帮助235万个大病家庭,筹集了255亿元善款。 轻松筹大病救助平台能够为多达千万的用户提供筹款服务,每周增加的相关数据量多达10GB,包括发起筹款的项目信息、用户分享信息、订单数据等,不断增加的数据,很容易在目前的RDS数据库上,达到存储的上限。轻松筹通过将数据迁移至阿里云POLARDB,很好的解决了存储容量和性能的瓶颈。 轻松筹基于阿里云POLARDB的简单架构设计轻松筹最为看重就是阿里云POLARDB存储容量大和免分库分表的特性。因为阿里云POLARDB采用了集群架构,并且采用了计算和存储分离以及读写分离的机制,所以其存储容量最高能够支持100TB,用户无需因为单机容量的天花板而去购买多个MySQL实例做分片,并且也不需要考虑分库分表,因此就简化应用的开发,同时也降低了运维的负担。 其次,轻松筹还看中了POLARDB强大的读写分离能力。当应用程序使用集群地址时,POLARDB通过内部的代理层对外提供服务,应用程序的请求都先经过代理,然后才访问到数据库节点。Proxy不仅可以做安全认证和保护,还可以解析SQL,把写操作发送到主节点,把读操作均衡地分发到多个只读节点,实现自动的读写分离。对于轻松筹的小程序而言,在后台使用POLARDB集群就像使用一个单点的MySQL数据库一样简单。 此外,在性能方面,阿里云POLARDB利用基于Redo的物理复制代替基于Binlog的逻辑复制,提升主备复制的效率和稳定性,即使对大表进行加索引、加字段等DDL操作,也不会造成数据库的延迟,能够实现毫秒级延迟。此外,POLARDB内置并行查询引擎,对执行时长超过1分钟的复杂分析类SQL加速效果明显。这样的性能优势能够很好地满足轻松筹的需求。 POLARDB助力“大病救助”平台数据管理效率提升 在阿里云POLARDB的强大能力的基础之上,轻松筹的“大病救助”平台的数据管理效率有了非常大的提升,其主要体现在以下三个方面: 自适应数据增长 轻松筹的大病筹款项目随着时间的累积,每年以上T以上的结构化数据进行新增进行存储。每年新增数据表达到数百个,单表数据量更是达到亿级别。由于POLARDB采用分布式存储服务,能够根据数据增长自适应增加存储空间,按照实际数据使用量进行计费,不必为数据容量的限制和升级所担忧。 724 高可用服务 阿里云POLARDB采用自带读写分离的Active-Active多活高可用集群架构 ,能够更好的监测故障和进行快速故障自动恢复,确保99.95%的高可用服务的同时,集群自带只读节点,使得系统的聚合读取性能成倍提升。 即时数据检索和查询 大病筹款的数据需要周期性批量写入到POLARDB,而同时又需要支持即时的检索查询和分析处理,POLARDB的读写分离架构,很好的支撑了这类场景。同时,POLARDB还能够在几分钟以内在线增加只读节点,进一步提升系统的吞吐处理能力,结合读写分离连接地址,自动进行请求的识别转发,通过自适应负载均衡处理,让集群的计算力能够发挥到最大,消除了计算瓶颈。 本文作者:桐碧2018阅读原文 本文为云栖社区原创内容,未经允许不得转载。

April 24, 2019 · 1 min · jiezi

阿里云首次在ASPLOS19发布重磅论文揭秘帮助ECS快速迭代的热升级技术

摘要: 阿里云首次在ASPLOS上发表论文,第24届ACM编程语言和操作系统(ASPLOS'19),于2019年4月13日至17日,在普罗维登斯召开,阿里云高级技术专家郑晓代表团队在会上发表了技术报告。第24届ACM编程语言和操作系统(ASPLOS'19),于2019年4月13日至17日,在普罗维登斯召开,阿里云高级技术专家郑晓代表团队在会上发表了技术报告。 论文主题为《Fast and Scalable VMM Live Upgrade in Large Cloud Infrastructure》,作者是张献涛,郑晓,沈益斌等。这篇论文被计算机系统结构的顶级会议ASPLOS'19接受,是业界对于VMM热升级这项突破性技术的认可。 论文ACM下载地址:https://dl.acm.org/citation.cfm?id=3304034PDF下载地址:https://yq.aliyun.com/download/3532 该论文系统的阐述了当前云计算领域面临的基础架构带业务热升级问题。提出了一种新型的,比热迁移更行之有效的方法,特别适合超大规模集群范围的使用,解决了困扰云计算行业多年的问题。该方案在阿里云大规模采用,服务百万级别的客户虚拟机数量。论文解决了在客户业务不中断的情况下以毫秒级的速度更换底层虚拟化组件。 阿里云热升级技术特点决定了可以同时热升级任意数量任意规格的虚拟机,并且升级时间恒定。更难得的是,在业界尚未有异构计算设备热迁移方案的情况下,阿里云热升级技术同时支持异构计算等以设备直通方式工作的虚拟机。帮助ECS在过去五年进行了快速的升级迭代,保障了产品和业务的快速奔跑。 ASPLOS(编程语言和操作系统的体系结构支持会议)会议全称为ACM International Conference on Architectural Support for Programming Languages and Operating Systems,是综合体系结构、编程语言和操作系统三个方向的计算机系统领域顶级会议,为CCF A类会议。从1982年创办至今的三十多年里,ASPLOS推动了多项计算机系统技术的发展,包括(但不限于)RISC、RAID、大规模多处理器、Cluster架构和网络存储等。 本文作者:阿里云头条阅读原文 本文为云栖社区原创内容,未经允许不得转载。

April 23, 2019 · 1 min · jiezi

3分钟干货之微服务架构的局限性

虽然微服务是降低整体结构的最佳方式。然而,它有其自身的一些缺点。但在得出任何结论之前,让我们来看看其中的一些。1.开发环境超载随着应用程序及其数据库的增长,代码库也在不断扩展。随着针对每个微服务的代码扩展,它会使每个加载的应用程序的开发环境过载。这可能导致生产力的重大延迟。 DevOps复杂性单功能微服务的开发和部署并非易事。使用多种技术并创建API来集中系统是一项挑战。这需要一个经验丰富的DevOps团队。采购这样一个经验丰富的DevOps团队对于维护基于微服务的应用程序的复杂性至关重要。3.增加资源和网络使用由于多个组件协同工作,因此在某种程度上彼此进行通信非常重要。此通信将导致网络使用量增加。这需要高速可靠的网络连接。此外,运行这些应用程序的费用也会增加。所有服务都单独运行,增加了运营成本。4.测试测试应用程序可能具有挑战性,因为有单独的组件。与单片应用程序相比,微服务需要更长的时间进行测试,并且在出现任何错误时更加复杂。有时,由于测试最终会影响整个应用程序,可能会导致延迟。5.安全在Web应用程序方面,安全性至关重要。使用微服务,实现这一点很困难。当存在独立模块的集群时,每个模块都需要遵守为整个系统定义的认证和授权规范。除此之外,每个模块可能与其他模块通信,跟踪数据流变得非常困难。需要其他措施,例如具有负载平衡的API网关,以确保行为一致。这些额外的步骤导致每个微服务的开销。6.应用程序的复杂性由于微服务是独立组件,因此每个微服务通常都有一个最适合其需求的技术堆栈。例如,机器学习模块可能使用python堆栈,而计量服务可能使用Java堆栈,UI服务可能使用MEAN堆栈。这会导致复杂性,因为资源池和管理和构建新功能所需的技能将非常高。7.高初始投资微服务独立运行,它们需要独立的容器或资源来运行它们。每个项目可能有很多微服务一起工作,需要更高的投资来设置包括微服务,安全容器,负载平衡器,API网关等的所有集群。

April 22, 2019 · 1 min · jiezi

RPC框架是啥?

本博客 猫叔的博客,转载请申明出处在我刚刚了解分布式的时候,经常对RPC和分布式有些混淆,甚至一直以为两者对等,所以我们先看看他们有什么区别?RPC实现了服务消费调用方Client与服务提供实现方Server之间的点对点调用流程,即包括了stub、通信、数据的序列化/反序列化。且Client与Server一般采用直连的调用方式。而分布式服务框架,除了包括RPC的特性,还包括多台Server提供服务的负载均衡、策略及实现,服务的注册、发布与引入,以及服务的高可用策略、服务治理等等。那么RPC是什么呢?百度百科是这样表示的:RPC(Remote Procedure Call)—远程过程调用,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议。RPC协议假定某些传输协议的存在,如TCP或UDP,为通信程序之间携带信息数据。在OSI网络通信模型中,RPC跨越了传输层和应用层。RPC使得开发包括网络分布式多程序在内的应用程序更加容易。它甚至给出了工作原理,这一点很惊喜。1.调用客户端句柄;执行传送参数2.调用本地系统内核发送网络消息3.消息传送到远程主机4.服务器句柄得到消息并取得参数5.执行远程过程6.执行的过程将结果返回服务器句柄7.服务器句柄返回结果,调用远程系统内核8.消息传回本地主机9.客户句柄由内核接收消息10.客户接收句柄返回的数据我喜欢搜查更多的信息资料,所以我又找到了知乎上的回答。知乎1.7k的点赞,应该还是可以参考的。恰如回答提到的,RPC是指远程过程调用,也就是说两台服务器A,B,一个应用部署在A服务器上,想要调用B服务器上应用提供的函数/方法,由于不在一个内存空间,不能直接调用,需要通过网络来表达调用的语义和传达调用的数据。至于为什么使用RPC?答主也提到,无法在一个进程内,甚至一个计算机内通过本地调用的方式完成的需求,比如不同系统间的通讯,甚至不同组织间的通讯。这里再说一下关于Netty,Netty框架不局限于RPC,更多的是作为一种网络协议的实现框架,比如HTTP,由于RPC需要高效的网络通信,就可以选择Netty作为基础。除了网络通信,RPC还需要有高效的序列化框架,以及一种寻址方式,如果是带会话(状态)的RPC调用,还需要有会话的状态保持的功能。好了,让我们再来整理一下,什么是RPC?RPC(远程过程调用)一般用来实现部署在不同机器上的系统之间的方法调用,使得程序能够像访问本地系统资源一样,通过网络传输去访问远端系统资源。一般来说,RPC框架实现的架构原理都是类似的。可以这样说,客户端调用:负责发起RPC调用,为调用方用户提供使用API。服务端响应:主要是服务端业务逻辑实现。序列化/反序列化:负责对RPC调用通过网络传输的内容进行序列化与反序列化,不同的RPC框架有不同的实现机制。一般分为文本(XML、JSON)与二进制(Java原生的、Hessian、protobuf、Thrift、Avro、Kryo、MessagePack),需要注意的是,不同的序列化方式在可读性、码流大小、支持的数据类型及性能等方面都存在较大差异,我们可以根据需要自行选择。Stub:我们看成代理对象,它会屏蔽RPC调用过程中的复杂的网络处理逻辑,使其透明简单,且能够保持与本地调用一样的代码风格。通信传输:即RPC的底层通信传输模块,一般通过Socket在客户端与服务端之间传递请求与应答消息。公众号:Java猫说学习交流群:728698035现架构设计(码农)兼创业技术顾问,不羁平庸,热爱开源,杂谈程序人生与不定期干货。

April 20, 2019 · 1 min · jiezi

好书共读 | 国内外互联网技术大牛们都写了哪些书籍?

出自 GitHub 开源组织 Doocs源地址:https://github.com/doocs/tech…后面将会在 GitHub 陆续更新书籍清单,有兴趣的朋友可以一起来维护。书籍是人们获取知识的主要途径。然而,如今的社会太浮躁,不少人不愿意花时间静下心来仔细读书,很多开发人员也是如此。殊不知,书籍沉淀了前人的经验和思考。本项目主要收集国内外各大互联网公司技术大牛们出版的值得一看的书籍,欢迎推荐书籍、完善内容和排版。如果你有比较好的 idea,也欢迎在 issues 上交流。注意,本项目所有书籍资源仅供交流和学习使用,请勿商用。若喜欢且有条件,请购买正版书籍,以便更好地支持原书作者。Common#TitleAuthor(s)AbstractResource1编码:隐匿在计算机软硬件背后的语言[美]Charles Petzold 著左飞 薛佟佟 译讲述计算机工作原理,却并不晦涩难懂。不管你是计算机高手,还是对这个神奇的机器充满敬畏之心的菜鸟,读一读大师的经典作品,必然有所收获。1f7s2码农翻身:用故事给技术加点料刘欣用故事方式讲述软件编程的若干重要领域,侧重于基础性、原理性的知识。2d9sBackend#TitleAuthor(s)AbstractResource1Effective Java 原书第 3 版[美]Joshua Bloch 著俞黎敏 译Java 经典书籍,内容涵盖 Java 9 及以下版本。w2f22码出高效:Java 开发手册杨冠宝(花名:孤尽)高海慧(花名:鸣莎)结合阿里巴巴实践经验与故障案例,与 Java 底层源码解析融会贯通。9yyp3互联网轻量级SSM框架解密:Spring、Spring MVC、MyBatis源码深度剖析李艳鹏 等SSM 框架源码深度剖析。39i14Java 8 In Action 中文版[英]Raoul-Gabriel Urma [意]Mario Fusco [英]Alan Mycroft 著陆明刚 劳佳 译全面介绍 Java8 这个里程碑版本的新特性,包括 Lambdas、流和函数式编程6063Database#TitleAuthor(s)AbstractResource1Redis 设计与实现黄健宏基于 Redis 3.0,内容通俗易懂,可以深入了解 Redis 底层。q2ky2高性能 MySQL 第三版[美] Baron Schwartz 等著 宁海元 等译MySQL 领域极佳之作。0ijqFrontend#TitleAuthor(s)AbstractResourceArchitecture#TitleAuthor(s)AbstractResource1企业 IT 架构转型之道:阿里巴巴中台战略思想与架构实战钟华(花名:古谦)分享阿里巴巴建设共享服务体系的经验和实践。euzo2大型网站系统与 Java 中间件实践曾宪杰(花名:华黎)围绕大型网站和支撑大型网站架构的 Java 中间件的实践展开介绍。hrkh3大型网站技术架构:核心原理与案例分析李智慧梳理大型网站技术发展历程,剖析大型网站技术架构模式,深入讲述大型互联网架构设计的核心原理。8epr4亿级流量网站架构核心技术:跟开涛学搭建高可用高并发系统张开涛总结并梳理了亿级流量网站高可用和高并发原则,通过实例详细介绍了如何落地这些原则。2v7a5逆流而上:阿里巴巴技术成长之路阿里巴巴集团成长集编委会总结阿里巴巴技术团队在基础架构、中间件、数据库、业务开发等领域的经典实践以及对未来的思考。coi5Big Data#TitleAuthor(s)AbstractResource1HBase 不睡觉书杨曦一本让读者看了不会睡着的 HBase 技术书。sjcw

April 19, 2019 · 1 min · jiezi

总要先爬出坑的JEE架构

本博客 猫叔的博客,转载请申明出处先来看看官网对它的定义。Java平台企业版(Java EE)是社区驱动的企业软件的标准。Java EE是使用Java Community Process开发的,其中包括来自行业专家,商业和开源组织,Java用户组以及无数个人的贡献。每个版本都集成了符合行业需求的新功能,提高了应用程序的可移植性并提高了开发人员的工作效率 如今,Java EE的提供了丰富的企业软件平台,并与超过 20个兼容的Java EE实现可供选择。Java EE 8,你值得了解,起码官网还提示了你它还在更新新的功能。说到JEE,做web项目的朋友其实都有所了解,它将企业级软件架构分为三个层级,web层、业务逻辑层和数据存储层。先看看图,旧时代的辉煌!先介绍一下:WEB容器:给处于其中的应用程序组件(JSP,SERVLET)提供一个环境,使JSP,SERVLET直接跟容器中的环境变量接口交互,不必关注其它系统问题。主要由WEB服务器来实现。例如:TOMCAT,WEBLOGIC,WEBSPHERE等。该容器提供的接口严格遵守J2EE规范中的WEB APPLICATION 标准。我们把遵守以上标准的WEB服务器就叫做J2EE中的WEB容器。同时,JEE 平台将不同的模块化组件聚合后运行在通用的应用服务器上,例WebLogi,WebSphere , JBoss 等,这也包含 Tomcat Tomcat 仅仅是实现了 JEE Web 规范的 Web 容器。EJB容器:Enterprise java bean 容器。更具有行业领域特色。他提供给运行在其中的组件EJB各种管理功能。只要满足J2EE规范的EJB放入该容器,马上就会被容器进行高效率的管理。并且可以通过现成的接口来获得系统级别的服务。例如邮件服务、事务管理。WEB容器和EJB容器在原理上是大体相同的,更多的区别是被隔离的外界环境。WEB容器更多的是跟基于HTTP的请求打交道。而EJB容器不是。它是更多的跟数据库、其它服务打交道。但他们都是把与外界的交互实现从而减轻应用程序的负担。例如SERVLET不用关心HTTP的细节,直接引用环境变量session,request,response就行、EJB不用关心数据库连接速度、各种事务控制,直接由容器来完成。可以看到每个层次的职责如下:Web层:负责与用户交互或者对外提供接口业务逻辑层:为了实现业务逻辑而设计的流程处理和计算处理模块数据存取层:将业务逻辑层处理的结果持久化以待后续查询,并维护领域模型中对象的生命周期。值得一提的是,JEE平台是典型的二八原则的应用场景,它将 80%通用的与业务无关的逻辑和流程封装在应用服务器的模块化组件里,通过配置的模式提供给应用程序访问,应用程序实现 20%专用逻辑,并通过配置的形式来访问应用服务器提供的模块化组件。事实上,应用服务器提供的对象关系映射服务、数据持久服务、事务服务、安全服务、消息服务等通过简单的配置即可在应用程序中使用。JEE 时代的架构已经对企业级应用的整体架构进行了逻辑分层,包括上面提到的 Web 层、业务逻 和数据存取层,分别对应上图中的 Web 容器、 JB 容器和数据存取 ORM 组件与数据持久层 (数据库) 不同的层级有自己的职责,并从功能类型上划分层级,每个层级的职责单一。在分层架构下需要对项目管理过程中的团队进行职责划分,井建立团队交流机制。根据康威定律,设计系统的组织时,最终产生的设计等价于组织的沟通结构 ,通俗来讲,团队的交流机制应该与架构分层交互机制相对应。由于在架构上把整体的单体系统分成具有不同职责的层级,对应的项目管理倾向于把大的团队分成不同的职能团队,主要包括:用户 交互 UI 团队、后台业务逻辑处理团队、 数据存取 ORM 团队与 DBA 团队等,每个团队只对自己的职责负责,并对使用方提供组件服务质量保证。让我们在看看另一个经典,职能团队划分。JEE通过对单体架构的分层,结合职能划分,开始通过架构在一定程度上进行逻辑拆分,让各个专业的人能更加高效的做他们应该做的事情。但是,每个层次的多个业务逻辑的实现会被放在同一应用项目中,并且运行在同一个服务器上。尽管大多数公司会使用规范来约束不同业务逻辑的隔离性来解祸,但是久而久之,随着复杂业务逻辑的选代增加及开发人员的不断流动,新的程序员为了节省时间和赶进度,非法使用了其他组件的服务,业务组件之间、 组件之间、数据存取之间的稿合性必然增加,最后导致组件与组件之间难以划清界限,完全祸合在一起,将来的新功能迭代、增加和维护将难上加难。(反正你如果是入职接手一个老项目,那你一般都会很头疼)就当时而言,尽管 JEE 支持 Web容器和 EJB 容器的分离部署,大多数项目仍然部署在同 个应用服务器上井跑在一JVM 进程中。说说你和JEE的那些事吧!公众号:Java猫说学习交流群:728698035现架构设计(码农)兼创业技术顾问,不羁平庸,热爱开源,杂谈程序人生与不定期干货。

April 19, 2019 · 1 min · jiezi

基于Tablestore管理海量快递轨迹数据架构实现

快递轨迹管理对于一个快递公司,在全国范围内有着大量的快递点、快递员、运输车辆以及仓储中心。而快递自产生后,就会在这些地点、人物之间流转。因而,一套完善的快递管理追踪系统是快递公司的重要管理工具;用户通过平台客户端下单后,产生唯一的快递单号作为唯一身份标识。快递除了订单号,还会有很多属性信息,如:邮寄人、邮寄人手机、邮寄人地址、收件人、快递类型等信息。生成快递订单后,用户的邮寄物品才会成为“快递”。快递公司配合扫码机器,将快递的流转事件、地点、时间等信息不定期推送至系统。快递流转信息不仅可以是简单的量化数据,也可以是描述性文字、地理位置等特殊信息。系统将流转信息记录成快递的监控数据,同时修改快递状态、实时位置等。直至快递送达收件人手中,结束快递生命周期。通过系统,用户可以管理自己的历史邮寄单列表、收件列表,掌握自己邮寄中的快递轨迹。快递公司也可以查询、修改快递信息、追踪快递时效,并借助海量轨迹监控数据,掌握快递产生、收件的高频路线,在高频位置铺设更多的基础设施、转移调度快递员;功能需求面向用户:1、用户在线下单生成快递单,等候快递员上门取件;2、管理历史订单列表,了解快递明细;3、追踪特定快递周转状态、运送轨迹;面向平台:1、借助扫码器,实现快递周转事件采集、存储;2、统计、查询所有快递订单,实现全订单的管理:CRUD;3、掌握所有邮寄中快递的实时位置;4、掌握任意一个订单的周转状态、运送轨迹;5、基于历史快递数据,分析快递时效;6、方便掌握高频地域、路线,为增设基础设施、快递员提供依据;等等…系统样例,如下所示:官网控制台地址:项目样例实现方案MySQL方案与难点通常,用户会选用MySQL作为方案数据库,因为MySQL作为数库在查询、分析等功能上有优势,用户创建两个表:订单表、事件追踪表实现对快递数据的存储。但是快递场景有几个强需求:第一、需要有强大的查询、统计能力,实现快递单的管理;第二、对于海量快递,有着高并发写入需求,对写入性能要求较高;第三、数据持续膨胀,但历史快递订单、事件数据多为冷数据,存储成本需要尽可能低;第四、数据未来挖掘潜在价值较高,需要有较好的计算生态;而MySQL方案在面对第二、第三个强需求时,劣势凸显,海量并发、不断的数据膨胀、存储成本高一直以来都是关系型数据库的痛点;表格存储方案选择表格存储有以下优势:其一、表格存储的多元索引(SearchIndex)功能轻松满足用户的多维查询、GEO检索、统计等功能需求;其二、基于LSM tree打造的分布式NoSQL数据库,轻松支持海量高并发读、写,零运维轻松应对数据量的不断膨胀,理论上无上限。其三、表格存储按量计费,提供容量型、高性能型两种实例,容量型对冷数据更适宜,提供了更低存储成本。其四、更重要的,表格存储拥有较为完善的计算生态,提供全、增量通道服务,提供流计算、批计算一体的计算体系,对未来监控数据价值挖掘提供渠道。表格存储在时序场景需求的技术点上拥有极高的匹配,而基于时序场景打造的Timestream模型更是将时序场景通用功能,封装成易用的场景接口,使用户更容易的基于表格存储,根据自身需求设计、打造不同特点的轨迹追踪系统;数据结构设计基于快递的时序,将快递的属性信息作为meta数据,而快递的周转路径、状态、位置等则为data数据,下面对两类数据做简单介绍。快递元数据meta数据管理着快递的属性信息,支持指标、标签、属性、地理位置、更新时间等参数,模型会为所有属性创建相应的索引,提供多维度条件组合查询(包含GEO查询)。其中Identifier是时间线的标识,包含两部分:name部分(监控指标标识)、tags部分(固有不可变参数集合)。在快递场景中,用户通常是基于快递单号直接定位快递,因而tags使用空的。而属性信息则存储快递的邮寄人信息、收件人信息、邮寄起/止地址等,location字段,用于最新位置追踪,可不定期根据产生新的状态周转数据时更新。快递轨迹数据data数据记录着快递的状态周转信息,主要为量化数据、地理位置、文字表述等任意类型。data数据按照+有序排列,因而同一快递的所有数据物理上存在一起,且基于时间有序。这种数据存储方式,极大的提升了时间线的查询效率。对应到快递轨迹,监控数据主要记录了:【who】do【something】@【where】with the location【geo】以及联系方式等。读写接口使用介绍写数据写接口根据数据类型分为两类:meta写入(新增快递)、data写入(快递周转数据)新增快递:当用户通过系统直接下快递单后,产生唯一订单号,加上用户填写的快递单信息组成必要的凯迪数据。此时,就会生成一个时间线,产生一个meta数据;快递周转:当快递发生取件、运输周转、派送、取件是,产生的状态转变数据时,就会产生一条追踪数据,通过data数据的写接口不定期的写入;读数据与写数据一样,针对两类数据提供了两类读接口:meta读取(快递查询)、data读取(查询快递轨迹)查询快递:根据快递号、寄件人手机、收件人手机等信息,获取对应快递的列表,掌握所有快递的最新动态;查询快递轨迹:基于单个meta的Identifier,获取该快递从产生到结束整个生命周期内的轨迹周转数据,可以通过列表、地图轨迹展示等方式,直观的了解快递的周转过程;方案核心代码SDK与样例代码SDK使用:时序模型Timestream模型集成于表格存储的SDK中,目前已在4.11.0版本中支持;<dependency> <groupId>com.aliyun.openservices</groupId> <artifactId>tablestore</artifactId> <version>4.11.0</version></dependency>代码开源:https://github.com/aliyun/tablestore-examples/tree/master/demos/MailManagement建表准备在创建完成实例后,用户需要通过时序模型的sdk创建相应的meta表(快递元数据)、data表(快递周转数据):private void init() { AsyncClient asyncClient = new AsyncClient(endpoint, accessKeyId, accessKeySecret, instance); //快递抽象Timestream TimestreamDBConfiguration mailConf = new TimestreamDBConfiguration(“metaTableName”); mailDb = new TimestreamDBClient(asyncClient, mailConf);}public void createTable() { mailDb.createMetaTable(Arrays.asList(//自定义索引 new AttributeIndexSchema(“fromMobile”, AttributeIndexSchema.Type.KEYWORD), new AttributeIndexSchema(“fromName”, AttributeIndexSchema.Type.KEYWORD), new AttributeIndexSchema(“toMobile”, AttributeIndexSchema.Type.KEYWORD), new AttributeIndexSchema(“toName”, AttributeIndexSchema.Type.KEYWORD), new AttributeIndexSchema(“toLocation”, AttributeIndexSchema.Type.GEO_POINT) )); mailDb.createDataTable(“dataTableName”);}写数据数据写入主要分两部分,meta表创建新快递、data表采集快递周转信息创建快递单(meta表写入)//metaWriter对应meta表,提供读、写接口TimestreamMetaTable mailMetaWriter = mailDb.metaTable();//identifier作为时间线的身份标识(unique),仅含:快递单号ID,TimestreamIdentifier identifier = new TimestreamIdentifier.Builder(“mail-id-001”) .build();//基于identifier创建meta对象,并为meta设置更多属性,Attributes为属性参数TimestreamMeta meta = new TimestreamMeta(identifier) .addAttribute(“fromName”, whos.get(Rand.nextInt(whos.size()))) .addAttribute(“fromMobile”, “15812345678”) .addAttribute(“toName”, whos.get(Rand.nextInt(whos.size()))) .addAttribute(“toMobile”, “15812345678”) .addAttribute(“toLocation”, “30,120”);//创建新的时间线,然后写入监控数据mailMetaWriter.put(meta);采集快递周转事件(data表写入)//dataWriter分别对应data表,提供读、写接口TimestreamDataTable mailDataWriter = mailDb.dataTable(“mailDataTableName”);TimestreamMeta meta;//meta上一步已经构建//创建新的时间线,然后写入监控数据mailDataWriter.write( meta.getIdentifier(), new Point.Builder(14500000000, TimeUnit.MILLISECONDS) .addField(“who”, “张三”) .addField(“do”, “取件”) .addField(“where”, “云栖小镇”) .addField(“location”, “30,120”) .build());数据读取数据读取分为两类:快递订单多维查询(meta表读取)//reader对应meta表,提供读、写接口,此处名字为突出读功能TimestreamMetaTable metaReader = mailDb.metaTable();//构建筛选条件Filter filter = AndFilter( Name.equal(“mail-id-001”), Attribute.equal(“fromMobile”, “15812345678”));Iterator<TimestreamMeta> metaIterator = mailDb.metaTable() .filter(filter) .fetchAll();while (iterator.hasNext()) { TimestreamMeta meta = iterator.next();//deal with metas}快递轨迹追踪(data表读取)//dataWriter分别对应data表,提供读、写接口TimestreamDataTable dataReader = db.dataTable(“dataTableName”);TimestreamMeta meta;//基于已获取的meta列表,分别获取每个快递的轨迹追踪Iterator<Point> dataIterator = mailDb.dataTable(mailDataTableName) .get(meta.getIdentifier()) .fetchAll();while (iterator.hasNext()) { Point point = iterator.next();//deal with points long timestamp = point.getTimestamp(TimeUnit.MILLISECONDS);//毫秒单位时间戳 String location = point.getField(“location”).asString();//获取该点String类型的位置信息}本文作者:潭潭阅读原文本文为云栖社区原创内容,未经允许不得转载。 ...

April 18, 2019 · 1 min · jiezi

对话阿里云Alex Chen:下一代存储应如何面对云转型?

摘要: 如何定义下一代存储标准?在阿里云智能存储产品资深总监Alex Chen看来,其本质必须具备以下四个特性:安全稳定、优化、无缝上云、智能。数字经济"乘云而上"。十年前,阿里云开始自主研发云计算操作系统飞天之路,开启了中国云时代;十年后,阿里云在中国市场份额超过2-8名总和,培育了整个中国云计算市场,数字经济在云上蓬勃发展。十年前,EMC、NetApp、IBM等国际独立存储大厂称霸市场,中国企业存储市场被国际寡头瓜分,一本万利;十年后,中国存储市场国产率超过50%,Dell EMC、NetApp、Commvault、Veritas都紧紧包围阿里云构建合作伙伴生态,云上数字经济成为了企业存储走向新的发展阶段的原动力。如果说云计算是数字经济时代发展的新范式,那么,存储作为数字化基础架构的核心,将成为支撑数字化到智能化转型升级的基石。尤其在混合云大势得道的今天,存储架构应对不同介质、技术、应用的演进升级,存储系统对云和云上应用的支撑能力,以及对海量数据的智能化分析和管理,都成为了下一代存储的核心考量标准。软件定义、分布式、融合、云资源化、两地三中心……这些技术名词几乎占据了存储热搜榜,在面向云的数字化和智能化的转型风口,未来存储之路如何发展?如何定义下一代存储标准?在阿里云智能存储产品资深总监Alex Chen看来,其本质必须具备以下四个特性:安全稳定、优化、无缝上云、智能。更安全更稳定数据是企业最重要的资产,存储是数据的载体,数据安全对存储的要求不言而喻。云环境下,数据存储是由大量数据存储节点构成分布式数据中心,通过虚拟化拓展了存储容量并提高存储和读取数据性能,让用户可以充分享受高效、稳定的存储服务。但同时,数据的加密存储、数据隔离、数据迁移、数据安全审计等环节也都考验着云存储的安全可靠性。在这点上,任何云厂商都也不例外。Alex介绍,打造更高数据安全稳定标准是阿里云始终坚持的首要目标。在安全方面,阿里云存储产品具备全面的静态数据加密能力。以对象存储(OSS)为例,提供包括KMS密钥、BYOK密钥、OSS托管密钥完成服务端数据加密和客户端线下加密等5种加密方式,也是中国首家通过Cohasset Associates审计认证,符合美国证券交易委员会(SEC)和金融业监管局(FINRA)合规要求的云厂商,已成功在海外服务国际金融行业客户,此举也标志着阿里云已实现合规方面的里程碑式建设。在稳定性方面,经过十年的技术积累和沉淀,阿里云自研飞天大规模的分布式存储引擎已经换代升级为盘古2.0;基于盘古2.0,整个阿里巴巴今天有60%-70%的流量跑在公共云上,扎实的底层存储系统支撑了十年“双11”大规模高并发洪峰考验,也为阿里云成为最佳实践的云打下良好基础。更优化不同应用需要不一样的存储架构,对IOPS、延时、吞吐的要求也自然不同,没有一个存储产品可以做到完全覆盖所有的应用场景。在阿里云的产品设计上,针对不同场景下,提供满足用户定制化需求的最优存储类型服务。在数据库和实时业务分析场景下,阿里云推出全球百万级IOPS的企业级ESSD云盘,相比于SSD云盘分别提升40倍性能和降低70%读写延时,在实际的业务场景测试下,以MySQL和PostgreSQL为例,采用ESSD云盘可获得3-4倍的TPS性能提升。此外,ESSD云盘支持不停机扩展容量、不停机提高IO读写性能上限、数据加密等高级数据服务功能,给客户在弹性、安全等方面带来了更多的技术红利。在容器共享存储、动态网站、DevOps开发测试的小文件读写场景下,阿里云推出文件存储NAS极速型规格,提供百微秒级延时,同时提供文件系统级快照,以提升数据安全性。在大数据和离线数据分析、机器学习场景下,阿里云发布全球首个云原生文件存储HDFS,无需关心和维护底层存储,降低TCO,真正解决了传统自建HDFS系统计算存储耦合的问题,使得真正实现了计算存储分离,实现存储计算分离后分别拥有享受可线性扩展的吞吐能力和免运维的快速弹性伸缩能力。在HPC、人工智能、基因生命科学场景下,阿里云发布高性能文件存储CPFS,提供针对亿级文件,提供TB/s级超高吞吐的并行文件存储服务,并与阿里云计算生态无缝对接,满足计算密集型场景应用的高性能要求。无缝上云根据IDC公开报告显示,85%的大型企业表示不会将所有数据存储一地,而是会采用更多方式且适合自己的方法,在混合云环境中实现数据在其整个生命周期中的流转。Alex认为,通过混合云IT架构无缝上云已成为企业应用的新常态,混合云存储将成为架起本地数据中心和公共云的桥梁,开启传统企业用户上云的新路径。在3月的阿里云北京峰会上,阿里云发布全新Apsara SA系列混合云存储阵列,实现了本地数据中心架构和公共云存储的无缝结合,融合了IP SAN、FC SAN、NAS和OSS多种存储协议,提供异构存储虚拟化、双活容灾、混合云协同计算、在线多控横向扩展等企业级存储特性,支持端到端数据加密,满足数据库,虚拟化,文件共享,数据分析等各类场景下企业客户对数据存储和灾备等需求。更智能如果说单纯的卖存储、安全、计算等能力是云计算的1.0时代,那么以智能化为核心的2019年,则是阿里云进入2.0时代的标志。Alex表示,阿里云存储在第一阶段完成了以弹性扩展、灵活高效、降低成本为核心的存储基础服务,在第二阶段,除了支撑集团100%业务上云外,还要帮助更多企业实现数据管理的数字化和智能化,不仅是存储,更是数据智能管理平台。针对不同业务场景,阿里云发布了智能媒体管理视频型实例,提供场景化封装数据智能分析管理,为云上文档、图片、视频提供一站式数据处理、分析、检索等智能管理体验。阿里云日志服务是面向日志类数据的智能化一站式平台,针对AIOps场景,新增面向趋势预测、异常发现、智能聚类、根因分析(推导)等4个高频场景系列函数,提升DevOps分析与诊断的效率,该功能已通过阿里巴巴“双11”实战验证。后记2018年底,阿里云正式升级为阿里云智能。3个月后的阿里云北京峰会上,阿里云首次对外公布了云的下一阶段发展定位和云到云智能的思考。在对Alex Chen的采访中,这位曾在IBM存储领域有着19年丰富经历的专家同时坦言,“安全稳定、优化、无缝上云、智能”不仅是云时代下一代存储的本质性特点,是阿里云未来几年存储创新的主方向,也将是企业存储厂商产品服务能力比拼的主赛道。2018年,阿里云已实现完整的存储基础服务,丰富的数据服务,多元的应用场景的产品布局,成功签约5家渠道代销商,并与合作伙伴在产品层面打造混合云解决方案,开拓企业级存储市场。不难预见,2019年阿里云将持续围绕下一代存储理念持续技术创新,不断拓展存储边界,深耕数据密集型细分行业,并同更多的合作伙伴一起构建企业级存储生态,这同时也意味着以阿里云为代表的云计算厂商也真真正正的进入企业级存储市场竞争格局中。而在这样的2019年,无论对于存储市场还是用户,都是好事。本文作者:株莉阅读原文本文为云栖社区原创内容,未经允许不得转载。

April 16, 2019 · 1 min · jiezi

【推荐】最新200篇:技术文章整理

作为面试官,我是如何甄别应聘者的包装程度Go语言和Java、python等其他语言的对比分析Redis和MySQLRedis:主从复制的原理详解Redis:RDB 和 AOF 持久化的原理是什么?Redis:面试中经常被问到的 Redis 持久化与恢复Redis:实现故障恢复自动化:详解Redis哨兵技术Redis:查漏补缺:最易错过的技术要点大扫盲MySQL:意外宕机不难解决,但你真的懂数据恢复吗MySQL:每秒57万的写入,带你飞MySQL:三大知识点,索引、锁、事务,原理分析MySQL:查询速度慢与性能差的解决方案MySQL:事务ACID特性的实现原理MySQL:大佬是怎么思考设计MySQL优化方案的MySQL:一份非常完整的MySQL规范面试必备面试必备:浅谈Java中15种锁的分析比较面试官问:Spring AOP 的实现机制面试官问:ZooKeeper 一致性协议 ZAB 原理面试必备:46张PPT讲述JVM、GC算法和性能调优面试必备:最新 Java 面试题汇总,附答案面试必备:基于 Zookeeper 的分布式锁实现面试必备:30 道 Dubbo 面试题及答案面试必备:数组下标为什么从0开始,而不是1面试必备:Java并发编程75道面试题及答案稳了面试必备:一次生产的JVM优化面试必备:动图+源码+总结:演示JDK8 中的数据结构面试必备:133 道 Java 面试题及答案架构架构:数据库分库分表,何时分?怎样分?架构:分库分表-垂直?水平?架构:主备+分库?主从+读写分离?架构:分库分表就能无限扩容吗架构:通过10张图介绍,分布式架构如何演进!架构:MQ消息队列应用场景比较介绍架构:架构师成长之路必备技能)架构:谈谈架构架构:秒杀系统架构优化思路架构:Web系统大规模并发:电商秒杀与抢购架构:小团队的微服务架构演进之路架构:高并发文章浏览量计数系统设计Google 出品的 Java 编码规范Java性能优化的45个细节(珍藏版)面试必备面试必备:通俗易懂,常用线程池执行的-流程图面试必备:我们来谈下高并发和分布式中的幂等处理面试必备:大型分布式系统中的缓存架构面试必备:美团面试经历,贡献出来一起学习面试必备:高性能MySQL索引与优化实践面试必备:搭建网站扫码登录的功能设计面试必备:技术变化那么快,学 Docker 看这篇就够了面试必备:一文看懂 MySQL 高性能优化技巧实践面试必备:分布式事务不理解?一次给你讲清楚!面试必备:京东到家订单中心ES集群架设演进历程面试必备:一次性能优化:吞吐量从1提升到2500面试必备:Spring 面试问题 TOP 50面试必备:看京东系统架构师如何让笨重的架构变得灵巧面试必备:日请求8亿Web流量分布式系统的高容错性实践面试必备:微服务架构:如何用十步解耦你的系统?面试必备:想了解五大MQ之间的差异?这一篇文章就够了!面试必备:学习MySQL高性能优化原理,这一篇就够了!面试必备:优雅地SpringBoot中实现消息的发送和消费实践面试必备:堪称最详细的支付系统设计面试必备:动画+原理+代码+优化,解读十大经典排序算法面试必备:设计一个成功的微服务,堪称必备的9个基础知识面试必备:掌握分布式场景下的秒杀架构与秒杀实践面试必备:互联网寒冬?进BAT等大厂 堪称必备神器面试必备:缓存穿透,缓存雪崩的四种解决方案以下是 2018年11月23日 之前的文章面试必备面试必备:深入Spring MVC DispatchServlet 源码分析面试必备:一文读懂Spring AOP面向切面编程面试必备:理解JWT鉴权的应用场景及使用建议面试必备:浅谈偏向锁、轻量级锁、重量级锁面试必备:一致性哈希算法的理解与实践面试必备:深入理解为什么要设计幂等性的服务面试必备:面试官最爱的volatile关键字面试必备:Rabbitmq延迟队列实现定时任务面试必备:HashMap源码解析JDK8面试必备:Dubbo服务消费者调用过程面试必备:Dubbo服务提供者发布过程面试必备:Dubbo中暴露服务的过程解析面试必备:Java中transient关键字的作用面试必备:JavaSQL注入危害这么大,该如何来防止呢面试必备:Java虚拟机运行时数据区面试必备:Redis之数据持久化RDB与AOF面试必备:Redis持久化RDB和AOF优缺点是什么面试必备:Redis集群下的RedLock算法(真分布式锁) 实践面试必备:Redis服务器被攻击后该如何安全加固面试必备:Zookeeper的Leader选举过程面试必备:ZooKeeper和CAP理论及一致性原则面试必备:MySQL从删库到恢复,还用跑路吗?面试必备:MySQL/InnoDB中,7中锁的理解面试必备:MySQL常用30种SQL查询语句优化方法面试必备:MySQL InnoDB B+树索引和哈希索引的区别面试必备:常用的分布式事务解决方案介绍有多少种面试必备:对称加密,非对称加密,公钥和私钥面试必备:如何加密传输和存储用户密码架构架构:应用消息中间件设计可以解决哪些实际问题?架构:搭建大众点评CAT实时应用监控平台架构:如何实现一个TCC分布式事务框架的一点思考架构:Dapper大规模分布式系统的跟踪系统架构:Dubbo 整合 Pinpoint 做分布式服务请求跟踪架构:理解大型分布式架构的演进历史、技术原理、最佳实践架构:解密 Redis 助力双十一背后电商秒杀系统架构:瞬间点击量过万,Redis热点Key的5种解决方案架构:通过案例读懂 RESTful 架构风格架构:一文读懂Apache Flink架构及特性分析架构:大数据推荐系统实时架构和离线架构架构:携程:日处理20亿数据,实时用户行为架构实践架构:什么是微服务架构架构:有赞服务化架构演进架构:微服务架构下静态数据通用缓存机制架构:小型系统如何“微服务”开发架构:Oracle推出开源轻量级 Java 微服务框架 HelidonJava并发Java并发:接口限流算法:漏桶算法&令牌桶算法Java并发:深入浅出AQS之共享锁模式源码分析Java并发:深入浅出AQS之独占锁模式源码分析Java并发:了解无锁CAS就从源码分析Java并发:分布式应用限流实践Java并发:Semaphore信号量源码分析Java并发:CAS源码分析Spring Cloud(十一)分布式配置中心 Spring Cloud Bus 消息总线集成(十)分布式配置中心 Spring Cloud Config 中使用 Refresh(九)分布式配置中心 Spring Cloud Config 集成 Eureka 服务(八)分布式配置中心 Spring Cloud Config(七)服务网关 Zuul Filter 使用(六)服务网关 zuul 快速入门(五)断路器监控(Hystrix Dashboard)(四) 服务提供者 Eureka + 服务消费者 Feign(三) 服务提供者 Eureka + 服务消费者(rest + Ribbon)(二)Consul 服务治理实现(一)服务的注册与发现(Eureka)Spring BootSpring Boot 中使用 RabbitMQSpring Boot 中使用 RocketMQSpring Boot 中使用 SolrCloudSpring Boot 中使用 MongoDB 增删改查Spring Boot 中使用 Dubbo 详解Spring Boot 中使用 LogBack 配置Spring Boot 中使用 Docker镜像push到DockerHub上Spring Boot 写的一个java开源图床搭建搭建:网站配置免费的HTTS证书搭建:Apache RocketMQ 单机环境搭建:MongoDB分片(sharding) / 分区 / 集群环境搭建:MongoDB 的安装与详细使用(二)搭建:MongoDB 的安装与详细使用(一)搭建:SolrCloud 集群服务搭建:Solr 单机服务搭建:RabbitMQ 3.6 单机服务搭建:RabbitMQ 3.6 集群服务搭建:离线部署 CDH 5.12.1 及部署Hadoop集群服务搭建:Mycat 读写分离数据库分库分表中间件及简单使用DockerDocker Compose 1.18.0 之服务编排详解Docker 部署 SpringBoot 项目整合 Redis 镜像做访问计数DemoDocker Registry 企业级私有镜像仓库Harbor管理WEB UIDocker Registry Server TLS 的私有仓库Docker Hub 仓库使用,及搭建 Docker RegistryDocker 容器常用操作命令讲解Docker 安装在之初窥 Dockerfile 部署 Nginx面试题面试题:百度、腾讯、阿里、谷歌 面试题视频详解合集面试题:2018最新JAVA算法/数据结构面试题和答案面试题:70道Spring面试题与答案面试题:2018最新Redis面试题与答案面试题:50道多线程面试题与答案(二)面试题:50道多线程面试题与答案(一)面试题:Spring常见的一些面试题与答案面试题:300道Java面试题与答案面试题:40道常见面试题与答案面试题:20道数据库面试题与答案 ...

April 13, 2019 · 1 min · jiezi

IP应用加速 – DCDN迈入全栈新篇章

4月11日,第七届"亚太内容分发大会"暨CDN峰会国际论坛中,阿里云资深技术专家姚伟斌发布了DCDN子产品IP应用加速(IPA)。IPA是基于阿里云CDN本身的资源优化,对传输层(TCP&UDP)协议进行全栈能力提升,同时利用就近接入、智能路由、传输协议优化,以及多种负载均衡技术,实现更高效、更安全、更快速、更便捷的动态加速产品。通常全球内容传输会存在一些痛点,比如:偏远用户、长尾用户访问质量差;对跨运营商,跨国的覆盖要求;游戏、RTC等行业对可靠性、实时性要求很高;电商、金融等行业对安全性要求更高;失败率高等等,IP应用加速的出现,能很好的解决这些问题。优质的内容分发加速最基本的指标是可靠性,阿里云通过覆盖全球的2500个节点,利用超过99%精度的IP数据,并支持TCP和UDP自适应接入实现智能调度同时自研协议栈、多路径传输、动态选路、DDoS防御和全链路加密提供安全、可靠的传输链路。IPA功能优势及架构覆盖更多场景:除了七层外,还对四层、三层网络协议进行支持,全协议栈加速通道,满足更多用户需求和业务场景。更高可靠性:有效解决偏远地区、跨境传输的互联互通问题,降低错误率提供更低延时加速体验降低成本:大幅度减少机器及专线成本,节省预算。安全防护:抗攻击、流量清洗,满足高安全性的业务场景需求以下为整体架构图,包括边缘智能就近接入,节点间实时探测,动态选路,节点间高性能自研协议栈,源站自动选择。针对更高性能的传输需求,阿里云自研的高性能私有传输协议,实现数据多路径传输,改造TCP协议栈提升整个传输效率,加速整个数据传输的可靠性和实时性。同时对内部链路,也支持秒级智能路由切换功能,极大降低数据传输时候应对丢包的可能性。下图是线上实测的数据,相对于TCP协议来说,传输的效率会提升20%以上。IPA适用场景直播互动:弹幕分发、礼物分发、登录连接、评论分享、聊天室消息…游戏行业:游戏互动指令、游戏语音传输、TCP数据接口、UDP内容交互…在线教育:师生音视频互动、文件分享、即时消息、屏幕共享…办公系统:SSL VPN、远程桌面、移动办公APP、邮箱系统、OA…云服务同步:数据中心同步、云ERP、云CRM、远程登录系统…金融行业:手机银行、网银支付、在线交易、股票买卖…在接入方式上,IPA只需要用户提交一个域名即可接入,仅仅1分钟一键就可以开启四层加速的功能,有效降低原来开专线、买服务器等业务加速的复杂度,缩短业务上线时间。应用案例办公通讯软件这个场景下的最大痛点是偏远地区消息不稳定以及海外通信质量差,会出现失败率高的情况,IPA通过下图中的优化架构,从HTTPDNS接入,在节点内部通过ACL有效保证端口的高可靠性,全球访问速度提升超过50%。互动直播应用互动直播中发弹幕、送礼物的场景,对交流的实时性要求非常高,经常会出现登录与加速缓慢,互动体验差等问题。阿里云IPA架构支持客户端与中心服务器之间更有效的交流,同时覆盖了东南亚以及全国各地的地区,最终实现评论、分享延时降低20%以上。办公ERP系统办公ERP系统的痛点是数据传输延迟高,不稳定,表单查询成功率低等问题,导致协同办公效率低下。通过IPA对于超大文件的传输优化,实现传输速率提升30%以上,可用性提升50%。金融行业金融交易的展示不实时,用户的交易就无法保障,针对海外交易延时偏高,价格变动频繁,交易过程失败率高,对于安全性要求更高等问题,因此,阿里云针对针对链路传输加密,对源站保障负载均衡,最终整体延迟降低超过了80%。谈到IP应用加速的未来规划,姚伟斌说:未来IPA会提供三层、四层、七层全栈加速能力,支持数十万海量边缘节点接入,真正实现端-边-云的Overlay边缘传输网络,并尝试与生态硬件集成,为5G时代的边缘智能网络提供基础。本文作者:樰篱阅读原文本文为云栖社区原创内容,未经允许不得转载。

April 12, 2019 · 1 min · jiezi

如何画出一张合格的技术架构图?

阿里妹导读:技术传播的价值,不仅仅体现在通过商业化产品和开源项目来缩短我们构建应用的路径,加速业务的上线速率,也体现在优秀工程师在工作效率提升、产品性能优化和用户体验改善等经验方面的分享,以提高我们的专业能力。接下来,阿里巴巴技术专家三画,将分享自己和团队在画好架构图方面的理念和经验,希望对你有所帮助。当我们想用一张或几张图来描述我们的系统时,是不是经常遇到以下情况:对着画布无从下手、删了又来?如何用一张图描述我的系统,并且让产品、运营、开发都能看明白?画了一半的图还不清楚受众是谁?画出来的图到底是产品图功能图还是技术图又或是大杂烩?图上的框框有点少是不是要找点儿框框加进来?布局怎么画都不满意……如果有同样的困惑,本文将介绍一种画图的方法论,来让架构图更清晰。先厘清一些基础概念1、什么是架构?架构就是对系统中的实体以及实体之间的关系所进行的抽象描述,是一系列的决策。架构是结构和愿景。系统架构是概念的体现,是对物/信息的功能与形式元素之间的对应情况所做的分配,是对元素之间的关系以及元素同周边环境之间的关系所做的定义。做好架构是个复杂的任务,也是个很大的话题,本篇就不做深入了。有了架构之后,就需要让干系人理解、遵循相关决策。2、什么是架构图?系统架构图是为了抽象地表示软件系统的整体轮廓和各个组件之间的相互关系和约束边界,以及软件系统的物理部署和软件系统的演进方向的整体视图。3、架构图的作用一图胜千言。要让干系人理解、遵循架构决策,就需要把架构信息传递出去。架构图就是一个很好的载体。那么,画架构图是为了:解决沟通障碍达成共识减少歧义4、架构图分类搜集了很多资料,分类有很多,有一种比较流行的是4+1视图,分别为场景视图、逻辑视图、物理视图、处理流程视图和开发视图。场景视图场景视图用于描述系统的参与者与功能用例间的关系,反映系统的最终需求和交互设计,通常由用例图表示。逻辑视图逻辑视图用于描述系统软件功能拆解后的组件关系,组件约束和边界,反映系统整体组成与系统如何构建的过程,通常由UML的组件图和类图来表示。物理视图物理视图用于描述系统软件到物理硬件的映射关系,反映出系统的组件是如何部署到一组可计算机器节点上,用于指导软件系统的部署实施过程。处理流程视图处理流程视图用于描述系统软件组件之间的通信时序,数据的输入输出,反映系统的功能流程与数据流程,通常由时序图和流程图表示。开发视图开发视图用于描述系统的模块划分和组成,以及细化到内部包的组成设计,服务于开发人员,反映系统开发实施过程。以上 5 种架构视图从不同角度表示一个软件系统的不同特征,组合到一起作为架构蓝图描述系统架构。怎样的架构图是好的架构图上面的分类是前人的经验总结,图也是从网上摘来的,那么这些图画的好不好呢?是不是我们要依葫芦画瓢去画这样一些图?先不去管这些图好不好,我们通过对这些图的分类以及作用,思考了一下,总结下来,我们认为,在画出一个好的架构图之前, 首先应该要明确其受众,再想清楚要给他们传递什么信息 ,所以,不要为了画一个物理视图去画物理视图,为了画一个逻辑视图去画逻辑视图,而应该根据受众的不同,传递的信息的不同,用图准确地表达出来,最后的图可能就是在这样一些分类里。那么,画出的图好不好的一个直接标准就是:受众有没有准确接收到想传递的信息。明确这两点之后,从受众角度来说,一个好的架构图是不需要解释的,它应该是自描述的,并且要具备一致性和足够的准确性,能够与代码相呼应。画架构图遇到的常见问题1、方框代表什么?为什么适用方框而不是圆形,它有什么特殊的含义吗?随意使用方框或者其它形状可能会引起混淆。2、虚线、实线什么意思?箭头什么意思?颜色什么意思?随意使用线条或者箭头可能会引起误会。3、运行时与编译时冲突?层级冲突?架构是一项复杂的工作,只使用单个图表来表示架构很容易造成莫名其妙的语义混乱。本文推荐的画图方法C4 模型使用容器(应用程序、数据存储、微服务等)、组件和代码来描述一个软件系统的静态结构。这几种图比较容易画,也给出了画图要点,但最关键的是,我们认为,它明确指出了每种图可能的受众以及意义。下面的案例来自C4官网,然后加上了一些我们的理解,来看看如何更好的表达软件架构1、语境图(System Context Diagram)这是一个想象的待建设的互联网银行系统,它使用外部的大型机银行系统存取客户账户、交易信息,通过外部电邮系统给客户发邮件。可以看到,非常简单、清晰,相信不需要解释,都看的明白,里面包含了需要建设的系统本身,系统的客户,和这个系统有交互的周边系统。用途这样一个简单的图,可以告诉我们,要构建的系统是什么;它的用户是谁,谁会用它,它要如何融入已有的IT环境。这个图的受众可以是开发团队的内部人员、外部的技术或非技术人员。即:构建的系统是什么谁会用它如何融入已有的IT环境怎么画中间是自己的系统,周围是用户和其它与之相互作用的系统。这个图的关键就是梳理清楚待建设系统的用户和高层次的依赖,梳理清楚了画下来只需要几分钟时间。2、容器图(Container Diagram)容器图是把语境图里待建设的系统做了一个展开。上图中,除了用户和外围系统,要建设的系统包括一个基于javaspring mvc的web应用提供系统的功能入口,基于xamarin架构的手机app提供手机端的功能入口,一个基于java的api应用提供服务,一个mysql数据库用于存储,各个应用之间的交互都在箭头线上写明了。看这张图的时候,不会去关注到图中是直角方框还是圆角方框,不会关注是实线箭头还是虚线箭头,甚至箭头的指向也没有引起太多注意。我们有许多的画图方式,都对框、线的含义做了定义,这就需要画图的人和看图的人都清晰的理解这些定义,才能读全图里的信息,而现实是,这往往是非常高的一个要求,所以,很多图只能看个大概的含义。用途这个图的受众可以是团队内部或外部的开发人员,也可以是运维人员。用途可以罗列为:展现了软件系统的整体形态体现了高层次的技术决策系统中的职责是如何分布的,容器间的是如何交互的告诉开发者在哪里写代码怎么画用一个框图来表示,内部可能包括名称、技术选择、职责,以及这些框图之间的交互,如果涉及外部系统,最好明确边界。3、组件图(Component Diagram)组件图是把某个容器进行展开,描述其内部的模块。用途这个图主要是给内部开发人员看的,怎么去做代码的组织和构建。其用途有:描述了系统由哪些组件/服务组成厘清了组件之间的关系和依赖为软件开发如何分解交付提供了框架4、类图(Code/Class Diagram)这个图很显然是给技术人员看的,比较常见,就不详细介绍了。案例分享下面是内部的一个实时数据工具的架构图。作为一个应该自描述的架构图,这里不多做解释了。如果有看不明白的,那肯定是还画的不够好。画好架构图可能有许多方法论,本篇主要介绍了C4这种方法,C4的理论也是不断进化的。但不论是哪种画图方法论,我们回到画图初衷,更好的交流,我们在画的过程中不必被条条框框所限制。简而言之,画之前想好:画图给谁看,看什么,怎么样不解释就看懂。作者简介:三画,阿里巴巴技术专家,梓敬、鹏升和余乐对此文亦有贡献。三画曾多年从事工作流引擎研发工作,现专注于高并发移动互联网应用的架构和开发,和本文贡献者均来自阿里巴巴零售通部门。目前零售通大量招Java开发,欢迎有志之士投简历到 lst-wireless@alibaba-inc.com,和我们一起共建智能分销网络,让百万小店拥抱DT时代。本文作者:三画阅读原文本文来自云栖社区合作伙伴“ 阿里技术”,如需转载请联系原作者。

April 12, 2019 · 1 min · jiezi

更效率、更优雅 | 阿里巴巴开发者工具不完全盘点

从人工到自动化,从重复到创新,技术演进的历程中,伴随着开发者工具类产品的发展。阿里巴巴将自身在各类业务场景下的技术积淀,通过开源、云上实现或工具等形式对外开放,本文将精选了一些阿里巴巴的开发者工具,希望能帮助开发者们提高开发效率、更优雅的写代码。由于开发者涉及的技术领域众多,笔者仅从自己熟悉的领域,以后端开发者的视角盘点平时可能有得到的工具。每个工具按照以下几点进行介绍:工具名称和简介使用场景使用教程获取方式一、Java 线上诊断工具 ArthasArthas 阿里巴巴2018年9月开源的一款Java线上诊断工具。工具的使用场景:这个类从哪个 jar 包加载的?为什么会报各种类相关的 Exception?我改的代码为什么没有执行到?难道是我没 commit?分支搞错了?遇到问题无法在线上 debug,难道只能通过加日志再重新发布吗?线上遇到某个用户的数据处理有问题,但线上同样无法 debug,线下无法重现!是否有一个全局视角来查看系统的运行状况?有什么办法可以监控到JVM的实时运行状态?Arthas支持JDK 6+,支持Linux/Mac/Windows,采用命令行交互模式,同时提供丰富的 Tab 自动补全功能,进一步方便进行问题的定位和诊断。使用教程:基础教程:https://alibaba.github.io/arthas/arthas-tutorials?language=cn&id=arthas-basics进阶教程:https://alibaba.github.io/arthas/arthas-tutorials?language=cn&id=arthas-advanced获取方式:(免费)开源地址:https://github.com/alibaba/arthas二、IDE 插件 Cloud ToolkitCloud Toolkit 是一款 IDE 插件,可以帮助开发者更高效地开发、测试、诊断并部署应用。通过 Cloud Toolkit,开发者能够方便地将本地应用一键部署到任意机器(本地或云端),并内置 Arthas 诊断、高效执行终端命令和 SQL 等。工具的使用场景:每次修改完代码后,是否正在经历反复地打包?在 Maven 、Git 以及其他运维脚本和工具的之间频繁切换?采用 SCP 工具上传?使用XShell或SecureCRT登陆服务器?替换部署包?重启?文件上传到服务器指定目录,在各种 FTP、SCP 工具之间频繁切换 ?使用教程:IntelliJ IDEA 版:https://help.aliyun.com/document_detail/98762.htmlEclipse 版:https://help.aliyun.com/document_detail/29970.htmlPyCharm 版:https://help.aliyun.com/document_detail/112740.htmlMaven 版:https://help.aliyun.com/document_detail/108682.html获取方式:(免费)工具地址:https://www.aliyun.com/product/cloudtoolkit三、混沌实验注入工具 ChaosBladeChaosBlade 是一款遵循混沌工程实验原理,提供丰富故障场景实现,帮助分布式系统提升容错性和可恢复性的混沌工程工具,可实现底层故障的注入,提供了延迟、异常、返回特定值、修改参数值、重复调用和try-catch 块异常等异常场景。工具的使用场景:微服务的容错能力不易衡量?容器编排配置是否合理无法验证?PaaS 层健壮性的测试工作无从入手?使用教程:https://github.com/chaosblade-io/chaosblade/wiki/新手指南获取方式:(免费)开源地址:https://github.com/chaosblade-io/chaosblade/wiki/新手指南四、Java 代码规约扫描插件该插件用于检测 Java 代码中存在的不规范的位置,并给予提示。规约插件是采用kotlin语言开发。使用教程:IDEA插件使用文档:https://github.com/alibaba/p3c/wiki/IDEA插件使用文档Eclipse插件使用文档:https://github.com/alibaba/p3c/wiki/Eclipse插件使用文档获取方式:(免费)开源地址:https://github.com/alibaba/p3c五、应用实时监控工具 ARMSARMS 是一款 APM 类的监控工具,提供前端、应用、自定义监控 3 类监控选项,可快速构建实时的应用性能和业务监控能力。工具的使用场景:晚上10点收到37条报警信息,你却无从下手?当我们发现问题的时候,客户/业务方已经发起投诉?每个月花几十万买服务器,却无法保障用户体验?使用教程:前端监控接入:https://help.aliyun.com/document_detail/106086.html应用监控接入:https://help.aliyun.com/document_detail/63796.html自定义监控:https://help.aliyun.com/document_detail/47474.html获取方式:(收费)工具地址:https://www.aliyun.com/product/arms六、静态开源站点搭建工具 DocsiteDocsite 一款集官网、文档、博客和社区为一体的静态开源站点的解决方案,具有简单易上手、上手不撒手的特质,同时支持 react 和静态渲染、PC端和移动端、支持中英文国际化、SEO、markdown文档、全局站点搜索、站点风格自定义、页面自定义等功能。使用教程:https://docsite.js.org/zh-cn/docs/installation.html获取方式:(免费)项目地址:https://github.com/txd-team/docsite七、Android 平台上的秒级编译方案 FreelineFreeline 可以充分利用缓存文件,在几秒钟内迅速地对代码的改动进行编译并部署到设备上,有效地减少了日常开发中的大量重新编译与安装的耗时。Freeline 最快捷的使用方法就是直接安装 Android Studio 插件。使用教程:https://github.com/alibaba/freeline/blob/master/README-zh.md获取方式:(免费)项目地址:https://github.com/alibaba/freeline八、性能测试工具 PTSPTS 可以模拟大量用户访问业务的场景,任务随时发起,免去搭建和维护成本,支持 JMeter 脚本转化为 PTS 压测,同样支持原生 JMeter 引擎进行压测。使用教程:https://help.aliyun.com/document_detail/70290.html获取方式:(收费)工具地址:https://www.aliyun.com/product/pts九、云效开发者工具KTKT 可以简化在 Kubernetes 下进行联调测试的复杂度,提高基于Kubernetes的研发效率。使用教程:https://yq.aliyun.com/articles/690519获取方式:(免费)工具地址:https://yq.aliyun.com/download/3393十、架构可视化工具 AHASAHAS 为 K8s 等容器环境提供了架构可视化的功能,同时,具有故障注入式高可用能力评测和一键流控降级等功能,可以快速低成本的提升应用可用性。工具的使用场景:服务化改造过程中,想精确的了解资源实例的构成和交互情况,实现架构的可视化?想引入真实的故障场景和演练模型?低门槛获得流控、降级功能?使用教程:https://help.aliyun.com/document_detail/90323.html获取方式:(免费)工具地址:https://www.aliyun.com/product/ahas本文作者:中间件小哥阅读原文本文为云栖社区原创内容,未经允许不得转载。 ...

April 11, 2019 · 1 min · jiezi

蚂蚁金服CTO程立:做工程要有“拧螺丝”的精神

摘要: “做工程要有‘拧螺丝’的精神,其实在工作中,我们也做了很多‘拧螺丝’的事情,包括在搭建每一个架构、每一个系统的过程中。”“一台机器可能有无数颗螺丝,需要一个一个地拧,而且需要一圈一圈地拧,才能让系统间严丝合缝,顺利工作。代码的世界里,一个项目到底成功与否,也是取决于几个模型的关键特殊设置,就像拧螺丝一样。”蚂蚁金服CTO程立说道,“做工程就需要这种奋力的精神。”近日,蚂蚁金服CTO程立接受了科技媒体infoQ专访,过程中,程立谈到了过去十年中国互联网技术的发展,与此同时,作为架构师出身,程立也谈到了做工程的心得。程立表示,“做工程要有‘拧螺丝’的精神,其实在工作中,我们也做了很多‘拧螺丝’的事情,包括在搭建每一个架构、每一个系统的过程中。”比如,程立回忆说,在十年的“双11”大促中,蚂蚁金服技术团队护航支付宝,只在2012年出过一次“问题”。据介绍,那时问题就出在一个“螺丝”上——一个类似软件“保险丝”的设计,即某两个系统之间,可以想象有一根“线”作为连接。简单而言,当时技术团队设计,“保险丝”在压力过大时熔断,来保护后面的系统不会崩溃。而在开始的时候,支付交易出现了不稳定的情况。后来发现,其实是“保险丝”设定的容量不对,于是把“保险丝”换成“铜丝”,让它不要起到保险丝的作用,就顺利过去了。“可以看到,大促前我们做了非常多的准备,但成败就在于一个关键的环节。”针对一个问题咬住不放松的奋力,贯穿了支付宝技术的研发实践当中。比如,在2010年,整个支付宝技术团队的目标只有一个:将支付宝支付成功率提升到极致。程立介绍,在这个目标驱动下, 2010年,支付宝不仅实现了支付成功率的提升,还实现了现在每天都会使用——快捷支付的创新,让移动支付成为可能。这个过程中,既有技术浪潮下对云支付架构的升级,也有对无数技术细节的打磨。拧过无数颗螺丝,包括从2010年第三代技术架构调整后到今天,支付宝金融科技技术让移动支付、实时风控与新型信用等成为可能,并且让技术真正成为金融业务创新的驱动力,解决了过去难以解决的金融业务问题,如“310”小微企业贷款、实时反欺诈等等。脚踏实地是因为对未来有更深的期待。蚂蚁金服CTO程立表示,过去十年是信息技术、互联网技术从量变到质变的过程,我们用技术改变了每个人的生活,改变社会的经济,但是,真正的技术革命才刚刚开始。“中国对创新的拥抱,是技术发展的最好土壤。在这片孕育创新的土壤上,未来中国互联网依然可以领先世界,生长出来更多原创的技术创新,做更多事情。我们还可以预见,图灵奖得主真正在中国土壤上生长出现。”本文作者:华蒙阅读原文本文为云栖社区原创内容,未经允许不得转载。

April 11, 2019 · 1 min · jiezi

百度社招面试题——如何用Redis实现分布式锁

关于Redis实现分布式锁的问题,网络上很多,但是很多人的讨论基本就是把原来博主的贴过来,甚至很多面试官也是一知半解经不起推敲就来面候选人,最近结合我自己的学习和资料查阅,整理一下用Redis实现分布式锁的方法,欢迎评论、交流、讨论。1.单机Redis实现分布式锁1.1获取锁获取锁的过程很简单,客户端向Redis发送命令:SET resource_name my_random_value NX PX 30000my_random_value是由客户端生成的一个随机字符串,它要保证在足够长的一段时间内在所有客户端的所有获取锁的请求中都是唯一的。NX表示只有当resource_name对应的key值不存在的时候才能SET成功。这保证了只有第一个请求的客户端才能获得锁,而其它客户端在锁被释放之前都无法获得锁。PX 30000表示这个锁有一个30秒的自动过期时间。1.2 释放锁if redis.call(“get”,KEYS[1]) == ARGV[1] then return redis.call(“del”,KEYS[1])else return 0end之前获取锁的时候生成的my_random_value 作为参数传到Lua脚本里面,作为:ARGV[1],而 resource_name作为KEYS[1]。Lua脚本可以保证操作的原子性。1.3 关于单点Redis实现分布式锁的讨论网络上有文章说用如下命令获取锁:SETNX resource_name my_random_valueEXPIRE resource_name 30由于这两个命令不是原子的。如果客户端在执行完SETNX后crash了,那么就没有机会执行EXPIRE了,导致它一直持有这个锁,其他的客户端就永远获取不到这个锁了。为什么my_random_value 要设置成随机值?保证了一个客户端释放的锁是自己持有的那个锁。如若不然,可能出现锁不安全的情况。客户端1获取锁成功。客户端1在某个操作上阻塞了很长时间。过期时间到了,锁自动释放了。客户端2获取到了对应同一个资源的锁。客户端1从阻塞中恢复过来,释放掉了客户端2持有的锁。用 SETNX获取锁网上大量文章说用如下命令获取锁:SETNX lock.foo <current Unix time + lock timeout + 1>原文在Redis对SETNX的官网说明,Redis官网文档建议用Set命令来代替,主要原因是SETNX不支持超时时间的设置。https://redis.io/commands/setnx2.Redis集群实现分布式锁上面的讨论中我们有一个非常重要的假设:Redis是单点的。如果Redis是集群模式,我们考虑如下场景:客户端1从Master获取了锁。Master宕机了,存储锁的key还没有来得及同步到Slave上。Slave升级为Master。客户端2从新的Master获取到了对应同一个资源的锁。客户端1和客户端2同时持有了同一个资源的锁,锁不再具有安全性。就此问题,Redis作者antirez写了RedLock算法来解决这种问题。2.1 RedLock获取锁获取当前时间。按顺序依次向N个Redis节点执行获取锁的操作。这个获取操作跟前面基于单Redis节点的获取锁的过程相同,包含随机字符串my_random_value,也包含过期时间(比如PX 30000,即锁的有效时间)。为了保证在某个Redis节点不可用的时候算法能够继续运行,这个获取锁的操作还有一个超时时间(time out),它要远小于锁的有效时间(几十毫秒量级)。客户端在向某个Redis节点获取锁失败以后,应该立即尝试下一个Redis节点。计算整个获取锁的过程总共消耗了多长时间,计算方法是用当前时间减去第1步记录的时间。如果客户端从大多数Redis节点(>= N/2+1)成功获取到了锁,并且获取锁总共消耗的时间没有超过锁的有效时间(lock validity time),那么这时客户端才认为最终获取锁成功;否则,认为最终获取锁失败。如果最终获取锁成功了,那么这个锁的有效时间应该重新计算,它等于最初的锁的有效时间减去第3步计算出来的获取锁消耗的时间。如果最终获取锁失败了(可能由于获取到锁的Redis节点个数少于N/2+1,或者整个获取锁的过程消耗的时间超过了锁的最初有效时间),那么客户端应该立即向所有Redis节点发起释放锁的操作(即前面介绍的单机Redis Lua脚本释放锁的方法)。2.2 RedLock释放锁客户端向所有Redis节点发起释放锁的操作,不管这些节点当时在获取锁的时候成功与否。2.3 关于RedLock的问题讨论如果有节点发生崩溃重启假设一共有5个Redis节点:A, B, C, D, E。设想发生了如下的事件序列:客户端1成功锁住了A, B, C,获取锁成功(但D和E没有锁住)。节点C崩溃重启了,但客户端1在C上加的锁没有持久化下来,丢失了。节点C重启后,客户端2锁住了C, D, E,获取锁成功。客户端1和客户端2同时获得了锁。为了应对这一问题,antirez又提出了延迟重启(delayed restarts)的概念。也就是说,一个节点崩溃后,先不立即重启它,而是等待一段时间再重启,这段时间应该大于锁的有效时间(lock validity time)。这样的话,这个节点在重启前所参与的锁都会过期,它在重启后就不会对现有的锁造成影响。如果客户端长期阻塞导致锁过期解释一下这个时序图,客户端1在获得锁之后发生了很长时间的GC pause,在此期间,它获得的锁过期了,而客户端2获得了锁。当客户端1从GC pause中恢复过来的时候,它不知道自己持有的锁已经过期了,它依然向共享资源(上图中是一个存储服务)发起了写数据请求,而这时锁实际上被客户端2持有,因此两个客户端的写请求就有可能冲突(锁的互斥作用失效了)。如何解决这个问题呢?引入了fencing token的概念:客户端1先获取到的锁,因此有一个较小的fencing token,等于33,而客户端2后获取到的锁,有一个较大的fencing token,等于34。客户端1从GC pause中恢复过来之后,依然是向存储服务发送访问请求,但是带了fencing token = 33。存储服务发现它之前已经处理过34的请求,所以会拒绝掉这次33的请求。这样就避免了冲突。但是其实这已经超出了Redis实现分布式锁的范围,单纯用Redis没有命令来实现生成Token。时钟跳跃问题假设有5个Redis节点A, B, C, D, E。客户端1从Redis节点A, B, C成功获取了锁(多数节点)。由于网络问题,与D和E通信失败。节点C上的时钟发生了向前跳跃,导致它上面维护的锁快速过期。客户端2从Redis节点C, D, E成功获取了同一个资源的锁(多数节点)。客户端1和客户端2现在都认为自己持有了锁。这个问题用Redis实现分布式锁暂时无解。而生产环境这种情况是存在的。结论Redis并不能实现严格意义上的分布式锁。但是这并不意味着上面讨论的方案一无是处。如果你的应用场景为了效率(efficiency),协调各个客户端避免做重复的工作,即使锁失效了,只是可能把某些操作多做一遍而已,不会产生其它的不良后果。但是如果你的应用场景是为了正确性(correctness),那么用Redis实现分布式锁并不合适,会存在各种各样的问题,且解决起来就很复杂,为了正确性,需要使用zab、raft共识算法,或者使用带有事务的数据库来实现严格意义上的分布式锁。参考资料Distributed locks with Redis基于Redis的分布式锁到底安全吗(上)? - 铁蕾的个人博客https://martin.kleppmann.com/…热门阅读技术文章汇总【Leetcode】101. 对称二叉树【Leetcode】100. 相同的树【Leetcode】98. 验证二叉搜索树 ...

April 10, 2019 · 1 min · jiezi

世界冠军之路:菜鸟车辆路径规划求解引擎研发历程

阿里妹导读:车辆路径规划问题(Vehicle Routing Problem, VRP)是物流领域最经典的优化问题之一,具有极大的学术研究意义和实际应用价值。菜鸟网络高级算法专家胡浩源带领仓配智能化算法团队经过两年的研发,逐步沉淀出了一套完善、强大的车辆路径规划求解引擎,为菜鸟内外部多项业务提供了技术支持。通过不断地对算法进行探索打磨,我们终于在车辆路径规划问题最权威的评测平台上打破了多项世界纪录,标志着菜鸟网络在此领域的技术研究已经进入世界前列。问题介绍车辆路径规划问题是运筹优化领域最经典的优化问题之一。在此问题中,有若干个客户对某种货物有一定量的需求,车辆可以从仓库取货之后配送到客户手中。客户点与仓库点组成了一个配送网络,车辆可以在此网络中移动从而完成配送任务。在求解此问题过程中,需要优化的决策变量为每个客户的配送任务应该分配到哪一辆车上,以及每辆车完成客户配送任务的先后顺序,优化目标为最小化使用的车辆数和车辆总行驶距离(通常情况下最小化车辆数为第一优化目标)。以i,j表示配送网络中的节点(i,j∈{0,1,2,…,N}), 其中0表示仓库点,其它表示客户点),以k表示车辆(k∈{1,2,…,K}),以[图片上传失败…(image-4ad9e3-1554866885896)]为决策变量,表示车辆k是否从i点行驶到j点。则标准的车辆路径规划问题可以使用以下数据规划的形式描述:其中,表达式(1)表示优化目标为最小化使用车辆数;表达式(2)表示每个点有且仅有一辆车负责配送其所需要的货物;表达式(3)表示每辆车最多负责一条配送线路;表达式(4)表示网络中的流量平衡条件;表达式(5)表示每辆车负责配送的货物不超过其承载能力限制;表达式(6)为防止孤立子环出现的约束条件。车辆路径规划问题在物流领域和生产领域的应用非常广泛。所以在实际应用中也出现了一些在标准问题的基础上增加了某些变化之后的变型问题。其中较为常见的包括:CVRP:Capacitated VRP, 限制配送车辆的承载体积、重量等。VRPTW:VRP with Time Windows, 客户对货物的送达时间有时间窗要求。VRPPD:VRP with Pickup and Delivery, 车辆在配送过程中可以一边揽收一边配送,在外卖O2O场景中比较常见。MDVRP: Multi-Depot VRP, 配送网络中有多个仓库,同样的货物可以在多个仓库取货。OVRP:Open VRP, 车辆完成配送任务之后不需要返回仓库。VRPB: VRP with backhauls, 车辆完成配送任务之后回程取货。以上各类问题之间的关系可以通过图1表示:经典求解算法车辆路径规划问题是典型的NP-hard问题,非常具有挑战性。同时因为其在实际应用的巨大价值,学术界和工业界对此类问题的优化算法的探索已经持续了几十年的时间。已有的经典求解算法可以分为精确解算法和启发式算法两大类。在精确解算法方面,最基本的方法为分支定界算法,虽然其能够从理论上保证在有限时间内获得最优解,但是在实际计算中存在计算耗时巨大的情况。为了提高求解效率,研究者们先后提出了多种Branch-and-Cut以及Branch-Cut-and-Price方法,大幅降低了算法的求解时间。但是对于实际应用中较大规模的问题而言(例如超过200个点的问题),精确解算法依然无法能够在合理的时间内完成计算。所以还有一大部分研究集中于启发式算法领域。启发式算法的思想为通过一系列启发式的规则来构造和改变解,从而逐步提升解的质量。对于VRP而言,较为经典的启发式算法为Clarke-Wright算法等。此外,经过不断的探索研究,元启发式算法被证明在求解VRP方面具有很好的效果和效率。一些经过精心设计的元启发式算法,例如模拟退火、禁忌搜索、遗传算法、蚁群算法、变邻域搜索、自适应大规模邻域搜索算法等在求解VRP上有着非常好的表现。菜鸟车辆路径规划引擎研发历程阶段一:核心基础算法研发在研发之初,菜鸟仓配智能化算法团队充分调研了VRP领域的相关学术论文和软件产品等,最终确定了以自适应大规模邻域搜索(Adaptive Large Neighborhood Search, ALNS)为核心算法进行算法引擎的建设。相对于其它算法,ALNS算法的优势包括:算法框架易于拓展,除了求解标准的VRP之外,还能够求解VRPPD,MDVRP等变型问题;相对于普通的Local Search类型的算法,ALNS在每一步搜索过程中能够探索更大的解空间;ALNS算法在搜索过程中能够自适应地选择合适的算子,从而对于不同类型的问题数据能够有比较稳定的良好求解结果;通过设计实现不同类型的算子,ALNS可以实现不同的搜索策略,从而便于算法的升级拓展。经典的ALNS算法的主流程如图2所示:如图2所示的ALNS算法的主要步骤为:使用一定的规则构造一个初始解(即Initial过程);基于算子的权重,选择此次迭代过程中使用的Ruin算子和Insert算子;对此次迭代的初始解执行Ruin操作,即将部分已经被车辆服务的客户点删除,使初始解成为一个不可行解;对步骤(3)获得的解执行Insert操作,即对于还没有被车辆服务的客户点,将其插入到解中,尽量获得一个可行解;基于优化目标函数评估步骤(4)获得的新的解,并根据一定的策略决定是否接受新解;判断是否达到终止条件。如果是,则终止计算,返回当前找到的最好解;否则,基于此轮计算中算子的表现,更新算子的权重,并返回到步骤(2)。以ALNS算法为核心,菜鸟仓配智能化算法团队完成了第一版VRP优化引擎的研发。对比测试结果表明其求解效果和效率显著优于jsprit等国际上流行的开源VRP Solver。在此基础上,菜鸟仓配智能化算法团队还对引擎进行了服务化,从而更方便地服务于公司内外部用户。阶段二:算法体系丰富与升级为了更好地服务于公司内外部用户,菜鸟仓配智能化算法团队不断对VRP优化引擎的核心算法组件进行了丰富与升级。主要体现在以下几个方面:1.完善功能:在原算法核心框架的基础上,增加了对Pickup and Delivery(车辆一边揽收一边派送)、Multi Trip(车辆多趟派送)等类型问题的支持;而且通过对实际业务问题的抽象,总结出了不同类型的优化目标方程(例如最小化阶梯定价的总成本、最小化配送时间等)以及约束条件(例如车辆行驶距离限制、车辆配送订单数限制、车辆跨区数限制等)。从而使求解引擎能够求解的问题更加全面广泛。2.丰富算子:为了提升引擎的求解效果和稳定性,菜鸟仓配智能化算法团队还在VRP求解引擎中增加了更加丰富的优化算子,例如不同类型的局部搜索算子(例如Two-Opt, Three-Opt, Cross-Exchange等)、不同类型的中间结果接受策略(例如Greedy, Simulated Annealing等)。3.提升效果:菜鸟仓配智能化算法团队还尝试了多种算法来提升引擎的求解效果,主要包括:Guided ejection search (GES):此算法通过不断尝试删减一辆车,并将此辆车服务的客户添加到其它车辆上,从而实现降低车辆的使用数。此算法在降低车辆数方面具有非常好的效果;Fast local search (FLS): 在搜索过程中,只搜索那些有希望改善当前解的的邻域空间,从而大幅降低搜索计算量,提升算法求解速度;Guided local serach (GLS): 在搜索过程中对局部最优解的某些特征施加惩罚项,从而改变搜索方向,避免陷入局部最优;Edge assembly crossover (EAX): 一种基于两个解生成一个新的解的方法,新生成的解能够很好的继承父代个体的空间结构;Branch-and-Price-Based Large Neighborhood Search:此算法将VRPTW问题分解为了Restricted Master Problem和Subproblem。其中在Restricted Master Problem中,基于一系列可行的路径,通过求解Set Partition问题来获得原问题的解;在Subproblem中,通过Tabu Search来搜索新的可行的路径;Path-Relink:此算法的核心思想为通过从initial solution到guiding solution的逐步移动,探索两个解之间的广阔的邻域,从而有可能发现更好的解;Hybrid Cluster and Heuristics:此算法是针对超大规模的问题而设计,首先通过合适的聚类算法对客户点进行聚类,从而将原问题分解为多个小规模的子问题,然后并行求解,最终将子问题的解组装成为原问题的解。阶段三:算法并行化升级对于大部分启发式算法而言,可以天然地通过并行化计算来提升搜索效率和效果,例如并行地计算评估多个相邻解的质量、向多个邻域方向进行搜索或者使用多种策略进行搜索等,甚至并行地使用多种算法进行搜索等。所以为了进一步提升VRP引擎的求解质量,菜鸟仓配智能化算法团队对VRP引擎进行了并行化升级。在此过程中,先后研发实现了三套并行化算法架构。Population IslandPopulation Island的算法架构如图3所示。在算法执行过程中,有若干个Island并行执行计算,每个Island独立地进行演化,其中各有一个Master和若干Worker,其中Worker负责具体的搜索任务的计算执行,Master负责任务的分配协调以及与其它Island之间的通信等。每隔一定的计算步数,各个Island的Master之间会相同通信,分享搜索过程中获得的知识,从而提升整体的搜索效率。Parallel MemeticParallel Memetic的算法架构如图4所示。整个算法可以分为两个阶段,第一个阶段的计算重点在于减少使用的车辆数(Delete Route),在此阶段中,若干个Worker并行计算,并每隔一定的步数相互通信分享信息。第一阶段结束之后,会获得若干中间结果,将这些结果作为第二阶段中每个Worker上的初始演化种群进行计算。第二阶段的计算重点在于降低车辆行驶距离(Reduce Distance),第二阶段的Worker之间同样有相互通信分享知识的机制,而且可以通过控制演化过程中父代个体的选择机制来进行动态地调节Exploration与Exploitation。Central PoolCentral Pool的算法架构如图5所示。在算法中有若干个Worker负责具体的搜索任务,并将搜索得到的解返回到Central Pool中,由Central Manager对解进行排序、筛选、聚类等处理,然后Central Manager会依据当前Central Pool中的解集情况生成新的计算任务并发送给Worker执行。Central Manager可以对解空间进行合理的刻画,并通过计算任务的管控分配在Exploration与Exploitation之间进行平衡,从而提升求解效率。已获得成果通过对优化算法的不断迭代升级,以及在工程架构上的更新完善,菜鸟网络的车辆路径规划引擎在服务内外部客户的同时也在技术沉淀上获得了重大成果。在VRP算法领域,最权威的评测对比平台为欧洲独立研究机构SINTEF发起并管理的世界最好解榜单(Best Known Solution),其中包括了对Solomon数据集(1987年提出)和Gehring & Homberger数据集(1999年提出)共356份测试数据的世界纪录。全世界最顶尖的优化算法学者(例如Jakub Nalepa, D. Pisinger, Yuichi Nagata等)以及优化技术公司(例如Quintiq等)都不断地在此平台上刷新世界纪录,将车辆路径规划领域的技术逐渐地推向极致。菜鸟网络仓配智能化算法团队在算法研发过程中也一直以此数据集为主要算法评估指标。随着算法的不断升级优化,在越来越多的数据上接近甚至持平世界纪录。最终,在2018年9月,仓配智能化算法团队的算法终于获得了比世界纪录更好的结果,并经过了平台的验证,向全世界的研究者进行了公开。截止到2019年4月初,菜鸟网络在此评测数据集上共持有48项世界纪录,持有数量在众多研究团队中位居前列,这标志着菜鸟在这项领域的技术进入了世界顶尖水平,为菜鸟和集团赢得了巨大的技术影响力。总结及展望在历时两年的研发过程中,菜鸟仓配智能化算法团队的同学们付出了巨大的努力和心血。同时在这个过程中,集团多个事业部的兄弟团队在算法研究、工程技术等方面也提供了很多很好的专业建议,在此表示衷心的感谢!在之后的工作中,菜鸟仓配智能化算法团队将会把VRP引擎打造成为更强大、稳定、易用的优化产品,为菜鸟和集团的各项业务发展提供技术支持,并有计划地向外输出,为中国的物流行业赋能提效。本文作者:何柱、守初、本华阅读原文本文来自云栖社区合作伙伴“ 阿里技术”,如需转载请联系原作者。 ...

April 10, 2019 · 1 min · jiezi

深度揭秘:机器学习对软件开发带来哪些影响?

摘要: 当软件开发碰见机器学习,到底能碰撞出什么样的火花呢?机器学习有望从根本上改变软件开发的本质,这也许是自FORTRAN和LISP被发明以来软件开发领域改变最大的一次。这些变化对数百万正在从事软件开发的人而言,意味着什么呢?失业?裁员?现有的软件开发将变得面目全非?自20世纪70年代以来,我们尽可能的构建了足够多的软件。我们有高级语言,低级语言,脚本语言以及用于构建和测试软件的工具,但我们利用这些工具做的事情却没有发生太大变化。我们现在拥有的语言和工具比50年前要好得多,但它们本质上是一样的。我们仍然使用代码编辑器,但这些编辑器变得更花哨了:他们有彩色的高亮,变量名补全,它们有时可以帮助我们完成重构等任务,但他们仍然是emacs和vi的后代。面向对象编程代表了一种不同的编程风格,但从某种本质上而言并不是“全新”的事物,对于函数式编程我们可以一直追溯到50年代。未来我们将专注于机器学习而不是人工智能。机器学习曾经被称为“AI最管用的那一部分”,更重要的是,“机器学习”这种提法可以避开类似“通用智能”这种叫法。因为这样的系统目前不存在,并且可能永远不存在,目前来看只有人类才能做到这一点。而机器学习可能只比模式识别多一点点,但我们已经看到模式识别可以完成很多工作。实际上,手工编码的模式识别是我们当前工具集的核心:这真的是现代优化编译器所正在做的。麦肯锡估计“使用现有技术,只有不到5%的职业可以完全自动化。然而,大约有60%的职业工作活动中,具有30%或更多的组成部分能够被自动化。”软件开发和数据科学不会成为完全被自动化的职业之一。但优秀的软件开发人员一直在寻求对于繁琐,重复的任务的自动化,毫无疑问,软件开发本身将日益变得可以被自动化。这并不是一个激进的愿景,因为我们在过去的半个世纪里持续的为了自动化工具而努力。编译器对编写机器代码的过程进行了自动化。脚本语言通过将更大,更复杂的程序粘合在一起来自动执行许多枯燥无味的任务。软件测试工具、自动部署工具、容器和容器编排系统等等,这些都是为了对开发、部署、管理软件系统的过程进行自动化的工具。而且这些都没有利用机器学习,但这肯定是下一步它们要做的。机器学习会不会吞并软件?毕竟,“软件吞噬世界”是一个日益抽象和普遍化的过程。笔记本电脑,手机或智能手表已经逐渐取代收音机,电视机,锁和钥匙,电灯开关,这是因为我们并没有将计算机仅仅看成数字计算器而是通用机器。从这个角度来看,很容易将机器学习想象成下一个抽象层次,这是我们迄今为止发现的最通用的问题解决工具。当然,神经网络已经证明了它们可以执行许多特定任务。由资深人士乐观地表示,对于许多任务而言,收集数据比编写程序更容易。对于一些非常有趣且困难的程序,这无疑是正确的,比如说收集围棋或国际象棋的训练数据很容易,但很难写一个程序成功地玩这些游戏。另一方面,数据收集并不总是那么容易。我们无法设想自动标记图片的程序,特别是在Facebook和阿里巴巴这样收集了数十亿张图片的网站,而且其中许多图片已被人类标记过。对于像人脸识别这样的任务,我们不知道如何编写软件,而且很难收集数据。对于其他任务,例如计费,可以很容易地根据一些简单的业务规则编写程序。如果你能够收集数据,你编写的程序将更好地适应不同的情况,还能够检测异常,这一点当“将人类纳入软件迭代的循环”时,尤为如此。正在代替代码的机器学习机器学习正在使代码变得高效:Google的Jeff Dean说,500行TensorFlow代码已经取代了谷歌翻译中的500000行代码。虽然代码行数是一个值得质疑的指标,但无论是从编程工作量角度来看还是从需要维护的代码量来看,这个突破都是可称赞的。更重要的是这段代码是如何工作的:相比于五十万行的代码,这是一个经过训练以用于翻译的神经网络。神经网络可以随着语言的变化和使用场景的变化,在新数据上被重新训练,而且整个代码都不需要重写。虽然我们不应低估训练任何复杂度的神经网络的难度,但我们同样也不应低估管理和调试一个巨大代码库带来的问题。研究表明,神经网络可以通过组合现有模块来创建新程序。虽然以这种方式构建的程序很简单,但是让单个神经网络能够学习执行几个不同的任务是很重要的,每个任务通常都需要一个单独的程序。Pete Warden认为:“开发人员必须成为一名教师(教机器),一名训练数据的策划人。”我们发现,这种说法非常具有启发性。软件开发不会消失,但开发人员必须以不同的方式来思考自己。你如何构建一个解决一般问题的系统,然后教该系统解决一个特定的任务?这貌似听起来像是一个风险很高又麻烦的场景。但这意味着我们的系统将变得更加灵活,具有很强的适应性。Warden设想的未来,更多是关于产出的,而不是关于撰写代码行数。Peter经过更加系统的思考,认为机器学习可以从训练数据中产生短程序,而不是很大的程序。数据管理和基础设施早期的迹象表明,机器学习有着可以胜过传统的数据库索引的性能:它可以学习预测数据的存储位置或者预测数据是否存在。机器学习明显更快,并且需要更少的内存,但也有着相当大的限制性:当前基于机器学习的工具不包括多维索引,并假设数据库不经常更新。重新训练比重建传统数据库索引需要更长的时间。尽管如此,研究人员正在研究如何学习到多维索引,查询的优化,重新训练的性能。机器学习已经进入了数据基础设施的其他领域。数据工程师正在使用机器学习来管理Hadoop,从而可以更快地响应Hadoop集群中的内存不足等问题。 Kafka工程师使用机器学习来诊断问题,从而简化了管理许多配置的问题,这些配置会影响数据库的性能。数据工程师和数据库管理员不会过时,但他们可能需要发展一下他们的机器学习技能。机器学习将帮助他们使困难的问题变得更简单,管理数据基础架构这个工作,将不会像正确设置数百个不同的配置参数那样,它会更像是在训练一个系统,让整个管理工作运行的更有条理。使困难问题变得可管理是数据科学最重要的问题之一。数据工程师负责维护数据管道:提取数据、清理数据、特征工程和模型构建。同时他们还需要负责在非常复杂的环境中部署软件,一旦部署了这些基础架构,还需要不断监视它,以检测(或防止)资源用尽,确保模型正确运行。这些都是非常适合用机器学习处理的任务,我们越来越多地看到像MLFlow这样的软件能够被用于管理数据管道。数据科学在自动化编程的早期表现形式中,工具旨在使数据分析师能够执行更高级的分析任务。Automatic Statistician是一种更新的工具,可自动进行探索性数据分析,并为时间序列类型的数据提供统计模型,且附有详细说明。随着深度学习的兴起,数据科学家发现自己需要寻找合适的神经网络架构和参数。让神经网络学着找到合适自己架构的过程,也可能被自动化。毕竟,神经网络就只是单纯的自动化学习工具:虽然构建神经网络结构需要大量的人力工作,但是不可能手动调整模型的所有参数。未来的场景应该是使用机器学习来探索所有可能的神经网络架构:正如一篇文章指出的,10层网络可能就有10的10次方种可能性。已经有其他研究人员使用强化学习来让神经网络架构开发变得更加容易。模型创建不是一劳永逸的事情:数据模型需要不断进行测试和调整。我们开始看到的用于持续监控和模型调整的这些工具并不是特别新颖,比如用于A/B测试的老虎机算法已经存在了一段时间,对于许多公司来说,老虎机算法算是强化学习的第一步。机器学习同样也可以用来查找软件中的漏洞,有些系统会浏览代码,并寻找已知的缺陷。这些系统不一定需要能够修复代码,也不承诺找到所有潜在的问题。但是他们可以很容易地对危险的代码进行高亮显示,并且他们可以允许在大型代码库上进行开发的程序员提出诸如“还有类似这样的问题存在于其他地方吗?”之类的问题。游戏开发者也正在探索利用机器学习来降低游戏开发成本以及创造更多有趣的游戏。机器学习可以用来制作看起来更逼真的背景和场景吗?游戏开发者都知道对逼真的场景和图像进行绘制和建模又耗钱,又费时。目前,非玩家角色(NPC)所做的一切都必须明确编程。机器学习可以用来模拟NPC的行为吗?如果NPC可以学习到行为,我们可以期待更有创意的游戏玩法出现。展望未来软件开发人员的未来是什么样的?软件开发是否会同样走上麦肯锡为其他行业预测的演化路径呢?在软件开发和数据科学中所涉及的30%的工作是否会被自动化?也许,刚刚我们所谈的只是对未来某种情况的简单解读。但毫无疑问,机器学习将改变软件开发。如果未来我们现在所认为的“编程”中很大一部分被自动化了,那也没什么好惊讶的。编译器不进行机器学习,但他们通过自动生成机器代码来改变软件行业,这在未来可能并不是什么新鲜事。重要的问题是软件开发和数据科学将如何变化。一种可能性,实际上是一种事实:软件开发人员会在数据收集和准备方面投入更多精力。没有数据训练,机器学习就什么都不是。开发人员必须做的,不仅仅是收集数据; 他们必须构建数据管道,以及构建管理这些管道的基础设施,我们称之为“数据工程”。在许多情况下,这些管线本身将使用机器学习来监控和优化自己。我们可以看到训练机器学习算法成为一个独特的子专业;我们可能很快会有一个新职业-“训练工程师”,就像我们目前谈论的“数据工程师”一样。Andrew Ng在他自己的《机器学习渴望》一书时中说:“这本书的重点不是教你ML算法,而是教你如何让ML算法有效。没有编码,也没有复杂的数学。本书几乎完全侧重于模型训练过程,而不仅仅是编码,训练才是让机器学习有效工作的本质。”我们提出的想法都涉及一种能力:它使人类能够生产出更快、更可靠、更好的能够生效的产品。开发人员将能够将更多时间花在有趣且更重要的问题上,而不是把基本工作做好。那些问题可能是什么问题呢?在一篇关于智能增强的讨论里,Nicky论证了,计算机在针对一个问题寻找最佳答案上表现出色。因为计算机的本质是计算工具。但是他们不是很擅长“找到一个值得回答的有趣问题”,这件事是人类做的。那么,我们需要提出哪些重要的问题呢?这些重要的问题已经在不断的被发现了,比如我们刚刚开始认识到道德在计算中的重要性,才开始考虑更好的用户界面,包括会话界面:它们将如何运作?即使在人工智能的帮助下,我们的安全问题也不会消失。先不管安全问题怎样,我们所有的设备都在变得“聪明”。这意味着什么?我们希望它们做什么?人类不会编写尽可能多的低级代码。但是正因为他们将不会去编写那些代码,所以他们可以自由地思考代码应该做什么,以及它应该如何与人交互。需要解决的问题永远不会少。很难想象“人类不再创建软件”的未来,但很容易想象“将人纳入软件研发的循环”中在未来将占越来越多的比重。本文作者:【方向】阅读原文本文为云栖社区原创内容,未经允许不得转载。

April 8, 2019 · 1 min · jiezi

阿里云智能技术战略架构师陈绪:透视2019云计算酣战

本文作者是阿里云智能技术战略架构师陈绪。2019年3月21日阿里云北京峰会落下帷幕,阿里云智能总裁张建锋阐释了阿里云战略加速的“四级火箭”:达摩院加持的云、数据智能的云、最佳实践的云和被集成的云,在业界引起巨大反响。作为“企业级基础设施专场 - CIO核心能力:云上构建亿级规模的IT基础设施”的出品人,我有幸主持了该专场,也做了一个10分钟的开场演讲,很高兴结合大会的组织过程,把我对2019年云计算发展的思考和大家做一个分享。企业级基础设施专场 - CIO核心能力:云上构建亿级规模的IT基础设施感谢许呙兢同学的信任和重托,我和专场架构师张强及另一位出品人孟蓁一起,操持了议题的甄选和确定。国内公共云的营收,目前很大一部分还来自IaaS基础设施,首先这说明中国的云计算发展阶段还处于早期,对于弹性、效率等价值的认可还有很大的挖掘空间。业界有一个说法:当下挣钱的东西都不前沿,当下前沿的东西都不挣钱。而企业基础设施的技术和产品既要挣钱,又要前沿,那么主题应该怎么安排呢?应该说,同学们要发布产品和介绍技术的积极性还是很高的。初期review之后,经过话题整合,很快我们就确立了8个演讲。何诚同学的“飞天基础设施智能运维创新和实践”胡晓博同学的“基于ECS构建稳定、高业务弹性、低成本的企业应用实践解析”Alex Chen同学的“普惠数据智能经济 下一代云上存储创新”NetApp总监王熙明先生的“DT时代的企业混合云存储架构探讨”谭礼铨同学的“构建安全、智能、开放的下一代企业级网络”潘岳同学的“异构计算为企业上云提供核动力”张子轩同学和周剑同学的“实现规模化、自动化的云上IT管理”章君同学的“云上护航服务 保障云上尖峰时刻”主线非常清晰,就是从IDC、弹性计算、存储、存储生态、网络、GPU异构、OpenAPI、云上护航等维度展示阿里云技术设施的亿级能力,逻辑是从下往上逐层展示我们的最新技术和产品,提升客户的兴趣!特别感谢王熙明先生带来NetApp对混合云存储的思考,我也受益良多。为何要我开场我本意是找一位美女同学来开场和主持。许呙兢同学指出,我在业界小有名气,如果请我开场,会吸引更多目标人群报名参会;同时,许呙兢对业界媒体大咖“狒哥”的主持风格大为赞赏,就是每个演讲完毕后由主持人做一个简要的点评,帮助听众理解,希望我也能沿袭。作为出品人,当然要以专场的价值作为第一价值,我就积极接受了开场和主持的任务。那么,我想既然要开场,那么有两个事情要说清楚,第一是本专场演讲的安排逻辑,第二还得送一碟开胃小菜,就是本文要将的2019年云计算发展趋势。一般来说,趋势得凑足十条,不能多也不能少。于是我拍拍脑袋想了14条,发在内部钉群,征集部门同学们的反馈,结果就沉淀了以下十条,希望引起大家的共鸣。2020年前后,中国会出现盈亏平衡的公共云我认为,公共云的盈亏平衡点对于公司的长远发展是至关重要的。2015年7 月 24 日,全球电商巨头亚马逊发布了 2015 年第二季度财报,一直以来因为亏损而出名的亚马逊终于盈利了。该季度AWS 贡献了 18.24 亿美元净营收,同比增长 81%;AWS 运营利润也从上年同期的 7700 万美元增加到 3.91 亿美元。财报发布后,亚马逊股价在盘后大涨近20%。之后,AWS的营收和盈利都一骑红尘,快速增长。也正是在这个时间阶段,阿里云的“骗子”成了“神”。不久后,央视在2016年3月7日《走近科学》栏目播出了一部专题片“王博士的计算梦”。注意,这个论断中的多个关键词:2020年前后。2019年是没戏的,原因可以从各公共云公司的财报中看到体现。我们内部的同学和我说:十年的努力,让我们对成本已经控制到极致,我们都不盈利,别人怎么可能盈利。中国。上文已经说过AWS已经在全球第一个盈利。公共云。其实在中国做云公司盈利说难也难,说简单也简单。我就知道有些小公司,人数不多,一年接几个小单子,账面上就是盈利的。但问题是,这些订单都是通过以前的关系得来,不具备扩大的潜力。所以,一时的盈亏平衡是没有意义的,长期地从盈亏平衡开始的快速盈利才是关键。在IT行业,特别是赢家通吃的领域,有一个证明过多次的现象。第一名盈利,第二名不盈利,第三名及之后全都亏钱。2018年年底,中国有几个云计算公司大打口水仗,都说自己是第N名,完全是没有任何意义的PR行为。还有一种手法,就是采用财务手法来调节收入。报表可能这么显示,近几年的财务报表都是微盈利。由于没有看到详细的报表,可以猜测很大一部分收入是来自私有云订单或者硬件的销售,短期内覆盖了公共云的亏损。我所说的“盈亏平衡的公共云”,指的是真正从IaaS、PaaS等领域获得盈利,这样才有长远发展的价值,而非短期对投资者的一种迎合。我坚持认可公共云领域的马太效应,就是强者恒强,大者恒大。如果发展顺利,出现盈亏平衡的中国公共云厂商的时间节点是2020年,如果慢一点,大概率是2021年。只有出现不可阻挡的优势,才会有公司退出这个领域,美国前几年就出现过多家公司退出公共云领域。通过开放API管理混合云会更受大客户欢迎本文的发展趋势条目是早就准备好的,我也没有参加张建锋总裁的主题演讲资料准备,但是我高兴地发现,上午主会场的演讲为这一条做了一个铺垫。因为本条和作为一级火箭的“被集成”是相辅相成的。“被集成”是公司战略,那么战术上如何被集成?手段是通过OpenAPI。前几天技术战略部的一位同学和我分享了英特尔中国研究院院长宋继强博士的一张演讲照片,图中显示的“统一的异构计算软件开发接口”OneAPI和这里说的OpenAPI也是一脉相承。2018年中,阿里云OpenAPI的开发工作开始加速。这说明,我们的“被集成”不是突然提出的,而是经过了长时间的内部酝酿。为什么要有OpenAPI?因为阿里云提供的首先是资源,包括计算、存储、网络等等,我们也提供官方的后台控制管理界面。要控制一台机器,十台机器都是简单的,但是要通过官方后台控制成百上前台机器就比较麻烦。同时,GC6和GC7的大客户,往往拥有很强的技术研发团队,对自己的业务也非常清楚。他们更希望开发自己的控制台,并灵活地调用各种阿里云提供的资源。没有OpenAPI,这种开发就无法进行。当年淘宝的聚石塔,也是为商家提供了API,方便商家定制自己的后台,从而获得了较大成功。大客户一旦感受到API带来的方便,就无法离开。更进一步,AWS一直在致力于提供优秀、统一、高效的API,帮助大客户更好地使用资源。当很多国外客户和合作伙伴进入中国的时候,他们缺省就认为阿里云会有系统的OpenAPI可以调用。我曾经谈到过公共云是终局,但是混合云是必经的历史阶段,现在正处于这个历史阶段,所以要满足混合云的需求,也必须提供OpenAPI,更好地实现阿里云的“被集成”。客户倾向于用云存储灾备技术保障数据可靠性承接上一条的混合云,用户对混合云很感兴趣,主要是因为弹性。弹性是云的基本特征,没有弹性的云其实不是真正的云。私有云要获得弹性,手段就是构建混合云。同时,混合云还可以带来数据的高可靠性。2018年,中国市场出现过多次因为存储不稳定带来的灾难事故,而且某些极端情况下数据完全丢失无法恢复。事件发生之后,客户对数据可靠性的需求和投资的意愿都有很大提升。阿里云存储的可靠性是11个9,在提供3AZ的环境下,可靠性达到12个9。要保证用户的数据绝对不丢失怎么办?我不认为请客户自己买一块移动硬盘来定期备份数据会是云计算的未来发展方向,我认为:客户倾向于用云存储灾备技术保障数据可靠性。NetApp的王熙明总监介绍了备份和灾备的区别。备份是一个有很长历史的名词,就是在另一个媒介上把数据拷贝一份,如果原来的数据丢失,拷贝回来即可。而灾备就是一个云计算的名词了,灾备是指将你的私有云的数据和代码在云上完整地备一份,一旦本地私有云出问题,无论是数据丢失或者是虚机崩溃,公共云上能够立刻拉起计算的环境,并接管对客户的服务,让最终用户感觉不到私有云出了问题。所以这里的存储不仅是对数据的备份,而且还有对整个计算环境的备份和实时拉起的能力。阿里云的混合云存储团队,经过2年的艰苦工作,研发了HDR(Hybrid Disaster Recovery)解决方案。具体技术就不一一赘述了,我这里强调一点,HDR方案不仅是灾备方案,而且也能解决客户的搬站问题。简单而言,使用HDR的一半功能,将客户的私有云可以迁移到公共云上;接着使用另一半功能,客户私有云和阿里云公共云构成灾备解决方案。迁移上云只是灾备技术的一个子集。中国出现第一家真正全面云化的大型公司什么叫全面云化,我觉得有两个关键指标:一是公司的核心业务都要放到云上,很多的公司,特别是金融和电信公司,外围和中间层都是用了虚拟化、云原生等云计算技术,但是核心交易系统还是跑在传统大机上,这个就不是全面云化;二是公司内部只能有一朵云,这意味着所有的资源是统一调度和管理的,有多朵云的不是真正全面云化。每个成功的互联网公司都有自己的技术发展历程,在业务快速发展的过程中,都是怎么有效怎么来,怎么快怎么来。这就导致基础设施的架构设计不太优雅,或者说不符合现代云计算操作系统的要求。将原有的业务迁移上云,需要时间和详细的分析规划,同时不能影响现有业务。打铁还需自身硬,公共云公司将自己的业务全部上云,会最有说服力。正如张建锋总裁指出的,现在阿里巴巴集团业务有60-70%是使用阿里云的资源,在未来1-2年内,将100%使用阿里云的资源。一旦成功,这将会成为一个历史性的分水岭。因为据我所知,很多云计算公司内部有多朵完全隔离的云,而且整合也是遥遥无期,没有日程表。全面云化,说起来简单,做起来难。自建预算大幅削减的企业成为上公共云的主力军对于云计算能帮助企业节省成本的文章我写过一些,最近我不停地看到这种趋势落到了实处。为了完成数字化转型,从而享受数字经济带来的技术和成本红利,是敦促企业上云的第一动力。云计算,已经不是一个上亦或不上的问题,而是一个早上或者晚上的问题。不跟上云时代的步伐,就会被时代抛弃。2019年经济形势严峻,很多公司都开始考虑将线下的计算集群和自建的云计算放到公共云上来。很多客户停止了自建,原因是成本高企,在慢慢消化原来自建机器的同时,剩下的就是往公共云上放多少业务的问题。2019年之前,这些客户更愿意自己拥有云资产。愿意考虑上云,说明客户遇到了问题,很大程度上是自建预算大幅削减的问题。即使是技术能力不错的公司,也会因为财务预算的原因选择上公共云,大家要积极做好承接的准备。回顾中国的云计算历史,公共云爆发式增长的时期并没有过去,还有大批企业的传统IT没有上云,现在很多公司会直接跨越自建的阶段,直接使用公共云。Kubernetes和Kata Containers会成为业界主流Kubernetes是容器的管理和编排工具,已经成为云原生的代表项目广为认可。阿里云就是Kubernetes的所有者CNCF基金会的白金会员。今天我们谈一下Kata Containers,最近有一则新闻,是Hyper公司的创始团队赵鹏、王旭等同学加入蚂蚁金服,Hyper也是Kata Container的主要贡献者。但是,我们今天谈到对于Kata Containers的认知和使用和这则新闻并没有直接联系。2015年,英特尔宣布Clear Containers开源项目,并于2017年底和Hyper的runV合并,新项目称为Kata Containers,与Open Container Initiative(OCI)规范以及Kubernetes的容器运行时接口(CRI)完全兼容。顺便说一下,2019年1月发布的Kata Containers 1.5版本已经支持了AWS发布的Firecracker虚拟机管理程序。什么是Kata Containers?四个字:安全容器。Docker容器很好,但是不能解决安全问题。安全问题的解决之道是利用CPU硬件的虚拟化功能。Kata Containers将容器的敏捷性和VT硬件虚拟化带来的安全性完美地结合在一起。公共云的规模效应带来无可辩驳的成本优势我看到很多专家从各种维度讲解私有云比公共云便宜,这里就不一一分析了。其实我是很疑惑的,因为这个逻辑上不通,因为大规模使用云计算而带来的成本摊销,是云计算提升IT效率的重要手段之一。如果规模化没有带来更高层次SLA上的价格优势,就从根本上否定了云计算的价值。首先,这些专家往往没有计算自建的私有云所带来的人员、维护等多项费用。而公共云的使用是一揽子付费,付款之后,电费、空间、机房等费用都包含在内了。此外,计算的灵活性也是一个问题。平均每天需要10台物理机进行计算的客户不会因为一年365天中有一天要用100台机器的规模而采购100台物理机。既要享受100台的峰值计算力,又要不多买一台机器的私有云,是做不到的。要使用云,要为云带来的弹性和效率买单。开源生态成为云厂商维护开发者关系的手段从1995年开始我接触Linux并长期在开源社区活动,深刻体会到开源和开发者关系之间的血肉联系。我也多次谈到,自主研发和开源并不矛盾,这就意味着云厂商可以更好地使用开源生态这个杀手锏来加强和开发者之间的连接。前微软CEO鲍尔默曾经在微软大会上喊出“Developer、Developer、Developer”的口号,他认识到获得开发者支持是微软成功的关键。云平台的成功标志也是能否获得广泛的开发者支持。我在英特尔期间于2015年4月发起创立的中国开源黑客松(半年一次)已经坚持到第九届,开发者以代码会友,解决网友见面问题。这种活动会成为中国的主流。我更倾向于加入技术联盟,以代码说话是开源生态的基本交流方式。我于2007接手的、从2006年发起的中国Linux内核开发者大会将在2019年第一次来到杭州,希望为大家带来Linux内核顶尖大师的讲座和交流机会。目前很多公司的开发者关系,还停留在口号上,没有落到实处。开源产生以来,涌现出很多优秀的开源项目,这些项目成为了业界事实上的标准。帮助更多的开源项目在云平台上取得成功,是撬动开发者的重要手段。成功的重要标志就是能否带来实际的经济收益。开发者关系和开源生态给开发者带来的不仅仅是名气,而是要给开发者带来实实在在的盈利。只有云平台自己挣钱,其他参与方都只挣经验不挣钱的生态是不健康、不可持续的生态。云端GPU计算在业务中应用的广度和深度将成为未来十年衡量企业竞争力的新标尺2018年12月25日,斯坦福大学发布最新的DAWNbench深度学习推理榜单,阿里云获得了图像识别性能及成本双料冠军,打破了基于亚马逊AWS计算平台保持的长达8个月的纪录。这是该榜单首次出现中国科技公司。对,这是中国公司第一次上榜,我相信绝不是最后一次。这只是拉开了云端GPU计算强势登陆云计算市场的帷幕。算力不仅指CPU的计算能力,也包括GPU的计算能力,特别是在公有云中的计算能力。随着人工智能的兴起和进入大规模实用阶段,GPU的算力将成为企业竞争的基本指标。如何更好地使用云端GPU快速经济地满足业务对计算的需求,是一个值得考虑的问题。城市大脑的关键技术能力是对高清摄像头产生的海量视频进行高速处理,能处理上千路甚至上万路视频的GPU能力会非常必要。作为现代的科技企业,特别是人工智能相关的企业,用好云端GPU,宜早不宜晚。多家中小云厂商登录科创板,但长远发展靠技术相信很多朋友都开通了科创板的账户,其实就是在沪市账户上开通科创板的交易权限。顾名思义,科创板是为了鼓励科技创新而设立的股票交易板块,规则和主板、中小板、科创板、新三板等有很多不同。我这里讲一下科创板的的差异化IPO条件对云厂商的影响,简单来水,从大方向的指引、财务盈利指标等方面,科创板将所有阻碍中小云厂商IPO的障碍全部移除了。2019年1月30日证监会发布的《科创板首次公开发行股票注册管理办法(试行)》指出:“科创板重点支援新一代资讯技术、高端装备、新材料、新能源、节能环保以及生物医药等高新技术产业和战略性新兴产业,推动互联网、大数据、云计算、人工智能和制造业深度融合。” 这是直接点名鼓励云计算公司申请IPO上市。2019年3月1日上交所发布的《上海证券交易所科创板股票上市规则》指出:“2.1.2 发行人申请在本所科创板上市,市值及财务指标应当至少符合下列标准中的一项:(一)预计市值不低于人民币10亿元,最近两年净利润均为正且累计净利润不低于人民币5000万元,或者预计市值不低于人民币10亿元,最近一年净利润为正且营业收入不低于人民币1亿元;(二)预计市值不低于人民币15亿元,最近一年营业收入不低于人民币2亿元,且最近三年累计研发投入占最近三年累计营业收入的比例不低于15%;(三)预计市值不低于人民币20亿元,最近一年营业收入不低于人民币3亿元,且最近三年经营活动产生的现金流量净额累计不低于人民币1亿元;(四)预计市值不低于人民币30亿元,且最近一年营业收入不低于人民币3亿元;(五)预计市值不低于人民币40亿元,主要业务或产品需经国家有关部门批准,市场空间大,目前已取得阶段性成果。医药行业企业需至少有一项核心产品获准开展二期临床试验,其他符合科创板定位的企业需具备明显的技术优势并满足相应条件。”注意,二到五都删除了盈利要求。这是比照当年美国的纳斯达克,那里孕育了微软、英特尔等新一代IT巨头,而当时是没法要求这些公司盈利的。可以看到第四、五条简直就是为国内中型云计算厂商度身定制的。3.各地政府对科创板IPO企业的财务激励为鼓励本地企业赴科创板上市,很多省市出台多项补贴政策。补贴最高的达到2000万元,补贴最低的省市也有100-200万元。上海市徐汇区可给予落地项目建设单位不超过项目总投资50%,且每年最高不超过2000万元的补贴。真金白银的补贴会极大提升云计算公司上市的积极性。4.2019年3月1日上交所发布的《上海证券交易所科创板股票上市规则》指出:“2.4.5 上市公司核心技术人员减持本公司首发前股份的,应当遵守下列规定:(一)自公司股票上市之日起12个月内和离职后6个月内不得转让本公司首发前股份;(二)自所持首发前股份限售期满之日起4年内,每年转让的首发前股份不得超过上市时所持公司首发前股份总数的25%,减持比例可以累积使用;(三)法律法规、本规则以及本所业务规则对核心技术人员股份转让的其他规定。”注意:核心技术人员股份锁定期,由3年调整为1年,期满后每年可以减持25%的首发前股份。这意味着,科创板上市后云计算公司的核心人员在1年之后,就可以开始部分抛售公司股票套现退场。这也是大力鼓励云计算公司上市,毕竟1年后无论盈利与否,员工都可以卖出股票了。我的判断是,2019年会有不止1家中小云计算厂商登录科创板,以获得继续发展的资金支持。但是这里想强调的是:云计算的竞争将会是一场持久战,是一场靠技术硬碰硬的战争,希望上市的公司们能够沉下心来,真心以客户第一的价值观,赢得市场。这既是对客户负责,对公司自己负责,也是对整个中国云计算产业的健康发展负责。从另外一个角度来看,科创板采用的是注册制,同时前五个交易日不设涨跌幅,之后每天涨跌幅是20%。这就是意味着,在财务透明的同时,投资者会有更大的投票权,这也能极大降低“割一把韭菜就走”的冲动。本文作者:阿里云头条阅读原文本文为云栖社区原创内容,未经允许不得转载。

April 8, 2019 · 1 min · jiezi

PB 级数据处理挑战,Kubernetes如何助力基因分析?

摘要: 一家大型基因测序功能公司每日会产生 10TB 到 100TB 的下机数据,大数据生信分析平台需要达到 PB 级别的数据处理能力。这背后是生物科技和计算机科技的双向支撑:测序应用从科研逐步走向临床应用,计算模式从离线向在线演进,交付效率越来越重要。作者李鹏,原文首发于InfoQ,《容器混合云,Kubernetes 助力基因分析》引言James Watson 和 Francis Crick 于 1953 年发现了 DNA 的双螺旋结构,从此揭开了物种进化和遗传的神秘面纱,开启了人类对数字化遗传的认知,但是人类基因奥秘却是一点点被读懂的。1956 年,一则癌症和染色体相关性的发现令整个癌症研究界震动:慢性骨髓性白血病(CML)患者的第 22 号染色体,比一般然明显短很多。二十余年后,学者们发现,9 号染色体的 Abl 基因,与 22 号染色体的 BCR 基因连到了一块,交错易位产生了一条 BCR-Abl 融合基因。BCR-Abl 蛋白一直处于活跃状态且不受控制,引发不受控的细胞分裂,从而导致癌症。也就是说,只要细胞表达 BCR-Abl 蛋白,就有血癌风险。美国着手深入研究,并成功推出了治疗慢性骨髓性白血病的新药。这,就是格列卫,也是去年《我不是药神》中被我们熟知的‘高价药’。在格列卫诞生前,只有 30% 的慢性骨髓性白血病患者能在确诊后活过 5 年。格列卫将这一数字从 30% 提高到了 89%,且在 5 年后,依旧有 98% 的患者取得了血液学上的完全缓解。为此,它也被列入了世界卫生组织的基本药物标准清单,被认为是医疗系统中“最为有效、最为安全,满足最重大需求”的基本药物之一。容器混合云如何应对基因测序的 IT 挑战基因测序在血液肿瘤领域应用的越来越广泛。根据病人的诊断结果, 血液肿瘤专科医生会选择相应的检查,比如 PCR 结合实时荧光探针技术, 来检测测 BCR-Abl 融合基因, 以诊断慢性骨髓性白血病, 也可以通过二代测序方式,SEGF(Single-end Gene Fusion)能够通过单端 NGS 测序数据检测复杂的基因融合类型。在另一面,无创产检唐氏/爱德华式筛查,近年来以高准确率和对胎儿的低风险,越来越受到国内年轻产妇的欢迎。基因公司每年都完成几十万例的 NIPT 检查,每一例的 NIPT 涉及到数百 MB+ 的数据处理,存储和报告生成。一家大型基因测序功能公司每日会产生 10TB 到 100TB 的下机数据,大数据生信分析平台需要达到 PB 级别的数据处理能力。这背后是生物科技和计算机科技的双向支撑:测序应用从科研逐步走向临床应用,计算模式从离线向在线演进,交付效率越来越重要。基因计算面临以下几方面挑战:1.数据存储:数据增长快,存储费用高,管理困难;长期保存数据可靠性难以保障;需要寻求低成本大数据量的数据压缩方式;元数据管理混乱,数据清理困难。2.分发共享:海量数据需要快速、安全的分发到国内多地及海外;传统硬盘寄送方式周期长,可靠性低;多地中心数据需要共享访问。3.计算分析:批量样本处理时间长,资源需求峰谷明显,难以规划;大规模样本的数据挖掘需要海量计算资源,本地集群难以满足;计算工作1. 3. 流流程迁移困难、线上线下调度困难、跨地域管理困难;线下弹性能力差,按需计算需求。4.安全合规:基因数据安全隐私要求极高;自建数据中心安全防护能力不足;数据合约(区块链);RAM 子账号支持。而这样看来一套完备架构方案则是必不可少的。与传统高性能计算相比,按需切分任务的需求,自动从云中申请资源,自动伸缩能力达到最小化资源持有成本,90% 以上的资源使用率,用完后自动返还计算资源。最大化资源的使用效率,最低单样本的处理成本,最快速的完成大批量样本的处理。随着基因测序业务增长,自动完成线下资源使用,和线上资源扩容。高速内网带宽,和高吞吐的存储,和几乎无限的存储空间。基因计算不同于常规的计算,对海量数据计算和存储能力都提出了很高的要求。主要通过容器计算的自动伸缩特性和阿里云 ECS 的自动伸缩能力的打通,可以大规模弹性调度云上的计算资源。通过对基因数据的合理切分,实现大规模的并行计算同时处理 TB 级别的样本数据。通过按需获取的计算能力,以及高吞吐的对象存储的使用,大幅降低了计算资源持有的成本和单个样本的处理成本。整体技术架构是云原生容器混合云,云上云下资源一体,跨地域集群统一管理。作为主要 Player,容器技术在数据分拆,数据质量控制,Call 变异提供了标准化流程化、加速、弹性、鉴权、观测、度量等能力,在另外一方面,高价值挖掘需要借助容器化的机器学习平台和并行框架对基因、蛋白质、医疗数据完成大规模线性代数计算来建立模型,从而使精准医疗能力成为现实。基因工程中的关键问题及解决方案数据迁移与传输数据迁移、数据拆分阶段百万小文件的读取对底层的文件系统压力,通过避免不必要小文件的读写提高样本的处理效率。 通过数据中心与阿里云的专线连接,实现高吞吐低延迟的数据上云以及与工作流结合的上云、校验、检测方式。而最终需要达成的目标是:在短时间内完成数十 TB 级数据的加密搬迁,确保数据传输客户端的高性能与安全性,实现并发传输、断点续传,且保有完善的访问授权控制。基因计算典型任务:增强型工作流基因计算的典型特征就是数据分批计算,需要按照特定步骤先后依次完成。将该问题抽象后,即需要申明式工作流定义 AGS(AlibabaCloud Genomics Service) workflow。其工作流的特点是:多层次,有向无环图。科研大工作流 1000-5000+ 深度的 DAG,需要准确的流程状态监控和高度的流程稳定性。简单流程从任意步骤重现启动 ,失败步骤可以自动完成重试和继续,定时任务,通知,日志,审计,查询,统一操作入口 CLI/UI 。[图片上传失败…(image-f4ed64-1554348389942)]我们采用的方案是:1.简单 YAML 申明式定义,多层次,有向无环图, 复杂依赖支持, 任务自动分拆,自动并行化;2.云原生,与社区 Argo 完全兼容的增强性 Workflow 定义;3.实时资源统计,监控集成云监控,云日志 SLS 集成, 审计集成, 定时任务;4.统一操作入口 ags-cli 与 Kubectl 集成;5.阿里云存储卷申明式支持,NAS,OSS,CloudDisk, 缓存加速支持。云上云下资源的统一调度通过跨越 IDC 和云上可用区的混合云 ACK 集群实现计算资源的统一调度和数据的云端汇聚。自动化,流程化上云数据,和后续的数据处理流程,形成 24 小时内完成批次下机数据的本地, 上云,云端处理和报告生成。按需弹性提供计算节点或者无服务化计算资源,形成按需计算能力,处理突发分析任务。我所带领的阿里云基因数据服务团队努力构建更具弹性的容器化集群,分钟级数百节点自动伸缩能力和分钟级数千轻量容器拉起的 Serverless 能力, 通过提高并行度来提高内网带宽的利用率,最终提高整体数据吞吐率,通过 NAS 客户端和服务端的 TCP 优化来提高 IO 读写速度,通过为 OSS 增加缓存层和分布式的缓存来实现对象存储读取加速等等。还有很多问题,篇幅原因在此不一一展开:如何进行基因数据管理、最优化单位数据处理成本、采用批量计算的方式进行对样本分析、怎样使得基因数据处理安全及跨组织安全分享等等。生命科学和精准医学应用,未来已来NovaSeq 测序仪带来了低成本(100$/WGS)高产出(6TB 通量)的二代测序方案,大量 NovaSeq 的使用为基因测序公司每天产出的几十 TB 数据,这就要求大量的算力来分拆和发现变异,以及需要大量的存储来保存原始数据和变异数据。阿里云基因数据服务不断提升极致弹性的计算能力,和大规模并行处理能力,以及海量高速存储来帮助基因公司快速自动化处理每天几十上百 TB 的下机数据,并产通过 GATK 标准产出高质量的变异数据。以 PacBio 和 Nanopore 为代表的三代测序的出现,超过 30K 到数百 K 的长读,和 20GB 到 15TB 的大通量产出,长读和数据量对数据比对,分拆,发现变异带来了更大的算力需要和高 IO 吞吐的需求,对基因计算过程中优化基因分析流程,拆分数据,按需调度大量计算资源,提供超高的 IO 吞吐带来了更大的挑战。解码未知,丈量生命。科技的每一小步,都会成为人类前行的一大步。本文作者:李鹏(Eric Li),阿里云资深架构师,数据科学家,美国 FDA2018 精准医疗大赛Top2 Winner ,金融/生物计算行业解决方案专家,专注于基于 Kubernetes 的容器产品开发和银行,生信行业的生产落地。在加入阿里云之前,曾在 IBM 担任 Watson 数据服务容器平台首席架构师,机器学习平台架构师,IBM 2015 Spark 全球大赛金奖获得者,带领多个大型开发项目,涵盖云计算,数据库性能工具、分布式架构、生物计算,大数据和机器学习。本文作者:木环阅读原文本文为云栖社区原创内容,未经允许不得转载。 ...

April 4, 2019 · 1 min · jiezi

UI2Code智能生成Flutter代码——机器生成代码

背景在《UI2CODE–整体设计》篇中,我们提到UI2Code工程的整体流程。前步图片分析之后,我们可以得到对应的DSL布局描述。利用DSL的资讯,结合IntelliJ Plugin介面工具,面向使用者提供生成对应Flutter代码。本篇主要介绍我们如何处理DSL的资讯,想法上即是Flutter的翻译机。总体概念如下:输入的DSL是什么?DSL做为一种描述语言,抽象表示为了解决某一类任务而专门设计的计算机语言。在此我们的DSL代表图像识别和布局识别侧的输出,为一JSON格式。这些资讯主要描述了这个图层(Layer)的范围(Frame)、是什么样子的类型(Type)、是什么样子的样式(Styles)、含有哪些数据(Value)等等。图层集(Layers)栏位则代表了这张视觉稿的所有图层。核心思路本节的目标是将DSL翻译成目标的Flutter代码。我们首先需要理解的是分散的图层间的关系,可能会有交叠、可能是并列排版。知道了关系之后,需想办法转化成Flutter widget的视图,根据此视图来生产对应代码。架构上我们把DSL tree和Flutter tree的建立,分拆为两个独立的分界。这样比较容易定义问题,并且保持弹性。如果今天的目标语言换成Weex或是iOS UI,我们就只需要更动代码翻译的模组。第一把刀:DSL tree建立上图的左侧代表了来源DSL的layers资料,代表者一个一个的图层。右侧是目标的DSL Tree,这棵树的结构上明确叙述了图层之间的包裹、交叠等关系。并且包含了某些特殊关系的节点聚合。作法上利用每个Layer的Frame,以及所属的类别(文字、图像、容器),利用下面的规则组合树的关系:图层之间的包裹关系,例如某些图层为容器,代表下面是可以挂其他节点的(这边带有背景属性的容器,我们定义称之为Shape)区块式组件(Block, 如ListView/GridView)。可以将图层组成View item的关系闲鱼定义的组件资讯(如CI以及BI),这部份非闲鱼工程可以忽略重复布局(Repeat)的资讯,将相同的图层归类合并,目的为简化树根据以上我们采用了分层,由大至小的次序将Layer分群合并。另外,在合并时layer之间彼此可能有关联;它们可能同属于Block,也可能同属于某个Repeat。所以对于上面定义的Repeat、BI、Block、CI、Shape都可能有交错的嵌套关系,这是必须要处理的部份。第二把刀:Flutter tree建立在Flutter Tree的建构中,核心概念先处理布局。布局的概念如剥洋葱一般,我们先去除四周的padding,然后以人类视觉layout的直觉先尝试横切分,再进行竖切分。1.先剥洋葱去除padding2.接著我们的算法会先尝试是否可以横切,如下图我们可以切割成为Row1/ Row23.针对Row1在尝试再进行竖切,如下图可以得到Column1/ Column2/ Column3根据以上切分的规则,我们就可以定义出如Row、Column、Padding的几个节点,以及它们的Parent/ Child关系。将DSL tree同一层的节点做切分,一边切分一边建立Flutter node,遍历完整颗DSL,即可得到粗略的Flutter tree关系。= 无法切分时的处理当图层切分不开时,这时候就要使用绝对布局叠层的概念,这个概念在Flutter内称之为Stack。多个图层在DSL tree的关系为兄弟节点,根据此些图层的Frame,我们判断出来它们是彼此相交的,我们会以Z-order概念,来决定上下交叠的关系。最后,这些图层将组成一个新Stack节点,并且产生此节点的Frames为此些图层覆盖的范围。= 针对文字的进阶处理基本上交叠的图层以Stack的处理就可以正确显示,但在文字图层上可能含有误区。如上图因为文字本身的上下左右是含有padding的,在我们图层的识别时,可能会计算出彼此的frame是交叠的,但实际上UI希望它们并不是Stack关系。为了解决这个问题,我们引入了一个oriFrame的概念,用文字最原始的像素当做是oriFrame。所以遇到为文字的图层时,我们会先判断本身的oriFrame是否交叠,如果是的话才采用Stack切割,否则就以此oriFrame对原始的frame做修正。文字还有什么特性?另外,因为文字的内容通常是动态的,所以拥有了”所见不一定为所得”的特性。这些特性主要包含了是否该换行、内容区域是否可以拉伸、文字Padding等,这些特性都会影响到我们的布局。以下图为例,我们在处理Layout时肉眼很明显可以知道这些特徵。文字的行数我们可以以视觉稿当做最大显示范本,文字区域的宽度部分,则需要特别判断哪些区域是可以被拉伸的。确立文字范围在决定拉伸对象之前,我们需要定义哪些widget是将内容完整显示,不能被拉伸的:如图片、Container容器、Stack区域、Component组件接著处理的流程如下:首先判断所有Child内是否有多行文字或宽度固定的文字,如果是的话针对其处理。需要加上Flex。若无以上的状况,则判断Child间的Padding关系如果可拉伸的widget的Padding大于平均值的个数有多个,则这些都加上Flex如果只有单个时,则找寻最大Padding的widget(使用分群拉伸算法)最后,但当Row里面存有拉伸的状况时,需要把Row的最后一个child加上Right padding,否则拉伸元素会填满父容器。分群拉伸算法:这个算法的目的是找到最佳拉伸的对象。我们的思考上将Widget做分组,分组后判断整体的Alignment(如左右对齐)或是拉伸关系。若在拉伸状况下,判断适合让哪个组别拉伸,在进一步判断适合让组别的内部元件拉伸。举例如下为一个Row排列的控件,其中排列为Image、CI、Text1、Text2、Text3:依据Widget之间的距离,在上图分为了Group1及Group2两个群体。先以Group1判断是否存在可拉伸的对象, 接著才判断Group2。所以这5个Widget分别得到了3, 2, 1, 4, 5的优先级。以本例而言,Text1为最高优先,而且其为可拉伸的,故决定将Flex属性加于此。在Expanded的处理上,是我们目前遇到最大的困难点,甚至人工判断都可能有歧义。上面的规则是我们归纳出众多视觉稿的通解,但不能100%完全解决问题。所以这部份判断错误的部分,我们期待在Plugin的交互中使用人工解决。= 判断Alignment优化以上的处理已经可以正确生成Flutter tree,但是我们想进一步地将Flutter代码更加优雅。在此我们针对了三种元件的Alignment做了处理,分别是Container、Row、Column,其概念都是分析内部元件的padding关系,决定为居左、居中、或是居右对齐。举例如Column内部的children我们去判断左右的padding是否相等。若是则移除其padding,并且加上crossAxisAlignment为center。针对Row/ Container我们则会判断crossAxisAlignment(垂直方向)以及mainAxisAlignment(水平方向)。水平部份,这边我们采用更精细的方法,我们利用欧式距离建立一个非监督算法,计算views是更为接近哪一个(居左、居中、居右)。算法这边先不详述,之后再以篇幅介绍。最后:生成Flutter代码经过前面的步骤后,最终我们产生了一个Flutter Tree。生成时在节点的定义上,我们分为了两种,分别是View与Layout,以是否可以拥有Child为区别。以下是我们针对Flutter Tree所定义的部份类别:在节点的定义中,皆存储了各节点的Parent、Child属性。根据这些关系,我们定义每个节点的代码样板,例如FColumn对应的样板为:new Column(#{alignment},children: <Widget>[ #{children},]), 最后我们以Root widget开始遍历整颗树,将每个节点所生成的Flutter代码结合,这样我们就可以得到整个Widget tree的代码了。数据分离为了更好的重复利用生成代码,我们把生成的代码和数据再进一步做分离。分离后输出分为代码区以及Data model数据区:我们切割这些区域的目的为简化Widget tree直观上的代码复杂度,以及将数据抽离,让资料可由外部呼叫传入,以达成动态性。整体架构回顾总合以上的概念,工程的细部架构如下:前面所说的针对文字以及Alignment的处理,在这边我们设计了一个工厂模式,如上图中经过Flutter Tree Builder后,我们可以去遍历整颗Widget tree,在工厂中判断判断符合条件的规则,经过处理去震荡优化原本的Widget tree。在这边未来我们可以不断地加上合适的规则,让Widget tree更加优化。整体架构使用静态分析的方法,读到此各位可能会有疑问:一些如动态的事件、View的Visibility、Input输入文字框等怎么处理?由于这些动态性在静态分析下无法解决,所以我们增强了Plugin上的编辑性,使用者只要勾选某些属性,即会在生成代码时自动判断,在Flutter自动增加对应的逻辑。以弥补静态图无法处理的问题。由于UI的灵活性高,十个人写的代码可能有十种不同风格。并且在分析上游的UI2DSL,以及Flutter代码的翻译,某些部份的精确性取决于我们的样本的认知,是否能够在有限的样本内观查出泛化的定律,分析上还是存有很多挑战性。结合落地业务在整个UI2CODE的效果中,大约七成以上的页面都可以正确分析出来,剩下的是一些小细节如文字的处理等,基本上我们工具都能够将大框架的处理好,使用者可能只需微小的调整。UI2CODE案子在内部团队上线后,已经在闲鱼APP内的"玩家页面"采用了自动化生成的代码。在采用自动化工具后,大约减少了三分之二的UI开发时间(因初期还在熟悉工作流程,未来相信可以更快速)。同时,若在客户端大量采用我们工具,还可以让团队的代码结构有一些的规范,让生成工具来规范Widget UI以及Data Binding的框架,一致性以及后续的维护,相信是一个很大的诱因。并且闲鱼团队近期计画开发一款新的APP,在初期时能够快速开发UI,也将采用我们的工具。期望有更多的业务和经验积累。后续计画近期我们推出了第一版UI2CODE,先计画于内部团队使用,利用使用的经验,让我们在叠代之下不断提高准确性。并且,我们正在调研结合NLP以及AST(语法树)的可能性,希望能够产出更有质量的代码。我们也期望未来能将此工具开放于Flutter community,对于推动整个Flutter技术有所推进。希望能让更多人跟我们一起找寻更有效率的写代码方法,如果有任何想法欢迎与我们交流,我们也持续不断地在进化工具中,谢谢各位的阅读!本文作者: 闲鱼技术-上叶,余晏阅读原文本文为云栖社区原创内容,未经允许不得转载。

April 4, 2019 · 1 min · jiezi

对话行癫:解密阿里云顶层设计和底层逻辑

几十个问题,万字长文,阿里云新任总裁行癫履新后首次出面与钛媒体独家深入讨论了一下阿里云对云计算未来的判断,深度解读未来阿里云生态战略,揭秘阿里技术委员会和阿里中台思想的原生思考。转载自钛媒体,作者:刘湘明 。标题为《钛媒体独家对话行癫:最详解密阿里云顶层设计和底层逻辑》 。分享给大家。钛媒体注:张建锋(花名行癫)的阿里生涯,一直在踩着技术与业务的交界线前进,某种意义上可以看作阿里战略重点转移的缩影——在担任集团CTO和阿里云总裁之前,他先后管过淘宝网技术架构部、B2C开发部及淘宝网产品技术开发部,还分管过聚划算事业部、本地生活事业部、1688事业部及天猫事业部。2015年还担任过阿里中国零售事业群总裁。2018年11月,还在担任阿里巴巴集团首席技术官,同时也在负责达摩院的张建锋,被任命为阿里云智能事业群总裁。云计算的市场发展很快,根据调研机构Canalys给出的数据,2018年全球云计算市场规模突破800亿美元,达到804亿美元,同比增长46.5%。市场的高速发展,也带来云生态环境的快速变化,技术、客户需求、伙伴关系都伴随着规模的扩张和应用的深入在不停地演变。张建锋过往的这些经历,对于他在这个快速变化的云生态环境里,理解技术与业务的关系,切换合作伙伴视角去思考问题,都带来莫大的益处。在这个高速发展的市场里,阿里云在全球排名前三,在中国排名第一。“阿里云在中国公共云市场的市场占有率是第二至第八名的总和。” 2019年3月21日,新岗位上的张建锋在北京阿里云峰会上第一次公开亮相时,这样描述阿里云的市场地位。只有操盘的人才会真实地感受到,高速的发展和庞大的规模,带来的不仅仅是风光,也还有巨大的压力。上任之后,张建锋组织管理层讨论几个核心问题:第一,阿里云如何健康地增长?第二,云的未来是什么样?第三,阿里云的核心能力是什么,该做什么,不做什么?3月21日他的发言,可以看作是这4个月讨论的结果呈现。相比他发布的一系列未来阿里云要做的事情,大家其实更应该关注阿里云不做什么——在过去的十年里,阿里云一共发布了162个产品,4610个新功能,但对于巨大体量的阿里云,清晰自己的边界,永远都是一个最重要的话题。这涉及到对于自己定位和能力的思考,更涉及到怎么看待自己与自己所营造的生态环境的关系。在大会发言的最后,张建锋明确了阿里云两个生态新定位——被集成,自己不做SaaS。这两个定位的发布,如果从弥漫阿里的金庸武侠文化来解读,与《天龙八部》中虚竹破解珍珑棋局的做法颇为神似——阿里云作为平台放弃一些主动和实地,反而让自己有了更大的腾挪空间。众所周知,随着企业上云的大势不可逆转,越来越多企业级的客户需求被叠加到云上,已经对阿里云的交付能力提出巨大挑战。被集成概念的提出,把很大部分发展空间和主动权明确留给生态伙伴,阿里云自己则专注于云生态核心能力的精益求精。但这看似双赢的设计背后,依然存在很多挑战,平台如何把自己的能力封装成成熟的产品,接受合作伙伴的考验和挑剔?技术和组织,要为这样的变化,做出什么调整?这些都是阿里云未来发展的顶层架构设计,但所有这些设计的背后,都是对于这个产业和自己,最底层最深刻的思考。在会后,张建锋接受钛媒体联合创始人刘湘明的独家专访,就云计算的未来、阿里云的战略选择,以及云对于企业的影响,进行了深入的讨论。关于云计算的未来一个有1万人的平台公司是一个非常大的平台型公司了,像淘宝做的这么大,也就几千人的规模。如果一个公司的人数与业务线性相关,可能是做了太多自己不擅长的东西。钛媒体:你关注到云计算竞争的焦点在发生什么样的变化,好像大家还比较关心价格?行癫:价格是初级竞争,最终还是回归到核心价值。价值要从两端来体现,一个是技术端,一个是应用端。云一开始都是做基础设施,但阿里巴巴从做云第一天起,做的就不仅是现在这个云,当初的理念是做一个数据处理平台,这和当时数据处理能力与业务的脱节也有关系,因为是十年前,很少有公司是基于智能、基于数据的,大部分是基于流程。后来做了一段时间,发现光做这个还不够,在中国要想成功,还得有基础设施。当然我们做的过程也比较曲折,一开始还想在开源系统上做数据处理,后来发现也不对,必须自研,阿里巴巴不仅是做了一个云的基础设施体系,也做了一个数据处理体系(备注:现在叫MaxCompute,当时叫做ODPS),这个是绝无仅有的,包括国内国外。当然这个过程有点远,所以回过头来又必须把IaaS层做好。底层的竞争肯定是拼基础设施的成熟度、稳定性和价格,但是上层的竞争肯定是拼人工智能等等。钛媒体:你刚才谈到数据处理,开源为什么不行?行癫:其实所有的开源软件公司都没有面对过这么大的数据量,Hadoop 、Spark是比数据库的处理能力前进了一大步,用分布式、用MapReduce的方法,但他们的数据量跟阿里巴巴数据量比还是差非常远。第二个是开源的稳定性要求也达不到我们的要求。所以那时候我们第一次做了一个5K的集群,开源当时不可能超过5000台机器的,我们第一次突破了机器的限制,可以用更大规模的集群来处理。第三我们考虑成本,因为数据量规模小不关心成本,大了以后我们更加考虑成本,现在我们阿里巴巴每年业务量都是增长50%以上,但是我们的成本不能线性增长。我们去年开始大规模混布(备注:一种新技术,使得在线处理与离线处理不再分别拥有专有的机器,而是运行在同一个集群的机器上,可以极大地节省资源,对于调度部署能力要求极高),我们没有专用的离线机器去处理大数据,都是用在线跑的机器做大规模的混布。双11来了,前一个小时暂时不处理数据分析全部用来跑应用,高峰过去之后,调度所有机器去做数据分析,开源是不可能做这个事情的。我觉得大数据领域如果自己公司没有应用,很难设计出一个很有弹性,很高性价比的、很高稳定性的处理平台。钛媒体:现在国外的云计算谈混合云比较多,你怎么来看混合云未来对云计算的影响?行癫:混合云未来还是一个很重要的发展方向,很多客户对混合云还是有非常刚性的需求,包括一些政府、银行客户,他们觉得对自己的应用可管可控,或者物理的隔离是很重要的事情。今天从现在的情况来看,公共云上的隔离,我们用硬件来做隔离,比如我们有神龙的服务器,原来是虚拟机的隔离,现在隔离水平也在逐年提高。但对混合云的需求这不完全是技术的原因,还有思路上的原因,所以很长一段时间内混合云还是会广泛存在。钛媒体:你怎么看待云计算的后台化趋势?你今天上午谈到阿里云不做SaaS,其实SaaS是一个很重要的跟云计算客户的连接,这样的话会不会未来云计算的厂商都会变成被遗忘的状态,就像现在的电厂、自来水厂一样。行癫:被遗忘而不可替代,也是值得期待的事情,就像空气一样,我觉得是一个非常好的状态,不见得一定要跑到最前面去和客户接触。因为真正的2B一定介入客户的业务流程,不然不能叫2B,最多只能叫to custom。但这个行业的需求太分散了,像SAP、Oracle,发布了很多ERP,他们仍然有十几万的工程师,包括自己的合作伙伴。当然也有比较集中的,比如微软,因为办公大家的需求比较一致,除此之外的业务领域,差异非常大。我们把云定位成平台,不是定位成软件系统,所以云和电商在定位上没有很大的差别。电商是无数的品牌商、商家在平台上卖他们的产品,不需要关心支付、交易的事情。云未来一定会更专业,专业化分工是现在文明一个重要基石,我们要做生态也是要解决这个问题。我们的专业到底是什么?我们擅长于做大规模的系统,擅长技术创新,对技术未来演进的趋势有一些看法。当然,我们有丰富的业务场景,让我们把前面这些事情做的比别人好,这是我们的优势。但大量行业的业务还是需要行业内专业的人去做。他们也需要创新,不是简单把云作为一个IaaS,而是要看如何基于数据、基于智能去发展,所以我们要和合作伙伴一起完成转型。再一个,中国的IT发展的很不平衡,有些公司信息化还没有实现,就要讲数据化、智能化,有些公司IT能力很弱,更需要我们合作伙伴做一些贴身的服务,包括实施、咨询、辅导,但这些阿里云都干不了。钛媒体:刚才你谈到Oracle、SAP的人员规模,是不是在你心里面对阿里云的规模是有一个预期的?行癫:是。我觉得一个有1万人的平台公司是一个非常大的平台型公司了,像淘宝做的这么大,也就几千人的规模。如果一个公司的人数与业务线性相关,可能是做了太多自己不擅长的东西。钛媒体:刚才谈到一些人工智能,现在做人工智能和开源这两个事情,起来非常快,你觉得未来对于云计算会有什么影响?行癫:开源使得云越来越标准化。不管从上面互联网的一些技术部件,包括云的一些主要的模块,像容器等等,会越来越标准化,这个对云的发展是有利的。第一个是因为开源是一些发达的大公司在用,他们的技术会更稳定。最关键的一点是,云上大量的开发技术体系会更一致,大量工程师会熟悉这套体系,更容易把自己的应用变成云的一部分,单靠一家公司去制定标准还是非常难的。钛媒体:开源基本上被大厂商瓜分掉了,未来会给开源市场带来什么影响,开源未来会不会走向收费的道路?行癫:现在有点这个趋势。原来的开源可能就是免费开源,现在有的公司做收费的服务。但是大家都在云上了,那些公司的生意模式就发生变化了,所以他们去修改开源协议,这个我觉得是反趋势、反潮流的。最终他们会发现,过了一两年时间,最后一定是云公司来做原生的云,要不然是大互联网公司推出完全免费的开源。大的互联网公司不care这点小钱,他是要繁荣整个生态。钛媒体:关于云计算最后一个问题,技术的角度来说,现在云计算你最关注的技术是什么?行癫:第一个是你刚才谈到混合云现在发展非常快,所以我们还是做了非常多工作。第二个是安全,大家都上云的话,安全就变的非常关键。从产品角度来看,数据库发展非常快,大家都在想替代Oracle数据库,但是在关键核心应用上要1比1替代还是有挑战,所以现在完全基于云原生的数据库发展非常快,像AWS完全把数据库作为一个核心能力来做,目前国内也是发展非常快。当然还有一个最底层的IaaS层的,像容器、做隔离,我们也在推神龙服务器,做硬件层的隔离,这块发展也非常快。云原来是有人做了一个比较完整的框,现在每个框它本身都在快速演进,它其实还不完全是静止的。当然生意模式也在演进,微软从SaaS往下做,aws属于另外一条道路。关于阿里云的未来钛媒体:上任四个月,这段时间你做了些什么事呢?行癫:主要是在讨论,阿里云要做到高增长,还要做到人员非线性增长,这个是我们讨论比较多的。第二个讨论云的未来,云以后到底是怎么样一个商业形态。第三个我们的核心能力到底是什么,我们不做什么,做什么,这个也讨论比较多。在这个讨论的前提下,我们怎么达成共识,怎么样去调整组织,怎么样去落实这个KPI,怎么样通过工具去保证这个流程。钛媒体:今天你的发言应该是一个讨论结果的展现。行癫:对,我觉得这是我们内部共同认定的。当然,阿里集团内部也发生一些变化,希望阿里云智能变成阿里经济体所有的技术跟产品的统一出口和客户界面,这个跟原来的定位可能也有区别,所以现在金融云、钉钉等等都作为整体一部分来考虑。我觉得阿里巴巴也是技术和商业结合最好的一家公司,有的公司CTO天天换,因为没有这个土壤,外面来的人的技术,来了之后一直跟业务结合不了,就会被组织抛弃。钛媒体:外界一直认为,技术是阿里云的一个短板。你怎么看?行癫:很多人问这个问题,阿里巴巴到底是什么公司。阿里巴巴一直是技术性公司,只是商业做得太成功了,所以人家搞不清楚到底是技术公司还是商业公司。阿里做的事情实在太多了,电子商务、支付、物流、文娱等等,所以人家觉得阿里是一家比较业务导向的公司。我一直认为,技术依赖于业务,业务依赖于技术,各个阶段比重不一样,有的时候业务拉着技术走,技术推着业务走,世界上没有纯技术的公司。阿里巴巴是一家非常奇特的公司,我们是互联网的规模、企业级的复杂程度、金融级的准确度。举个小例子——搜索引擎,你搜索一个关键词,出来5页、出来10页、出来500页,用户不care,你丢掉一半数据,人家也不觉有什么问题。但阿里不一样,只要丢了一个商品,卖家立即打过来了。你交易出一分钱的错误,人家百分之百打电话过来,而且是非常严重的问题。全世界没有一家公司,要同时处理这些事情,再加上每年要给你来一个双11,这是很复杂的。在成本没有大幅增加的情况下,要同时满足这三个条件,而且要有非常高的弹性。所以阿里技术不管怎么讲都是非常复杂的。技术有两种,一种是做单点突破,像语音、搜索、算法。第二是处理复杂流程。这是两种一样难的事情。今天在人才市场上处理复杂系统、构架复杂系统的人更稀缺,因为要有很多经验,才能处理这么一个系统。这是第一个事情。第二个事情阿里是工程能力非常强的公司。有的公司能研究,但是写不出系统,但阿里不一样,今天你有事情要做,我们一定是可以非常确定告诉你,多长时间,多少天能够上线,全球很少有公司能达到这样一个自信。第三个外界的看法,可能是因为突破性的技术不够多。但达摩院现在很多技术是非常领先的,包括语音,像法院的语音系统是用我们的。另外视频处理,在城市大脑这样的应用就更不用说了。我们自己的芯片很快就有流片,八九月就能出。到这个程度,就更立体,让大家觉得阿里巴巴是一家怎么样的公司。我觉得阿里巴巴也是技术和商业结合最好的一家公司,有的公司CTO天天换,因为没有这个土壤,外面来的人的技术,来了之后一直跟业务结合不了,就会被组织抛弃。钛媒体:你刚刚谈到提到业务技术互相拉动,你觉得阿里现在谁在拉动谁?行癫:最早,业务比技术跑的快,技术一直追业务,因为业务增长实在太快了。前两年我觉得是技术推动业务,特别是人工智能兴起的之后,包括我们程序化交易、广告平台、千人千面、推荐、搜索大量用算法和AI,包括客服等等大量用数据智能在驱动业务。云也是一样,云是技术的突破才能带来成本下降、效率的提升。云是比较典型的,原来的电商业务这两年大部分红利是靠技术突破带来的。因为商业模式突破已经非常难,今天大家都聪明,以后的竞争门槛会抬高,这个门槛很多都是技术门槛。阿里巴巴这几年的实践,特别中台提出以后,我们积累核心能力更快,浪费更少。然后我们数据中台提出后,数据全部打通,这个也是效率很高。这个是公司中台成功的一个很重要的地方。当然跟组织能力有关系,不是说有理念一定会实施。有些公司可能推都推不下去,我们也是花了大概两年的时间,逐步整合。一个中台你得证明自己,你比别人技术好,这不是这么快和容易的事情。关于阿里的中台钛媒体:你认为中台跟组织结构的关系是什么?行癫:这个还是非常非常有关系的,包括组织能力、信任关系,包括一些考核,这里边有非常多一些关系。你做中台,做不好就变成一个原来的公社。公社其实就是一个中台体系,你专门种玉米,你专门种水稻,但是为什么到后来大家都搞不下去了呢?中台不是把所有部门理一理,这个让你做,那个不让你做,技术能力跟不上、组织能力跟不上,还是低效的。我比较特别,我做中台,原来的部门都做过,还是能够影响到很多人。第二、我们还是很踏实的,承认哪些做得好,哪些做不好,也不是所有都拿来做。第三、阿里制度上做了一些创新,我们有一个技术委员会,到现在很多人都在学,但是我觉得他们都还没明白,我们到底怎么运作的。我们技术委员会下面有技术小组,因为我们有很多专家,语音的、视频的、视觉的,如果原来是三个部门做,那么三个部门成立一个小组,你们先去解决统一的问题、发展的问题。他们如果不能解决,我再出面解决。所以我们是提倡让工程师用技术的手段来解决技术的分歧和发展。中台不仅是个组织,中台是个理念,所以说这个中台的技术,如果放在高德是最适合的,就放在高德,但是对高德来说,这个技术一定要有一个定位,要为全体人负责,不仅是为自己服务。所以有些是中台的技术,但不一定在中台,例如智能机器人技术,那就是在客服部门,因为他最贴近现场。但是一些中心业务技术,要不在达摩院,要不在中台部门统一建设。阿里制度上做了一些创新,我们有一个技术委员会,到现在很多人都在学,但是我觉得他们都还没明白,我们到底怎么运作的。钛媒体:智能云的概念,和原来的IaaS是不太一样的,它会带来什么新的变化?包括组织架构、KPI等等。行癫:组织架构,现在所有CTO线的技术部门跟云的技术部门都整合。例如原来两个数据库部门,现在合并成一个数据库部门。原来两个网络部门,现在合并成一个网络部门。钛媒体:KPI的问题,我原来也跟孙权聊过这个事。现在你最看中的是什么?行癫:我觉得第一个是规模,因为这个意味着你产业的竞争,这个肯定是非常核心。第二个我们还是非常关注公共云的份额,因为最终云的基础还是公共云的发展,当然也有混合云的发展这个也很关键。第三个提倡生态,到底在多少生态上,阿里巴巴有多高的竞争力?现在我们有几千家主要的合作伙伴,我们希望把主要业务放在阿里云上的,要占一个更大的比重。钛媒体:钉钉未来会跟阿里云有更紧密的协同吗?云端协同未来是不是一个重要的打法?行癫:刚才我们讲的数据化智能化,另外很大一块就是工作在线化,包括办公的协同,这个我们想靠钉钉的能力来补上这块体系。现在,云是两个驱动力,数据+智能,到明年我们会加一块工作协同。我们认为这个工作协同是互联网公司跟其他公司的区别,因为互联网公司大量的运用这些新工具来做工作的协同,传统企业很少用这种工具。像钉钉这样的生产力工具出现之后,发生了很大变化,原来用邮件,现在钉钉在线实时工作效率非常高了。以前的审批也是,通过它的机制全部串联起来。再进一步像文本,供应链体系,都通过钉钉体系串联起来,更轻快。手机协同性不是很好,我们希望通过钉钉串联起来。然后把钉钉这个能力变成我们合作伙伴的一个基础能力输出。这是我们的一个想法。钛媒体:是不是钉钉对阿里云的价值,类似于office365对于微软 Azure?行癫:有一点类似,但是还是没有那么SaaS化。钉钉主要是一个协同沟通的平台。我们希望未来的企业既是数据的,又是智能的,还是在线协同的,这是我们对我们客户的一个主要未来的描述。钛媒体:今天还有一个事挺有意思的:繁星计划-小程序,小程序在大的部署当中现在是一个什么样的角色?行癫:小程序是很重要的角色,因为现在越来越多应用都会在无线端,不管数字政府还是各行各业的应用。这个应用有两种形式,一种是做独立APP,另一种是依托于某一个大的流量入口,我们觉得大部分长尾应用自己去做独立APP都有很大难度,可能会依托于大的流量入口,比如微信、阿里这样的。阿里跟微信有很大差别,我们叫一云多端,不仅是在支付宝、淘宝可以跑,在高德也可以跑,甚至可能以后在微博上也能跑。就像是Android一样,开发一次到处可以跑,但是微信更像是iphone,在他这里开发这里跑。我们的小程序是一个生态,我们会提供云到端的一系列工具,让开发者很快就能做出来。钛媒体:可不可以理解小程序更像一个端?行癫:一个轻量化的端,是各行各业一个轻量化的出口。钛媒体:据我所知是拿支付宝小程序做了一个框架。行癫:对,因为支付宝在这个方面接触比较多、探索比较多。这就是我们的一个好处,一下子全部都能用。关于被集成钛媒体:你今天提到“被集成”这个概念是非常新鲜的,这个思路是怎么被提出的?因为阿里其实一直是平台,平台和被集成有矛盾吗?行癫:原来阿里是个平台,我也做过两年中台,我一直在琢磨中台跟平台到底有什么区别。像阿里巴巴、淘宝、天猫这种平台只要搭好了,客户直接开店就可以了,不需要关心任何事情,但我觉得中台不一样,中台自己单独的产品不能直接产生价值、不能直接对外服务,一定要变成别人产品的一部分,让别人的产品提供更好的服务,这是我理解的中台。包括数据智能和人工智能,这两个东西肯定不是平台,肯定要变成人家的一部分,从这个角度上,阿里云智能既是一个平台,也是一个中台,所以我们提出口号叫“被集成”,就像英特尔的CPU一样,也是被集成,集成到各种各样的电脑里去,是一样的逻辑。钛媒体:“被集成”的策略对阿里云的运作,包括组织管理,都会产生一些比较大影响,这个其实是调用和被调用的关系,和以前太不一样了,内部需要做什么调整吗?行癫:其实我们原来自己也在做一些总包,我们也在做集成,集成我们的技术。但是我们发现我们的交付成本非常高。有些行业是没有办法的,像城市大脑,因为这个行业是新兴行业、增量应用,以前没有玩家,你要做些show case,这个行业我们会去做,但是做了以后去复制、大规模推广,我们肯定需要大家一起来干。钛媒体:这一步我觉得还是非常高明的,把原来阿里云很多问题缓解了,包括交付能力,把原来集中式交付变成了分布式交付。行癫:而且很多合作伙伴愿意做交付,他们擅长。钛媒体:被集成这个概念提出来以后,未来整个生态会怎么打造。行癫:简单一点就是,能合作伙伴签合同的,你们签。非得让阿里云签的,我们一起签。钛媒体:未来生态的打造会有什么变化?现在被集成之后这个关系就有点混乱。行癫:生态一定还是一个分工协同。传统的生态不像想象中那么整合,他们也是分工协作的。比如说做一个传统企业的ERP系统,他们也是分工协作的,比如德勤做咨询,SAP做软件,埃森哲去实施。我们不去破坏大家的分工合作,只是我们的产品技术变成这个体系的一部分,是这么一个逻辑。钛媒体:原来传统的2B的生态,还是一个比较均衡的生态,因为基本后来都是大公司。但是在互联网生态,基本是一个大平台,然后一堆小公司。行癫:我个人觉得,大公司一定会做比较通用的系统,但是通用系统如果被云化,像有些大公司有可能就被取代了。但是专业化的服务能力,是个性化,c2m。个性化意味着什么?意味着对大品牌来说,是要碎片化,云这个服务我觉得以后也是一样的,一定有很多细分的专业服务商,而不是一个很大的专业服务商,服务很多行业。我认为这是一个趋势。就像化妆品一样,不是天天涂大宝,它很细分,有很多的品牌。钛媒体:那未来的这种生态的打造思路会不太一样,要靠什么政策,把大家吸引过来?行癫:原来,简单的生态是reseller的模式,但是今天我觉得,我们更希望合作伙伴理解这个行业,跟我们掌握的技术有一个共创。比如我们有一个很好的语音技术,我们不知道什么行业可以用。合作伙伴掌握这个技术,也懂得客户应该怎么用,比如人可以用在考勤上,或者用在什么门禁上。所以我今天更看中的生态伙伴是对这个行业未来有定义能力的、有创新能力的公司,是我们优先去合作的人。真正头部的概念就是说这家公司是不是够专业、是不是对行业未来有洞察。毕马威有两句话说的非常好。他们把今年的策略总结成两句话,一句叫发现,一句叫实现。我们希望跟合作方一样要能发现,而且有能力实现它。钛媒体:现在怎么看阿里云的短板?行癫:我觉得阿里云的短板很明显,我们虽然做云,但是2B服务能力是我们比较缺的,所以需要通过生态快速的发展来补。第二个从核心技术积累上,有这么多年的积累之后,我们原来是一个平台化、产品化的结构,这两个还不一样,平台都得自己做,所以不用单产品剥离出去,别人可以很好用,我们内部也可以用的很好,因为开发者就在公司内部,你可以直接问他,所以他构建了一个非常复杂的平台,但是这个复杂的平台不是单一个单产品,非常结构化的构成,所以我们今天也在加紧产品化。产品化包括要丰富的文档,手册,这个其实还是有很多工作要去做。钛媒体:被集成这个事情有没有指标?你怎么衡量?行癫:我们有几千家合作伙伴,我们希望有业务的合作伙伴数量,要有非常严格的指标,包括他们的规模。对于我们大型头部的合作伙伴,大家都不是收入的指标,包括德勤、埃森哲,我们还是希望打造头部标杆案例,真正从行业未来定义的案例,这是都是我们一些共同的目标。钛媒体:今天上午说不做SaaS,咨询会做的非常少,但咨询这个事情非常重要,意味着你跟客户密切的交流,未来阿里云怎么保持跟客户之间的沟通,未来怎么了解客户的需求?行癫:今天,我们不仅是把产品简单提供给合作伙伴,我们大部分的时候,还是跟伙伴一起做样板市场,所以我刚才讲为什么头部的,有市场定义能力的人一起做,包括德勤,埃森哲,也是和我们一起在定义这个市场,只是我们今天把产品能力变成他们的解决方案的一部分。钛媒体:其实包括未来整个被集成这个事情,对阿里云也有压力,比如说技术能力封装。行癫:其实被集成是更高的要求。不仅是我接触客户少了,都是合作方在接触了。合作方为什么选阿里云,为什么不选其他的云厂商,对我要求更高,要服务好,产品一定要有竞争力。钛媒体:这样把主动权交出去了。行癫:是的,那个主动权我就是掌握了也没有用,因为那也不是云要做的事情。怎么走好我觉得还是很有挑战的。关于企业上云的未来钛媒体:因为现在架构变的非常重要,很多企业正在经历架构变化的过程,从技术到架构这一步的跨越是很困难的事情吗?行癫:企业的架构,我认为绝大部分是业务架构,不是纯粹的技术架构,他缺的是把自己的业务都分析清楚,变成了一堆业务架构的能力,用技术手段去实现。互联网公司两者兼而有之,我们公司有些是业务架构,有些是技术架构,技术架构更偏纯技术,业务架构非常复杂,它做很多决定,比如说做电子商务系统,他决定要分多少个模块,各个模块关系怎么样,最好用什么技术实现。技术怎么实现的,是技术架构干的事情,我觉得大部分企业缺乏非常好的业务架构,这个业务架构你没法招聘,一定要自己培养,这样才能理解自己业务。钛媒体:你做阿里CTO一段时间了,我特别想了解,作为一家大企业的CTO,你最大的职责是什么?行癫:阿里的CTO,第一要对未来有看法有判断,到底未来要有什么样的技术;第二个组织内部基础资源整合好,不能各自为战。第三,技术工程师的文化要定义,我们经常讨论这个事情,到底怎么激励我们的公司,第四保证业务系统的技术需求得到及时的满足,不能业务系统都支持不好,就有难度了。钛媒体:因为现在整个技术变化非常大,我想也听听,你给这些传统企业的CEO、CIO一些建议,他们怎么样树立自己的技术视角,怎么让他们用自己的视角判断技术价值?行癫:我觉得大部分公司关注好业务就差不多了,大部分中小企业都是这个状态。技术不要成为瓶颈,就非常不错了。只有很大型的互联网公司,他才能判断有没有系统性技术风险,比如一些新技术,基于一些新技术的商业模式,他可能要反复思考一些问题。比如5G起来,智能手机普及了,大概会对我们商业模式技术体系有什么影响,物联网起来了会有什么影响,智能驾驶到底会怎么样,这些都是我们要去提前想的。钛媒体:这些问题你会怎么判断?行癫:我们也会反复判断,对我们业务有什么用,因为我们业务很复杂,区块链怎么样,我们怎么用,我们不做有什么风险,这是我们经常在看。但是很难总结方法论,得出一个结论,这个是非常难的。钛媒体:现在企业里边,大家都在追求很时髦的东西,上云、架构,但是有一些被忽略的问题,包括运维、安全。从你的角度来看,传统企业上云有哪些问题应该提起他们的重视,有哪些被忽略的问题?行癫:云上系统,上云的第一刻开始,我们阿里很多人都投在运维,这样才能保证系统永远处于健康状态。原来都是开箱即用的技术,弄个oracle就可以了,弄个数据库DBA就可以了,但现在不行了。以后整个系统要保持效率最高,运维工作还是非常重要,但中国公司绝大部分没有付费做运维这个习惯,这个我觉得还需要一个改变。安全其实压力小了很多,因为云解决了很多原来线下没法解决的问题,比如说有个补丁、有个漏洞,我们第一时间知道,厂商会告诉我们,我们全部把它修复了。总体上,上云比不上云安全得多。钛媒体:真正上云之后,企业尤其是传统企业,会带来很多变化,包括能力和人员的配备。这块你看的更多,你怎么看这些变化?行癫:现在诞生了非常多一些第三方公司,专门帮政府云上做运维,给政府的IT部门带来很大变化。企业也一样,比如原来信息化部规模可能比较大,因为原来的人可能要端到端覆盖,所以工种也比较复杂。上云以后,总的来说,从固定资本投入,还有对人员的一些要求都会有很大变化,至少DBA就不是很重要的岗位了。钛媒体:人工智能的出现,有一个副作用,那就是它对技术能力的要求,几乎超过了哪怕最大规模的传统企业的承受能力。这对企业的技术选型和系统建设策略会带来很大的影响,这件事你怎么看?行癫:我觉得他们肯定更应该关注跟行业属性相关的,这部分别人没有办法复制,其他都是市场上可以采购的,包括云服务、语音服务、数据处理服务、AI服务。他需要明白的是,这个技术对我们的行业产生什么影响。很多行业现在没有能力承载(一些技术的开发),倒不在于一次性投入有多高,主要没有一个规模化的业务场景去做承载,它的演进时间就没有公司能容忍。但现在一些公司还在做云,做人脸识别,这个不会构成它的核心能力,它的核心能力是跟自己业务相关的部分。钛媒体:现在一些大型的企业,还有两三千人的IT团队,还在做大量的自己研发的工作,你觉得未来这种事未来会变的更多还是更少?行癫:我觉得更少,专业化的分工一定是现代社会的精髓,漠视这一点,可能不会获得最高效率。怎么利用社会分工,专业化服务,这是大公司也好,小公司也好,真正能够提升自己的效率,能够集中在自己核心优势的一个地方。阿里云,刚才你也问我,我觉得如果我们现在有几万人,那说明肯定不够聚焦,那样的话肯定在做我们并不擅长的事情。本文作者:阿里云头条阅读原文本文为云栖社区原创内容,未经允许不得转载。

April 2, 2019 · 1 min · jiezi

天马行空脚踏实地,阿里巴巴有群百里挑一的天才应届生

阿里巴巴有一群天马行空脚踏实地的阿里星。阿里巴巴的春季校招已经启动。在阿里的技术大咖储备团队中,有三分之一是来自高校招聘,这当中,有一项名为阿里星的神秘计划。这是校招中专门针对高校顶尖大学生的一个培养计划,每年平均录取人数不到20人,录取比例不足1%。百里挑一的阿里星作为阿里面向应届生的顶级人才计划,只有精英中的精英才有机会获得阿里星称号。自2011年起,每一届阿里星都是百里挑一的人才,他们大多是博士,经过十几轮面试,入职前就自带各种主角光环,比如“高考状元”“清华博士”“SCI期刊审稿人”等等。在以阿里星身份入职后,这些精英应届生将获得上不封顶的年薪,由副总裁级别担任主管进行重点培养,定期和阿里合伙人面对面交流,更重要的是,他们有机会直面最具挑战性的项目。8年来,历届阿里星中有人成为了阿里云高级安全工程师,有人成为了菜鸟高级算法工程师,也有人直接踏进达摩院科学家的战队。在最近一届的阿里星中,也有不少新星崭露头角——比如中科大毕业的陈谦,年仅27岁就独立研发人机对话系统,在国际大赛中接连击败IBM、麻省理工等机构,拿下两个世界第一,将人机对话准确率的世界纪录提升至94.1%。“前几年传得很神,说阿里星都是3岁会编程,10岁夺国际奖项的天才。”菜鸟高级算法工程师丁见亚第一次听说阿里星时,还在清华大学攻读博士,旁人偶尔说起,自动化专业的师兄盖坤是第一届的阿里星,目前已是阿里的算法研究员。从小学编程的天才2018年,直到丁见亚自己也成了阿里星,他才明白“3岁会编程”的标准或许有点夸大其词,然而不可否认的是,阿里星们大都是从小接触编程。丁见亚的第一行代码,就是在小学的机房里写下,用来控制屏幕上一只小乌龟的运动轨迹。而2018届阿里星中年纪最小的刘煜堃,小学六年级就会熬夜翻看论坛,通过视频偷偷学习黑客知识。相比其他一路顺风顺水的同学,刘煜堃可算是一个经历过失败的天才。上高中后,他又迷上了网络游戏,尤其到寒暑假,一天能玩上七八个小时,影响了学习,最终高考发挥失常进了福州大学,就读信息安全专业。大二暑假,导师推荐刘煜堃与同学组队,参加了CTF(网络安全技术)竞赛,作为“萌新”却意外打进决赛,刘煜堃由此入坑,回校后组建了一支战队。每周六早上9点,战队成员围坐在电脑前,在规定的48小时内轮流上线解题,通过挖掘漏洞攻击对手得分,修补漏洞避免丢分。从两周一赛,到一周一赛,刘煜堃一路“打”进了清华大学网络与信息安全实验室,成为清华蓝莲花战队的一员。2016年,蓝莲花战队代表中国参加世界黑客大赛DEF CON CTF决赛并获得亚军。实践经历成敲门砖在2018届阿里星中,只有刘煜堃是硕士,但多年CTF的战绩成为他入选阿里星的敲门砖,最终成为阿里云智能安全部的高级安全工程师。这也是阿里在历年校招中始终秉承的理念——文凭只是衡量人才的一个方面,实践能力也很重要,而最能反映实践能力的就是实践经历。丁见亚曾在滴滴实习,需要分析供给侧与需求侧的诉求,建立合理的定价模型,以作为平台定价的参考。2017年暑假,丁见亚还跟着导师做过一篇关于“分享经济”的论文。这两次经历成为丁见亚在阿里星面试时与主管的谈资。“主管一听我的论文,就问我对滴滴的定价怎么看,这刚好是我下一趴要讲的内容。”一般情况下,阿里星的面试起码进行4轮,有些人的面试高达13轮。刘煜堃的主管曾告诉他,在面试时,自己最看重的是阿里星的技术功底、技术视野和求知欲,光靠理论知识,很难达到这个标准。![清华求学的胡庆达](https://upload-images.jianshu…丁见亚同样有着丰富的实践经历,他还在EJOR等高水平期刊发表了多篇论文,并数次担任SCI期刊审稿人。同样来自清华大学的2018届阿里星胡庆达,在成为阿里云数据库技术专家之前,除了有“多篇顶级会议论文”的标签,也在工业圈的实践经验上,积累了近20万行的代码。到阿里就为了战斗都说结业是一项双向选择,那么作为应届生中百里挑一的精英,阿里星们为什么选择了阿里?2018届阿里星杨涛,是安徽省芜湖市高考状元。一次,他在清华大学的报告厅里,听到阿里巴巴达摩院副院长华先胜关于城市大脑的演讲,被“用数据智能助力城市管理和服务”这一目标感染。2018年6月,博士毕业离校前夕,杨涛在清华的老图书馆里,接到了阿里HR的面试电话,希望他以阿里星的身份加入达摩院。“懂技术的人,对技术是有一种敬仰和向往。”杨涛接下了这份邀约。刘煜堃则是在面试时,被主管一句话击中,“阿里云上的场景是天然的战场,你打过仗,能力才会得到提升。”成就感,也是未来星选择阿里的重要因素。丁见亚放弃了在美国名校读博后的机会,加入了阿里旗下的菜鸟网络。阿里一直鼓励工程师把技术和业务场景结合起来,在加入菜鸟大快递智能化部门后,畅游在“数据场景”中的丁见亚更是坚定了最初的选择。偶然听到周围朋友刷着手机感叹“现在快递越送越快了”,丁见亚会暗自窃喜。在物流车调度场景中,丁见亚和同事通过机器学习的算法挖掘物流车的历史线路规律,甚至连司机爱超的小道,以及中途停靠抽烟片区的偏好,也被纳入计算因子,这套算法替代了人工调度,输出一套最优化的方案。“数据配合当下场景加强用户的体感,这满足了我在数学建模中的梦。”马云曾经对来阿里求职的人说过,“我不能保证你有钱,也不能保证你成名,但能保证一定有更多历练。”阿里星计划正是凭借着更多更丰富的实战场景和历炼的机会,吸引着高校中最年轻、最顶级的竞赛控、学习控、技术控、逻辑控、实战控。天马行空脚踏实地奋斗在阿里巴巴生态圈里,阿里星们“高考状元”“清华博士”“论文达人”的光环早已褪去,但是不断学习,不断接受挑战,仍然是这些学霸的本色。“清华流行一句话,不要让考上清华成为你的人生巅峰。”丁见亚每周至少阅读两篇论文“补充能量”,他也喜欢通过“撸铁”释放压力,午餐前的一个小时,他会先在菜鸟园区内的健身房完成一系列的力量训练。丁见亚还有个坚持十年的习惯——随时随地思考,随时随地记录,哪怕在洗澡时想出的点子,他也会立马擦干双手,把想法记录到手机上。刘煜堃的主管,经常对他提出高出职级范围的要求。“目前安全攻防人才多数关注于单点突破,而安全架构的设计必须考虑周全。”在推进的可信云项目中,主管要求刘煜堃在保持现有攻防技能的情况下,承担更多的安全架构设计,在项目结束后能完成从一个顶级的攻防人才到安全架构人才的转变。如何缩短理论研究与实际应用的距离,则是胡庆达要攻破的难题。他还记得刚入职那天,主管说过“造火箭得先学会拧螺丝”。杨涛到了达摩院后,与优酷合作,用算法来选择个性化的视频封面分发,实现视频领域的“千人千面”,他明白了“阿里的科研并不是天马行空的科研,是始终面向商业需求”。“天马行空,脚踏实地。”阿里巴巴集团CEO张勇的这句话很契合阿里星们的真实状态,2019年春季校招初始,更多的“最强大脑”将会加入阿里巴巴的生态圈,赶上这场技术创造新商业的变革时期。本文作者:王安忆阅读原文本文来自云栖社区合作伙伴“ 天下网商”,如需转载请联系原作者。

April 1, 2019 · 1 min · jiezi

跨平台技术演进

前言大家好,我是simbawu,关于这篇文章,有问题欢迎来这里讨论。随着移动互联网的普及和快速发展,手机成了互联网行业最大的流量分发入口。以及随着5G的快速发展,未来越来越多的“端”也会如雨后春笋般快速兴起。而“快”作为互联网的生存之道,为了占领市场,企业也会积极跟进,快速布局。同一个应用,各个“端”独立开发,不仅开发周期长,而且人员成本高。同时,作为技术人员,也不应该满足于这种重复、低能的工作状态。在这样的形势下,跨平台的技术方案也受到越来越多人和企业的关注。接下来,我将从原理、优缺点等方面为大家分享《跨平台技术演进》。H5说到跨平台,没人不知道H5。不管是在Mac、Windows、Linux、iOS、Android还是其他平台,只要给一个浏览器,连“月球”上它都能跑。浏览器架构下面,我们来看看让H5如此横行霸道的浏览器的架构:User Interface 用户界面:提供用户与浏览器交互Browser Engine 浏览器引擎:控制渲染引擎与JS解释器Rendering Engine 渲染引擎:负责页面渲染JavaScript Interpreter JS解释器:执行JS代码,输出结果给渲染引擎Networking 网络工作组:处理网络请求UI Backend UI后端:绘制窗口小部件Data Storage 数据存储:管理用户数据浏览器由以上7个部分组成,而“渲染引擎”是性能优化的重中之重,一起了解其中的渲染原理。渲染引擎原理不同的浏览器内核不同,渲染过程会不太一样,但主要流程还是一致的。分为下面6步骤:HTML解析出DOM TreeCSS解析出CSSOMDOM Tree与CSSOM关联生成Render TreeLayout 根据Render Tree计算每个节点的尺寸、位置Painting 根据计算好的信息绘制整个页面的像素信息Composite 将多个复合图层发送给GPU,GPU会将各层合成,然后显示在屏幕上。从以上6步,我们可以总结渲染优化的要点:Layout在浏览器渲染过程中比较耗时,应尽可能避免重排的产生复合图层占用内存比重非常高,可采用减小复合图层进行优化以上就是浏览器端的内容。但H5作为跨平台技术的载体,是如何与不同平台的App进行交互的呢?这时候JSBridge就该出场了。JSBridge原理JSBridge,顾名思义,是JS和Native之间的桥梁,用来进行JS和Native之间的通信。通信分为以下两个维度:JavaScript 调用 Native,有两种方式:拦截URL Scheme:URL Scheme是一种类似于url的链接(boohee://goods/876898),当web前端发送URL Scheme请求之后,Native 拦截到请求并根据URL Scheme进行相关操作。注入API:通过 WebView 提供的接口,向 JavaScript 的 Context(window)中注入对象或者方法,让 JavaScript 调用时,直接执行相应的 Native 代码逻辑,达到 JavaScript 调用 Native 的目的。Native 调用 JavaScript:JavaScript暴露一个对象如JSBridge给window,让Native能直接访问。那么App内加载H5的过程是什么样的呢?App打开H5过程打开H5分为4个阶段:交互无反馈打开页面 白屏请求API,处于loading状态出现数据,正常展现这四步,对应的过程如上图所以,我们可以针对性的做性能优化。优缺点分析下面,我们进行H5的优缺点分析:优点跨平台:只要有浏览器,任何平台都可以访问开发成本低:生态成熟,学习成本低,调试方便迭代速度快:无需审核,及时响应,用户可毫无感知使用最新版缺点性能问题:在反应速度、流畅度、动画方面远不及原生功能问题:对摄像头、陀螺仪、麦克风等硬件支持较差虽然H5目前还存在不足,但随着PWA、WebAssembly等技术的进步,相信H5在未来能够得到越来也好的发展。小程序2018年是微信小程序飞速发展的一年,19年,各大厂商快速跟进,已经有了很大的影响力。下面,我们以微信小程序为例,分析小程序的技术架构。小程序跟H5一样,也是基于Webview实现。但它包含View视图层、App Service逻辑层两部分,分别独立运行在各自的WebView线程中。View可以理解为h5的页面,提供UI渲染。由WAWebview.js来提供底层的功能,具体如下:消息通信封装为WeixinJSBridge日志组件Reporter封装wx api(UI相关)小程序组件实现和注册VirtualDOM,Diff和Render UI实现页面事件触发每个窗口都有一个独立的WebView进程,因此微信限制不能打开超过5个层级的页面来保障用户体验。App Service提供逻辑处理、数据请求、接口调用。由WAService.js来提供底层的功能,具体如下:日志组件Reporter封装wx apiApp,Page,getApp,getCurrentPages等全局方法AMD模块规范的实现运行环境:iOS:JavaScriptCoreAndriod:X5内核,基于Mobile Chrome 53/57DevTool:nwjs Chrome 内核仅有一个WebView进程View & App Service通信视图层和逻辑层通过系统层的JSBridage进行通信,逻辑层把数据变化通知到视图层,触发视图层页面更新,视图层将触发的事件通知到逻辑层进行业务处理。优缺点分析优点预加载WebView,准备新页面渲染View层和逻辑层分离,通过数据驱动,不直接操作DOM使用Virtual DOM,进行局部更新组件化开发缺点仍使用WebView渲染,并非原生渲染,体验不佳不能运行在非微信环境内没有window、document对象,不能使用基于浏览器的JS库不能灵活操作 DOM,无法实现较为复杂的效果页面大小、打开页面数量都受到限制既然WebView性能不佳,那有没有更好的方案呢?下面我们看看React Native。React NativeRN的理念是在不同平台上编写基于React的代码,实现Learn once, write anywhere。Virtual DOM在内存中,可以通过不同的渲染引擎生成不同平台下的UI,JS和Native之间通过Bridge通信React Native 工作原理在 React 框架中,JSX 源码通过 React 框架最终渲染到了浏览器的真实 DOM 中,而在 React Native 框架中,JSX 源码通过 React Native 框架编译后,与Native原生的UI组件进行映射,用原生代替DOM元素来渲染,在UI渲染上非常接近Native App。### React Native 与Native平台通信React Native用JavaScriptCore作为JS的解析引擎,在Android上,需要应用自己附带JavaScriptCore,iOS上JavaScriptCore属于系统的一部分,不需要应用附带。用Bridge将JS和原生Native Code连接起来。Native和 JavaScript 两端都保存了一份配置表,里面标记了所有Native暴露给 JavaScript 的模块和方法。交互通过传递 ModuleId、MethodId 和 Arguments 进行。优缺点分析优点垮平台开发:相比原生的ios 和 android app各自维护一套业务逻辑大同小异的代码,React Native 只需要同一套javascript 代码就可以运行于ios 和 android 两个平台,在开发、测试和维护的成本上要低很多。快速编译:相比Xcode中原生代码需要较长时间的编译,React Native 采用热加载的即时编译方式,使得App UI的开发体验得到改善,几乎做到了和网页开发一样随时更改,随时可见的效果。快速发布:React Native 可以通过 JSBundle 即时更新 App。相比原来冗长的审核和上传过程,发布和测试新功能的效率大幅提高。渲染和布局更高效:React Native摆脱了WebView的交互和性能问题,同时可以直接套用网页开发中的css布局机制。脱了 autolayout 和 frame 布局中繁琐的数学计算,更加直接简便。缺点动画性能差:React Native 在动画效率和性能的支持还存在一些问题,性能上不如原生Api。不能完全屏蔽原生平台:就目前的React Native 官方文档中可以发现仍有部分组件和API都区分了Android 和 IOS 版本,即便是共享组件,也会有平台独享的函数。也就是说仍不能真正实现严格意义上的“一套代码,多平台使用”。另外,因为仍对ios 和android的原生细节有所依赖,所以需要开发者若不了解原生平台,可能会遇到一些坑。生态不完善:缺乏很多基本控件,第三方开源质量良莠不齐展望未来虽然RN还存在不足,但RN新版本已经做了如下改进,并且RN团队也在积极准备大版本重构,能否成为开发者们所信赖的跨平台方案,让我们拭目以待。改变线程模式。UI 更新不再同时需要在三个不同的线程上触发执行,而是可以在任意线程上同步调用 JavaScript 进行优先更新,同时将低优先级工作推出主线程,以便保持对 UI 的响应。引入异步渲染能力。允许多个渲染并简化异步数据处理。简化 JSBridge,让它更快、更轻量。既然React Native在渲染方面还摆脱不了原生,那有没有一种方案是直接操控GPU,自制引擎渲染呢,我们终于迎来了Flutter!FlutterFlutter是Google开发的一套全新的跨平台、开源UI框架,支持iOS、Android系统开发,并且是未来新操作系统Fuchsia的默认开发套件。渲染引擎依靠跨平台的Skia图形库来实现,依赖系统的只有图形绘制相关的接口,可以在最大程度上保证不同平台、不同设备的体验一致性,逻辑处理使用支持AOT的Dart语言,执行效率也比JavaScript高得多。Flutter架构原理Framework:由Dart实现,包括Material Design风格的Widget,Cupertino(针对iOS)风格的Widgets,文本/图片/按钮等基础Widgets,渲染,动画,手势等。此部分的核心代码是:flutter仓库下的flutter package,以及sky_engine仓库下的io,async,ui(dart:ui库提供了Flutter框架和引擎之间的接口)等package。Engine:由C++实现,主要包括:Skia,Dart和Text。Skia是开源的二维图形库,提供了适用于多种软硬件平台的通用API。其已作为Google Chrome,Chrome OS,Android, Mozilla Firefox, Firefox OS等其他众多产品的图形引擎,支持平台还包括Windows7+,macOS 10.10.5+,iOS8+,Android4.1+,Ubuntu14.04+等。Skia作为渲染/GPU后端,在Android和Fuchsia上使用FreeType渲染,在iOS上使用CoreGraphics来渲染字体。Dart部分主要包括:Dart Runtime,Garbage Collection(GC),如果是Debug模式的话,还包括JIT(Just In Time)支持。Release和Profile模式下,是AOT(Ahead Of Time)编译成了原生的arm代码,并不存在JIT部分。Text即文本渲染,其渲染层次如下:衍生自minikin的libtxt库(用于字体选择,分隔行)。HartBuzz用于字形选择和成型。Embedder:是一个嵌入层,即把Flutter嵌入到各个平台上去,这里做的主要工作包括渲染Surface设置,线程设置,以及插件等。从这里可以看出,Flutter的平台相关层很低,平台(如iOS)只是提供一个画布,剩余的所有渲染相关的逻辑都在Flutter内部,这就使得它具有了很好的跨端一致性。Dart优势很多人会好奇,为什么Flutter要用Dart,而不是用JavaScript开发,这里列下Dart的优势Dart 的性能更好。Dart在 JIT模式下,速度与 JavaScript基本持平。但是 Dart支持 AOT,当以 AOT模式运行时,JavaScript便远远追不上了。速度的提升对高帧率下的视图数据计算很有帮助。Native Binding。在 Android上,v8的 Native Binding可以很好地实现,但是 iOS上的 JavaScriptCore不可以,所以如果使用 JavaScript,Flutter 基础框架的代码模式就很难统一了。而 Dart的 Native Binding可以很好地通过 Dart Lib实现。Fuchsia OS。Fuchsia OS内置的应用浏览器就是使用 Dart语言作为 App的开发语言。优缺点分析优点性能强大:在两个平台上重写了各自的UIKit,对接到平台底层,减少UI层的多层转换,UI性能可以比肩原生优秀的语言特性:参考上面Dart优势分析路由设计优秀:Flutter的路由传值非常方便,push一个路由,会返回一个Future对象(也就是Promise对象),使用await或者.then就可以在目标路由pop,回到当前页面时收到返回值。缺点优点即缺点,Dart 语言的生态小,精通成本比较高UI控件API设计不佳与原生融合障碍很多,不利于渐进式升级总结移动互联网的普及和快速发展,跨平台技术风起云涌,这也是技术发展过程中的必经之路,等浪潮退去,才知道谁在裸泳。我个人更看好H5或类H5方案,给它一个浏览器,连“月球”都能跑,这才是真正的跨平台,其他都是浮云。广而告之本文发布于薄荷前端周刊,欢迎Watch & Star ★,转载请注明出处。欢迎讨论,点个赞再走吧 。◕‿◕。 ~ ...

April 1, 2019 · 1 min · jiezi

六年打磨!阿里开源混沌工程工具 ChaosBlade

阿里妹导读:减少故障的最好方法就是让故障经常性的发生。通过不断重复失败过程,持续提升系统的容错和弹性能力。今天,阿里巴巴把六年来在故障演练领域的创意和实践汇浓缩而成的工具进行开源,它就是 “ChaosBlade”。如果你想要提升开发效率,不妨来了解一下。高可用架构是保障服务稳定性的核心。阿里巴巴在海量互联网服务以及历年双11场景的实践过程中,沉淀出了包括全链路压测、线上流量管控、故障演练等高可用核心技术,并通过开源和云上服务的形式对外输出,以帮助企业用户和开发者享受阿里巴巴的技术红利,提高开发效率,缩短业务的构建流程。例如,借助阿里云性能测试 PTS,高效率构建全链路压测体系,通过开源组件 Sentinel 实现限流和降级功能。这一次,经历了 6 年时间的改进和实践,累计在线上执行演练场景达数万次,我们将阿里巴巴在故障演练领域的创意和实践,浓缩成一个混沌工程工具,并将其开源,命名为 ChaosBlade。ChaosBlade 是什么?ChaosBlade 是一款遵循混沌工程实验原理,提供丰富故障场景实现,帮助分布式系统提升容错性和可恢复性的混沌工程工具,可实现底层故障的注入,特点是操作简洁、无侵入、扩展性强。ChaosBlade 基于 Apache License v2.0 开源协议,目前有 chaosblade 和 chaosblade-exe-jvm 两个仓库。chaosblade 包含 CLI 和使用 Golang 实现的基础资源、容器相关的混沌实验实施执行模块。chaosblade-exe-jvm 是对运行在 JVM 上的应用实施混沌实验的执行器。ChaosBlade 社区后续还会添加 C++、Node.js 等其他语言的混沌实验执行器。为什么要开源?很多公司已经开始关注并探索混沌工程,渐渐成为测试系统高可用,构建对系统信息不可缺少的工具。但混沌工程领域目前还处于一个快速演进的阶段,最佳实践和工具框架没有统一标准。实施混沌工程可能会带来一些潜在的业务风险,经验和工具的缺失也将进一步阻止 DevOps 人员实施混沌工程。混沌工程领域目前也有很多优秀的开源工具,分别覆盖某个领域,但这些工具的使用方式千差万别,其中有些工具上手难度大,学习成本高,混沌实验能力单一,使很多人对混沌工程领域望而却步。阿里巴巴集团在混沌工程领域已经实践多年,将混沌实验工具 ChaosBlade 开源目的,我们希望:让更多人了解并加入到混沌工程领域;缩短构建混沌工程的路径;同时依靠社区的力量,完善更多的混沌实验场景,共同推进混沌工程领域的发展。ChaosBlade 能解决哪些问题?衡量微服务的容错能力通过模拟调用延迟、服务不可用、机器资源满载等,查看发生故障的节点或实例是否被自动隔离、下线,流量调度是否正确,预案是否有效,同时观察系统整体的 QPS 或 RT 是否受影响。在此基础上可以缓慢增加故障节点范围,验证上游服务限流降级、熔断等是否有效。最终故障节点增加到请求服务超时,估算系统容错红线,衡量系统容错能力。验证容器编排配置是否合理通过模拟杀服务 Pod、杀节点、增大 Pod 资源负载,观察系统服务可用性,验证副本配置、资源限制配置以及 Pod 下部署的容器是否合理。测试 PaaS 层是否健壮通过模拟上层资源负载,验证调度系统的有效性;模拟依赖的分布式存储不可用,验证系统的容错能力;模拟调度节点不可用,测试调度任务是否自动迁移到可用节点;模拟主备节点故障,测试主备切换是否正常。验证监控告警的时效性通过对系统注入故障,验证监控指标是否准确,监控维度是否完善,告警阈值是否合理,告警是否快速,告警接收人是否正确,通知渠道是否可用等,提升监控告警的准确和时效性。定位与解决问题的应急能力通过故障突袭,随机对系统注入故障,考察相关人员对问题的应急能力,以及问题上报、处理流程是否合理,达到以战养战,锻炼人定位与解决问题的能力。功能和特点场景丰富度高ChaosBlade 支持的混沌实验场景不仅覆盖基础资源,如 CPU 满载、磁盘 IO 高、网络延迟等,还包括运行在 JVM 上的应用实验场景,如 Dubbo 调用超时和调用异常、指定方法延迟或抛异常以及返回特定值等,同时涉及容器相关的实验,如杀容器、杀 Pod。后续会持续的增加实验场景。使用简洁,易于理解ChaosBlade 通过 CLI 方式执行,具有友好的命令提示功能,可以简单快速的上手使用。命令的书写遵循阿里巴巴集团内多年故障测试和演练实践抽象出的故障注入模型,层次清晰,易于阅读和理解,降低了混沌工程实施的门槛。场景扩展方便所有的 ChaosBlade 实验执行器同样遵循上述提到的故障注入模型,使实验场景模型统一,便于开发和维护。模型本身通俗易懂,学习成本低,可以依据模型方便快捷的扩展更多的混沌实验场景。ChaosBlade 的演进史EOS(2012-2015):故障演练平台的早期版本,故障注入能力通过字节码增强方式实现,模拟常见的 RPC 故障,解决微服务的强弱依赖治理问题。MonkeyKing(2016-2018):故障演练平台的升级版本,丰富了故障场景(如:资源、容器层场景),开始在生产环境进行一些规模化的演练。AHAS(2018.9-至今):阿里云应用高可用服务,内置演练平台的全部功能,支持可编排演练、演练插件扩展等能力,并整合了架构感知和限流降级的功能。ChaosBlade(2019.3):是 MonkeyKing 平台底层故障注入的实现工具,通过对演练平台底层的故障注入能力进行抽象,定义了一套故障模型。配合用户友好的 CLI 工具进行开源,帮助云原生用户进行混沌工程测试。近期规划功能迭代:增强 JVM 演练场景,支持更多的 Java 主流框架,如 Redis,GRPC增强 Kubernetes 演练场景增加对 C++、Node.js 等应用的支持社区共建:欢迎访问 ChaosBlade@GitHub,参与社区共建,包括但不限于:架构设计模块设计代码实现Bug FixDemo样例文档、网站和翻译本文作者:中亭阅读原文本文来自云栖社区合作伙伴“ 阿里技术”,如需转载请联系原作者。 ...

March 29, 2019 · 1 min · jiezi

信用算力基于 RocketMQ 实现金融级数据服务的实践

导读:微服务架构已成为了互联网的热门话题之一,而这也是互联网技术发展的必然阶段。然而,微服务概念的提出者 Martin Fowler 却强调:分布式调用的第一原则就是不要分布式。纵观微服务实施过程中的弊端,可以推断出作者的意图,就是希望系统架构者能够谨慎地对待分布式调用,这是分布式系统自身存在的缺陷所致。但无论是 RPC 框架,还是 REST 框架,都因为驻留在不同进程空间的分布式组件,而引入了额外的复杂度。因而可能对系统的效率、可靠性、可预测性等诸多方面带来负面影响。信用算力自2016年开始实施微服务改造,通过消息队列(Message Queue),后文简称MQ,来规避微服务存在的缺陷,实现金融级数据服务。以下是一些使用场景和心得。为什么需要 MQ一、案例介绍先来看一个当前的真实业务场景。对于通过信息流获客的企业而言,当用户注册时,因业务需求会调用用户服务,然后执行一系列操作,注册 -> 初始化账户信息 -> 邀友奖励发放 -> 发放优惠券 -> … -> 信息流数据上报。用户服务的开发人员压力非常大,因为需要调用非常多的服务,业务耦合严重。如果当时账户服务正在执行发版操作,那么初始化账户动作会失败。然而平台经过不断的迭代更新,后续又新增了一个签到业务,新注册用户默认签到一次。这就需要修改用户服务,增加调用签到服务的接口。每当遇到此种情况,开发用户服务的同学就非常不爽了,为什么总是我?新增签到业务和用户服务又有什么关系?为解决此类重度依赖的问题,我们在架构层面引入了 MQ,用来规避微服务之间重度耦合调用的弊端。新架构如下图:用户完成注册动作后,只需要往 MQ 发送一个用户注册的通知消息,下游业务如需要依赖注册相关的数据,订阅注册消息的 topic 即可,从而实现了业务的解耦。看完上述真实的案例后,大家可能产生疑惑,到底什么是 MQ,使用 MQ 又有什么好处?适合使用 MQ 的场景和不适合使用 MQ 的场景有哪些不同?二、什么是 MQ?简单来说,MQ(MessageQueue)是一种跨进程的通信机制,用于上下游传递消息。适合使用 MQ 的场景有:1、上游不关心下游执行结果,例如上述案例中用户注册后,我们并不关心账户是否初始化,是否上报了信息流等;2、异步返回执行时间长:例如上述案例中,当邀友奖励发放,需要经历很多风控规则,执行时间比较长,但是用户并不关注奖励何时发放。不适合使用MQ场景调用方实时关注执行结果,例如用户发起注册动作后,需要立刻知道,注册结果是成功还是失败,这种需要实时知道最终执行结果的场景,就不适合使用MQ。三、使用MQ的好处:1、解耦2、可靠投递3、广播4、最终一致性5、流量削峰6、消息投递保证7、异步通信(支持同步)8、提高系统吞吐、健壮性MQ 的技术选型目前业内比较主流的 MQ 包括 RocketMQ、ActiveMQ、RabbitMQ、Kafka等,关于性能、存储、社区活跃度等各方面的技术对比已经很多,本文不再重复。但我们发现通过简单的选型对比,很难抉择到底选择哪款MQ产品。因为金融行业对于数据一致性以及服务可用性的要求非常高,所以任何关于技术的选项都显得尤为重要。经调研,如微众银行、民生银行、平安银行等国内知名的互联网银行和直销银行代表,都在使用 RocketMQ,且 RocketMQ 出生在阿里系,经受过各种生产压力的考验,非常稳定。并且,目前此项技术已经捐增给 Apache 社区,社区活跃度非常高。另外 RocketMQ 开发语言是Java,开发同学遇到解决不了的问题点,或者不清楚的概念,可以直接 Debug 源码。经过多方面的比较,我们选择 RocketMQ 作为规避微服务弊端的利器。MQ 在微服务下的使用场景MQ 是一种跨进程的通信机制,用于上下游传递消息,目前信用算力将 RocketMQ 应用于解耦、流量削峰、分布式事务的处理等几个场景。一、解耦通常解耦的做法是生产者发送消息到 MQ,下游订阅 MQ 的特定 topic,当下游接收到消息后开始处理业务逻辑。那么,消息发送方到底应该是由谁来承担?是服务提供者在处理完RPC请求后,根据业务需求开始发送消息吗?但此刻开发人员就会抱怨为什么总是我?为什么处理完业务后需要发送 MQ?为此,在解耦的过程中通过订阅数据库的 BinLog 日志,开发了一套 BinLog 日志解析模块,专门解析日志,然后生成 JSON 字符串后发送消息到 MQ,下游订阅 MQ 即可。流程如下:目前所有需要依赖下游服务的业务线,其数据变动都采用此方案。方案优缺点:优点:1、服务之间依赖完全解耦,任何基于注册行为的业务变更,都无需依赖上游,只需订阅MQ即可;2、系统的稳定性和吞吐量增加了,用户注册的响应时间缩短了;缺点:1、引入MQ后系统复杂性增加,维护成本增加;2、从注册开始到全部数据初始化结束的整体时间增加了;二、流量削峰每逢遇到会员日的时候,平台会发送大量的会员福利活动通知,以短信、站内信、PUSH 消息的方式通知注册用户。所有的消息会在很短的时间全部推送到消息中心,同时正常的业务通知任然有大量业务消息推送到消息中心。为保障平台的稳定性和可靠性,在消息中心前置了多种 topic,如短信、推送、站内提醒。消息中心接收到消息后会全部写入不同 topic 的 MQ,多个消费者来消费并把信息推送给终端用户。三、分布式事务用户在平台上支付他订购某种业务的时候,需要涉及到支付服务、账户服务、优惠券服务、积分服务,在单体模式下这种业务非常容易实现,通过事务即可完成,伪代码如下:然而,在微服务的情况下,原本通过简单事务处理的却变得非常复杂,若引入两阶段提交(2PC)或者补偿事务(TCC)方案,则系统的复杂程度会增加。信用算力的做法是通过本地事务 + MQ 消息的方式来解决, 虽然 RocketMQ 也支持事务消息,但是其他主流 MQ 并没有此项功能,所以综合考虑采用如下方案:消息上游:需要额外建一个tc_message表,并记录消息发送状态。消息表和业务数据在同一个数据库里面,而且要在一个事务里提交。然后消息会经过MQ发送到消息的消费方。如果消息发送失败,会进行重试发送;消息上游:开启定时任务扫描tc_message表,如果超过设置的时间内状态没有变更,会再次发送消息到MQ,如重试次数达到上限则发起告警操作;消息下游:需要处理这个消息,并完成自己的业务逻辑。此时如果本地事务处理成功,表明已经处理完成了,需要发起业务回调通知业务方;方案优缺点:优点:1、用最小的代价实现分布式事物,以达到数据最终一致性;2、方案非常灵活,任何环节都可以人为控制;缺点:1、复杂性增加了,业务操作的时候需要写入 tc_message 表以及发送 MQ,同时还需要考虑状态超时未变更的补发机制以及告警处理机制;2、用户看到的数据,存在有短暂不一致的情况;心得体会使用 RocketMQ 3年多了,总体来说运行的非常稳定,基本上没有发生过生产事故,下面说说这几年使用下来的心得体会:1、一个应用尽可能用一个 Topic,消息子类型用 tags 来标识。Topic 名称和 Tags 名称可以自行设置。Producer,Consumer都需要规范,要做到见名知意。发送消息时候必须携带 Tags,消费方在订阅消息时,才可以利用 Tags 在 Broker 做消息过滤。2、每条消息在业务层面有唯一标识码,方便在系统出现异常的情况,可以通过业务维度查询。举个栗子,当用户在平台注册成功后,会以 Topic 和 UserID 作为唯一标识码(topic_user_10011),服务器会为每个消息创建索引,该消息会持久化入库,以防将来定位消息丢失等问题。下游收到消息后会以 Topic+Key 方式来记录消费行为,包括消息日期、当前机器IP地址、处理结果等;也可以通过 Topic+Key 的方式来查询这条消息内容,包括消息被谁消费,以及这条 MQ 在每个环节的处理状态。3、消息发送成功或者失败,都需要记录 log 日志,且必须打印 sendresult、MsgID、唯一标识码。4、由于上游会做消息重试机制,所以下游消息必须要做幂等处理。5、需要封装 MQ 的 API 在封装后,API 需屏蔽底层 MQ 的特性,开发人员无需关注到底是用的哪个 MQ 来支持本地分布式事物、MQ 消息自动入库、自动打印日志,减少开发人员操作成本。总的来说,MQ 是一个互联网架构中常见的解耦利器,在这3年中,信用算力在微服务中一直使用 MQ 来为金融客户提供高质量的数据服务。虽然 MQ 不是唯一方案,但是从目前阶段来看,的确是一种非常不错的解决方案。本文作者:潘志伟(信用算力技术总监,QCon 演讲嘉宾,十多年 Java 从业经验,精通微服务架构,精通大数据。拥有亿级用户平台架构经验,万级并发的API网关经验。)本文作者:中间件小哥阅读原文本文为云栖社区原创内容,未经允许不得转载。 ...

March 29, 2019 · 1 min · jiezi

Kubernetes 如何打赢容器之战?

阿里妹导读:Kubernetes 近几年很热门,在各大技术论坛上被炒的很火。它提供了强大的容器编排能力,与此同时 DevOps 的概念也来到大家身边,广大的开发同学也能简单地运维复杂的商业化分布式系统,打破了传统开发和运维之间的界限。本文会以初学者的视角,希望能让读者更好地理解 Kubernetes 出现的背景、超前的设计理念和优秀的技术架构。背景PaaSPaaS 技术,一句话概括就是:它提供了“应用托管”的能力。早期的主流做法基本上是租 AWS 或者 OpenStack 的虚拟机,然后把这些虚拟机当作物理机一样,用脚本或者手工的方式在上面部署应用。这个过程中如何保证本地环境和云端环境的一致性是一个很大的课题,而提供云计算服务的公司的核心竞争力就是比拼谁做的更好。从某种意义上来说 PaaS 的出现,算是一个比较好的解决方案。以 Cloud Foundry 为例,在虚拟机上部署上 Cloud Foundry 项目后,用户可以很方便地把自己的应用上云。以上帝视角来看这个过程:Cloud Foundry 最核心的是提供了一套应用的打包和分发机制,它为不同的编程语言定义了不同的打包格式,它能把可执行文件、启动参数等等一起打包成压缩包然后上传至 Cloud Foundry 存储中心,最后由调度器选择虚拟机,由虚拟机上的 Agent 下载并启动应用。分布式系统随着软件的规模越来越大,业务模式越来越复杂,用户量的上升、地区的分布、系统性能的苛刻要求都促成服务架构从最初的单体变成 SOA 再到如今的微服务,未来还可能演变为 Service Mesh ,Serverless 等等。如今,一个完整的后端系统不再是单体应用架构了,多年前的 DDD 概念重新回到大家的视线中。现在的系统被不同的职责和功能拆成多个服务,服务之间复杂的关系以及单机的单点性能瓶颈让部署和运维变得很复杂,所以部署和运维大型分布式系统的需求急迫待解决。容器技术前面提到诸如 Cloud Foundry 的 PaaS,用户必须为不同语言、不同框架区分不同的打包方式,这个打包过程是非常具有灾难性的。而现实往往更糟糕,当在本地跑的好好的应用,由于和远端环境的不一致,在打包后却需要在云端各种调试,最终才能让应用“平稳”运行。而 Docker 的出现改变了一切,它凭借镜像解决了这个问题。Docker 一不做二不休,干脆把完整的操作系统目录也打包进去,如此高的集成度,保证了云端和本地环境的高度一致,并且随时随地轻易地移植。谁也不知道就因为“镜像”这个简单的功能,Docker 完成了对 PaaS 的降维打击,占有了市场。此时,一些聪明的技术公司纷纷跟进 Docker,推出了自家的容器集群管理项目,并且称之为 CaaS。容器技术利用 Namespace 实现隔离,利用 Cgroups 实现限制;在 Docker 实现上,通过镜像,为容器提供完整的系统执行环境,并且通过 UnionFS 实现 Layer 的设计。Docker 容器是完全使用沙箱机制,相互之间不会有任何接口。通过 Docker,实现进程、网络、挂载点和文件隔离,更好地利用宿主机资源。Docker 强大到不需要关心宿主机的依赖,所有的一切都可以在镜像构建时完成,这也是 Docker 目前成为容器技术标准的原因。所以我们能看到在 Kubernetes 中默认使用 Docker 作为容器(也支持 rkt)。Kubernetes铺垫了这么多,终于说到本文的主角了。说 Kubernetes 之前,不得不提 Compose、Swarm、Machine 三剑客,其实在 Kubernetes 还未一统江湖之前,它们已经能实现大部分容器编排的能力了。但是在真正的大型系统上,它们却远远不如 Mesosphere 公司出品的大型集群管理系统,更别说之后的 Kubernetes 了。在容器化和微服务时代,服务越来越多,容器个数也越来越多。Docker 如它 Logo 所示一样,一只只鲸鱼在大海里自由地游荡,而 Kubernetes 就像一个掌舵的船长,带着它们,有序的管理它们,这个过程其实就是容器编排。Kubernetes 起源于 Google,很多设计都是源自于 Borg,是一个开源的,用于管理云平台中多个主机上的容器化的应用,Kubernetes 的目标是让部署容器化的应用简单并且高效,并且提供了应用部署,规划,更新,维护的一种机制。小结至此,读者了解了 Kubernetes 的前世今生,由 PaaS 的火热,引爆了容器技术的战争,而赢得这场战争中最关键的即是拥有强大的容器编排的能力,而 Kubernetes 无疑是这场战争的胜利者。设计理念这一部分,我们会围绕 Kubernetes 的四个设计理念看看这些做法能给我们带来什么。声明式 VS 命令式声明式和命令式是截然不同的两种编程方式,在命令式 API 中,我们可以直接发出服务器要执行的命令,例如: “运行容器”、“停止容器”等;在声明式 API 中,我们声明系统要执行的操作,系统将不断向该状态驱动。我们常用的 SQL 就是一种声明式语言,告诉数据库想要的结果集,数据库会帮我们设计获取这个结果集的执行路径,并返回结果集。众所周知,使用 SQL 语言获取数据,要比自行编写处理过程去获取数据容易的多。apiVersion: extensions/v1beta1kind: Deploymentmetadata: name: etcd-operatorspec: replicas: 1 template: metadata: labels: name: etcd-operator spec: containers: - name: etcd-operator image: quay.io/coreos/etcd-operator:v0.2.1 env: - name: MY_POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace - name: MY_POD_NAME valueFrom: fieldRef: fieldPath: metadata.name我们来看看相同设计的 YAML,利用它,我们可以告诉 Kubernetes 最终想要的是什么,然后 Kubernetes 会完成目标。声明式 API 使系统更加健壮,在分布式系统中,任何组件都可能随时出现故障。当组件恢复时,需要弄清楚要做什么,使用命令式 API 时,处理起来就很棘手。但是使用声明式 API ,组件只需查看 API 服务器的当前状态,即可确定它需要执行的操作。显式的 APIKubernetes 是透明的,它没有隐藏的内部 API。换句话说 Kubernetes 系统内部用来交互的 API 和我们用来与 Kubernetes 交互的 API 相同。这样做的好处是,当 Kubernetes 默认的组件无法满足我们的需求时,我们可以利用已有的 API 实现我们自定义的特性。无侵入性感谢 Docker 容器技术的流行,使得 Kubernetes 为大家提供了无缝的使用方式。在容器化的时代,我们的应用达到镜像后,不需要改动就可以遨游在 Kubernetes 集群中。Kubernetes 还提供存储 Secret、Configuration 等包含但不局限于密码、证书、容器镜像信息、应用启动参数能力。如此,Kubernetes 以一种友好的方式将这些东西注入 Pod,减少了大家的工作量,而无需重写或者很大幅度改变原有的应用代码。有状态的移植在有状态的存储场景下,Kubernetes 如何做到对于服务和存储的分离呢?假设一个大型分布式系统使用了多家云厂商的存储方案,如何做到开发者无感于底层的存储技术体系,并且做到方便的移植?为了实现这一目标,Kubernetes 引入了 PersistentVolumeClaim(PVC)和 PersistentVolume(PV)API 对象。这些对象将存储实现与存储使用分离。PersistentVolumeClaim 对象用作用户以与实现无关的方式请求存储的方法,通过它来抹除对底层 PersistentVolume 的差异性。这样就使 Kubernetes 拥有了跨集群的移植能力。架构首先要提及的是 Kubernetes 使用很具代表性的 C/S 架构方式,Client 可以使用 kubectl 命令行或者 RESTful 接口与 Kubernetes 集群进行交互。下面这张图是从宏观上看 Kubernetes 的整体架构,每一个 Kubernetes 集群都由 Master 节点 和 很多的 Node 节点组成。MasterMaster 是 Kubernetes 集群的管理节点,负责管理集群,提供集群的资源数据访问入口。拥有 Etcd 存储服务,运行 API Server 进程,Controller Manager 服务进程及 Scheduler 服务进程,关联工作节点 Node。Kubernetes API Server 提供 HTTP Rest 接口的关键服务进程,是 Kubernetes 里所有资源的增、删、改、查等操作的唯一入口。也是集群控制的入口进程; Kubernetes Controller Manager 是 Kubernetes 所有资源对象的自动化控制中心,它驱使集群向着我们所需要的最终目的状态; Kubernetes Schedule 是负责 Pod 调度的进程。NodeNode 是 Kubernetes 集群架构中运行 Pod 的服务节点。Node 是 Kubernetes 集群操作的单元,用来承载被分配 Pod 的运行,是 Pod 运行的宿主机。关联 Master 管理节点,拥有名称和 IP、系统资源信息。运行 Docker Runtime、kubelet 和 kube-proxy。kubelet 负责对 Pod 对于的容器的创建、启停等任务,发送宿主机当前状态; kube-proxy 实现 Kubernetes Service 的通信与负载均衡机制的重要组件; Docker Runtime 负责本机容器的创建和管理工作。实现原理为了尽可能地让读者能明白 Kubernetes 是如何运作的,这里不会涉及到具体的细节实现,如有读者感兴趣可以自行参阅官网文档。这里以一个简单的应用部署示例来阐述一些概念和原理。创建 Kubernetes 集群介绍架构的时候我们知道,Kubernetes 集群由 Master 和 Node 组成。Master 管理集群的所有行为例如:应用调度、改变应用的状态,扩缩容,更新/降级应用等。Node 可以是是一个虚拟机或者物理机,它是应用的“逻辑主机”,每一个 Node 拥有一个 Kubelet,Kubelet 负责管理 Node 节点与 Master 节点的交互,同时 Node 还需要有容器操作的能力,比如 Docker 或者 rkt。理论上来说,一个 Kubernetes 为了应对生产环境的流量,最少部署3个 Node 节点。当我们需要在 Kubernetes 上部署应用时,我们告诉 Master 节点,Master 会调度容器跑在合适的 Node 节点上。我们可以使用 Minikube 在本地搭一个单 Node 的 Kubernetes 集群。部署应用当创建好一个 Kubernetes 集群后,就可以把容器化的应用跑在上面了。我们需要创建一个 Deployment,它会告诉 Kubernetes Master 如何去创建应用,也可以来更新应用。当应用实例创建后,Deployment 会不断地观察这些实例,如果 Node 上的 Pod 挂了,Deployment 会自动创建新的实例并且替换它。相比传统脚本运维的方式,这种方式更加优雅。我们能通过 kubectl 命令或者 YAML 文件来创建 Deployment,在创建的时候需要指定应用镜像和要跑的实例个数,之后 Kubernetes 会自动帮我们处理。查看 Pods 和 Nodes下面来介绍下 Pod 和 Node:当我们创建好 Deployment 的时候,Kubernetes 会自动创建 Pod 来承载应用实例。Pod 是一个抽象的概念,像一个“逻辑主机”,它代表一组应用容器的集合,这些应用容器共享资源,包括存储,网络和相同的内部集群 IP。任何一个 Pod 都需要跑在一个 Node 节点上。Node 是一个“虚拟机器”,它可以是虚拟机也可以是物理机,一个 Node 可以有多个 Pods,Kubernetes 会自动调度 Pod 到合适的 Node 上。Service 与 LabelSelectorPods 终有一死,也就是说 Pods 也有自己的生命周期,当一个 Pod 挂了的时候,ReplicaSet 会创建新的,并且调度到合适的 Node 节点上。考虑下访问的问题,Pod 替换伴随着 IP 的变化,对于访问者来说,变化的 IP 是合理的;并且当有多个 Pod 节点时,如何 SLB 访问也是个问题,Service 就是为了解决这些问题的。Service 是一个抽象的概念,它定义了一组逻辑 Pods,并且提供访问它们的策略。和其他对象一样,Service 也能通过 kubectl 或者 YAML 创建。Service 定义的 Pod 可以写在 LabelSelector 选项中(下文会介绍),也存在不指定 Pods 的情况,这种比较复杂,感兴趣的读者可以自行查阅资料。Service 有以下几种类型:ClusterIP(默认):在集群中内部IP上暴露服务,此类型使Service只能从群集中访问;NodePort:通过每个 Node 上的 IP 和静态端口(NodePort)暴露服务。NodePort 服务会路由到 ClusterIP 服务,这个 ClusterIP 服务会自动创建。通过请求 :,可以从集群的外部访问一个 NodePort 服务;LoadBalancer:使用云提供商的负载均衡器,可以向外部暴露服务。外部的负载均衡器可以路由到 NodePort 服务和 ClusterIP 服务;ExternalName:通过返回 CNAME 和它的值,(适用于外部 DNS 的场景)Labels 和 Selectors 能够让 Kubernetes 拥有逻辑运算的能力,有点像 SQL。举个例子:可以查找 app=hello_word 的所有对象,也可以查找 app in (a,b,c) abc的所有对象。Labels是一个绑定在对象上的 K/V 结构,它可以在创建或者之后的时候的定义,在任何时候都可以改变。扩容应用前文提到我们可以使用 Deployment 增加实例个数,下图是原始的集群状态:我们可以随意的更改 replicas (实例个数)来扩容,当我们更改了 Deployment 中的 replicas 值时,Kubernetes 会自动帮我们达到想要的目标实例个数,如下图:更新应用更新应用和扩容类似,我们可以更改 Deployment 中的容器镜像,然后 Kubernetes 会帮住我们应用更新(蓝绿、金丝雀等方式),通过此功能,我们还可以实现切换应用环境、回滚、不停机 CI/CD。下面是部署的过程,需要注意的是我们可以指定新创建的 Pod 最大个数和不可用 Pod 最大个数:总结到了最后,大家对 Kubernetes 有个大概的了解了,但 Kubernetes 远远不止本文所介绍的这些内容。在云原生概念逐渐清晰的今天,Kubernetes 作为 CNCF 中一个接地气的落地项目,其重要性不言而喻。本文作者: 淘敏阅读原文本文来自云栖社区合作伙伴“ 阿里技术”,如需转载请联系原作者。 ...

March 28, 2019 · 3 min · jiezi

我在阿里云做前端

前言今年是我毕业的第10个年头,半路出家做了前端,title一直是前端,你可以说我很专注,有时候也有些遗憾。一直以来,当别人问起你是做什么的,我说前端或者全栈,别人说:哦,做页面的啊!心里难免有些失落。前端是个资源型角色,在认知里对业务的理解深度不够,加上通常负责业务领域很广,比较难有积累和沉淀。如果你问一个毕业10年的JAVA老司机,他跟你谈的一定是大流量下的分布式架构,而前端可能还是昨天茶余饭后讨论vue和react,或者是angular谁更强。如何突破,如何提供业务更多价值,前端们一直在苦苦探寻。网上很多文章,给人启发,但每个人面对的环境,负责的业务不同,不一定都适用。结合自己过去几年在阿里云的前端经验,也做个总结。1.0版本-工具&团队今年是我来阿里云的第五个年头了,从没有想过会在一个公司呆的如此之久,更没想过我能在一个岗位上沉淀4、5年。刚入职在阿里云控制台团队,主要负责云盾控制台、drds控制台等,开发过程中发现大部分场景是「表格」、「表单」,为了避免自己不断重复开发,封装了simpleForm以及控制台cli脚手架,可以做到新开发控制台一键敲定(这个脚手架直到去年还有人问我如何用……也是经久不衰)。这个时候也萌生了做个ide,可视化搭建UI视图,不过限于精力和当时团队的方向,且当时vscode还没今天这么流行,没有尝试,比较遗憾。不过做WebIDE这个点,算是在心里种下了。后由于组织结构调整,我从控制台团队独立出来,负责当时的网站运营方向,开始比较艰难的从0-1组件团队过程。当时业务相对比较简单,主要是:阿里云官网以及官网的Nodejs、云市场业务。由于在控制台团队主要用的angularjs,感觉上手成本比较大,在建立新团队,以及我自己可以选择的时候,React成了我的首选。当时vue还没成熟,其实能选的也只有react。新的技术体系,需要有配套的工程化体系,当时Def还处在1.0时期,为了稳定以及减少开发成本,很自然我们在xef上做了插件式开发,结合自己业务特性,分装了响应的模板,以及定制了开发周期。后由于xef1.0升级2.0,导致我们工具的不稳定,且改动非常大,逐步将我们的工程化体系独立,这就有了后续的DBL(当时叫屌爆了)。我跟老板做汇报时,老板觉得这名字上不了大雅之堂,还硬是憋了个比较有内涵的名字——实在不好记,我现在都记不起来了。这个阶段,我们做了很多技术上的尝试,团队成员都非常苦逼,也非常有激情。团队基础设施建设,我们一直在优化,随着Dawn的基于中间件式的pipeline方式设计,可以说是将工程化做到一个比较高的高度,未来不管是webpack升级到多少,或者新的打包工具出现,对我们来说影响都比较小。面向未来的模式,让我们只需要修改内核,使用者无感知。新的工程化方案也积极跟阿里云其他团队沟通和交流,之前跟风驰和释然也达成一致意见作为阿里云统一构建工具推进,不过落地的不是很好。同时,新的方案也完全遵循集团的标准,跟淘宝阿大团队无缝对接。另外还有一个好处是:dawn不局限在react,你可以使用任何框架;dawn不局限在redux,你可以使用任何你喜欢的数据管理,实际上我们自己有用mota,mobx,graphql-apollo等等。Dawn连接:https://github.com/alibaba/dawn讲完工程化,其实应该讲讲组件化,这是个无法回避的问题,但这对我们来说也是个艰难的过程。15年的时候,我们用过antd(已开源),但是在上层做了一层业务封装;后来fusion开始盛行,在跟ued沟通后,考虑到集团统一,用了一段时间的fusion(已开源);最后我们还是选择了自建组件库,这是一个很无奈的举动。具体细节不表,其中一个重要原因是我们的前台业务需要「阿里云自己的设计元素」,在经过团队很长时间的建设,APS组件库已经作为团队组建库的基础,在其之上构建了业务组件,并在之上构建了业务解决方案。除了折腾传统前端领域,也尝试做了很多跨栈的事情。在我所负责的业务中,由于「端」业务的确实,我们更多的是偏「全栈」。前端同学做全栈,讲实话是不行的——绝大部分前端同学在架构、运维部署方面还是经验偏少,考虑更多的是跟展现层相关。在全栈路径上,由于我们负责的是核心交易链路,我们没有用大家熟悉的nodejs,而选择跟后端一样的语言——Java。做这个决策,其实是挺困难的,也是有故事的。原先有个系统,前端同学用Nodejs写的,但由于业务非常复杂,加上前端一直是个资源瓶颈的角色,一个人干三个人的活,所以这个同学最后搞不定,离职了。这么个系统就变成了后端想接无法接,前端「没人力」接的状况,非常尴尬。从那以后,业务系统中就决定了直接使用Java。在全栈路上,我们主要有两个策略:大前端下自己写部分业务的Java利用serverless通过代理统一配置化转大前端写Java,阿里云其实非常多的前端都已经具备了这个能力,我自己也有独立开发几个系统从0-1上线,分布式部署且支持国际化的经历。做了一段时间后发现,其实效率上还好,并没有传说中nodejs比Java要高效很多的体感.利用serverless通过代理统一配置化转,有段时间看社区有部分人提到Graphql,对此产生了兴趣,就顺便了解了下,通过代理的方式可以将后端数据转换成前端需要的格式,非常吸引人,也就一下子扎进去。我自己也同时做了Nodejs的版本给团队同学普及,同时做了Java版本的demo给后端普及。同时了解到b2b的Mbox平台跟我们想要的能力比较像,找过他们给我们分享,但由于业务系统整个搭建在他们平台有一定得风险,于是决定了自建代理平台,这也是「云查询」平台的背景。云查询主要是战锋主导并推进落地的,在集团内取得了不错的影响力,很多BU很多部门去做过分享。在业务上,通过云查询,我们实现了不用管应用的运维和部署,实现业务逻辑和接口的转换,并自动扩容。尤其是营销体系,在元策&隐天和战锋得协同下,取得了比较大的效率提升,并支持了阿里云去年的双十一。具体「云查询」文章介绍可以看我另外一篇文章。云查询经过一段比较长时间的发展,我们已经逐步将它作为基础能力下沉,在云查询的serverless之上长出了不同的「轻应用」,以支持不同的垂直业务场景。比如:可视化搭建领域「页橱」、基于权限&角色的中后台解决方案「Flex」等;还记得我之前说过5年前我想做WebIde,没有开始;2年前,看到其他云厂商有WebIDE,我们由于业务压力,业务压力没有搞成;今年我们总算是有一点启动,已经和appStudio的同学在共建,基于appStudio基础之上把我们的dawn、云查询做打通,做云端集成化、一站式的研发体验。通过以上的技术基础建设,已经为我们构建了很好的基础基础。业务布局对应着团队、组织的建设。过去几年,团队从0-1建设,到目前xx个在岗同学,形成了4个梯队,三个3业务方向&一个技术架构方向,一路走来,感觉带团管理水很深,很多时候不是说你带的人越多越好,最近看到一本书提到一个词「情感成熟」,这个非常重要。一个技术好,做业务的好手未必能管理好团队,在不同阶段需要适应不同角色的要求,最重要的是时刻保持忧患意识、保持持续学习。在团队建设时,需要重点区分manager和leader,尤其是业务团队我们更希望成为leader,去带着做业务,而不仅仅是做绩效管理。2.0,也就是过去一年,我们在业务思维指导下,owner了部分业务,并利用横向的技术打通、横向的业务思维,取到了一些成果,接下来进入2.02.0业务思维-以横向视角推进业务赋能我们通常把组织中的人分为:一字型、|字型、T字型、+字型。前端正好是—字型团队,负责的业务非常广,而前端又是个非常稀缺的岗位,招聘很困难,所以盘子越大资源瓶颈越明显。「一字型」角色团队,典型的问题就是对业务的深度理解不够,单纯从技术层面去做营销的搭建、中后台的可视化,结果都不尽如人意。这么说起来,可能你觉得没法往下看了,天花板在那里,如何突破其实并没有太多可参考的例子。我写这篇总结,正是有些这样的感悟,希望给大家做一些输入,帮助大家去思考。「一字型」虽然从业务上看我们的深度不够,但从专业技能看我们是标准的「|字型」。前端经过这10来年的发展,语言、框架、工具已经逐步趋于稳定,各种端的性能也越来越流畅,生态非常活跃,任何你碰到的困难相信社区都已经有比较成熟的方案。前端生态快速发展的10年,也验证了我们这些人有着非常强大的学习能力,7天一个框架、3天一个数据库估计都不是太大难事(略夸张,但表达的是这么个意思)。前端直接对接客户,对客户体验的敏感、对流程数据化的敏感、对业务逻辑流程的感知,都是我们生存的根,也是我们独一无二的能力,这个根我们不能丢。有句话叫:饱暖思淫欲,不太恰当,姑且一比。在前端纵深领域的深耕,让我们成为了「紧缺资源」,随着工具的完善,前端们也更希望利用技术为业务赋能。如何赋能?挡在我们面前的是「意识」。在营销中,认知、需求、品牌、品类、价格五个要素中,「认知」最为重要。比如阿里是做电商的、腾讯是做社交的、百度是做搜索的,bat在自己主营业务范畴不断布局,构建了庞大的生态,做过很多尝试,但看起来最终还是围绕本身的基因做生态投资成功率要高一些。那我们想要业务赋能,瓶颈就在于「你个切页面」也要赋能吗?好好做好体验、提效不好吗?我认为「体验、提效」这是前端最核心的能力,也是毕生都努力要实现的目标,坦白讲我们没法马上解决资源瓶颈问题,毕竟现在毕业生都在应聘算法、ai、人工智能;我们也没办法搞一轮体验提升计划;这是个很漫长的过程。但如果我们能以业务的角度出发,去发现问题进而辅助以技术手段解决,并沉淀平台,应对未来千变万化的需求,可能更为实际一些。做为团队的TL,除了在专业上给与同学「|」型的能力纵深,也更希望带着团队同学获得更多业务体感。离开业务谈技术、谈中台都是空中楼阁;离开业务谈前端,注定只能是重复造轮子,而这种低水平的重复正在发生,且可能会持续很久。在很长一段时间里,我都试图把我们「一字型」业务广度做个抽象和融合,希望把「点状」形成「线」,进而形成整体「面」解决方案。我所负责的业务中,主要有4个大方向:官网&营销—for长尾商业化流程后台-for 小二核心售卖流程—核心能力层销售、合作伙伴官网&营销:主要包含获客、激活、转换、留存几个节点,构建高效的「人」、「货」、「场」。很长一段时间里,阿里云的内容维护、营销大促都是基于集团CMS来的。传统大促会场、卡片的方式,前端挖坑后运营编辑内容,而阿里云的「商品」跟淘系有着比较大的差别,另外我们也没有招商、选品的体系,导致这种简单人肉运行的大促方式存在很多弊端,比如不高效、不复用、不能做个性化、数据流程监控力度不够精细等。此外「投放」能力的建设还不够,没有办法做到精细化的人群做精准的营销内容投放。为了解决这些问题,去年开始,由前端团队和pd一起推进完善的营销体系建设:在原有商品的基础上,构建了「营销商品」的概念。更抽象的「货」,且可视化在线配置直接拉取了实时价格和库存。通过我们1.0工具建设的dawn,打通开发流程,使得整个开发链路一致,成本更低。可抽象的货匹配上专门为货打造的UI视图,形成场景能力沉淀。构建ACE(Alibaba Cloud Experience)架构体系,打通搭建体系,通过技术降级打通各类「场」,更好的承载好营销商品的投放。通过全链路场景的曝光,点击,转化,以及最终成交的商品信息等数据的积累,生成用户画像,提供内容场景化方案(在不同场景中精确得向用户展示商品或信息)完善「人」的定位。商业化商品配置:上面提到「营销商品」时提到「基础商品」。目前阿里云基础商品主要分为:「公有云商品」和「技术输出型」。过去很长一段时间我们偏公有云的能力建设,今年年初才开始逐步融入专有云体系。在商业化系统中,我们的小二需要配置售卖规则、价格,需要定义商品模型;同时复杂的规格之间的约束,异常复杂。如何提高商业化的输入和输出的强体验,我们还有很长的路要走。结合今年的专有云项目,从模板的方式出发,将一类产品做个聚合,简化商品模型配置的步骤,大大提高了配置效率,提高体验。销售&合作伙伴:15年刚开始组建团队(这里指的都是前端团队,不是业务团队),15年-18.3月大部门的核心kpi是营收、是首购用户数,主打的是中长尾客户,获得了非常高速的市场增长。后来团队cover范围不断扩大,也负责销售&合作伙伴体系,围绕着「市场营销」、「商机培育」、「商机转化」、「合同履约」构建了我们自己的销售crm系统。toC的业务通常比较好理解,毕竟我们也是c的一员。这段toB的经历,结合业务一号位的培训班,让了解到销售系统的核心,除了工具,最想要的是解决方案,是产品能力的丰富。大概介绍了各个方向的业务,回到我们讨论的主题来——借助横向优势,整合资源&架构提供业务赋能。为了分析他们之间的共性,我们经过很多次的讨论,终于汇聚得到我们的业务流程大图(对外脱敏后的示意图):从这个流程大图中,各个分支最后都需要依赖「售卖能力」,这个售卖能力表现在营销中是「弹窗buy(减少跳出,直接购买)」、购物车(多产品交叉购买、数据算法推荐)、套餐(多产品打包优惠售卖)、提货券(下单和生产分离的售卖能力);表现在销售链路中是「产品配置清单」、「采购单」、「CBM提供给大客户的CTO价格计算器」表现在商品商业化链路中是「模板化」配置清单能力在一大团子中找到业务的共性「售卖能力」,在经历一段时间比较耗资源、耗时的烟囱式开发方式后,抽象出了售卖的核心支持层——紫金阙。这一层,我们定位为业务中台,偏前端层面,也是大前端的领域范畴。唯一需要指出的是,我们用的是Java,没有用nodejs,无其他差别。最后架构如下(脱敏,细节忽略):新的架构模式下,我们减少了大量的前后端沟通,比如「分销采购市场」以传统开发方式需要1-2个月,我们2周就搞定了。新的架构模式,在可预见的未来,可以很好的支持各种营销新玩法,也可以支持销售和合作伙伴的『解决方案』。我想说的是,如果没有我们全量业务的横向视角,我们的抽象方案不会这么通用,这是前端团队的优势。如果没有大前端稳定的技术生态,我们也没机会去做业务赋能。这才是前端的未来,利用横向优势整合,结合某个领域做深做透,形成垂直深度,为业务提供价值,也让我们的技术方案「有的放矢」。前端经常是围绕一个点做需求,得到工具,但无法提供解决方案,因为没有业务属性;唯有结合业务特性,做好沉淀,工具变成平台才能释放更大价值。3.0探索以技术能力为业务提供增值「云计算」核心是解决企业成本的问题,用低成本获得超强的计算、存储能力,获得高并发下弹性扩容的能力。云计算提出了很多概念:IAAS、PAAS、SAAS。。。相对前端角色来讲,体感并不是很强。但是BAAS的出现,让前端眼前一亮。试下想,原先我们需要大量后台开发的应用,逐步都沉淀成领域能力,提供baas服务给前端调用,前端再也不用考虑部署、运维,只关心业务代码,想想也是心动。目前市面上提供类似服务的公司很多,有专门做后台数据存储的如Leancloud、有做数据分析的、有做消息推送的等。所以,Baas会是前端的春天吗?这个拭目以待。扯了理想,我们也说说现状。目前阿里云大概是Buy In Aliyun,我们售卖的是IAAS层的资源,用户核心的业务流程还是基于自己的研发体系。在前端这个纵深领域内,基于云打造「云端一站式研发流程」,将企业前端变成:Work In Aliyun or Dev In Aliyun。通过对企业前端生命周期的分解,通过WebIDE来承载整个流程:1. 将创建关联阿里云的code2.阿里云前端构建工具dawn作为基础构建能力,可定制化团队构建的中间件(webpack、lint、server、mock等)、构建stage(init、dev、test、publish);基于工程化化能力提供统一的规范,提供各种不同应用框架的初始化模板。3.代码点击发布后,自动编译,并发布到cdn。在此基础流程之上,我们提供serverless相关能力,通过调用BaaS领域服务能力,以及FaaS网关触发能力,实际上我们可以完全一站式,且是前端主导的应用开发。还记得我前面提到我们的serverless应用「云查询」,这一层我们逐步进行能力下沉,变成serverless基础能力。各公司几乎都有营销搭建体系,过去搭建的玩法不够多样,主要依托cms能力自行开发,随着现在各种「端」能力的延伸、多样性化,营销搭建也变得越来越复杂。而我们基于「云查询」之上沉淀出的「页橱」搭建体系,完全可以借助「云端一站式研发流程」提供很好的SAAS化服务。这是我们的优势,「云端前端解决方案」也只有我们适合做这个,这里只列举了其中一个场景,类似的机会还有很多。总体感觉,一云多端借助serverless前端的春天已然来临。抓住我们核心的竞争力,并同时发现业务中的问题,跨端推进解决,这是最好的出路。你问我做什么的,我…… 我就是阿里云CPO(首席页面仔啊)ps:阿里云智能业务中台&阿里通信招P6-P8前端,欢迎来撩。base可北京可杭州,杭州工位在美丽的西溪园区哦。旁边挨着的都是UED妹子&测试妹子。xiaoming.dxm@alibaba-inc.com本文作者:城池cc阅读原文本文为云栖社区原创内容,未经允许不得转载。

March 28, 2019 · 1 min · jiezi

商品价格的多币种方案

首发于 樊浩柏科学院假若,你是某个国内电商平台的商品中心项目负责人。突然今天,接到了一个这样的需求:商品在原人民币价格的基础架构上,须支持卢比(印度)价格。需求需求点,可以描述为:购买的用户,商品价格需要支持卢比;营运人员,商品管理系统依然使用人民币价格;同样这个需求,定了以下两个硬指标:必须实现需求;必须快速上线;问题首先,我们必须承认的是,这确实是个简单的需求,但这也是个够坑爹的需求。主要遇到的问题如下:涉及商品价格的系统众多;各上层系统调用商品价格接口繁多;商品价格相关字段较多;为了实现快速上线,我们在原人民币的商品价格基础架构上,只能进行少量且合适的改造。所以,最后我们的改造方向为:尽量只改造商品价格源头系统,即商品中心,其他上层系统尽量不改动。可行性调研改造商品中心,商品价格支持卢比。可行的改造方案有 2 种:1、数据表价格字段存卢比将原人名币价格相关的数据表字段,存卢比值,数据表并新增人名币字段。2、接口输出数据时转化为卢比原人名币相关的数据表字段依然存人民币值,在接口输出数据时,将价格相关字段值转化为卢比。针对以上方案,我们需要注意 2 个问题:汇率会每天变化,所以商品价格也会变化;后续商品价格,可能须支持多币种;上述 方案 ①,商品中心只需改造数据表。然后每天根据汇率刷新商品价格,原价格字段就都变成了卢比。方案相对简单,也容易操作,但缺点是:对任然需要人民币价格的系统,即商品管理系统须改造。方案 ②,需要改造商品中心业务逻辑。由于涉及的价格字段较多,改造较复杂,主要优点是:汇率变动对商品价格影响较小,且可拓展支持多币种价格(可以根据地区标识,获取相应的商品价格)。解决方案最终,为了系统的可扩展性,我们选择了方案 ②。这里主要改造了商品中心,主要解决 透传地区标识 和 支持多币种价格 这 2 个问题。透传地区标识我们的业务系统主要分为 API 和 Service 项目,API 暴露出 HTTP 接口,API 与 Service 和 Service 与 Service 之前使用 RPC 接口通信。由于商品中心涉及到价格的接口繁多,不可能对每个接口都增加地区标识的参数。所以我们弄了一套调用链路透传地区标识的机制。机制原理思路就是,先将地区标识放在全局上下文中,API 接口通过 Header 头X-Location携带地区标识;而对于 RPC 接口,我们的 RPC 框架已支持了 Context,不需要改造。代码实现传递全局上下文由于 RPC 框架已支持了 Context,所以 API 和 RPC 接口透传全局上下文略有不同。实现如下:class Location{ public static function init() { global $context; if (empty($context[’location’])) { return; } // API在这里直接获取X-Location头 if (!empty($_SERVER[‘HTTP_X_LOCATION’])) { $context[’location’] = $SERVER[‘HTTP_X_LOCATION’]; } // RPC Server会自动获取Context }}上述init()方法,需要在项目入口位置初始化。其中,RPC 接口不需要操作全局上下文。因为 RPC Client 在调用时会自动获取全局变量$context值并在 RPC 协议数据中追加 Context,同时 RPC Server 在收到请求时会自动获取 RPC 协议数据中的 Context 值并设置全局变量$context。RPC Client 传递 Context 实现如下:protected function addGlobalContext($data){ global $context; $context = !is_array($context) ? array() : $context; // data为待请求的RPC协议数据 $data[‘Context’] = $context; return $data;}RPC Server 获取 Context 实现如下:public function getGlobalContext($packet){ global $context; $context = array(); // packet为接收的RPC协议数据 if(isset($packet[‘Context’])) { $context = $packet[‘Context’]; }}当设置了 Context 后,RPC 通信时协议数据会携带location字段,内容如下:RPC325{“data”:"{"version":"1.0","user":"xxx","password":"xxx","timestamp":1553225486.5455,"class":"xxx","method":"xxx","params":[1]}",“signature”:“xxx”,“Context”:{“location”:“india”}}设置地区标识到这里,我们只需要在全局上下文设置地区标识即可。一旦我们设置了地区标识,所有业务系统就会在本次的调用链路中透传这个地区标识。实现如下:class Location{ public static function set($location) { global $context; $context[’location’] = $location; // API需要在这里单独设置X-Location头 header(‘X-Location: ’ . $context[’location’]); }}获取地区标识设置了地区标识后,就可以在本次调用链路的所有业务系统中直接获取。实现如下:class Location{ public static function get() { global $context; if (!isset($context[’location’])) { return ‘china’; } return $context[’location’]; }}支持多币种价格商品中心有了地区标识后,商品中心服务就可以根据地区标识对价格字段进行转化了。因为设计到价格的数据表和价格字段较多,这里直接从数据层(Model)进行改造。改造获取数据方法下述的ReadBase类是所有数据表 Model 的基类,所有获取数据表数据的方法都继承或调用自getOne() 和getAll()方法,所以我们只需要改造这两个方法。class ReadBase{ public function getOne(array $cond, $fields) { $data = $this->getReader()->select($this->getFields($fields))->from($this->getTableName())->where($cond)->queryRow(); return $this->getExchangePrice($data); } public function getAll(array $cond, $fields) { $data = $this->getReader()->select($this->getFields($fields))->from($this->getTableName())->where($cond)->queryAll(); if ($data) { foreach ($data as &$one) { $this->getExchangePrice($one); } } return $data; }}后缀匹配价格字段由于涉及到价格字段名字较多,且具有不确定性,所以这里使用后缀方式匹配。为了防止一些字段命名不规范,这里引入了黑名单机制。protected function isExchangeField($field){ $priceSuffix = array(‘cost’, ‘price’); $black = array(); $len = strlen($field) ; foreach ($priceSuffix as $suffix) { $lastPos = $len - strlen($suffix); // 非黑名单且非is if (!in_array($field, $black) && false === strpos($field, ‘is’) && $lastPos === strpos($field, $suffix) ) { return true; } } return false;}前缀为is_的字段一般定义为标识字段,默认为非价格字段。计算地区价格上述getExchangePrice()方法,用来根据地区标识转化价格覆盖到原价格字段,并自增以_origin后缀的人民币价格字段。public function getExchangePrice(&$data){ if (empty($data)) { return $data; } $originPrice = array(); foreach ($data as $field => &$value) { // 是否是价格字段 if ($this->isExchangeField($field)) { $originField = $field . ‘_origin’; $originPrice[$originField] = $value; // 获取对应地区的价格 $value = $this->getExchangePrice($value); } } $data = array_merge($originPrice, $data); return $data;}public static function getExchangePrice($price){ // 获取地区标识 $location = Location::get(); // 汇率 $exchangeRateConfig = \Config::$exchangeRate; if ($location === ‘china’) { return $price; } else if (isset($exchangeRateConfig[$location])) { $exchangeRate = $exchangeRateConfig[$location]; } else { throw new \BusinessException(“not found $location exchange rate”); } // 向上取值并保留两位小数 $exchangePrice = bcmul($price, $exchangeRate, 3); return number_format(ceil($exchangePrice * 100) / 100, 2, ‘.’, ‘’);}其中,getExchangePrice()方法会调用Location::get()获取地区标识,并根据汇率计算实时价格。最终,商品中心改造后,得到的部分商品价格信息,如下:# 人民币价格10,汇率10.87market_price: 108.7market_price_origin: 10API系统对于所有 API 的项目,我们只需要让客户端在所有的请求中增加X-Location头即可。GET /product/detail/1 HTTP/1.1Request Headers X-Location: indiaAPI 项目需在入口文件处,初始化地区标识。如下:Location::init();商品管理系统对于商品管理系统,我们为了方便运营操作,所有商品价格都应以人民币。因此,我们只需要初始化地区标识为中国,如下:Location::init();// 地区设置为中国Location::set(‘china’);总结为了实现需求很容易,但是要做到合理且快速却不简单。本文的实现的方案,避免了很多坑,但同时也可能又埋下了一些坑。没有一套方案是万能的,慢慢去优化吧! ...

March 25, 2019 · 2 min · jiezi

我的博客发布上线方案 — Hexo

首发于 樊浩柏科学院之前一直在使用 Hexo 推荐的发布方案,缺点是本地依赖 Hexo 环境,无法随时随地地更新博客。为了摆脱 Hexo 环境约束进而高效写作,有了下述的发布方案。本文的发布方案中,Git 仓库只是托管 md 文件,通过 Webhook 通知服务器拉取 md 文件,然后执行构建静态文件操作,完成一个发布过程。我的写作环境为 Typora(Win10),博客发布在阿里云的 ECS(CentOS)上,文章托管在 GitHub。需求迭代随着时间成本的增高,只能利用碎片时间来进行写作。因此,我的写作场景变成了这样:习惯使用 MarkDown 写原稿,有 MarkDown 编辑器就行;写作场地不限定,有电脑就行;写作时间不确定,有灵感就写;新的问题之前(包括 Hexo 推荐)的发布方案,都是先本地编写 MarkDown 源文件,然后本地构建静态文件,最后同步静态文件到服务器。发布流程图如下:显而易见,若继续使用之前的发布方案,那么每当更换写作场地时都需要安装 Hexo 环境,写作场地和时间都受到限制,不满足需求。新的方案问题主要是,本地受制于构建静态文件时需要的 Hexo 环境,那么是否可以将构建静态文件操作放到服务器端?发布流程首先,看下新方案的发布流程图:如流程图所示,整个发布系统共涉及到 3 个环境,分别为本地(写作)、Git 仓库(托管 md 源文件)、服务器(Web 服务)环境。在服务器环境构建静态文件,因此只需要在服务器端安装 Hexo 环境。 一个完整的发布流程包含 3 个部分:流程 ① :写作流程;流程 ② :发布流程;流程 ③ :构建流程;写作流程采用按分支开发策略,当写作完成后,只需要 push 修改到对应分支即可。只要有 MarkDown 编辑器,以及任何文本编辑器,甚至 马克飞象 都可以随时随地写作。当然,你可能说还需要 Git 环境呀?好吧,如果你是一名合格的 Coder,竟然没有 Git,你知道该干嘛了!再说没有 Git 环境,还可以通过 GitHub 来完成写作。发布流程采用 master 发布策略,当需要发布时,需要将对应开发分支 merge 到 master 分支,然后push master分支,即可实现发布。构建流程这里使用到 Webhook 机制,触发服务器执行构建操作,构建脚本见 Webhook 脚本 部分。当流程 ① 和 ② 结束后,Git 仓库都会向服务器发起一次 HTTP 请求,记录如下:当收到构建请求后,执行构建操作。构建流程图如下:首先检查当前变更分支,只有为 master 分支时,执行 pull 操作拉取 md 文件更新,然后再执行 hexo g完成静态文件的构建。Webhook脚本Webhook 脚本使用 PHP 实现,代码如下:主流程方法如下:public function run(){ //校验token if ($this->checkToken()) { echo ‘ok’; } else { echo ’error’; } fastcgi_finish_request(); //返回响应 if ($this->checkBranch()) { //校验分支 $this->exec(); //执行操作逻辑 }}这里使用 shell 脚本实现构建所需的所有操作,方便扩展。执行操作方法如下:public function exec(){ //shell文件 $path = $this->config[‘bash_path’]; $result = shell_exec(“sh $path 2>&1”); $this->accessLog($result); return $result;}构建 shell 脚本如下:#!/usr/bin/env bashexport NODE_HOME=/usr/local/nodeexport PATH=$NODE_HOME/bin:$PATHpwd=’/data/html/hexo’cd $pwd/sourcegit pullcd $pwd$pwd/node_modules/hexo/bin/hexo g总结新发布方案与之前方案的区别是:前者只需本地编写 md 文件,博客服务器构建静态文件;后者本地编写 md 文件后,需要本地构建静态文件,然后博客服务器只同步静态文件。当然,有很多办法可以解决当前问题,比如可以使用 持续集成。本文只是提供一个发布思路,在项目的生成环境中,我们也很容易应用上这种发布思路,开发出自己的发布系统。相关文章 »启用Hexo开源博客系统(2017-03-01) ...

March 25, 2019 · 1 min · jiezi

自如2018新年活动系统 — 抢红包

首发于 樊浩柏科学院2017 年是自如快速增长的一年,自如客突破 100 万,管理资产达到 50 万间,在年底成功获得了 40 亿 A 轮融资,而这些都要感谢广大的自如客,公司为了回馈自如客,在六周年活动时就发放了 6000 万租住基金,当然年底散币活动也够疯狂。活动规模既然公司对自如客这么阔,那对我们员工也得够意思,所以年底我们共准备了 3 个活动。1、针对 自如客 的服务费减免活动;2、针对 自如客 的 1000 万现金礼包;3、25 万的 员工 红包活动;散币活动 2 和 3 是通过微信红包形式进行,想散币就散吧,可微信告诉我们,想散币还得交税(>﹏<)。员工红包来说,25 万要交掉 10 多万税,此时心疼我的钱。好了,下面开始说点正事。技术方案说到红包,我们肯定会想到红包拆分和抢红包两个场景。红包拆分是指将指定金额拆分为指定数目红包的过程,即是用来确定每个红包的金额数;而抢红包就是典型的高并发场景,需要避免红包超发的情况。红包拆分可选的方案拆分方式1、实时拆分实时拆分,指的是在抢红包时实时计算每个红包的金额,以实现红包的拆分过程,对系统性能和拆分算法要求较高,例如拆分过程要一直保证后续待拆分红包的金额不能为空,不容易做到拆分红包的金额服从正态分布规律。2、预先生成预先生成,指的是在红包开抢之前已经完成了红包的拆分,抢红包时只是依次取出拆分好的红包金额,对拆分算法要求较低,可以拆分出随机性很好的红包金额,通常需要结合队列使用。拆分算法我并没有找到业界的通用算法,但红包拆分算法应该是拆分金额要看起来随机,最好能够服从正态分布,可以参考 微信 和 @lcode 提供的红包拆分算法。微信拆分算法的优点是算法较简单,拆分效率高,同时,由于该算法天然的特性,可以保证后续红包金额一定不为空,特别适合实时拆分场景,但缺点是会导致大额红包较大概率地在拆分的最后出现。 @lcode 拆分算法的优点是拆分金额基本符合正态分布,适合随机性要求较高的拆分场景。我们的方案我们这次的业务对红包金额的随机性要求不高,但是对系统可靠性要求较高,所以我们选用了预算生成方式,使用 二倍均值法 的红包拆分算法,作为我们的红包拆分方案。采用预算生成方式,我们预先生成红包并放入 Redis 的 List 中,当抢红包时只是 Pop List 即可,具体实现将在 抢红包 部分介绍。拆分算法可以描述为:假设剩余拆分金额为 M,剩余待拆分红包个数为 N,红包最小金额为 1 元,红包最小单位为元,那么定义当前红包的金额为:$$m = rand(1, floor(M/N2))$$其中,floor 表示向下取整,rand(min, max) 表示从 [min, max] 区间随机一个值。$M/N \ast 2$ 表示剩余待拆分金额平均金额的 2 倍,因为 N >= 2,所以 $M/N \ast 2 <= M$,表示一定能保证后续红包能拆分到金额。代码实现为:for ($i = 0; $i < $N - 1; $i++) { $max = (int)floor($M / ($N - $i)) * 2; $m[$i] = $max ? mt_rand(1, $max) : 0; $M -= $m[$i];}$m[] = $M;值得一提的是,我们为了保证红包金额差异尽量小,先将总金额平均拆分成 N+1 份,将第 N+1 份红包按照上述的红包拆分算法拆分成 N 份,这 N 份红包加上之前的平均金额才作为最终的红包金额。抢红包可选的方案限流1、前端限流前端限制用户在 n 秒之内只能提交一次请求,虽然这种方式只能挡住小白,不过这是 99% 的用户哟,所以也必须得做。2、后端限流常用的后端限流方法有 漏桶算法 和 令牌桶算法。漏桶算法 主要目的是控制请求数据注入的速率,如果此时漏桶溢出,后续的请求数据会被丢弃。而 令牌桶算法 是以一个恒定的速度往桶里放入令牌,而如果请求数据需要被处理,则需要先从桶里获取一个令牌,当桶里没有令牌时,这些请求才被丢弃,令牌桶算法的一个好处是可以方便地改变应用接受请求的速率。防超发1、库存加锁可以通过加锁的方式解决资源抢占问题,但是加锁会增加系统开销,大流量下更容易拖垮系统,不过可以尝试一下基于版本号的乐观锁。2、通过高速队列串行化请求之所会出现超发问题,是因为并发时会出现多个进程同时获取同一资源的现象,如果使用高速队列将并行请求串行化,那么问题就不存在了。高速队列可以使用 Redis 缓存服务器来实现,当然光使用队列还不够,必要保证整个流程调用链要短、要快,否则队列会积压严重,甚至会拖垮整个服务。我们的方案在限流方面,由于我们预估的请求量还在系统承受范围,所以没有考虑引入后端限流方案。我们的抢红包系统流程图如下:我们将抢红包拆分为 红包占有(流程①,同步) 和 红包发放 (流程②,异步)这两个过程,首先采用高速队列串行化请求,红包发放逻辑由一组 Worker 异步去完成。高速队列只是完成红包占有的过程,实现库存的控制,Worker 则处理耗时较长的红包发放过程。当然,在实际应用中,红包占用过程还需要加上一些前置规则校验,比如用户是否已经领取过,领取次数是否已经达到上限等?红包占有流程图如下:其中,red::list为 List 结构,存放预先生成的红包金额(流程①中的红包队列);red::task 也为 List 结构,红包异步发放队列(流程②中的任务队列);red::draw为 Hash 结构,存放红包领取记录,field为用户的 openid,value为序列化的红包信息;red::draw_count:u:openid为 k-v 结构,用户领取红包计数器。下面,我将以以下 3 个问题为中心,来说说我们设计出的抢红包系统。1、怎么保证不超发我们需要关注的是红包占有过程,从红包占有流程图可看出,这个过程是很多 Key 操作的组合,那怎么保证原子性?可以使用 Redis 事务,但我们选用了 Lua 方案,一方面是因为首先要保证性能,而 Lua 脚本嵌入 Redis 执行不存在性能瓶颈,另一方面 Lua 脚本执行时本身就是原子性的,满足需求。红包占有的 Lua 脚本实现如下:– 领取人的openid为xxxxxxxxxxxlocal openid = ‘xxxxxxxxxxx’local isDraw = redis.call(‘HEXISTS’, ‘red::draw’, openid)– 已经领取if isDraw ~= 0 then return trueend– 领取太多次了local times = redis.call(‘INCR’, ‘red::draw_count:u:’..openid)if times and tonumber(times) > 9 then return 0endlocal number = redis.call(‘RPOP’, ‘red::list’)– 没有红包if not number then return {}end– 领取人昵称为Fhb,头像为https://xxxxxxxlocal red = {money=number,name=‘Fhb’,pic=‘https://xxxxxxx’}– 领取记录redis.call(‘HSET’, ‘red::draw’, openid, cjson.encode(red))– 处理队列red[‘openid’] = openidredis.call(‘RPUSH’, ‘red::task’, cjson.encode(red))return true需要注意 Lua 脚本执行过程并不是事务的,脚本中的操作命令在执行时是有先后顺序的,当某个操作执行失败时不会回滚已经执行成功的操作,它的原子性是通过单线程模型实现。2、怎么提高系统响应速度如红包占有流程图所示,当用户发起抢红包请求时,若有红包则直接完成红包占有操作,同步告知用户是否抢到红包,这个过程要求快速响应。但由于微信红包支付属于第三方调用,若抢到红包后同步调用红包支付,系统调用链又长又慢,所以红包占有和红包发放异步拆分是必然。拆分后,红包占有只需操作 Redis,响应性能已不是问题。3、怎么提高系统处理能力从上述分析可知,目前系统的压力都会集中在红包发放这个环节,因为用户抢到红包时,我们只是同步告知用户已抢到红包,然后异步去发放红包,因此用户并不会立即收到红包(受红包发放 Worker 处理能力和微信服务压力制约)。若红包发放的 Worker 处理能力较弱,那么红包发放的延迟就会很高,体验较差。如抢红包流程图中所示,我们采用一组 Worker 去消费任务队列,并调用红包支付 API,以及数据持久化操作(后续对账)。尽管红包发放调用链又长又慢,但是注意到这些 Worker 是 无状态 的,所以可以通过增加 Worker 数量,以横向扩展提高系统的处理能力。4、怎么保证数据一致性其实,红包发放延时我们可以做到用户无感知,但是若红包发放(流程②)失败了,已经告知用户抢到红包,但是却木有发,估计他杀人的心都有了。根据 CAP 原理,我们无法同时满足数据一致性、数据可用性、分区耐受性,通常只需做到数据最终一致性。为了达到数据最终一致性,我们就引入了重试机制,生成一个全局唯一的外部订单号,当某单红包发放失败,就会放回任务队列,使得有机会进行发放重试,当然这一切都需要 API 做幂等处理。Worker可靠性保障这里必须将 Worker 可靠性单独说,因为它实在太重要了。Worker 的实现如下:$maxTask = 1000;$sleepTime = 1000;while (true) { while ($red = RedLogic::getTask()) { RedLogic::doTask($red); //处理多少个任务主动退出 $maxTask–; if ($maxTask < 0) { return EXIT_CODE_NORMAL; } } //等待任务 usleep($sleepTime);}这里使用 LPOP 命令获取任务,所以使用了 while 结构,并且无任务时需要等待,可以用阻塞命令 BLPOP 来改进。由于 Worker 需要常驻内存运行,难免会出现异常退出的情况(也有主动退出), 所以需要保持 Worker 一直处于运行状态。我们使用进程管理工具 Supervisor 来监控 Worker 的运行状态,同时管理 Worker 的数量,当任务队列出现堆积时,增加 Worker 数量即可。Supervisor 的监控后台如下:员工系统号散列公司员工都用唯一一个系统号 emp_code(自增字段)标识,登录成功后返回 emp_code,系统后续所有交互流程都基于 emp_code,分享出去的红包也会携带 emp_code,为了保护员工敏感信息和防止恶意碰撞攻击,我们不能直接将 emp_code 暴露给前端,需要借助一个 token(无规律)的中间者来完成交互。可选的方案1、储存映射关系,时时查询预先生成一个随机串 token,然后跟 emp_code 绑定,每次请求都根据 token 时时查询 emp_code。优点是可以定期更新,相对安全,缺点是性能不高。2、建立映射关系函数,实时计算建立一个映射关系函数,如 hash 散列或者加密解密算法,能够根据 emp_code 生成一个无规律的字符串 token,并且要能够根据 token 反映射出 emp_code。优点是需要存储介质存储关系,性能较高,缺点是很难做到定期失效并更新。我们的方案由于我们的红包活动只进行几天,所以我们选用了方案 2。对 emp_code 做了 hashids 散列算法,暴露的只是一串无规律的散列字符串。hashids 是一个开源且轻量的唯一 id 生成器,支持 Java、PHP、C/C++、Python 等主流语言,PHP 想使用 hashids,只需composer require hashids/hashids命令安装即可。然后,如下方式使用:use Hashids\Hashids;$hashids = new Hashids(‘salt’, 6, ‘abcdefghijk1234567890’);$hashids->encode(11002); //994k2kk$hashids->decode(‘994k2kk’); //[11002]需要说明的是,其中salt是非常重要的散列加密盐串,6表示散列值最小长度,abcde…7890为散列字典,太长影响效率,太短不安全。由于默认的散列字典比较长,decode 效率并不高,所以这里移除了大写字母部分。语音点赞语音点赞就是用户以语音的形式助力好友,核心技术其实是语音识别,而我们一般都会使用第三方语音识别服务。可选的方案1、客户端调用第三方服务识别客户端直接调用第三方语音识别服务,如微信提供了 JS-SDK 的语音识别 API ,返回识别的语音文本的信息,并且已经经过语义化。优点是识别较快,且不许关注语音存储问题,缺点是不安全,识别结果提交到服务端之前可能被恶意篡改。2、服务端调用第三方服务识别先将录制的语音上传至存储平台,然后服务端调用第三方语音识别服务,第三方语音识别服务去获取语音信息并识别,返回识别的语音文本的信息。优点是识别结果较安全,缺点是系统交互较多,识别效率不高。我们的方案我们业务场景的特殊性,存在用户可助力次数的限制,所以无需担心恶意刷赞的情况,因此可以选用方案 1,语音识别的交互流程如下:此时,整个语音识别流程如下:当然中国文字博大精深,语音识别的文本在匹配时,需要考虑容错处理,可以将文本转化为拼音,然后匹配拼音,或者设置一个匹配百分比,达到匹配值则认为语音口令正确。需要注意的是,微信只提供 3 天的语音存储服务,若语音播放周期较长,则要考虑实现语音的存储。其他红包发放测试我们使用了线上公账号进行红包发放测试,为了让线上公众号能够授权到测试环境,在线上的微信授权回调地址新增一个参数,将带有to=feature参数的请求引流到测试环境,其他线上流量还是保持不变,匹配规则如下:# Nginx不支持if嵌套,所以就这样变通实现set $auth_redirect “";if ($args ~ “r=auth/redirect”) { set $auth_redirect “prod”;}if ($args ~* “to=feature”) { set $auth_redirect “feature”;}if ($auth_redirect ~ “feature”) { rewrite ^(.)$ http://wx.t.ziroom.com/index.php last;}if ($auth_redirect ~ “prod”) { rewrite ^(.)$ http://wx.ziroom.com/index.php last;}CDN缓存由于本次活动力度较大,预估流量会比以往增加不少(不能再出现机房带宽打满的情况了,不然 >﹏<),静态页面占流量的很大一部分,所以静态页面在发布时都会放置一份在 CDN 上,这样回源的流量就很小了。灾备方案尽管做了很多准备,还是无法确保万无一失,我们在每个关键节点都增加了开关,一点出现异常,通过配置中心可以人工介入做降级处理。 ...

March 25, 2019 · 2 min · jiezi

阿里巴巴的微服务开源之路

侠之大者,为国为民。在金庸小说中,郭靖和黄蓉是“侠之大者,为国为民”的典范,他们以布衣之身帮助宋军守护襄阳十余年。技术的世界里,并无大小之分。但当一群程序员由服务公司内部转变为社会的程序员,将技术以开源的方式与社区的开发者一同协作、改进和使用时,他们便被赋予了更大的责任和期待。阿里云智能中间件的程序员们正和社区的开发者们一起,用键盘敲下国内微服务开源项目的过去和未来。国内首个非 Hadoop 生态体系的 Apache 社区顶级项目2016年的那届双11,RocketMQ 团队首次将低延迟存储解决方案应用于双11的支撑,经受住了流量的大考,整个大促期间,99.996%的延迟落在了10ms以内,完成了保障交易稳定的既定目标。对于读写比例几乎均衡的分布式消息引擎来说,这一技术上的突破,即便是放在全球范围内,也绝对是值得称赞的。另一边,在历时3个月的开源重塑后,RocketMQ 团队启动了向 Apache 软件基金会的捐赠之路,但迈出这一步并不容易。“当时国内的开源氛围还没有现在那么活跃,开源之后,很多设计文档、代码质量,以及社区建设还不够理想。我们一直期待,国内的开源项目和开源社区也可以在世界的开源舞台上发挥让人瞩目的价值,希望更多“中国智造”的开源项目成为世界级的开源项目。”阿里云智能高级技术专家冯嘉回忆道。经过近一年的努力,在2017年9月25日,Apache软件基金会官方宣布,阿里巴巴捐赠给 Apache 社区的开源项目 RocketMQ 从 Apache社区正式毕业,成为 Apache 顶级项目(TLP),这是国内首个非 Hadoop 生态体系的 Apache 社区顶级项目。值得一提的是,根据项目毕业前的统计,RocketMQ 有百分八十的新特性与生态集成来自于社区的贡献。毕业一年多后,RocketMQ 已经覆盖互联网金融等领域60%以上的消息场景,并被应用到金融、电力、物流、游戏、电子商务、共享出行等十几个行业。然而,随着云计算、大数据、人工智能等技术在全球范围的深入推进,催生出了如IoT、区块链、AI、边缘计算等新的应用场景,架构上如何进一步演进以更好的适应新的场景,服务好下一个十年,这是即将到来的 RocketMQ 5.0 要解决的问题。消息领域的里程碑事件RocketMQ 从 Apache 社区正式毕业的同时,消息领域出现了另一件里程碑事件,分布式消息领域的国际标准 OpenMessaging 开源项目正式入驻Linux基金会,这是国内首个在全球范围发起的分布式计算领域的国际标准。消息通信已经成为现代数据驱动架构的关键环节,但在全球范围内,消息领域仍然存在两大问题:一是,缺乏供应商中立的行业标准,导致各种消息中间件的高复杂性和不兼容性,相应地造成了公司的产品低效、混乱和供应商锁定等问题。二是,目前已有的方案框架并不能很好地适配云架构,即非云原生架构,因此无法有效地对大数据、流计算和物联网等新兴业务需求提供技术支持。这也是 RocketMQ 开源过程中,开发者和合作伙伴经常会提到的问题:“在消息领域,市场上出现了各类不同的开源解决方案,这导致了用户更高的接入和维护成本,为了确保各个消息引擎间能正常通信,还要投入大量的精力去做兼容。”这时候,建立一套供应商中立,和语言无关的消息领域的事实标准,成为各社区成员共同的诉求。此后,阿里巴巴发起 OpenMessaging 项目,并邀请了雅虎、滴滴出行、Streamlio 共同参与,一年后,参与OpenMessaging 开源标准社区的企业达20家之多,包括阿里巴巴、Datapipeline、滴滴出行、浩鲸科技、京东商城、科大讯飞、青云QingCloud、Streamlio、VIPKID、微众银行、Yahoo、中国移动苏州研发中心等(按首字母排序),此外,还获得了 Apache RocketMQ、Apache Pulsar 等顶级消息开源厂商的支持。相比于开源一个分布式消息项目,一套开源标准能被各家厂商所接受,对整个国内开源领域而言,是更具有里程碑意义的事件。从微服务框架到微服务生态Dubbo 是阿里巴巴于2012年开源的分布式服务治理框架,是国内影响力最大、使用最广泛的开源服务框架之一。在2016年、2017、2018年开源中国发起的最受欢迎的中国开源软件评选中,连续三年进入 Top10 名单。2019年2月 Dubbo 发布了2.7.0,这一版本将用于 Apache 基金会的正式毕业。(已进入 Near Graduation 阶段)从 Apache 孵化器毕业,除了有个名誉,对项目之后的维护、发展有什么影响?“从孵化器毕业是一种荣誉,但这并不是结束,而是另一种开始。这有点像求学,毕业并不意味着学习上的中断,而是发挥更大社会价值的开始。毕业也更像是一个成人礼,意味着Dubbo 团队已经符合Apache对一个成熟开源项目的要求,并开始具备独立发展的能力。”阿里云智能高级技术专家北纬在接受媒体采访时回答道。截至目前,Dubbo 已收获 2.5w+ star,在 GitHub 所有 Java 项目中排名前十,并有越来也多的企业用户选择 Dubbo 作为自己的微服务治理框架。但是,随着微服务化的逐渐深入,Dubbo 提供的能力逐渐无法满足微服务各个方面的需求。阿里云智能技术专家望陶在一次直播中分享道:“Dubbo 是一个微服务框架,帮助开发者快速构建高性能的微服务应用。但在 API Gateway,熔断限流,分布式监控,分布式事务等方面,缺乏一套比较完整的围绕 Dubbo 的解决方案,基本上是各个公司自研,或者需要调研外面开源的各种框架进行调研选型,花费了比较大的时间和精力在这上面,却无法形成一套体系化的方案。”因此,我们做了进一步的演进,即从微服务框架演进到微服务生态。通过和成熟的开源方案做集成,形成一个完整的微服务生态,组成 Dubbo Ecosystem,开发者无需为现有的系统做出过多的修改,就能快速开发微服务应用。Dubbo Ecosystem 的概念得以提出,离不开 2018 年夏天开源的两大微服务组件。技术人的仲夏之夜2018年夏天,国内开源领域,迎来了两位新成员。作为微服务和云原生生态下的两款重要开源组件,Nacos 主打云原生应用中的动态服务发现、配置和服务管理,Sentinel 则是聚焦在限流和降级两个方面。Nacos 和 Sentinel 均是在阿里近10年的核心业务场景下沉淀所产生的,他们的开源是对微服务和元原生领域开源技术方案的有效补充,同时也非常强调融入开源生态,除了兼容 Dubbo,也支持 SpringCloud 和 Kubenetes 等生态,以增强自身的生命力。“阿里巴巴早在 2007 年进行从 IOE 集中式应用架构升级为互联网分布式服务化架构的时候,就意识到在分布式环境中,诸如分布式服务治理,数据源容灾切换、异地多活、预案和限流规则等场景下的配置变更难题,因为在一个大型的分布式系统中,你没有办法把整个分布式系统停下来,去做一个软件、硬件或者系统的升级。”阿里云智能高级技术专家坤宇在 QCon 的现场分享道。相比其他服务配置中心开源方案,Nacos 的起步虽然晚了点,但除了配置中心,他还提供了动态服务发现、服务共享与管理的功能,在大规模场景下具备更优秀的性能,在易用性上更便捷,分布式部署上更灵活。Nacos 支持多种启动模式,用户可以根据业务场景自由选择,将各个功能模块,如注册中心和配置中心,分开部署或者合并部署,从而能够完整支持小型创业公司成长到大型企业,微服务全生命周期的演进。截止到目前,已经有40多家企业将 Nacos 部署到生产环境中,例如 虎牙直播 就是最早一批将 Nacos 大规模引入到生产环境的典型用户。“虎牙关注 Nacos 是从v0.2 开始的,我们也参与了社区的建设,可以说是比较早期的企业用户。引入Nacos前,我们也对比了Spring Cloud Config Server、ZooKeeper 和 ectd ,总体评估下来,基于我们微服务体系现状以及业务场景,决定使用 Nacos 作为服务化改造中服务注册和服务发现的方案。使用过程中,我们发现,随着社区版本的不断更新和虎牙的深入实践,Nacos 的优势远比调研过程中发现的多。”虎牙基础保障部中间件团队负责人张波在一次开发者活动上分享道。巧的是,一边是 Nacos宣布开源,并被列入 CNCF 云原生全景图,另一边是 Spring Cloud 生态下的服务注册和发现组件 Netflix Eureka 宣布停止开源投入,勇敢者的游戏充满了变数,但在 Nacos 团队看来,这场游戏自己可以走到最后,因为我们并不是一个人在战斗,Nacos 只是阿里众多开源项目中的一员,随后还会有更多的开源项目反哺给社区,形成生态,例如轻量级限流降级组件 Sentinel。2018年7月29日,AliwareOpen Source•深圳站现场,只能容纳400人的场地,来了700多位开发者。阿里云智能高级技术专家子矜在现场宣布了轻量级限流降级组件 Sentinel 的开源。Sentinel 经历了10年双11的考验,覆盖了阿里的所有核心场景,也因此积累了大量的流量归整场景以及生产实践。Sentinel 的出现,离不开阿里历届高可用架构团队的共同努力。“在双11备战中,容量规划是最重要也是最具挑战的环节之一。从第一年开始,双11的0点时刻就代表了我们的历史最高业务访问量,它通常是日常流量的几十倍甚至上百倍。因此,如何让一个技术和业务持续复杂的分布式站点去更平稳支撑好这突如其来的流量冲击,是我们这10年来一直在解的题。”阿里云智能高可用架构团队资深技术专家游骥在一次双11备战结束后分享道。这10年,容量规划经历了人工估算、线下压测、线上压测、全链路压测、全链路压测和隔离环境、弹性伸缩相结合的5个阶段。2013年双11结束后,全链路压测的诞生解决了容量的确定性问题。作为一项划时代的技术,全链路压测的实现,对整个集团而言,都是一件里程碑事件。![2014年,高可用架构团队获得集团 CTO 大奖](https://upload-images.jianshu…随后,基于全链路压测为核心,打造了一系列容量规划相关的配套生态,提升能力的同时,降低了整个环节的成本、提升效率。随着容量规划技术的不断演进,2018年起,高可用架构团队希望可以把这些年在生成环境下的实践,贡献给社区,之后便有了 Sentinel 的开源。Sentinel 开源后仅两个月,便被列入云原生全景图谱,位于编排和管理模块象限中,同时被列入云原生全景图谱的还有提供应用架构自动探测、故障注入式高可用能力演练和一键应用限流降级等功能的应用高可用服务 AHAS。近期,Sentinel 贡献的spring-cloud-circuitbreaker-sentinel模块正式被社区合并至Spring Cloud Circuit Breaker,由此,Sentinel 也加入了 Spring Cloud Circuit Breaker 俱乐部,成为 Spring Cloud 官方的主流推荐选择之一。Spring Cloud 官方推荐的微服务方案不止 Sentinel 一个,还有 Spring Cloud Alibaba.2018年,中国的 Java 圈发生了一件大事。Spring Cloud 联合创始人 Spencer Gibb 在 Spring 官网的博客页面宣布:阿里巴巴开源 Spring Cloud Alibaba,并发布了首个预览版本。随后,Spring Cloud 官方 Twitter 也发布了此消息。可能是受到 Spring Cloud Netflix 减少开源投入的影响,Spring Cloud Alibaba 开源后的热度超出了阿里巴巴高级技术专家姬望的预期。在接受开源中国采访的过程中,姬望认为“Spring Cloud Alibaba 是中国 Java 开发者的福音,弥补了 Spring Cloud 原生实现在大规模集群场景上的局限性。Spring Cloud 规范的实现目前有很多,比如 Netflix 有自己的一整套体系,Consul 支持服务注册和配置管理,ZooKeeper 支持服务注册等。但每套实现或多或少都有各自的优缺点,或许大多数 Spring Cloud 用户很难体会到 Netflix OSS 等实现的局限性,无论是服务发现、分布式配置,还是服务调用和熔断都不太适合大规模集群场景,比如我们内部也遇到 Eureka 性能问题。因此,我们将自身的超大规模集群经验与强大的 SpringCloud 生态整合,实现强强联合,希望能对业界会产生一些积极的化学变化。”夏天过后,开源的热度仍在延续效率的好处在于,我们可以把自己的注意力和时间聚焦在更需要创造力的事情上,做更有成就感的事情。对于工作在工程领域的开发者们而言,他们的效率意识更强。2018年9月,阿里将内部广泛使用的 Java 线上诊断工具进行开源,取名 Arthas (阿尔萨斯)。也许是击中了开发者线上排查问题的痛点,Arthas 在距离开源后的第一个 Release 版发布仅 147 天,就获得了超过 1w 的 star 数,并有40多位 Contributors 参与开源贡献。从中,我们不仅看到 Arthas 在开发者群体中的受欢迎程度,也发现越来越多的国内开发者开始擅于使用开源技术加速业务发展,更是不禁畅想起将来会有更多国内的优质开源项目获得全球开发者的关注和喜爱。技术领域,一切 里程碑 的达成,都源于一份技术情怀。阿里云智能技术专家断岭回忆到:“Arthas 在阿里巴巴内部起源于2015年,当时微服务方兴未艾,我们团队一方面专注 Spring Boot 的落地,提高开发效率。另外一方面,希望可以提高技术团队线上排查问题的能力和效率。当时,我们经过选型讨论,选择基于 Greys (Greys 是阿里巴巴杜琨@oldmanpushcart 开发的),一款 Java 开源在线问题诊断工具来开发,以提供更好的应用诊断体验。”我们在用户体验上做了大量的改进:彩色UI、Web Console 和内网一键诊断等。慢慢的,Arthas 成为阿里巴巴很多技术同事线上诊断问题的必备工具。尽管 Arthas 在阿里内部广受好评,但只是一个自用的工具。取之开源,用之开源,因此我们在2018年9月28日,正式开源了 Arthas,希望可以帮助 Java 开发人员提升诊断效率。随着越来越多的开发者开始使用 Arthas,众多开发者效率工具将 Arthas 内置到自己的产品中,丰富了 Arthas 的接入和打开方式,例如 IDE 插件 Cloud Toolkit。时间来到2019年。阿里云智能高级开发工程师煊檍在内网分享到:分布式事式问题一直是应用开发过程中的技术痒点。不敢说是痛点,因为长久以来,大家普遍对分布式事务问题的应对策略还是:能不用就不用,尽量绕开。但在微服务架构普遍落地的今天,分布式事务问题越来越绕不开,解决方案不是没有,但要么性能差,要么侵入性高,不容易落地。总之,是有点“不爽”。而这种“不爽”集中反映在了分布式事务开源中间件 Fescar 上。当阿里云智能高级开发工程师清铭在2019年1月 RocketMQ Meetup 上宣布分布式事务中间件 Fescar 正式开源后的一周内,Fescar 便收获了3000+ star,社区讨论的 issue 达58个。随后,Fescar 项目组整理并回答了开发者们集中关心的13个问题,例如 Fescar 的诞生背景、适用场景,和其他开源分布式事务方案之间的差别等。阿里巴巴中间件团队于2014年发布 TXC(Taobao Transaction Constructor),开始为集团内应用提供分布式事务服务。2016年,TXC 经过产品化改造,以 GTS(Global TransactionService)的身份上线阿里云,成为当时业界唯一一款云上分布式事务产品,以阿里云公有云和专有云解决方案的形式,交付给众多外部客户,并得到了客户的一致认可。2019 年,基于 TXC 和 GTS 的技术积累,中间件团队发起了开源项目 Fescar(Fast & EaSy Commit And Rollback, FESCAR),和社区一起共建分布式事务解决方案。TXC/GTS/Fescar 一脉相承,为解决微服务架构下的分布式事务问题交出了一份与众不同的答卷。而Fescar 的愿景是让分布式事务的使用像本地事务的使用一样简单和高效。最终的目标是希望可以让 Fescar 适用于所有的分布式事务场景。阿里巴巴的开源之路仍在延续。恰逢其时,阿里云峰会·北京的开发者专场现场,阿里云智能资深技术专家李三红宣布,阿里开源 Open JDK 长期支持版本 Alibaba Dragonwell,作为 JCP 最高执行委员会唯一的中国企业,将更主动的参与到 Java 生态的维护工作中。Dragonwell 意为龙井,象征着中国的茶文化。本文作者:中间件小哥阅读原文本文为云栖社区原创内容,未经允许不得转载。 ...

March 25, 2019 · 2 min · jiezi

数据脱敏大数据架构设计

需求背景系统有数据识别、数据脱敏逻辑,支持可配置规则,自定义等,需要进行异构数据同步,大数据量。现在针对以下几个需求进行讲解1、支持冗余设计2、支持任务自动分发,支持自动负载均衡3、支持随时扩容节点而无需关停原有的系统和业务架构和模块架构图五核心模块及其主要功能调度平台使用Nginx方式来调用数据中心,通过注册中心获取数据中心的服务列表可以合理的根据数据同步的情况,去调用服务;比如数据同步可能存在的顺序性,执行延时;读取控制台DB的配置信息,定时执行数据同步任务对数据同步的调用,可以按照简单的轮询方式,也可以根据数据同步服务器的性能情况,进行负载均衡数据同步负责执行数据库异构数据同步任务,可支持增量,全量模式,用DataX框架来实现服务于调度平台的调用会存储数据同步的执行结果,供控制台进行展示会上报服务器的性能指标到数据同步DB,以供调度平台参考控制台配置管理界面,服务于用户进行数据同步任务的配置信息,并存储到控制台DB中;数据识别负责针对数据库的数据进行数据识别任务数据脱敏按照内置规则、自定义配置,负责脱敏数据可提前进行数据脱敏,以供数据同步转换环节调用三个辅助服务发现模块注册中心用于服务发现和注册数据同步注册实例并定期报心跳可以用zookeerper来实现调度平台通过域名访问注册中心获取数据同步的地址列表Nginx和域名系统配合,协助调度平台访问注册中心获取数据同步地址列表和域名系统配合,协助用户访问控制台进行配置管理可用性分析高可用通过Nginx、注册中心来实现,可以支持动态扩容。每个主要模块都是以无状态集群方式部署的,各自模块都可以通过注册中心来实现服务注册,模块之间的调用服务发现来获取,并以域名方式实现。考虑到扩展,所以设想的方案是尽可能的做到每个服务职责单一。这样的拆分,也是考量到每个环节的瓶颈都不一样,目前预估不是很精确,这样可以为后续扩展提供方便性。数据脱敏、数据识别需要单独独立出来,原因:本身的服务不在数据同步中,可能提前预处理进行。通过集群部署方式,支持冗余设计。调度平台、Nginx集群通过数据同步性能情况,实现任务自动分发,支持自动负载均衡。可用性分析可用性表格分析场景影响降级原因某台数据同步下线无影响-数据同步无状态,调度平台重连其他的数据同步服务。所有数据同步下线调度平台无法执行数据同步任务控制台正常运行;调度平台把数据同步任务放入执行队列,等待执行-某个Nginx下线无影响-多Nginx部署,数据完全同步,注册中心、控制台域名通过SLB自动切换到其他存活的Nginx控制台DB宕机调度中心无影响,控制台无法更新配置调度平台开启配置缓存后,对配置的读取不受数据库宕机影响某台数据识别、数据脱敏下线无影响-数据识别、数据脱敏无状态,数据同步重连其他的数据识别、数据脱敏同步服务全部数据识别、数据脱敏下线无影响-数据同步可执行在线脱敏功能,会影响任务时长。结论数据同步、控制台、调度平台、数据识别、数据脱敏是数据脱敏的几大核心微服务模块,相互协作完成配置中心业务功能,Nginx、注册中心是辅助微服务之间进行服务发现的模块。采用微服务架构设计,架构和部署(部署方式可以用容器思路来操作)都有一些复杂,但是每个服务职责单一,易于扩展。

March 25, 2019 · 1 min · jiezi

100行Python代码理解深度学习关键概念:从头构建恶性肿瘤检测网络

摘要: 100行Python代码理解深度学习关键概念!在构建乳腺癌预测神经网络过程中,我们主要分为3大部分:1.用Python从零开始创建一个神经网络,并使用梯度下降算法训练模型。2.在该神经网络中使用威斯康星乳腺癌数据集,根据9种不同的特征,预测肿瘤是良性还是恶性的。3.探索反向传播和梯度下降算法的工作原理。在这个领域中,有很多大牛都通过视频和博文分享了自己掌握的专业知识,如fast.ai的Jeremy Howard、吴恩达、Andrej Karpathy、Yann Lecun等等。他们一致认为,深度学习的关键之一就是,尽快亲自动手编写一个深度学习的模型。当前,深度学习领域中有很多强大的库可供我们使用,如Tensorflow、 PyTorch、 Fast.ai、 Keras、 Mxnett、Nctk、DL4J 等。如果仅仅直接使用这些强大的库,我们可能会错过很多关键的东西,因此,我们需要进一步思考这些进程中最重要的那部分。如果能自己亲自动手编码创建一个神经网络,我们就不得不面对创建过程中出现的一些问题和障碍,挖掘深度学习背后隐藏的那些令人惊叹的知识。当前,深度学习领域中有各种各样的架构和开发:卷积神经网络、循环神经网络和生成对抗网络等等。在这些不同种类的网络背后,都包含了两个相同的算法:反向传播算法和梯度下降算法。探索神秘的函数宇宙中的很多事物都可以用函数表示。本质上来说,函数是一种数学结构,接受一个输入并产生一个输出,表示因果关系、输入输出关系。当我们审视周围的世界时,会接收到很多信息,我们将这些信息转化为数据,就可以从这些数据中学到很多知识。在利用这些数据进行学习的时候,会有很多不同的种类。通常来说,深度学习中有三种最常见的类型:1.监督学习:从一组有标签(已分类)的训练数据中学习函数,输入和输出是成对的数据集。2.非监督学习:从没有任何标签或分类的数据中学习到函数。3.强化学习:代理人会在特定环境中做出相应的动作,通过最大化代理人得到的奖励得到函数。监督学习本文中,我们主要关注监督学习。现在,我们有一个数据集,包含输入及对应的输出。下面,我们想了解这些输入和输出是如何通过一个神秘的函数联系起来的。当数据集达到一定的复杂度时,寻找这个函数的难度就相当大。因此,我们就需要使用神经网络和深度学习,来探索这个神秘的函数。本质上来说,神经网络通过一系列的中间“权重”连接我们的输入和期望输出数据。这些权重实际上就是一些数字。当我们使用正确的架构和参数,通过神经网络的结构和优化算法,我们可将神经网络近似成一个通用函数近似器,将输入和输出数据联系起来。创建一个神经网络一般来说,简单的神经网络包括两层(输入不计入层数):1.输入:神经网络的输入包含了我们的源数据。并且,神经元的数量与源数据的特征数量相匹配。下图中有4个输入,当我们使用威斯康星乳腺癌数据集创建神经网络的时候,就会使用9个输入。2.第一层:隐藏层,包含一些隐藏层神经元,这些神经元将会与周围层中的所有单元相连接。3.第二层:有一个单元,为神经网络的输出。在实际的神经网络构建过程中,我们可以使用更多的层,比如10个或20个层的网络。为了简单起见,在这里,我们使用2个层。千万不要小看这2个层,它能够实现很多功能。神经网络如何进行学习问题来了:在这个神经网络中,学习将在哪个部分进行?我们来回顾一下,我们在神经网络的输入层放置了一些数据,并向网络展示某个输入应该对应什么输出,也就是说,神经网络的输出(第2层)应该是什么结果。在神经网络中,每个神经元都有一个相关的权重以及一个偏差。这些权重只是神经网络在开始学习时候初始化的一些随机数字。神经网络根据输入数据和这些权重值进行计算,通过神经网络传播,直到输出产生最终的结果。这些计算的结果就是一个将输入映射到输出的函数。我们需要的就是,这些神经网络能够计算出一个最佳权重值。因为网络通过计算,不同的权重和不同的层结合起来,会近似出不同类型的函数。现在,我们来进一步探索正在探寻的函数。为了方便阅读,我们需要解释下这些变量的名称:1.X表示输入层,即提供给网络的数据集。2.Y表示与输入x对应的目标输出,由输入经过网络进行一系列的计算得到的输出。3.Yh(y hat)表示预测函数,即我们像网络提供输入数据集x后,经过神经网络一系列的计算产生的输出。因此,Y是理想的输出,Yh是神经网络接收到输入数据后产生的实际输出。4.W表示网络各层的权重。我们首先看第一层——隐藏层,它执行了一个运算WX(即W和X的乘积)。然后进行一个加权和:1.这一层中的每个单元都和前一层中的每个单元相连接。2.权重值存在于每个连接中。3.该层中每个单元的值都是由前一个层中每个单元的值权重的总和,而该权重则是1中所得到的权重。从某种程度上来说,权重表示连接的强度,即:不同层之间单元连接的强度。现在,我们要在这个架构中添加一个额外的量——偏差:WX+b。这个偏差能够给神经网络带来更多的灵活性,偏差允许网络“移动”单位的线性计算,加强网络学习这些函数的能力。b代表单位偏差项。我们看到,WX+b就是一个线性方程,通过乘积与和运算表示输入和输出的线性关系。现在,我们的神经网络只有2层,但是请记住,一个神经网络可以有很多层,比如20个甚至200个。因此,我们用数字表述这些变量属于哪一层。这样一来,定义隐藏层(第1层)的线性方程则为:W1X+b1,并为其输出命名为Z,表示某一层计算的输出。因此,我们得到如下方程:Z1=W1X+b1注意,这个计算应该针对每个层的每个单元进行。当我们为神经网络编写代码的时候,我们将使用向量化编程,也就是说,利用矩阵将某一层的所有计算放在一个单一的数学运算中。上面所讲述的是只有一个层的神经网络。现在,我们考虑一个有很多层的神经网络,每个层执都执行一个类似上面的线性运算,当所有的线性运算连接在一起时,这个神经网络就能够计算复杂的函数了。激活函数然而,现在就有一个问题:线性函数——太简单了吧。这个世界是复杂的,因此,线性函数远远满足不了实际需求。一般来说,复杂的函数往往都是非线性的。而且,如果神经网络的架构仅仅由线性函数计算,那么就很难计算非线性行为。这就是为什么我们要在神经网络的每一层末尾加上一个额外的量:激活函数。现在,我们介绍4个最典型的例子。为了方便我们后续对激活函数进行深入探索,首先需要介绍梯度这一概念。一个函数在某一点上的梯度也称为函数的导数,表示该函数在该点输出值的变化率。我们来思考这样一个问题:当特定输入发生变化时,函数的输出会发生怎样的变化?当梯度(导数)非常小,即函数的输出变化非常平坦时,我们称之为梯度消失。在后边的反向传播算法中,我们可以通过梯度了解网络中每个参数将会如何影响网络的输出,从而就能够决定如何调整网络的权值,也就是说了解这个参数的变化将会使网络的输出增加还是减少?梯度消失是我们所面临的一个问题,因为如果某一点的梯度变化很小或趋于0,我们就很难确定该神经网络在该点的输出方向。当然,我们也会遇到相反的情况——梯度爆炸。当梯度值非常大时,神经网络可能就会变得非常不稳定。不同的激活函数有各自的优点,但是都会面临梯度消失和梯度爆炸这两大问题。左上:Sigmoid激活函数;右上:Tanh激活函数;左下:Relu激活函数;右下:Leaky Relu激活函数(1)Sigmoid激活函数——1/(1+e-x)1.输出范围:[0,1]。2.非线性,输出为两个极端变量0和1。适用于二分类问题。3.曲线变化温和,因此,梯度(导数)比较容易控制。4.该激活函数的主要缺点为:在极端情况下,函数的输出曲线变得非常平坦,也就是说,函数的导数(变化率)将变得非常小,在这种情况下,Sigmoid激活函数的计算效率和速度将会非常低,甚至会完全没效率。5.当Sigmoid激活函数出现在神经网络的最后一层时,将会特别有用,因为Sigmoid激活函数有助于将输出变为0或1(即二分类问题)。如果将Sigmoid激活函数放在神经网络的其他层,就会出现梯度消失问题。(2)Tanh激活函数——(2/(1+e-2x))-11.输出范围:[-1,1]。2.曲线和Sigmoid激活函数的曲线类似,是Sigmoid激活函数曲线的缩小版。3.Tanh激活函数曲线较为陡峭,因此,该激活函数的导数(变化率)比较大。4.Tanh激活函数的缺点与Sigmoid激活函数类似。(3)Relu激活函数——max (0,x)1.如果输入大于0,那么,输出值等于输入值;否则,输出为0。2.Relu激活函数的范围是[0,+∞),这就意味着输出可能是+∞,可能会存在梯度爆炸问题。3.优点:使神经网络轻量化,因为一些神经元可能输出为0,防止所有的神经元被同时激活。4.Relu激活函数存在一个问题,即输入为0的时候,输出全部为0,这将会导致梯度为0,会让我们忽视某些神经元的一些有用的计算。5.Relu激活函数计算简单,成本低廉。6.当前,Relu激活函数是神经网络内层最经常使用的激活函数。(4)Leaky Relu激活函数——ex / Sum(ex)1.输出范围:[0,1]2.Leaky Relu激活函数将输入进行标准化处理为一个概率分布。3.通常用于多分类场景中的输出层。在这里,我们在输出层使用Sigmoid激活函数,在隐藏层使用Relu激活函数。好了,现在我们已经理解了激活函数,那么,就需要对其进行命名!A:表示激活函数的输出。因此,在神经网络的隐藏层中,将会进行如下计算:A1=Relu(Z1)Z1=W1X+b1在第二层的输出层中,将会进行如下计算:A2=Sigmoid(Z2)Z2=W2A1+b2请注意,第二层(输出层)的输入为第一层的输出,即A1。第二层的输出就是网络的最终输出。将上面的计算归纳一下,就得到2层神经网络所执行的全部计算:Yh = A2 = Sigmoid(W2ReLU (W1X+ b1) + b2 )因此,本质上来说,神经网络是一连串的函数,有些是线性函数,有些是非线性函数,它们共同组成了一个复杂的函数,将我们的输入数据和想要的输出数据连接了起来。现在,我们注意到,在这个方程的所有变量中,W和b是两个未知数,这就是神经网络需要学习的地方。也就是说,神经网络必须进行不断的学习,找到W和b的正确值,才能计算出正确的函数。因此,我们训练神经网络的目的也变得明了了,即寻找W1,b1,W2,b2的正确值。但是,在开始训练神经网络之前,我们必须首先对这些值进行初始化,即用随机函数对其进行初始化处理。初始化以后,我们就可以对神经网络进行编码,我们使用Python构建一个类,对这些主要的参数进行初始化处理。我们将如何进行实战编码呢?请继续阅读我们的第二部分:用Python构建一个神经网络。一站式开发者服务,海量学习资源0元起!阿里热门开源项目、机器学习干货、开发者课程/工具、小微项目、移动研发等海量资源;更有开发者福利Kindle、技术图书幸运抽奖,100%中–》https://www.aliyun.com/acts/product-section-2019/developer?utm_content=g_1000047140本文作者:【方向】阅读原文本文为云栖社区原创内容,未经允许不得转载。

March 19, 2019 · 1 min · jiezi

我们总结了每个技术团队都会遇到的 4 个难题

阿里巴巴 2019 年实习生校园招聘已经启动,为此,我们整理了一篇《每个技术团队都会遇到的4个难题》,帮助即将从校园进入公司实习的后端程序员,以实践的视角,看看一个后端技术团队会遇到的一些难题。虽然,技术上的难题远不止于此,但如果能从这篇文章中获得一些职业体感,也许对你的实习面试会有所帮助。- 正文开始 -从单个应用到多个应用,从百千级别的访问流量到十万、百万级别,从两三个人的创业技术团队到上千人的技术团队矩阵,这些过程中,技术团队都避不开了以下 4 个问题:如何预测业务峰值时的容量如何提升业务的稳定性如何提高业务的监控能力如何提高开发效率如何预测业务峰值时的容量早期的做法是在开发测试环境进行压测,来评估线上容量,但线下环境的机器规模,和线上差距很大,很难通过线下推导线上。根据经验,将采购的机器加入不同的应用里面,这时候就会遇到一个问题: 最大业务峰值容量是多少?这个问题,其实挺难回答的。这个应用多加几台,那个应用少加几台,整体的业务峰值承受能力就会不一样,加减的规则很难通过人的经验来确定,最多只能作为一些辅助判断。另外,核心交易链路的梳理,也是一个体力活,如果依赖人为处理,有可能会漏掉一些看起来不那么重要的”分支”,这是整个容量不确定的地方,可变的因子很多。比较有效的方式, 是在生产系统部署全链路压测,来验证各个生产环节是否能经受住各类流量的访问,让真实的流量来访问生产环境,实现全方位的真实业务场景模拟,确保各个环节的性能、容量和稳定性均可做到万无一失。如何提升业务的稳定性日常的各种运营活动,都有可能带来巨大的流量高峰,除了通过引入全链路压测来验证各个生产环节是否能经受住各类流量的访问, 构建系统的高可用保障能力也很关键,涉及多个组件或模块,例如软负载和配置中心、服务接入和调度编排、消息接收和发送、容器和调度、限流和降级 等。运营一次活动,最大的流量峰值是可以预测的,这就是服务的最大接待能力,比如50万笔的交易创建峰值,那超过的怎么办?这时候,采用限流的方式,被限流的客户在某一段时间内无法进行购物,一旦系统恢复服务能力,就可以继续服务被限流的客户,从而避免因流量超过上限,而影响整个平台的客户。如何提高业务的监控能力分布式应用系统在协作性,扩展性和一定的容错性方面,体现出了优势,但是在监控、运维和诊断层面,面临相当大的挑战。早期,架构师可以画出整个应用系统的交互架构图,随着业务的发展,当拥有大量的应用、微服务和容器,即便整理了一幅交互架构关系图,也会因为应用系统的变更,新需求的实现,整个应用系统的交互又会发生变化,这种变化无处不在,每天都在发生。因此,随着业务量的增加,需要覆盖面广且深的全链路跟踪监控系统 ,来诊断调用链的问题。越是复杂的业务形态,定位的难度越大,就越需要全方位、360度无死角的监控,因此,建立一个平台化、跨领域和立体化的监控,能极大的缩短业务遇到问题时的恢复时间。如何提高开发效率开发效率是一个很广泛的话题。不同的开发岗位,不同的使用场景,会有不一样的开发效率工具。这里,我们介绍几款后端工程师经常会用到的效率工具。云端部署效率工具:Cloud Toolkit 是一款 IDE插件,可以帮助开发者更高效地开发、测试、诊断并部署应用。借助这个工具,开发者能够方便地将本地应用一键部署到任意机器,或 ECS、EDAS、Kubernetes,并支持高效执行终端命令和 SQL 等。点此了解详情。MacOS 搜索利器:MacOS 自带的聚焦搜索(Spotlight),可以将文稿、邮件、应用等整合在一起,通过关键词匹配来进行搜索。Alfred 可以看作是Spotlight的增强版,是计算机依赖者的效率神器,支持添加自定义网络搜索引擎,指定规则精准定位本地文件,以及在命令框内使用计算器、词典等实用工具。画图效率工具:系统架构图是为了抽象的表示软件系统的整体轮廓和各个组件之间的相互关系和约束边界,以及软件系统的物理部署和软件系统的演进方向的整体视图。通过架构图,可以让干系人理解、遵循架构决策,就需要把架构信息传递出去。架构图就是一个很好的载体,所谓一图胜千言。点此了解详情。JSON 浏览效率插件对于 JSON 的数据,如果不编排,格式查看起来会很费劲。JSON-handle 是一款对 JSON 格式的内容进行浏览和编辑,以树形图样式展现 JSON 文档的插件,支持实时编辑。Java 代码规约扫描效率插件这是一款 Java 代码规约扫描工具,旨在以工具的手段进行代码规约的落地,项目包含三部分:PMD规则实现、IntelliJ IDEA 插件、Eclipse 插件,帮助开发人员在工程研发的多个阶段进行代码规约检查, 降低故障率、提升编码效率和质量。点此了解详情。当然,除了这些现成的效率工具,提升整个技术团队的开发效率,需要单独开发或改造一些系统,例如团队协作平台、服务化改造等,当你以实习生的身份加入公司后,若有机会参与到这些提升开发效率的项目过程中。由此形成的效率意识,将会影响到你今后的工作习惯和理念。本文作者:中间件小哥阅读原文本文为云栖社区原创内容,未经允许不得转载。

March 14, 2019 · 1 min · jiezi

Conflux 吐槽君:Hashgraph 是一个真正的企业级去中心化平台吗?

亲爱的好朋友们:上期小C吐了一下 IOTA。说实话,刚开始小C还有些忐忑,毕竟是小C出道的第一篇文章,文章内容也可能会引起一些激烈的辩论。结果,有非常多的朋友给了我点赞关注加鸡腿,这让小C非常受宠若惊。感谢大家对小C的支持和关注,小C一定会更加努力地为大家写出更多更好的文章,不辜负大家对小C的信任!今天小C又新鲜出炉一篇新的文章——想跟大家一起分享一下 Hashgraph 这个项目。Hashgraph 是什么?这个名为 Hashgraph 的分布式账本于 2016 年横空出世,稍晚于上次讲过的“第一个使用了 DAG 技术”的公链项目 IOTA——如果 DAG (Directed Acyclic Graph,有向无环图)也可以被称为一种“技术”的话。Hashgraph 项目团队宣称:“这不是区块链,这是市场上第一个(甚至唯一一个)‘银行级’的共识技术。” ¹ 江湖传闻 Hashgraph 可以拳打比特币,脚踢以太坊,靠的就是不分片即可高达 50 万 tps 的硬实力 ² ,唯一的限制只有网速和想象力……顺便说一下,小 C 听说18年天猫双11的交易量峰值是 49.1万笔/秒,17年时候才 25.6 万笔/秒。1:https://www.thestreet.com/story/14385913/1/is-hashgraph-technology-just-hype-or-can-it-dethrone-blockchain-.html2: https://www.hedera.com/whitepaper随手放狗搜一下 Hashgraph 就可以发现,无论是在 Wikipedia 还是在其他各种媒体上,这个项目的口气都大得吓人: “How Hedera Hashgraph is building a fast and secure blockchain alternative.”(Hashgraph 如何建造一个快速且安全的区块链替代者)这样的说法,已经算是非常谦虚的了,其他的还有以下这些:“Hedera Hashgraph Thinks It Can One-Up Bitcoin And Ethereum With Faster Transactions”(Hashgraph 自认为胜过比特币和以太坊一筹)“Hashgraph vs. Blockchain Is the end of Bitcoin and Ethereum near?”(Hashgraph 对区块链!比特币和以太坊的末日指日可待?)“Hashgraph wants to give you the benefits of blockchain without the limitations”(Hashgraph 想要给你们带来无限牛逼的分布式账本)……简直一个项目要单挑所有区块链了!开头说的“拳打比特币,脚踢以太坊”已经算是非常谦虚的口号了。不过仔细研究以后,小 C 发现 Hashgraph 项目团队确实没有骗我——Hashgraph 真的是一个“银行级”的公用账本,一个只有银行级用户才用得起的账本。Hashgraph是怎么做的?小 C 在这里先来简单介绍一下 Hashgraph 的共识算法,对这部分比较熟悉或者不感兴趣的观众可以直接跳到下一节。与 IOTA 所用的 Tangle 账本不同,Hashgraph 用了一种更规整的图结构“哈希图”去存储包含交易的区块(每个区块在 Hashgraph 中记为一个“事件”(event)),并通过一个 aBFT (Asynchronous Byzantine Fault Tolerant, 异步的拜占庭容错,指系统在不超过三分之一的节点被攻击者控制,且诚实的节点之间通信延迟可以被任意延长的情况下仍可以保证安全性)的共识算法来保证所有人对整个账本达成共识。简单来说,Hashgraph 共识算法的基本逻辑就是:假设大多数参与者都是好人,那么当交易被足够多数人(比如三分之二以上的比例)见证以后,就可以确认这些交易的顺序以及它们是否有效了。只要系统里大部分人都是诚实的,那么多数人见证过的历史就可以沉淀为无法改变的共识。Hashgraph 共识算法采用了一种“见证即投票”的方式对交易历史排序。当一个参与者 Alice 看到有新鲜事发生的时候,比如一笔新的交易 T,就把这些新鲜事打包到一个区块 B 里;除了亲眼所见的以外,Alice 构造的区块还需要引用两个更早的区块,其中一个是 Alice 自己生成的前一个区块,另一个是从其他参与者那里收到的最新的区块。然后再给 B 加上时间戳和 Alice 的签名,就可以把区块 B 悄悄地告诉另一个随机选择的参与者 Bob 了。将来 Bob 就可以再通过引用区块 B 的方式,作为见证者把 “Alice 告诉我某时某刻发生了一笔交易 T” 的信息继续传播给其他人。于是,Alice 发起的这笔交易 T 就能以八卦的形式在参与者之间飞快地传播,只需要大约 log(N) 次就可以传遍 N 个参与者。果然,八(yao)卦(yan)传播的速度就是比正经的广播要快得多呢~Hashgraph 将所有区块按照他们之间的哈希引用关系组织成 DAG ,称为一个“哈希图”。哈希图不同于一般的有向无环图, 它有着非常鲜明的结构特征,即每个参与者都有一条链,同时链上的每个区块都引用一个别的链的区块。哈希图实际上描述了“事件”在“八卦网络”(Gossip Network)中传播的路径。通过观察本地存储的哈希图我们不仅可以判断一个事件是否已经被大多数参与者见证,还可以确定每个参与者见证不同的事件的先后顺序。Hashgraph 的通信比传统 BFT 少?Hashgraph 相对于传统 BFT 算法最大的优势,就在于 N 个参与者只需要每人发送大约 log(N) 条消息就可以完成一轮投票。要知道,在普通的 BFT 算法里,每个参与者可是要发 N-1 条点对点的消息才能做完成一轮投票的。听上去是不是很厉害?简直 too good to be true!为什么 Hashgraph 可以做得这么好呢?其实有一个比较微妙的小问题,只是因为 Hashgraph 相关的文档写到这里都是一笔带过的,所以小 C 至今没有看明白:传播八卦的时候,一条消息到底有多长?按照 Baird 2016年的 Hashgraph 论文的说法(“… Alice will choose another member at random, such as Bob, and then Alice will tell Bob all of the information she knows so far”)似乎是要 Alice 把所有知道的信息都告诉 Bob。所以,Alice 发给 Bob 的信息可能不止是一个区块 B,还包括这个区块 B 直接间接引用的的所有其他区块——难道要把整个账本的历史都放在一条消息里发出去?即使 Alice 非常聪明,记得她上次都告诉了 Bob 哪些八卦,每次只需要同步新八卦,那么每条消息的长度也依然会达到参与者人数的线性量级。如此看来, Hashgraph 可以少发很多条消息就没那么神奇了。因为虽然条数少了,但是新包装的一条消息的内容可能就长得可以绕地球1圈~最后算下来,Hashgraph 似乎也就是一个没有比传统的 BFT 算法节约什么的 BFT 算法。Hashgraph 的“银行级”性能接下来,小 C 来给大家算一下 Hashgraph 的几十万 tps 到底是什么概念。如果按照 Hashgraph 的测试网数据 25万 tps,每笔交易按 250 字节计算, 仅同步交易就需要 250000*250=62500000 B/s=62.5 MB/s 带宽。如果按照官网白皮书所说的 50万 tps,则需要 125MB/s 带宽。注意,这还没有计算除了交易本身以外的任何开销。所以在 5G 普及之前,普通用户下载速度都赶不上 Hashgraph 增长的速度。姑且先不讨论带宽,那么什么样的机器才能处理每秒数十万笔交易呢?以现在典型的机器配置,单核 CPU 每秒钟也就能验证几千笔交易的签名,强如 EOS 的超级节点在峰值时刻处理的交易数量也不过每秒四千笔左右。而 Hashgraph 除了处理账本上的每笔交易以外还要维护八卦图和虚拟投票,这又是一笔不小的开销。综上所述,只有银行级或者企业级的硬件才配得上 Hashgraph 了。Hashgraph 的“银行级”安全性Hashgraph 超高的安全性要求三分之二以上的参与者见证才能确认一笔交易,这样少数坏人再也无法修改公共账本。但是另一方面,这个机制也有非常严重的缺点——共识参与者的活跃性问题。Hashgraph 共识参与者们必须非常活跃,否则就会因为见证人数不够而无法达成任何共识。在现实中任何一个去中心化的系统中,普通用户一般都是长期不在线的,能长期活跃在线的只有:1)银行和交易所;2)庄家;3)矿工(Hashgraph 没有 PoW,没有矿工) 以上都是。所以,一个由银行级和企业级用户维护共识的公共账本,当得起一句“银行级”的安全性。对 Hashgraph 项目的建议小 C 建议 Hashgraph 项目也不要总拿着“银行级”联盟账本的性能去找比特币和以太坊等公链碰瓷,都不是一个赛道上有什么好比的。还不如好好跟别的基于 pBFT(实用拜占庭容错)的公共账本比比孰优孰劣更有意义。如果 Hashgraph 实在眼红公链这块蛋糕,也应该严谨地分析 Hashgraph 在公链环境下的安全性,然后用同口径的性能数据去跟别人比较,否则再怎么比也只是鸡同鸭讲罢了。本来嘛,如果 Hashgraph 只是做一枚安安静静的 BFT 账本,不要出来喊打喊杀地要做颠覆区块链的“Blockchain killer”,我们也不会想起来要拍它不是吗?就像裘千丈裘老前辈的职业规划如果是做一名魔术师或者杂技演员,那绝对是一位德艺双馨的老艺术家,也不会挨打对不对?事实上,Hashgraph 项目也确实是按照联盟账本搞的,他们组织了一个由 39 个组织和企业构成的委员会去维护和运行这个分布式的账本。至于开不起银行的普通用户嘛……我觉得支付宝和微信都是不错的企业级账本和 APP 平台。他们如果愿意把各地的机房拆分成不同的公司分别运营甚至卖掉几个的话,应该也能达到不输 Hashgraph 的“去中心化”程度。好了,这一期的内容就先到这里了!小伙伴们,如果你们看后感觉到了欢乐,觉得内容充实又有趣的话,记得多都支持我呀!动动手指点个赞,关注一下我们公众号吧~顺便推荐一下我们的线下活动~在本期Conflux Meetup,我们为大家邀请到了Conflux CTO伍鸣、Conflux研究总监杨光、Cobo钱包高级副总裁李尧来一起聊一聊《下一代公链和DApps生态前景》。点击报名 ...

March 7, 2019 · 2 min · jiezi

阿里云TSDB在大数据集群监控中的方案与实战

目前大部分的互联网企业基本上都有搭建自己的大数据集群,为了能更好让我们的大数据集群更加高效安全的工作,一个优秀的监控方案是必不可少的;所以今天给大家带来的这篇文章就是讲阿里云TSDB在上海某大型互联网企业中的大数据集群监控方案中的实战案例,希望能为感兴趣的同学提供一些帮助。背景和需求阿里云时序时空数据库 (原阿里云时间序列数据库, 简称 TSDB) 是一种高性能,低成本,稳定可靠的在线时序数据库服务;提供高效读写,高压缩比存储、时序数据插值及聚合计算,广泛应用于物联网(IoT)设备监控系统 ,企业能源管理系统(EMS),生产安全监控系统,电力检测系统等行业场景。 TSDB 提供百万级时序数据秒级写入,高压缩比低成本存储、预降采样、插值、多维聚合计算,查询结果可视化功能;解决由于设备采集点数量巨大,数据采集频率高,造成的存储成本高,写入和查询分析效率低的问题。Elastic MapReduce(EMR)是阿里云提供的一种大数据处理的系统解决方案。EMR基于开源生态,包括 Hadoop、Spark、Kafka、Flink、Storm等组件,为企业提供集群、作业、数据管理等服务的一站式企业大数据平台。上海某大型互联网企业是阿里云EMR的Top客户,在阿里云上购买的EMR实例有近千台hadoop机器,这些机器目前除了阿里云本身ECS级别的监控以外,没有一套成熟的这对大数据的监控运维告警系统,对大数据业务来讲存在很大的风险。现在客户的需求是对购买的EMR集群做监控和告警,单台有20多个监控指标,采集精度可以根据客户需求调整,另外还要求对原有的业务无侵入,不需要业务层做太多的配置重启类操作。痛点和挑战该大型互联网企业客户最初计划采用的是Prometheus作为监控和告警解决方案,并且基于Prometheus的监控方案也在该企业内部其他系统应用了。这里提到了Prometheus,就多说几句。随着业内基于Kubernetes的微服务的盛行,其生态兼容的开源监控系统Prometheus也逐渐被大家热捧。Prometheus是一个开源监控系统,它前身是SoundCloud的监控系统,在2016年继Kurberntes之后,加入了Cloud Native Computing Foundation。目前许多公司和组织开始使用Prometheus,该项目的开发人员和用户社区非常活跃,越来越多的开发人员和用户参与到该项目中。下图就是prometheus方案的架构:这个方案在实际部署过程中发现Prometheus在存储和查询上存在性能的问题,主要是Prometheus本身采用的local storage方案在大数据量下的扩展性写入查询性能存在瓶颈。另外在这个方案的适配性不强,要改很多参数重启才行,这对于线上正在运行的业务来说,是不可接受的,需要重新设计解决方案。阿里云TSDB解决方案监控和告警整体上来说包括三个环节:1.采集指标2.存储指标3.查询告警因此基本方案就可以简化为:采集工具 + 数据库 + 查询告警。其中,数据库可以通过阿里云TSDB来解决存储和查询上的性能问题,查询告警可以通过成熟的开源工具Grafana。由于该互联网企业客户的要求对原有的业务无侵入,不需要业务层做太多的配置重启类操作,因此解决方案的调研就重点落在了采集工具的调研上了。对于采集工具而言,结合该互联网企业客户已经部署的Prometheus,且阿里云TSDB兼容开源时序数据库OpenTSDB的写入和查询协议,因此从减少成本和工作量的角度来看,可以考虑的方式是有两种:1. 使用Prometheus官方提供的开源的OpenTSDB Adapter 对接原生的Prometheus ,实现数据写入到TSDB。基本架构为:这种方案和该互联网企业客户的开发同学沟通后,发现满足不了对业务无侵入,不重启的需求,因此选择放弃;2. 采用其他开源工具,实现数据采集写入到TSDB。开源社区较为活跃,已经提供了不少开源的采集工具,因此我门评估了以下几个开源的采集工具:Collectd,https://collectd.orgtelegraf, https://github.com/influxdata/telegraf* statsd, https://github.com/etsy/statsdtcollector, http://opentsdb.net/docs/build/html/user_guide/utilities/tcollector.html从开发语言、部署方式以及是否支持定制开发等角度,我们初步选择tcollector作为采集工具。tcollector是一个客户端程序,用来收集本机的数据,并将数据发送到OpenTSDB。tcollector可以为你做下面几件事:运行所有的采集者并收集数据;完成所有发送数据到TSDB的连接管理任务;不必在你写的每个采集者中嵌入这些代码;是否删除重复数据;处理所有有线协议,以后今后的改进;因此,基于tcollector + TSDB + Grafana的监控告警架构如下,其中tcollector以http协议从目标结点上拉取监控指标,并以http的OpenTSDB协议将指标推送至阿里云TSDB。这个方案在不修改tcollector源码的基础上,能够满足客户对hadoop的监控。但是在PoC后,客户增加了对EMR实例中其他大数据组件的监控需求,如Hive, Spark, Zookeeper, HBase, Presto, Flink, azkaban, kafka, storm等。经过我们调研,tcollector对于这些组件的支持程度如下:原生支持:hbase;需定制化开发,不重启实例:Hive, Spark, Zookeeper;需定制化开发,需重启实例:Flink, azkaban, kafka, storm;经过一定工作量的制化开发,基于tcollector的方案基本可以满足用户的需求。最终我们在该互联网企业客户的EMR大数据集群的监控告警方案架构为:tcollector非常简单易部署,可以简单高效地完成了客户的需求。而且配置部署时,可以不用区分大数据组件的角色,解决了之前开源采集工具需要针对不同角色,来手动配置并启动相应插件的问题。至此,TSDB完美得解决了该互联网企业客户大数据集群监控接入TSDB的案例,让TSDB在迈向完善生态的路上更进一步了。另外值得一提的是,为了解决目前广泛使用的Prometheus开源系统在大量时序数据的存储、写入和查询存在性能瓶颈问题,阿里云TSDB也已经开始兼容了Prometheus生态,并且已经在多个客户场景进行了实战。后面我们会推出针对Prometheus的系列文章,对Prometheus感兴趣或者已经是Prometheus用户但是遇到性能问题的同学可以持续关注我们。阿里云时序时空数据库TSDB 1元购!立即体验:https://promotion.aliyun.com/ntms/act/tsdbtry.html?spm=5176.149792.775960.1.dd9e34e2zgsuEM&wh_ttid=pc本文作者:焦先阅读原文本文为云栖社区原创内容,未经允许不得转载。

March 6, 2019 · 1 min · jiezi

基于实时计算(Flink)与高斯模型构建实时异常检测系统

案例与解决方案汇总页:阿里云实时计算产品案例&解决方案汇总1. 概述异常检测(anomaly detection)指的是对不符合预期模式或数据集(英语:dataset)中其他项目的项目、事件或观测值的识别。实际应用包括入侵检测、欺诈检测、故障检测、系统健康监测、传感器网络事件检测和生态系统干扰检测等。之前我曾经介绍过一种异常检测的解决方案《准实时异常检测系统》,但那个架构中Flink主要承担的还是检测后的分析,真正的异常检测被前置到了业务系统中。在本文中,我将介绍一种直接使用Flink做实时异常检测的方案。2. 异常检测算法2.1 异常的种类异常(离群点)分为三种类型:全局离群点,最基本的异常,即一个单独的远离群体的点;情境(或条件)离群点,该点在全局不算异常,但在某个上下文中却是异常的,比如人的性别为男性不是异常,但如果选定范围为女厕所,那么这个就是异常的;集体离群点,单个点不算异常,但一系列组合起来却是异常。比如偶尔的服务延迟不是异常,但如果整个系统大部分服务都延迟那就是异常。本文以说明基本原理为主,所以使用最简单的全局离群点做例子,即只关注检测某个单独的事件是否偏离正常。完成的异常分类可参考:这里2.2 异常监测算法关于异常检测有大量的算法,详细理论可参考scikit-learn的《 Novelty and Outlier Detection》一章。本文选取最简单的一种算法,基于高斯分布分布的异常检测算法。假设我们已经有了一组正常数据,x(1),x(2),..,x(m),那么针对新的数据x,我们判断这个x是否正常,可以计算x在正常数据中出现的概率如何,如果x出现的概率大于某个阈值,则为正常,否则即为异常,这种方法叫做密度估计。那么我们可以假设,这些数据遵循高斯分布(正态分布),那么对某个特定的值来说,其在高斯分布的中间部分是比较正常的,在两端可能是异常的。通常如果我们认为变量 x 符合高斯分布 x~N(,2),则其概率密度函数为:异常检测算法的步骤为:对于给定的数据集 x(1),x(2),…,x(m),针对每一个特征计算 和 2 的估计值,计算方法如下。一旦我们获得了每个特征的平均值和方差的估计值,给定新的一个训练实例,根据模型计算每一特征的概率再相乘得到整体的概率:注:可能你要检测的事件只有一个特征,那么很显然就不用再乘了。选择一个阈值 ,将 p(x)= 作为判定边界,当 p(x)> 时预测数据为正常数据,否则为异常,这样就完成了整个异常检测过程。注:阈值的选择可以直接估算一个,也可以简单训练得出,具体训练方式这里不再赘述,可参考这里。总结一下,其实整个模型我们只需要计算正常数据中每个特征的平均值和方差,再加上最终整体阈值,所以模型是非常小的,完全可以把这些数据计算出来后随代码一起发布。(当然从解耦性来说,最好能够独立存储,通过注册或配置的方式来发布)3. 基于Flink和高斯分布的实时异常检测系统前面介绍了异常检测的基本算法,那么本小节我们就基于Flink和高斯分布设计一个实时异常检测系统。假设你是一个公司的运维人员,负责管理全公司的IT资源,为了保证公司IT稳定性,提前发现主机或者系统的问题,你设计了这样一个实时异常检测系统。系统采用Kapp架构,关于Kappa架构的说明可参考:数据仓库介绍与实时数仓案例。系统架构与所选软件如下图所示:数据源包括两个部分,主机运行信息与系统的运行日志,主机运行信息通过collectd 收集,系统运行日志通过Filebeat收集,二者均将数据推送到Kafka。数据通过Kafka流转,支持Flink计算过程中的实时分层。最终数据存储到Elastic Search中,并通过KIBANA可视化。异常检测由实时计算Flink完成,计算过程很简单:数据清洗,把原始数据格式化;计算特征值,计算所选事件的特征,比如某个服务打印日志的频率就是一个特征,假如系统调用失败,则会打印一条失败记录,那么当系统打印失败记录的频率变高时,系统可能出现了问题;计算特征统计值,即找到该特征的高斯分布(确定平均值和方差即可确定高斯分布);这里高斯分布直接在线计算,好处是随时可更新,没有显式的训练过程,缺点是可能受异常数据影响。另外一种方式是离线选取一些正常数据然后计算高斯分布。检测异常值,利用2.2节中的算法原理检测异常事件;输出,最后把检测出的异常数据写到下游;好了,一个简单的实时异常检测系统就完成了。4. 总结在本文中,在Kappa架构上添加简单的异常检测算法即可完成一个简单有效的实时异常检测系统。该架构具备良好的可扩展性,基于Flink的Kappa架构让系统能够应对超大规模数据流,并且能够在数据流转的过程中完成处理。此外,虽然本文中直接把异常检测算法内置到了Flink的逻辑中,但实际的应用中很容易把通过算法API的方式让系统解耦:算法团队训练并提供一个用以判别某个事件或特征是否异常的算法服务,在Flink的处理过程中计算好特征值之后调用这个算法服务进行检测。该方案来自真实的案例,如果有兴趣进一步了解,可参考下边资料:准实时异常检测系统数据仓库介绍与实时数仓案例实时欺诈检测(风控)Novelty and Outlier DetectionApplying the Kappa architecture in the telco industry,Kappa architecture and Bayesian models yield quick, accurate analytics in cloud monitoring systems.Anomaly detection高斯分布、异常检测Outlier Analysis: A Quick Guide to the Different Types of Outliers本文作者:付空阅读原文本文为云栖社区原创内容,未经允许不得转载。

March 6, 2019 · 1 min · jiezi

TableStore:爬虫数据存储和查询利器

TableStore是阿里云自研的在线数据平台,提供高可靠的存储,实时和丰富的查询功能,适用于结构化、半结构化的海量数据存储以及各种查询、分析。爬虫数据特点在众多大数据场景中,爬虫类型的数据非常适合存储在TableStore。主要是因为爬虫类型数据的一些特征和TableStore和匹配:数据量大爬虫数据一般都是抓取的互联网上的某个行业或领域的数据,数据规模和这个行业的数据规模有关,比如资讯类,每时每刻都在产生大量新闻报道,这个数据规模可能在10 TB到100 TB级别,如果考虑到历史存量数据,那么规模可能会更大。这么大量的数据存储已经不适合用单机的关系型数据库了,也不适合分库分表了,而需要一款分布式NoSQL数据库,这样可以将数据按一定的路由规则分布到不同机器上,实现自动的水平扩展,非常适合存储海量数据,尤其是爬虫类。宽行和稀疏列爬虫的数据一般来源于多个数据源,比如资讯数据可以来自人民网、新浪或者腾讯,每个数据源的数据特征不可能完全一样,每家有每家的特殊性,这样就会出现每一行数据的属性列有差异,虽然可以归一化处理后,可以将通用的属性列统一,但是不同数据源还是会存在一定差异性。如果为每个数据源建立一张表,那么工作量就会非常大,也不适合。这时候,就需要用到宽行和稀疏列功能,既能保证列数无上限,也能保证不同行不同列,还可以不额外增加存储成本和运维成本。查询类型多样爬虫数据的存储后,一般有两个出口,一个是数据处理程序,数据处理程序会读取最新的爬虫数据,然后按照自定义的处理逻辑做数据加工,处理完后会新数据写入原表或新表。数据处理完之后,数据可以提供给下游企业客户或终端用户使用了,场景的查询需求有下列几种:多种属性列组合查询。比如全网简历信息里面,通过年龄、学历、专长查询,且每个人查询的条件可能都完全不一样,需要多种属性列的自由组合查询。分词查询。不管是咨询类,还是简历类,都有大量的文本描述,这部分内容都需要支持分词后再查询。排序能力。比如资讯类数据中,查询某个新闻后,需要按时间逆序返回,越新的数据价值越大。随机读能力。如果是用来做全局数据分析或处理,那么随机读是一种必须要有的能力。轻量级统计分析。比如资讯类,想查看某个热点新闻的传播时间段和趋势,就需要统计每个时间段的此类新闻出现次数。这些查询能力,在传统的关系型数据库或者开源NoSQL中都无法提供。开源解决方案爬虫数据存储的方案已经演进了将近二十年了,千奇百怪的各种方案都有,主要的差异来源于两点:当前能获取到的存储系统能力。自身对系统可靠性、可用性的要求高低。我们下面以当前业界流行的开源系统为材料,打造一个爬虫数据存储的系统。当前业内的开源存储系统有两大类,一类是开源的关系型数据库,比如MySQL等,一类是NoSQL,比如HBase等。这两类数据存储系统都不能支持分词查询,那么还需要一个全文检索的系统,当前可选的有solr和Elasticsearch。基于上述的素材,我们就可以搭建一个存储爬虫的系统了:首先,选择存储系统,MySQL和HBase都可以,如果使用MySQL,则需要分库分表,两者架构图差不多,这里我们就选择HBase。再次,选择查询系统,可选的solr和Elasticsearch,虽然是同一类型系统,但是Elasticsearch的目前更流行,那我们也选择Elasticsearch。这样,架构图大致如下:大概解释下:流程:爬虫系统将抓取的数据写入HBase离线集群,然后数据处理系统周期性或流式的处理新到的数据,将处理后的结果写入HBase在线集群。HBase在线集群存储所有属性列的值,然后将需要查询的列通过co-processor发送给消息队列,最后再将消息队列中的数据被Elasticsearch消费,生成索引。最后,用户通过索引查询到PK,然后通过proxy到HBase在线集群读取这一行完整数据,最后返回给用户。数据存储集群有两个,一个是在线集群,一个是离线集群,原因是为了避免减少离线集群对在线查询的影响,因为离线系统重吞吐,而在线系统重延迟,所以,这里会分成两个集群,目的是挺高系统可用性。消息队列的目的是削峰填谷,减少对下游系统:Elasticsearch的压力,同时当Elasticsearch写入慢或者出故障后,不至于影响上游系统,目的也是为了提高系统可用性,避免单点故障导致整个系统雪崩。Proxy的目的是减轻客户端工作量,提高易用性的工具,原因是爬虫数据是系数列,这些列不可能全部都在Elasticsearch中创建索引,只有部分需要查询、分析的属性列才会在Elasticsearch中建立索引,但是查询的时候也需要未建立索引的字段,这样就需要一个系统做反查和合并,就是先查Elasticsearch获取到PK,然后通过PK到HBase在线集群查询这一行完整数据。这个系统中,需要运维6个不同开源系统,运维压力比较大。TableStore云解决方案最开始,我们说TableStore很适合存储爬虫数据,在介绍了开源系统的解决方案后,我们再来看一下TableStore的解决方案,以及相对于开源系统,可以为客户带来的收益。也先看一下架构图:大概解释下:爬虫系统抓取的数据写入TableStore的离线表,然后经过TunnelService的流式通道,数据进入数据处理系统做处理加工,再将加工后的数据写入在线表,用户直接查询在线表即可。将离线表和在线表同时放在TableStore服务中,会不会出现离线表干扰在线表的情况?这个不会的,TableStore服务内部有自动的负载均衡和隔离系统,会自动处理这些问题。所有的查询都可以直接查询在线表及其索引,提供了多字段组合查询、分词查询、排序和统计分析等功能,完全可以满足用户对查询的需求。数据处理部分一般有两种处理方式,一种是离线全量处理,这种可以使用阿里云的MaxCompute系统,MaxCompute可以直读TableStore的数据做计算,不需要额外把数据导过去。另一种是流式实时处理,TableStore提供了TunnelService系统,可以获取到实时的Table中的数据更新记录,然后将更新记录发送到函数计算、流式计算系统,或者自己的应用、flink等系统处理。这个架构中,用户只需要运维2个系统即可。示例我们接下来举一个简历类爬虫数据存储和查询的示例,帮忙读者快速理解。简历一般是一个PDF文档或者doc文档,是一个文件,但是我们可以从这些文件中抽取出结构化的信息,比如姓名、电话号码、身份证、邮箱、毕业学校、学历、专业领域、项目经验、兴趣、期望薪水和工作年限等。首先,我们设计TableStore中主表结构:主键列属性列属性列属性列属性列属性列属性列属性列属性列属性列身份证姓名电话号码邮箱毕业学校学历专业领域项目经验兴趣期望薪水工作年限StringStringStringStringStringStringStringStringStringLongDouble61xxx5王一152xxx7aa@xx.comMIT硕士[数据库,MySQL]1.数据库binlog优化。[足球]200003.5大概解释下:主键列需要一个唯一值,用来唯一确定某个人,这里我们用了身份证,有些场景获取不到身份证,那可以用手机号或其他ID。后面几个全部是属性列,包括姓名,电话号码等。期望薪水因为都是整数,所以可以选择Long类型,工作年限由于有小数,所以可以是Double类型。通过这张表,我们可以通过身份证,查询到该用户的详细信息。但是无法通过属性列查询,如果需要通过属性列查询,则需要创建多元索引。然后,我们再创建多元索引,多元索引的结构如下:属性列属性列属性列属性列属性列属性列属性列属性列属性列姓名电话号码毕业学校学历专业领域项目经验兴趣期望薪水工作年限Text:单字分词KeywordKeywordKeywordKeyword ArrayText:多层语义Keyword ArrayLongDouble解释下:上面的多元索引结构中包括9列,比Table中少了2列,是因为不需要通过“邮箱”和“身份证”两个属性列查询,所以,在建立index的时候就不需要为这两列创建index了。但是如果业务中确实需要通过邮箱查询,那么多元索引创建时加上邮箱即可。姓名的类型是Text:单字分词,意思是类型是Text,分词是单子分词,这样好处就是我可以通过搜索“小刚”搜索到“王小刚”、“冯小刚”等。电话号码、毕业院校、学历都是Keyword类型(对应Table中的String),因为这些都字符串都比较短,且查询方式是直接完全匹配或者前缀查询,那么用String就可以了。专业领域和项目经验两个属性列是Keyword Array的,因为是这两个属性列中会包括多个值,查询的时候只要有一个满足就可以返回,比如某个人的专业领域是:数据库、MySQL,那么我们查询“数据库”的时候,希望这个人返回。期望薪水和工作年限是数字类型的Long和Double,这样这两个属性列就可以支持范围查找,比如查找工作年限大于2年,小于5年,且期望薪水小于2万的简历。至此,我们就把简历库的table和index都建好了,用户就可以往Table中开始写数据,数据写入后会异步同步到Index中,这样就可以通过Index查询了。总结使用TableStore解决方案后,相对于开源解决方案,可以带来不少的收益:减少运维负担使用开源系统的架构中,需要运维6个系统,包括了3个开源系统:HBase、Kafka和Elasticsearch,为了运维这三个开源系统,需要有人对这三个系统比较熟悉,否则很难运维好。就算比较熟悉,也很难处理线上遇到的所有的问题,总会碰到无法解决的棘手问题而影响生产环境。如果使用了TableStore云解决方案,那么就不需要运维任何开源系统,只需要运维自己开发的两个系统,同时关注TableStore中的两个表就可以了,这两张表的运维全部是TableStore服务负责,且提供SLA保障,绝对比自己运维开源系统的可用性要高。同时,采用TableStore方案后,由于TableStore支持实时自动扩容,客户不再需要提前规划水位和集群容量,也不用担心高水位和突发流量对系统的冲击,将这些工作都交给了更擅长的云服务处理。这样,不仅降低了运维的工作量和压力,同时也降低了系统风险,提高了系统整体的可用性。减少时间成本TableStore云架构方案相对于开源方案,系统更少,从零开始到上线需要的开发时间更少,同时,TableStore是serverless的云服务,全球多个区域即开即用,可以大大降低客户的开发上线的时间,提前将产品推出,抢先争取市场领先优势。同时,TableStore支持按量付费,用户完全可以根据真实使用量付费,不再需要担心低峰期系统资源的浪费了,一定程度上,也能降低使用成本。最后目前,已经有不少行业的客户在使用TableStore存储爬虫数据,比如资讯类、生活类、文章类等等,也有部分用户在小数据量级时使用MySQL等关系型数据库,等数据规模大了后被迫迁移到TableStore存储。同时欢迎更多的客户开始使用TableStore存储你们的爬虫数据。本文作者:少强阅读原文本文为云栖社区原创内容,未经允许不得转载。

March 5, 2019 · 1 min · jiezi

The (Near) Future of Database | TiDB DevCon 2019

在 TiDB DevCon 2019 上,我司联合创始人兼 CTO 黄东旭分享了对数据库行业大趋势以及未来数据库技术的看法。以下是演讲实录,enjoy~<center>我司联合创始人兼 CTO 黄东旭</center>大家今天在这里看到了 TiDB 社区用户实践分享和我们自己的一些技术进展和展望,还有非常好玩的 Demo Show,正好在大会结束之前,我想跟大家聊一聊我心目中未来的 Database 应该是一个什么样子。其实我们并不是一个特别擅长发明名词的公司,我记得我们第一次去用 HTAP 这个词的时候,应该是 2016 左右。在使用 HTAP 这个词的时候,我们市场部同事还跟我们说 HTAP 这个词从来没人用过,都是论文里的词,大家都不知道,你把你们公司的产品定位改成这个别人都不知道怎么办?我们后来仔细想,还是觉得 HTAP 这个方向是一个更加适合我们的方向,所以还是选了 HTAP 这个词。现在很欣喜的看到现在各种友商、后来的一些数据库,都开始争相说 HTAP,就是说得到了同行的认可。那么在 HTAP 的未来应该是一个什么样子,我希望能够在今年这个 Talk 里面先说一说,但是这个题目起的有点不太谦虚,所以我特地加了一个「Near」, 分享一下这一年、两年、三年我们想做什么,和对行业大趋势的展望。<center>图1</center>今天我们的分享的一个主题就是:「我们只做用户想要的东西,并不是要去做一个完美的东西」。其实很多工程师包括我们自己,都会有一个小小的心理的洁癖,就是想要做一个超级快、超级牛的东西,但是做出来一个数据库,单机跑分一百万 TPS ,其实用户实际业务就需要 3000,然后所有的用户还会说我需要这些东西,比如需要 Scalability(弹性扩展), Super Large 的数据量,最好是我的业务一行代码都不用改,而且 ACID 能够完全的满足,怎么踹都踹不坏,机器坏了可以高可用,业务层完全不用动, 另外可以在跑 OLTP 的同时,完全不用担心任何资源隔离地跑 OLAP(这里不是要说大家的愿望不切实际,而是非常切实际,我们也觉得数据库本身就应该是这样的。所以大家记住这几个要点,然后慢慢看 TiDB 到底是不是朝着这个方向发展的)。本质上来说用户的需求就是「大一统」。看过《魔戒》的同学都知道这句话 :ONE RING TO RULE THEM ALL,就是一套解决方案去解决各种问题。过去很多,包括一些行业的大佬之前说在各种环境下都要出一个数据库来解决特定的一个问题,但是其实看上去我们想走的方案还是尽可能在一个平台里面,尽可能大范围去解决用户的问题。因为不同的产品之间去做数据的交互和沟通,其实是蛮复杂的。<center>图 2 理想中的「赛道」</center>这张图(图 2)什么意思呢?就是很多人设计系统的时候,总是会陷入跑分思维,就是说这个东西在实验室或者说在一个特定的 Workload 下,跑得巨快无比。如果大家去看一下大概 2000 年以后关于数据库的论文,很多在做一个新的模型或者新的系统的时候,都会说 TPCC 能够跑到多大,然后把 Oracle 摁在地上摩擦,这样的论文有很多很多很多。但是大家回头看看 Oracle 还是王者。所以大多数实验室的产品和工程师自己做的东西都会陷入一个问题,就是想象中的我的赛道应该是一个图 2 那样的,但实际上用户的业务环境是下面这样的(图 3)。很多大家在广告上看到特别牛的东西,一放到生产环境或者说放到自己的业务场景里面就不对了,然后陷入各种各样的比较和纠结的烦恼之中。<center>图 3 实际上用户的业务环境</center>TiDB 的定位或者说我们想做的事情,并不是在图 2 那样的赛道上,跑步跑得巨快,全世界没人在短跑上跑得过我,我们不想做这样。或者说,我们其实也能跑得很快,但是并不想把所有优势资源全都投入到一个用户可能一辈子都用不到的场景之中。我们其实更像是做铁人三项的,因为用户实际应用场景可能就是一个土路。这就是为什么 TiDB 的设计放在第一位的是「稳定性」。我们一直在想能不能做一个数据库,怎么踹都踹不坏,然后所有的异常的状况,或者它的 Workload 都是可预期的。我觉得很多人远远低估了这个事情的困难程度,其实我们自己也特别低估了困难程度。大概 4 年前出来创业的时候,我们就是想做这么一个数据库出来,我跟刘奇、崔秋三个人也就三个月做出来了。但是到现在已经 4 年过去了,我们的目标跟当年还是一模一样。不忘初心,不是忘不掉,而是因为初心还没达到,怎么忘?其实把一个数据库做稳,是很难很难的。<center>图 4 近年来硬件的发展</center>而且我们这个团队的平均年龄可能也就在二十到三十岁之间,为什么我们如此年轻的一个团队,能够去做数据库这么古老的一件事情。其实也是得益于整个 IT 行业这几年非常大的发展。图 4 是这几年发展起来的 SSD,内存越来越大,万兆的网卡,还有各种各样的多核的 CPU,虚拟化的技术,让过去很多不可能的事情变成了可能。举一个例子吧,比如极端一点,大家可能在上世纪八九十年代用过这种 5 寸盘、3 寸盘,我针对这样的磁盘设计一个数据结构,现在看上去是个笑话是吧?因为大家根本没有人用这样的设备了。在数据库这个行业里面很多的假设,在现在新的硬件的环境下其实都是不成立的。比如说,为什么 B-Tree 就一定会比 LSM-Tree 要快呢?不一定啊,我跑到 Flash 或者 NVMe SSD 、Optane 甚至未来的持久化内存这种介质上,那数据结构设计完全就发生变化了。过去可能需要投入很多精力去做的数据结构,现在暴力就好了。<center>图 5 近年来软件变革</center>同时在软件上也发生了很多很多的变革,图 5 左上角是 Wisckey 那篇论文里的一个截图,还有一些分布式系统上的新的技术,比如 2014 年 Diego 发表了 Raft 这篇论文,另外 Paxos 这几年在各种新的分布式系统里也用得越来越多。所以我觉得这几年我们赶上了一个比较好的时代,就是不管是软件还是硬件,还是分布式系统理论上,都有了一些比较大突破,所以我们基础才能够打得比较好。<center>图 6 Data Type</center>除了有这样的新的硬件和软件之外,我觉得在业务场景上也在发生一些比较大变化。过去,可能十年前就是我刚开始参加工作的时候,线上的架构基本就是在线和离线两套系统,在线是 Oracle 和 MySQL,离线是一套 Hadoop 或者一个纯离线的数据仓库。但最近这两年越来越多的业务开始强调敏捷、微服务和中台化,于是产生了一个新的数据类型,就是 warm data,它需要像热数据这样支持 transaction、支持实时写入,但是需要海量的数据都能存在这个平台上实时查询, 并不是离线数仓这种业务。所以对 warm data 来说,过去在 TiDB 之前,其实是并没有太好的办法去很优雅的做一层大数据中台架构的,「the missing part of modern data processing stack」,就是在 warm data 这方面,TiDB 正好去补充了这个位置,所以才能有这么快的增长。当然这个增长也是得益于 MySQL 社区的流行。<center>图 7 应用举例</center>想象一下,我们如果在过去要做这样很简单的业务(图 7),比如在美国的订单库跟在中国的订单库可能都是在不同的数据库里,用户库可能是另外一个库,然后不同的业务可能是操作不同的库。如果我想看看美国的消费者里面有哪些在中国有过消费的,就是这么一条 SQL。过去如果没有像 TiDB 这样的东西,大家想象这个东西该怎么做?<center>图 8 过去的解决方案</center>假如说这两边的数据量都特别大,然后已经分库分表了。过去可能只能第二天才可以看到前一天的数据,因为中间比如说一个 T+1 要做一个 ETL 到一个 data ware house 里。或者厉害一点的架构师可能会说,我可以做一套实时的 OLAP 来做这个事情,怎么做呢?比如说 MySQL 中间通过一个 MQ 再通过 Hadoop 做一下 ETL,然后再导到 Hadoop 上做一个冷的数据存储,再在上面去跑一个 OLAP 做实时的分析。先不说这个实时性到底有多「实时」,大家仔细算一算,这套架构需要的副本数有多少,比如 M 是我的业务数,N 是每一个系统会存储的 Replica,拍脑袋算一下就是下面这个数字(图 9 中的 R )。<center>图 9 过去解决方案里需要的 Replica 数量</center>所以大家其实一开始在过去说,TiDB 这个背后这么多 Replica 不好,但其实你想想,你自己在去做这个业务的时候,大家在过去又能怎么样呢?所以我觉得 TiDB 在这个场景下去统一一个中台,是一个大的趋势。今天在社区实践分享上也看到很多用户都要提到了 TiDB 在中台上非常好的应用。<center>图 10 现在的解决方案 </center>回顾完行业和应用场景近年来的一些变化之后,我们再说说未来。假设要去做一个面向未来的数据库,会使用哪些技术?1. Log is the new database第一个大的趋势就是日志,「log is the new database」 这句话应该也是业界的一个共识吧。现在如果有一个分布式数据库的复制协议,还是同步一个逻辑语句过去,或者做 binlog 的复制,那其实还算比较 low 的。<center>图 11 Log is the new database </center>上面图 11 左半部分是 Hyper,它是慕尼黑工业大学的一个实验性数据库项目,它做了一些分析,第一个柱形是正常的 SQL 语句的执行时间,比如说直接把一语句放到另外一个库里去执行,耗时这么多。第二个柱形是用逻辑日志去存放,耗时大概能快 23%,第三个柱形能看到如果是存放物理日志能快 56%。所以大家仔细想想,TiDB 的架构里的 TiFlash 其实同步的是 Raft 日志,而并不是同步 Binlog 或者其他的。上面图 11 右半部分是 Aurora,它的架构就不用说了,同步的都是 redo log 。其实他的好处也很明显,也比较直白,就是 I/O 更小,网络传输的 size 也更小,所以就更快。然后在这一块 TiDB 跟传统的数据库有点不一样的就是,其实如果很多同学对 TiDB 的基础架构不太理解的话就觉得, Raft 不是一个一定要有 Index 或者说是一定强顺序的一个算法吗?那为什么能做到这样的乱序的提交?其实 TiDB 并不是单 Raft 的架构,而是一个多 Raft 的架构,I/O 可以发生在任何一个 Raft Group 上。传统的单机型数据库,就算你用更好的硬件都不可能达到一个线性扩展,因为无论怎么去做,都是这么一个架构不可改变。比如说我单机上 Snapshot 加 WAL,不管怎么写, 总是在 WAL 后面加,I/O 总是发生在这。但 TiDB 的 I/O 是分散在多个 Raft Group、多个机器上,这是一个很本质的变化,这就是为什么在一些场景下,TiDB 能够获取更好的吞吐。2. Vectorized第二个大趋势是全面的向量化。向量化是什么意思?我举个简单的例子。比如我要去算一个聚合,从一个表里面去求某一列的总量数据,如果我是一个行存的数据库,我只能把这条记录的 C 取出来,然后到下一条记录,再取再取再取,整个 Runtime 的开销也好,还有去扫描、读放大的每一行也好,都是很有问题的。但是如果在内存里面已经是一个列式存储,是很紧凑的结构的话,那会是非常快的。<center>图 12 TiDB 向量化面临的挑战</center>这里面其实也有一些挑战。我们花了大概差不多 2018 年一年的时间去做向量化的改造,其实还挺难的。为什么?首先 TiDB SQL 引擎是用了 Volcano 模型,这个模型很简单,就是遍历一棵物理计划的树,不停的调 Next,每一次 Next 都是调用他的子节点的 Next,然后再返回结果。这个模型有几个问题:第一是每一次都是拿一行,导致 CPU 的 L1、L2 这样的缓存利用率很差,就是说没有办法利用多 CPU 的 Cache。第二,在真正实现的时候,它内部的架构是一个多级的虚函数调用。大家知道虚函数调用在 Runtime 本身的开销是很大的,在《MonetDB/X100: Hyper-Pipelining Query Execution》里面提到,在跑 TPC-H 的时候,Volcano 模型在 MySQL 上跑,大概有 90% 的时间是花在 MySQL 本身的 Runtime 上,而不是真正的数据扫描。所以这就是 Volcano 模型一个比较大的问题。第三,如果使用一个纯静态的列存的数据结构,大家知道列存特别大问题就是它的更新是比较麻烦的, 至少过去在 TiFlash 之前,没有一个列存数据库能够支持做增删改查。那在这种情况下,怎么保证数据的新鲜?这些都是问题。<center>图 13 TiDB SQL 引擎向量化</center>TiDB 已经迈出了第一步,我们已经把 TiDB SQL 引擎的 Volcano 模型,从一行一行变成了一个 Chunk 一个 Chunk,每个 Chunk 里面是一个批量的数据,所以聚合的效率会更高。而且在 TiDB 这边做向量化之外,我们还会把这些算子推到 TiKV 来做,然后在 TiKV 也会变成一个全向量化的执行器的框架。3. Workload Isolation另外一个比较大的话题,是 Workload Isolation。今天我们在演示的各种东西都有一个中心思想,就是怎么样尽可能地把 OLTP 跟 OLAP 隔离开。这个问题在业界也有不同的声音,包括我们的老前辈 Google Spanner,他们其实是想做一个新的数据结构,来替代 Bigtable-Like SSTable 数据结构,这个数据结构叫 Ressi,大家去看 2018 年 《Spanner: Becoming a SQL System》这篇 Paper 就能看到。它其实表面上看还是行存,但内部也是一个 Chunk 变成列存这样的一个结构。但我们觉得即使是换一个新的数据结构,也没有办法很好做隔离,因为毕竟还是在一台机器上,在同一个物理资源上。最彻底的隔离是物理隔离。<center>图 14 TiFlash 架构</center>我们在 TiFlash 用了好几种技术来去保证数据是更新的。一是增加了 Raft Leaner,二是我们把 TiDB 的 MVCC 也实现在了 TiFlash 的内部。第三在 TiFlash 这边接触了更新(的过程),在 TiFlash 内部还有一个小的 Memstore,来处理更新的热数据结果,最后查询的时候,是列存跟内存里的行存去 merge 并得到最终的结果。TiFlash 的核心思想就是通过 Raft 的副本来做物理隔离。这个有什么好处呢?这是我们今天给出的答案,但是背后的思考,到底是什么原因呢?为什么我们不能直接去同步一个 binlog 到另外一个 dedicate 的新集群上(比如 TiFlash 集群),而一定要走 Raft log?最核心的原因是,我们认为 Raft log 的同步可以水平扩展的。因为 TiDB 内部是 Mult-Raft 架构,Raft log 是发生在每一个 TiKV 节点的同步上。大家想象一下,如果中间是通过 Kafka 沟通两边的存储引擎,那么实时的同步会受制于中间管道的吞吐。比如图 14 中绿色部分一直在更新,另一边并发写入每秒两百万,但是中间的 Kafka 集群可能只能承载 100 万的写入,那么就会导致中间的 log 堆积,而且下游的消费也是不可控的。而通过 Raft 同步, Throughput 可以根据实际存储节点的集群大小,能够线性增长。这是一个特别核心的好处。4. SIMD说完了存储层,接下来说一说执行器。TiDB 在接下来会做一个很重要的工作,就是全面地 leverage SIMD 的计算。我先简单科普一下 SIMD 是什么。<center>图 15 SIMD 原理举例(1/2)</center>如图 15,在做一些聚合的时候,有这样一个函数,我要去做一个求和。正常人写程序,他就是一个 for 循环,做累加。但是在一个数据库里面,如果有一百亿条数据做聚合,每一次执行这条操作的时候,CPU 的这个指令是一次一次的执行,数据量特别大或者扫描的行数特别多的时候,就会很明显的感受到这个差别。<center>图 16 SIMD 原理举例(2/2)</center>现代的 CPU 会支持一些批量的指令,比如像 _mm_add_epi32,可以一次通过一个32 位字长对齐的命令,批量的操作 4 个累加。看上去只是省了几个 CPU 的指令,但如果是在一个大数据量的情况下,基本上能得到 4 倍速度的提升。顺便说一句,有一个很大的趋势是 I/O 已经不是瓶颈了,大家一定要记住我这句话。再过几年,如果想去买一块机械磁盘,除了在那种冷备的业务场景以外,我相信大家可能都要去定制一块机械磁盘了。未来一定 I/O 不会是瓶颈,那瓶颈会是什么?CPU。我们怎么去用新的硬件,去尽可能的把计算效率提升,这个才是未来我觉得数据库发展的重点。比如说我怎么在数据库里 leverage GPU 的计算能力,因为如果 GPU 用的好,其实可以很大程度上减少计算的开销。所以,如果在单机 I/O 这些都不是问题的话,下一个最大问题就是怎么做好分布式,这也是为什么我们一开始就选择了一条看上去更加困难的路:我要去做一个 Share-nothing 的数据库,并不是像 Aurora 底下共享一个存储。5. Dynamic Data placement<center>图 17 Dynamic Data placement (1/2)分库分表方案与 TiDB 对比</center>在今天大家其实看不到未来十年数据增长是怎样的,回想十年前大家能想到现在我们的数据量有这么大吗?不可能的。所以新的架构或者新的数据库,一定要去面向我们未知的 Scale 做设计。比如大家想象现在有业务 100T 的数据,目前看可能还挺大的,但是有没有办法设计一套方案去解决 1P、2P 这样数据量的架构?在海量的数据量下,怎么把数据很灵活的分片是一个很大的学问。为什么分库分表在对比 TiDB 的时候,我们会觉得分库分表是上一代的方案。这个也很好理解,核心的原因是分库分表的 Router 是静态的。如果出现分片不均衡,比如业务可能按照 User ID 分表,但是发现某一地方/某一部分的 User ID 特别多,导致数据不均衡了,这时 TiDB 的架构有什么优势呢?就是 TiDB 彻底把分片这个事情,从数据库里隔离了出来,放到了另外一个模块里。分片应该是根据业务的负载、根据数据的实时运行状态,来决定这个数据应该放在哪儿。这是传统的静态分片不能相比的,不管传统的用一致性哈希,还是用最简单的对机器数取模的方式去分片(都是不能比的)。在这个架构下,甚至未来我们还能让 AI 来帮忙。把分片操作放到 PD 里面,它就像一个 DBA 一样,甚至预测 Workload 给出数据分布操作。比如课程报名数据库系统,系统发现可能明天会是报名高峰,就事先把数据给切分好,放到更好的机器上。这在传统方案下是都需要人肉操作,其实这些事情都应该是自动化的。<center>图 18 Dynamic Data placement (2/2)</center>Dynamic Data placement 好处首先是让事情变得更 flexible ,对业务能实时感知和响应。另外还有一点,为什么我们有了 Dynamic Placement 的策略,还要去做 Table Partition(今天上午申砾也提到了)?Table Partition 在背后实现其实挺简单的。相当于业务这边已经告诉我们数据应该怎么分片比较好,我们还可以做更多针对性的优化。这个 Partition 指的是逻辑上的 Partition ,是可能根据你的业务相关的,比如说我这张表,就是存着 2018 年的数据,虽然我在底下还是 TiDB 这边,通过 PD 去调度,但是我知道你 Drop 这个 Table 的时候,一定是 Drop 这些数据,所以这样会更好,而且更加符合用户的直觉。但这样架构仍然有比较大的挑战。当然这个挑战在静态分片的模型上也都会有。比如说围绕着这个问题,我们一直在去尝试解决怎么更快的发现数据的热点,比如说我们的调度器,如果最好能做到,比如突然来个秒杀业务,我们马上就发现了,就赶紧把这块数据挪到好的机器上,或者把这块数据赶紧添加副本,再或者把它放到内存的存储引擎里。这个事情应该是由数据库本身去做的。所以为什么我们这么期待 AI 技术能够帮我们,是因为虽然在 TiDB 内部,用了很多规则和方法来去做这个事情,但我们不是万能的。6. Storage and Computing Seperation<center>图 19 存储计算分离</center>还有大的趋势是存储计算分离。我觉得现在业界有一个特别大的问题,就是把存储计算分离给固化成了某一个架构的特定一个指代,比如说只有长的像 Aurora 那样的架构才是存储计算分离。那么 TiDB 算存储计算分离吗?我觉得其实算。或者说存储计算分离本质上带来的好处是什么?就是我们的存储依赖的物理资源,跟计算所依赖的物理资源并不一样。这点其实很重要。就用 TiDB 来举例子,比如计算可能需要很多 CPU,需要很多内存来去做聚合,存储节点可能需要很多的磁盘和 I/O,如果全都放在一个组件里 ,调度器就会很难受:我到底要把这个节点作为存储节点还是计算节点?其实在这块,可以让调度器根据不同的机型(来做决定),是计算型机型就放计算节点,是存储型机型就放存储节点。7. Everything is Pluggable<center>图 20 Everything is Pluggable</center>今天由于时间关系没有给大家演示的插件平台。未来 TiDB 会变成一个更加灵活的框架,像图 20 中 TiFlash 是一个 local storage,我们其实也在秘密研发一个新的存储的项目叫 Unitstore,可能明年的 DevCon 就能看到它的 Demo 了。在计算方面,每一层我们未来都会去对外暴露一个非常抽象的接口,能够去 leverage 不同的系统的好处。今年我其实很喜欢的一篇 Paper 是 F1 Query 这篇论文,基本表述了我对一个大规模的分布式系统的期待,架构的切分非常漂亮。8. Distributed Transaction<center>图 21 Distributed Transaction(1/2)</center>说到分布式事务,我也分享一下我的观点。目前看上去,ACID 事务肯定是必要的。我们仍然还没有太多更好的办法,除了 Google 在这块用了原子钟,Truetime 非常牛,我们也在研究各种新型的时钟的技术,但是要把它推广到整个开源社区也不太可能。当然,时间戳,不管是用硬件还是软件分配,仍然是我们现在能拥有最好的东西, 因为如果要摆脱中心事务管理器,时间戳还是很重要的。所以在这方面的挑战就会变成:怎么去减少两阶段提交带来的网络的 round-trips?或者如果有一个时钟的 PD 服务,怎么能尽可能的少去拿时间戳?<center>图 22 Distributed Transaction(2/2)</center>我们在这方面的理论上有一些突破,我们把 Percolator 模型做了一些优化,能够在数学上证明,可以少拿一次时钟。虽然我们目前还没有在 TiDB 里去实现,但是我们已经把数学证明的过程已经开源出来了,我们用了 TLA+ 这个数学工具去做了证明。此外在 PD 方面,我们也在思考是不是所有的事务都必须跑到 PD 去拿时间戳?其实也不一定,我们在这上面也已有一些想法和探索,但是现在还没有成型,这个不剧透了。另外我觉得还有一个非常重要的东西,就是 Follower Read。很多场景读多写少,读的业务压力很多时候是要比写大很多的,Follower Read 能够帮我们线性扩展读的性能,而且在我们的模型上,因为没有时间戳 ,所以能够在一些特定情况下保证不会去牺牲一致性。9. Cloud-Native Architecture<center>图 23 Cloud-Native</center>另外一点就是 Cloud-Native。刚刚中午有一个社区小伙伴问我,你们为什么不把多租户做在 TiDB 的系统内部?我想说「数据库就是数据库」,它并不是一个操作系统,不是一个容器管理平台。我们更喜欢模块和结构化更清晰的一个做事方式。而且 Kubernetes 在这块已经做的足够好了 ,我相信未来 K8s 会变成集群的新操作系统,会变成一个 Linux。比如说如果你单机时代做一个数据库,你会在你的数据库里面内置一个操作系统吗?肯定不会。所以这个模块抽象的边界,在这块我还是比较相信 K8s 的。《Large-scale cluster management at Google with Borg》这篇论文里面提到了一句话,BigTable 其实也跑在 Borg 上。<center>图 24 TiDB 社区小伙伴的愿望列表</center>当然最后,大家听完这一堆东西以后,回头看我们社区小伙伴们的愿望列表(图 24),就会发现对一下 TiDB 好像还都能对得上 :D 谢谢大家。1 月 19 日 TiDB DevCon 2019 在北京圆满落幕,超过 750 位热情的社区伙伴参加了此次大会。会上我们首次全面展示了全新存储引擎 Titan、新生态工具 TiFlash 以及 TiDB 在云上的进展,同时宣布 TiDB-Lightning Toolset & TiDB-DM 两大生态工具开源,并分享了 TiDB 3.0 的特性与未来规划,描述了我们眼中未来数据库的模样。此外,更有 11 位来自一线的 TiDB 用户为大家分享了实践经验与踩过的「坑」。同时,我们也为新晋 TiDB Committer 授予了证书,并为 2018 年最佳社区贡献个人、最佳社区贡献团队颁发了荣誉奖杯。 ...

March 5, 2019 · 4 min · jiezi

基于Blink构建亲听项目以及全链路debug项目实时响应能力

案例与解决方案汇总页:阿里云实时计算产品案例&解决方案汇总本文全面总结了大数据项目组在亲听项目以及全链路debug项目上进行的实时流处理需求梳理,架构选型,以及达成效果一、背景介绍1.1亲听项目亲听项目专注于帮助用户收集、展示、监控和处理用户体验问题,是保证产品的主观评价质量的利器,关于其具体功能可参考在ata搜索"亲听"查看系列文章。目前亲听项目的实时流处理需求来自算法效果监控,算法效果监控需要对上游TimeTunnel日志进行解析后经过处理得到一些关键指标,亲听通过对这些指标的前端展示和阈值监控报警达到算法效果监控目的。需求要点可以总结如下:上游需要处理的TimeTunnel日志的实时数据量大约在日常峰值每秒数万条记录,大促峰值每秒几十万条记录从用户搜索行为到亲听系统得到搜索行为指标数据秒级的低延时数据的处理逻辑较为复杂且会随着算法迭代需要发生变化1.2全链路debug全链路debug专注于帮助用户在线上搜索结果出现异常和问题时帮助开发者复现搜索后端各子系统的中间结果,定位并解决子系统存在的问题,是系统层级质量保证和测试的有力工具。关于其具体功能可参考在ata搜索"全链路debug"查看系列文章。全链路debug的实时流处理需求是实时从TimeTunnel日志中提取出帮助排除搜索线上问题的关键内容,全链路debug利用这些内容帮助进行问题排查。全链路debug的实时流处理需求模型可以用下图描述:需求要点可以总结如下:上游需要处理的TimeTunnel日志的实时数据量大约在日常峰值每秒数万条记录,大促峰值每秒几十万条记录需要保存的单条记录较大,平均达到几K左右对上游TimeTunnel日志解析逻辑大部分为字段提取和透传且不会频繁变化二、解决方案2.1整体架构应对以上需求,亲听以及全拉链路debug的实时流处理系统的最终架构如下:亲听:全链路debug:对于亲听和全链路debug的实时流处理需求最终选择上述架构主要出于实时性和扩展性两方面考虑2.2实时性亲听和全链路debug的实时流处理需求在实时性要求上是类似的,即要对接tt日志,在tt日志记录写入到对于亲听和全链路debug的使用方可见延时要控制在秒级,这种实时性的需求可以分解为两个部分,第一是对实时流数据的处理,而是对实时流数据处理结果的存储和查询服务。对于实时流数据的处理,目前公司内的中间件产品blink能很好满足我们的需求,blink提供对接TimeTunnel的api接口,同时具备很好的实时流处理性能和运维体验;对于实时流处理结果的存储和查询,需要支持几万到几十万qps的写压力以及在每天累计几十T数据量情况下毫秒级延时的读性能,hbase能够基本满足对读写的需求,但是druid和drill能够在满足读写性能的同时提供更好的数据查询体验和实时流处理逻辑的可扩展性,所以对于实时流数据处理结果的存储和查询服务我们是优先考虑druid和drill的,但是全链路debug的实时流处理结果有一个特点就是单条记录数据大小平均为几K左右,这么大的单条记录的大小将导致druid需要的内存量过大且查询性能低下而不可用,所以对于全链路debug的实时流处理结果的存储和查询服务选择了hbase。2.3扩展性在亲听实时流处理系统的下游引入tt->druid,然后使用drill查询druid提供查询服务,是出于对扩展性的考虑。druid是一种支持实时流处理和查询的olap系统(ATA),对接druid使得可以把一部分实时流数据的处理逻辑交给druid,这样当实时流处理逻辑需要修改时,很多情况下就可以通过修改查询逻辑(只要修改一个请求druid时的json配置文件)而不需要修改blink任务(需要修改代码、打包、编译、调参、上线)实现,大幅提升实时流处理系统的扩展性,而亲听实时流处理需求频繁变化的业务特点非常需要这种扩展性;drill是高性能的SQL查询引擎,通过drill对接druid提供查询服务不但使查询语法从druid的json文件变为sql可读性大幅增强,同时drill对druid查询结果具有的二次处理能力也进一步增强了通过修改查询逻辑可以满足的实时流处理逻辑变化,进一步增强系统可扩展性。在blink和druid之间增加了TimeTunnel进行数据中转以保证blink产出流数据被转化为下游druid支持的流数据源形式。2.4经验总结使用table api编写stream api作为blink的底层api,具有较高的灵活性,但是可读性很不好,进而非常影响代码的可维护性和扩展性,当要在实时任务中加入新需求时经常要改动很多地方并且很容易出错,所有实时任务我们选择使用table api编写,table api使用类sql语法描述实时流处理逻辑,使得数据流处理逻辑变得非常清晰,可读性大幅增强,进而节约代码的维护和扩展成本。进行字段归类合并我们通过梳理业务方最终需要使用的字段内容,将blink任务输出到TimeTunnel中记录的字段进行了分类合并,除了出于druid查询性能考虑将若干需要进行group by以及count distinct查询的原有字段保留,其余全部按照诸如搜索请求相关信息、用户相关信息、搜索返回宝贝相关信息这样的概念将原有字段分组后合并为多值字段,而每个合并后的多值字段又会在blink代码中用一个udtf函数统一处理。这样做的好处在于代码逻辑上变得更清晰,当实时流处理需求发生变化,需要产出新的内容或修改现有内容产出逻辑时,只需找到新增内容或待修改内容对应的多值字段,修改对应udtf逻辑并重新上线blink任务即可,下游的druid build无需进行任何修改;同时用有限的几个udtf对整个实时流输出记录的处理逻辑进行归类,避免了记录处理逻辑频繁变化可能导致的代码中过时字段和udf泛滥,可读性下降,修改易出错的问题。drill处理逻辑前移请看下面这个sql:select * from druid.sqa_wireless_search_pv where INSTR(auction_tag, ‘15’)这个sql drill的处理逻辑是从druid表中召回druid.sqa_wireless_search_pv表中全部记录后逐条进行auction_tag字段的比对,过滤出包含‘15’字符串的记录,这种召回全部记录进行处理的操作对于drill来说会造成很大的性能问题,占用集群资源急剧上升,查询延时大幅提高,甚至导致集群oom使查询服务中断服务。在使用drill进行查询时应尽量避免执行类似召回大量记录进行处理的sql,我们对亲听算法效果监控现有sql进行了梳理,找到召回记录数目可能会过高的sql,通过将处理逻辑前移到blink任务阶段大幅优化drill查询性能(例如上面的sql只要将比对auction_tag字段是否含有‘15’的逻辑交给blink处理,并让blink任务新增产出一个tag字段,这样druid就可以针对tag字段建索引,通过where tag==‘true’这样的语句就可以直接召回需要的记录)三、成果总结目前tt->blink->hbase和tt->blink->tt->druid是在公司内使用非常广泛的两种实时流处理架构,能以秒级延时完成线上实时日志处理,这两种实时流处理架构比较好地满足了亲听和全链路debug项目的实时数据处理需求,极大提升了项目价值四、作者简介鸷鸟,来自搜索事业部-工程效率&技术质量-算法工程平台-实时大数据平台15年加入阿里,主要从事电商体系实时数据研发以及实时大数据平台研发本文作者:付空阅读原文本文为云栖社区原创内容,未经允许不得转载。

March 4, 2019 · 1 min · jiezi

数据流被污染?数据质量不高?蚂蚁金服数据资产管理平台了解一下

摘要: 蚂蚁金服的数据治理之道。今年年初,蚂蚁金服ATEC城市峰会在上海举办。金融智能专场分论坛上,蚂蚁金服数据平台部高级数据技术专家李俊华做了主题为《蚂蚁金服数据治理之数据质量治理实践》的精彩分享。演讲中,李俊华介绍了蚂蚁金服数据架构体系的免疫系统——数据质量治理体系,此外还着重介绍了数据质量实施的相关内容,以及蚂蚁的数据质量治理实践与所面对的实际挑战。![蚂蚁金服数据平台部高级数据技术专家李俊华](https://upload-images.jianshu…一、数据治理概况近年来,蚂蚁金服不断在数据架构上进行升级改造,其目的在于解决蚂蚁所面临的数据物理孤岛问题。如今,蚂蚁以及整个阿里巴巴集团的底座都统一到了同一个平台上,这样当实现第五代数据架构体系升级时,就降低了一站式研发的整体门槛,并使得蚂蚁金服的所有工程师都可以在平台上轻松玩转数据。如今,在蚂蚁的数据架构中已经能够很好地解决数据孤岛问题,而如今在数据治理体系中所需要关注的就是逻辑的孤岛。在对数据治理展开论述之前,先谈一谈数据价值。之前的情况是,当数据首先需要经过专门团队负责处理,删除没有价值的数据,负责上线或者下线数据。但是,对于数据价值的判断也是一个非常令人头疼的问题,大部分的数据只会上线不会下线,这样就造成了大量没有价值的数据的堆积。而如今,蚂蚁不仅关心下线没有价值的数据,同时也侧重数据资产的价值最大化。在数据价值方面,蚂蚁有一套完整的数据资产等级以及数据资产的易用模型,这样就能够驱动自身充分利用数据资产,来创造更多的价值。但是如果这些数据被使用了,但是质量却很低,这样就会使得数据资产的价值大打折扣。数据质量产生分析接下来将重点介绍蚂蚁金服在数据治理质量领域的实践思路和方案,并与大家分享两个案例。如下图所示的是抽象数据抽取的全流程图。当某个业务同学录入数据的时候出现一点错误,就会造成数据的质量问题,比如把客户的行业信息填错或者打错了一个字都会造成数据质量问题,而这样的问题很容易出现。在基于传统数据库资产开发数据应用的时候,基本都是从数据源端产数据过来,经过加工、分析再将数据发送出去,也就是“从业务中来,最后回到业务中去”。现在的方案与之前存在很大区别,以前做数据处理时,从数据生产的采集数据来,加工之后就给出去了,而如今蚂蚁很多数据应用将数据处理之后还会回到数据系统中。比如芝麻信用分的计算中存在很多大家看不到的场景,这些数据处理之后还会回到系统之中,而这个过程中每个环节都可能存在数据质量问题。二、数据质量治理的挑战在下图中的左侧展示了蚂蚁的业务形态。如今,蚂蚁的业务场景已经不再仅限于统计分析,而在蚂蚁的芝麻分、花呗、借呗以及“310”放款的背后都是数据在进行支撑并驱动着其发展。今天,蚂蚁的业务形态成为了“技术+数据+算法”三者的融合来追求价值最大化。与此同时,数据质量治理也存在着诸多挑战,它们来自于业务方面、数据方面、用户方面。三、数据质量治理实践数据质量治理思路从事金融业务的同学往往深有感触,互联网金融时代业务的生命周期缩短了很多,并且变化也非常频繁,相比于原本银行的节奏显得非常快。此外,目前无论是蚂蚁金服还是阿里巴巴都在谈“数据业务化、业务数据化”,数据和业务一同共同发展和前进,并且已经进入了发展的深水区。之前的几年,蚂蚁在业务上偏向于“T+1”,而如今,原来的架构体系不足以支撑蚂蚁未来继续发展以及高时效性的诉求。同时,如今蚂蚁的数据体量很大,而数据业务也驱动蚂蚁的整个人才体系的升级。现在,除了本身做数据算法研发的同学之外,其他的技术同学也都会在平台上使用数据,这些同学可能对于数据的认知不同,那么在数据驱动下真正保证数据质量就显得异常重要。那么如何实现数据质量治理呢?首先,需要有一套明确的组织,这是持续建设企业文化的土壤,而数据质量治理文化的建设一定是一个确定的、有组织的并且需要长期持续推进的事情。在组织保障和质量文化的基础之上,蚂蚁还侧重了研发流和数据流。在金融领域,研发流的管控更严格,也更严谨。而对于如今的互联网金融而言,也需要进行强管控,这是因为业务形态决定了研发周期很短,现在蚂蚁在研发流做了强管控,在一站式数据研发平台上,使用了分级管控。需求提出之后就会被等级管理,并且进行打标,进而走入不同流程。此外,研发流上还侧重分级管控,在同一套标准上定义级别,拉平不同的研发流。对于数据流而言,当一个应用发布到生产环境之后,大部分精力花费在数据流中,每天需要从生产环境将数据采集到处理平台,然后运行算法计算,之后将数据返回到生产环境中,走这样的闭环。如今,蚂蚁在数据流链路上做了很多事情,也建设了很多能力。对于数据流而言,如果源头被污染了,如果不能控制其污染到下游,那么越往下修复成本就越大。基于以上的数据质量治理思路,蚂蚁金服做了很多有意思的东西,在数据平台运行时会将整个体系监控起来,如果出现数据质量故障,就能够及时进行修复。此外,从研发到生产的各个环节,蚂蚁都做了大量的工作,这是因为基于平台进行数据研发的同学很多,需要尽量降低使用门槛。对于全数据流而言,主要建设了四大能力,包括感知能力、识别能力、智愈能力和运营能力。平台需要能够感知发布任务的故障问题以及数据质量问题,此外,平台需要能够识别出潜在风险,因为需要非常及时地了解被破坏的数据。当风险被识别出来之后,就需要智愈能力,之所以使用“智”,是因为原本数据处理任务往往是离线的,可能从凌晨开始到早上8点钟左右属于数据生产高峰,在这段时间里会有人员参与质量保障任务。而智愈能力就希望通过AI算法来配合数据处理工作,使得感知能力叠加算法能力,能够对于数据感染进行自愈。最后是运营能力,数据质量不会被展现在前台,如果数据质量足够好,完全可以实现无感知,使用者不用再担心数据能不能用,也不会出现敢不敢用的疑惑,因此数据质量对于运营而言也非常重要。其实,数据质量问题既不仅属于研发也不仅属于业务,而是需要全员参与,共同来解决,这就是数据治理的思路。蚂蚁数据质量治理架构如下图所示的是蚂蚁金服的数据质量治理架构体系。在系统层,按照上述所谈到的具体思路,研发阶段主要集中在数据测试、发布管控以及变更管理等方面的建设,这里着重提及变更问题,数据的变更不仅仅设计到系统层的变更管理,也会涉及到在线系统的相互打通。如今,在线数据源的变更,也会使得数据运营发生变更,更可能会导致数据运营的数据质量问题。在线研发部分为数据运营系统提供了一些相关的接口,能够通知使用者线上的哪些变更会影响到数据运营。对于发布管控能力而言,蚂蚁投入了大量精力进行研发。目前在蚂蚁已经没有专职负责数据测试的同学,基本上全部都是全栈工程师,所以对于研发而言可能管控不是非常强,但却实现了强大的发布管控能力,将与经验、规范、性能以及质量相关的检测全部在这部分执行。在生产阶段,则主要侧重于质量监控、应急演练以及质量治理这三个系统能力。质量监控告警系统能力在大部分的数据系统架构中应该都有,其功能类似于汽车的刹车功能,因此肯定是存在的。而蚂蚁却做了一件很有意思的事情——数据攻防演练,工程师会人为创造故障,然后测试系统能否在短时间内发现故障并进行有效修复,这部分也是目前蚂蚁在重点进行建设的能力。在质量治理部分,会根据不同应用的级别,发布到生产环境之后进行定期巡检,分析是否会影响数据质量。总之,对于数据质量架构体系的系统层而言,不仅原数据非常重要,如今更是结合机器学习来自动配置一些相关策略。数据质量治理方案如下图所示的是蚂蚁金服在实践中的事前、事中、事后的数据质量质量方案。整体而言,事前包括需求、研发、和预发三个阶段,而如今蚂蚁在事前可以做到的可管控、可仿真、可灰度。在事中,监控问题是重点建设的,出现问题不可怕,但是需要实现自主发现问题。而为了使得防御能力更强,蚂蚁实现了主动的攻击演练,而正是通过攻防演练,帮助蚂蚁发现了自身很多薄弱的地方。除此之外,还在事中提供了强大的应急能力,某些事件将会触发应急预案,在这部分,保证数据质量其实就是把不确定的数据风险变成确定的东西。在事后,数据质量也非常重要,事后需要通过有效的指标和管控手段来进行审计和度量,以此发现整个链路上不完善的地方并持续完善。数据质量治理案例最后为大家分享蚂蚁金服在数据质量治理方面的两个案例:案例1:在蚂蚁数据治理架构体系下的发布环节,实现了一个发布强管控的流程。任何脚本在提交时都需要经过检测,然后发布到线上,并再进行一次检测。案例2:数据治理涉及到整个链路,而针对不同链路上的数据版本,数据采集主要是将数据从一端搬运到另一端,不存在加工的过程,此时可以人为注入一些故障,分析数据质量治理体系能否发现问题并作出修改,因此这就产生了“攻”与“防”双方。数据加工处理又另外一套体系结构,其涉及逻辑的加工,更多地需要考虑注入怎样的故障,需要面临什么。如今,在蚂蚁真正落地数据质量治理体系的时候,在攻防演练环节投入了大量精力。本文作者:华蒙阅读原文本文为云栖社区原创内容,未经允许不得转载。

February 28, 2019 · 1 min · jiezi

如何成为优秀的技术主管?你要做到这三点

阿里妹导读:技术主管,又叫「技术经理」,英文一般是 Tech Leader ,简称 TL。随着工作经验的不断积累,能力的不断提升,每个人都有机会成为Team Leader。然而在机会到来前,我们必须提前做好准备,对TL的工作职责有一定了解。当然,这也会为当下更好地配合TL工作打下基础。今天,阿里巴巴高级技术专家云狄将结合自己多年的经验,从开发规范、开发流程、技术规划与管理三个角度出发,分享对技术TL这一角色的理解与思考,欢迎一起探讨交流。「技术主管」是开发团队中的某位程序员需要对一起创建系统的整个开发团队负责时所承担的角色。通常他既要对最终交付的软件系统负责,另外也会像一个程序员一样去开发实现系统。一个技术主管的 60% ~ 70% 的时间可能花在了开发任务分解分配、开发实践、技术架构评审、代码审核和风险识别上,而余下的 30% ~ 40% 的时间则花在为了保障系统按时交付所需的各种计划、协作、沟通、管理上。和团队管理者不同的是,技术主管的大部分管理工作都是针对具体研发任务和技术事务的。接下来基于我在技术TL这个角色上,在开发规范、开发流程、技术管理与规划等方面我的一些心路历程,和大家共勉。开发规范我当时负责的业务是集团收购一家子公司的业务,在整体技术标规范上与集团的技术标准存在很大的差异。开发规范可以说是我来到这个团队干的第一件事,我当时面对的问题是API接口格式混乱,没有标准的RPC服务化,代码没有统一标准的开发规范,技术框架组件非标准化等一系列问题,作为一名业务上的新人,我第一时间制定了一套相对标准、全面的技术开发规范,边写代码边梳理开发规范,引领团队走向统一标准化开发道路。针对团队研发规范暴露的上述问题,主要制定了如下规范:命名规范我自己非常注重搭建项目结构的起步过程,应用命名规范、模块的划分、目录(包)的命名,我觉得非常重要,如果做的足够好,别人导入项目后可能只需要10分钟就可以大概了解系统结构。具体规范包括包命名、类的命名、接口命名、方法命名、变量命名、常量命名。统一IDE代码模板约定了IDEA/Eclipse IDE代码的统一模板,代码风格一定要统一,避免不同开发人员使用不同模板带来的差异化以及代码merge成本。使用IDEA的同学可以安装Eclipse Code Formatter插件,和Eclipse统一代码模板。Maven使用规范所有二方库、三方库的版本统一定义到parent pom里,这样来所有业务应用工程统一继承parent pom里所指定的二方库、三方库的版本,统一框架与工具的版本(Spring、Apache commons工具类、日志组件、JSON处理、数据库连接池等),同时要求生产环境禁用SNAPSHOT版本。这样以来升级通用框架与工具的版本,只需要应用工程升级parent pom即可。代码Commit规范基于Angular Commit Message规范生成统一的ChangeLog,这样一来对于每次发布release tag非常清晰,Mac下都需要安装对应的插件,IDEA也有对应的插件,具体可以参考阮一峰老师的《Commit message 和 Change log 编写指南》。此刻忽然想起Linus面对pull request里的骚操作所发的飚:Get rid of it. And I don’t ever want to see that shit again. ——Linus代码的commit的规范对团队非常重要,清晰的commit信息生成的release tag,对于生产环境的故障回滚业非常关键,能够提供一些有价值的信息。统一API规范统一Rpc服务接口的返回值ResultDTO,具体代码如下:success代表接口处理响应结果成功还是失败,errorCode、errorMsg表示返回错误码和错误消息,module表示返回结果集,把ResultDTO定义到common-api顶层二方库,这样以来各个应用不需要来回转换返回结果。Http Rest接口规范约定同ResultDTO相差无几,需要额外关注一下加解密规范和签名规范、版本管理规范。异常处理规范异常处理不仅仅是狭义上遇到了Exception怎么去处理,还有各种业务逻辑遇到错误的时候我们怎么去处理。service服务层捕获的异常主要包括BusinessException(业务异常)、RetriableException (可重试异常) 到 common-api,定义一个公共异常拦截器,对业务异常、重试异常进行统一处理,对于可重试的异常调用的服务接口需要保证其幂等性。另外其他业务层有些特殊异常不需要拦截器统一处理,内部可以进行自我消化处理掉,根据场景对应的处理原则主要包括:直接返回抛出异常重试处理熔断处理降级处理这又涉及到了弹力设计的话题,我们的系统往往会对接各种依赖外部服务、Api,大部分服务都不会有SLA,即使有在大并发下我们也需要考虑外部服务不可用对自己的影响,会不会把自己拖死。我们总是希望:尽可能以小的代价通过尝试让业务可以完成;如果外部服务基本不可用,而我们又同步调用外部服务的话,我们需要进行自我保护直接熔断,否则在持续的并发的情况下自己就会垮了;如果外部服务特别重要,我们往往会考虑引入多个同类型的服务,根据价格、服务标准做路由,在出现问题的时候自动降级。推荐使用Netflix开源的hystrix容灾框架,主要解决当外部依赖出现故障时拖垮业务系统、甚至引起雪崩的问题。目前我团队也在使用,能够很好的解决异常熔断、超时熔断、基于并发数限流熔断的降级处理。分支开发规范早期的时候源码的版本管理基于 svn,后来逐步切换到 git,分支如何管理每一个公司(在Gitflow的基础上)都会略有不同。针对分支开发规范,指定如下标准:分支的定义(master、develop、release、hotfix、feature)分支命名规范checkout、merge request流程提测流程上线流程Hotfix流程虽然这个和代码质量和架构无关,按照这一套标准执行下来,能够给整个研发团队带领很大的便利:减少甚至杜绝代码管理导致的线上事故;提高开发和测试的工作效率,人多也乱;减少甚至杜绝代码管理导致的线上事故;方便运维处理发布和回滚;让项目的开发可以灵活适应多变的需求,多人协同开发。统一日志规范日志是产品必不可少的一个功能,具备可回溯性、能够抓取问题现场信息是其独一无二的优点,尤其在生产系统上问题定位等方面具有不可替代的作用。这里着重强调一下针对异常的日志规范:WARN和ERROR的选择需要好好考虑,WARN一般我倾向于记录可自恢复但值得关注的错误,ERROR代表了不能自己恢复的错误。对于业务处理遇到问题用ERROR不合理,对于catch到了异常也不是全用ERROR。记录哪些信息,最好打印一定的上下文(链路TraceId、用户Id、订单Id、外部传来的关键数据)而不仅仅是打印线程栈。记录了上下问信息,是否要考虑日志脱敏问题?可以在框架层面实现,比如自定义实现logback的ClassicConverter。正确合理的使用日志,能够指引开发人员快速查找错误、定位问题,因此约定了一套日志使用标准规范,现在可以更多的参考《阿里经济体开发规约——日志规约》。统一MYSQL开发规范表的设计和 Api 的定义类似,属于那种开头没有开好,以后改变需要花10x代价的,我知道,一开始在业务不明确的情况下,设计出良好的一步到位的表结构很困难,但是至少我们可以做的是有一个好的标准。统一工具与框架对开发过程中所用到的公共组件进行了统一抽象与封装,包括 dao 层框架mybatis、cache 组件 jetcache、httpclien t组件、common-tools (公共工具),同时抽取出全局唯一ID、分布式锁、幂等等公共组件,把以上公共组件进行集成到各个应用,进行统一升级、维护,这样以来方便大家将更多的精力集中到业务开发上。开发流程目前团队的开发模式还是基于传统的瀑布开发模式,整体开发流程涉及需求评审、测试用例评审、技术架构评审、开发与测试、验收与上线,这里主要基于TL的角度从需求管理、技术架构评审、代码评审、发布计划评审几个关键重点环节进行探讨,欢迎拍砖。需求管理美国专门从事跟踪IT项目成功或失败的权威机构 Standish Group的CHAOS Reports 报导了该公司的一项研究,该公司对多个项目作调查后发现,百分之七十四的项目是失败的,既这些项目不能按时按预算完成。其中提到最多的导致项目失败的原因就是"变更用户需求"。另外从历年的 Standish Group 报告分析看,导致项目失败的最重要原因与需求有关。Standish Group 的CHAOS 报告进一步证实了与成功项目最密切的因素是良好的需求管理,也就是项目的范围管理,特别是管理好项目的变更。产品因需求而生,在产品的整个生命周期中,产品经理会收到来自各个方面的需求,但是每一个需求的必要性、重要性和实现成本都需要经过深思熟虑的分析和计划,避免盲目的决定需求或者变更需求,这样很容易导致工作混乱,技术TL如果不能正确的对需求进行把控,会导致整个项目偏离正确的轨道。需求管理的第一步就是要梳理不同来源的需求,主要包括从产品定位出发、外部用户反馈、竞争对手情况、市场变化以及内部运营人员、客服人员、开发人员的反馈。首先技术TL对产品有足够认知和把控,简单来说就是我的产品是为了满足哪些人的哪些需求而做,产品需求一定要根植于客户的需求、根植于客户的环境。每款产品必定有其核心价值,能够为客户创造更多的价值,基于此考虑往往能得到一些核心需求,摒除价值不大的需求。需求管理中最重要的就是对发散性需求的管理,往往因此也会导致产品在执行过程中不断的变更或增加需求。由于人的思维是发散性的,所以往往在产品构思的过程中会出现各种新鲜好玩的想法,这些想法可能来自领导或者产品经理自己,但是这些想法往往都是和产品核心方向不相关的,但是由于这些想法能够在当时带来诱惑,因此这些不相关的需求会严重干扰了技术团队的精力,打乱或者延误产品原本的计划。同样技术研发同学也需要建立对产品的深度思考,不要把自己定位成产品需求的实现者,同样需要对需求负责。很多时候需求的变更或增加是因为我们面临太多选择和想要的太多,没有适当的控制自己的欲望,并以自己的喜好来决定需求,这些因素很容易导致产品没有明确的方向、团队成员疲于奔命,但是却没有实际的成果。所以技术TL一定要能够评估出重新审视产品和筛选需求的优先级,识别每一个需求的必要性、重要性和实现成本。通过深思熟虑给团队明确方向并专注,聚焦资源的支配,确保团队的精力都聚焦在产品的核心需求上。技术架构评审互联网时代,大家提倡敏捷迭代,总嫌传统方式太重,流程复杂,影响效率,什么都希望短平快,在扁平化的组织中,经常是需求火速分发到一线研发,然后就靠个人折腾去了,其实技术架构评审这同样是一个非常重要的环节。架构评审或技术方案评审的价值在于集众人的力量大家一起来分析看看方案里是否有坑,方案上线后是否会遇到不可逾越的重大技术问题,提前尽可能把一些事情先考虑到提出质疑其实对项目的健康发展有很大的好处。基于架构评审,我们的目标核心是要满足以下几点:1.设计把关,确保方案合格,各方面都考虑到了,避免缺陷和遗漏,不求方案多牛,至少不犯错。保证架构设计合理和基本一致,符合整体原则。维持对系统架构的全局认知,避免黑盒效应。通过评审发掘创新亮点,推广最佳实践。架构设计既要保证架构设计的合理性和可扩展性,又要避免过度设计。架构设计不仅仅是考虑功能实现,还有很多非功能需求,以及持续运维所需要的工作,需要工程实践经验,进行平衡和取舍。架构评审需要以下几点:技术选型:为什么选用A组件不选用B、C组件,A是开源的,开源协议是啥?基于什么语言开发的,出了问题我们自身是否能够维护?性能方面有没有压测过?这些所有问题作为技术选型我们都需要考虑清楚,才能做最终决定。高性能:产品对应的TPS、QPS和RT是多少?设计上会做到的TPS、QPS和RT是多少?而实际上我们整体随着数据量的增大系统性能会不会出现明显问题?随着业务量、数据量的上升,我们的系统的性能如何去进一步提高?系统哪个环节会是最大的瓶颈?是否有抗突发性能压力的能力,大概可以满足多少的TPS和QPS,怎么去做来实现高性能,这些问题都需要我们去思考。高可用:是否有单点的组件,非单点的组件如何做故障转移?是否考虑过多活的方案?是否有数据丢失的可能性?数据丢失如何恢复?出现系统宕机情况,对业务会造成哪些影响?有无其他补救方案?这些问题需要想清楚,有相应的解决方案。可扩展性:A和B的业务策略相差无几,后面会不会继续衍生出C的业务策略,随着业务的发展哪些环节可以做扩展,如何做扩展?架构设计上需要考虑到业务的可扩展性。可伸缩性:每个环节的服务是不是无状态的?是否都是可以快速横向扩展的?扩容需要怎么做手动还是自动?扩展后是否可以提高响应速度?这所有的问题都需要我们去思考清楚,并有对应的解决方案。弹性处理:消息重复消费、接口重复调用对应的服务是否保证幂等?是否考虑了服务降级?哪些业务支持降级?支持自动降级还是手工降级?是否考虑了服务的超时熔断、异常熔断、限流熔断?触发熔断后对客户的影响?服务是否做了隔离,单一服务故障是否影响全局?这些问题统统需要我们想清楚对应的解决方案,才会进一步保证架构设计的合理性。兼容性:上下游依赖是否梳理过,影响范围多大?怎么进行新老系统替换?新老系统能否来回切换?数据存储是否兼容老的数据处理?如果对你的上下游系统有影响,是否通知到上下游业务方?上下游依赖方进行升级的方案成本如何最小化?这些问题需要有完美的解决方案,稍有不慎会导致故障。安全性:是否彻底避免SQL注入和XSS?是否有数据泄露的可能性?是否做了风控策略?接口服务是否有防刷保护机制?数据、功能权限是否做了控制?小二后台系统是否做了日志审计?数据传输是否加密验签?应用代码中是否有明文的AK/SK、密码?这些安全细节问题需要我们统统考虑清楚,安全问题任何时候都不能轻视。可测性:测试环境和线上的差异多大?是否可以在线上做压测?线上压测怎么隔离测试数据?是否有测试白名单功能?是否支持部署多套隔离的测试环境?测试黑盒白盒工作量的比例是怎么样的?新的方案是否非常方便测试,在一定程度也需要考量。可运维性:系统是否有初始化或预热的环节?数据是否指数级别递增?业务数据是否需要定期归档处理?随着时间的推移如果压力保持不变的话系统需要怎么来巡检和维护?业务运维方面的设计也需要充分考虑到。监控与报警:对外部依赖的接口是否添加了监控与报警?应用层面系统内部是否有暴露了一些指标作监控和报警?系统层面使用的中间件和存储是否有监控报警?只有充分考虑到各个环节的监控、报警,任何问题会第一时间通知到研发,阻止故障进一步扩散。其实不同阶段的项目有不同的目标,我们不会在项目起步的时候做99.99%的可用性支持百万QPS的架构,高效完成项目的业务目标也是架构考虑的因素之一。而且随着项目的发展,随着公司中间件和容器的标准化,很多架构的工作被标准化替代,业务代码需要考虑架构方面伸缩性运维性等等的需求越来越少,慢慢的这些工作都能由架构和运维团队来接。一开始的时候我们可以花一点时间来考虑这些问题,但是不是所有的问题都需要有最终的方案。代码评审代码质量包括功能性代码质量和非功能性代码质量,功能质量大多通过测试能够去发现问题,非功能性代码质量用户不能直接体验到这种质量的好坏,代码质量不好,最直接的“受害者”是开发者或组织自身,因为代码质量好坏直接决定了软件的可维护性成本的高低。代码质量应该更多的应该从可测性,可读性,可理解性,容变性等代码可维护性维度去衡量,其中 CodeReview 是保证代码质量非常重要的一个环节,建立良好的 CodeReview 规范与习惯,对于一个技术团队是一件非常重要核心的事情,没有 CodeReview 的团队没有未来。每次项目开发自测完成后,通常会组织该小组开发人员集体进行代码 review,代码 review 一般 review 代码质量以及规范方面的问题,另外需要关注的是每一行代码变更是否与本次需求相关,如果存在搭车发布或者代码重构优化,需要自行保证测试通过,否则不予发布。CodeReview 我会重点关注如下事情:确认代码功能:代码实现的功能满足产品需求,逻辑的严谨和合理性是最基本的要求。同时需要考虑适当的扩展性,在代码的可扩展性和过度设计做出权衡,不编写无用逻辑和一些与代码功能无关的附加代码。在真正需要某些功能的时候才去实现它,而不是你预见到它将会有用。 —— RonJeffries编码规范:以集团开发规约、静态代码规约为前提,是否遵守了编码规范,遵循了最佳实践。除了形式上的要求外,更重要的是命名规范。目标是提高代码的可读性,降低代码可维护性成本。潜在的BUG:可能在最坏情况下出现问题的代码,包括常见的线程安全、业务逻辑准确性、系统边界范围、参数校验,以及存在安全漏洞(业务鉴权、灰产可利用漏洞)的代码。。文档和注释:过少(缺少必要信息)、过多(没有信息量)、过时的文档或注释,总之文档和注释要与时俱进,与最新代码保持同步。其实很多时候个人觉得良好的变量、函数命名是最好的注释,好的代码胜过注释。重复代码:当一个项目在不断开发迭代、功能累加的过程中,重复代码的出现几乎是不可避免的,通常可以通过PMD工具进行检测。类型体系之外的重复代码处理通常可以封装到对应的Util类或者Helper类中,类体系之内的重复代码通常可以通过继承、模板模式等方法来解决。复杂度:代码结构太复杂(如圈复杂度高),难以理解、测试和维护。监控与报警:基于产品的需求逻辑,需要有些指标来证明业务是正常work的,如果发生异常需要有监控、报警指标通知研发人员处理,review业务需求对应的监控与报警指标也是Code Review的重点事项。测试覆盖率:编写单元测试,特别是针对复杂代码的测试覆盖是否足够。实际上维护单元测试的成本不比开发成本低,这点团队目前做的的不到位。针对以上每次代码review所涉及到的经典案例会统一输出到文档里,大家可以共同学习避免编写出同样的Ugly Code。发布计划评审涉及到10人日以上的项目,必须有明确的发布计划,并组织项目成员统一参加项目发布计划review,发布计划主要包含如下几点:1)明确是否有外部依赖接口,如有请同步协调好业务方;2)发布前配置确认包括配置文件、数据库配置、中间件配置等各种配置,尤其各种环境下的差异化配置项;3)二方库发布顺序,是否有依赖;4)应用发布顺序;5)数据库是否有数据变更和订正,以及表结构调整;6)回滚计划,必须要有回滚计划,发布出现问题要有紧急回滚策略;7)生产环境回归测试重点Case。技术规划与管理我在带技术团队的这些年,对团队一直有一个要求,每周都要做系统健康度巡检,未雨绸缪、晴天修屋顶,避免在极端场景下某些隐藏的bug转变成了故障。系统健康度巡检为什么要把系统健康度巡检放到技术管理里,我觉得这是一个非常重要的环节。像传统的航空、电力、汽车行业都要有一定的巡检机制,保障设备系统正常运转,同样软件系统也同样需要巡检机制保障业务健康发展。随着业务的不断发展,业务量和数据量不断的上涨,系统架构的腐蚀是避免不了的,为了保障系统的健康度,需要不断的考虑对系统架构、性能进行优化。系统的监控与报警能够一定程度发现系统存在的问题,系统存在的一些隐患需要通过对系统的巡检去发现,如果优化不及时在极端情况会导致故障,巡检粒度建议每周巡检一次自己所负责的业务系统。系统巡检重点要关注如下几点:系统指标:系统CPU、负载、内存、网络、磁盘有无异常情况波动,确认是否由发布导致,还是系统调用异常。慢接口:通常rt大于3s的接口需要重点关注,极端并发场景下容易导致整个系统雪崩。慢查询:MYSQL慢查询需要重点关注,随着数据量上涨,需要对慢查询进行优化。错误日志:通过错误日志去发现系统隐藏的一些bug,避免这些bug被放大,甚至极端情况下会导致故障。技术规划技术规划通常由团队的TL负责,每个财年TL需要从大局的角度去思考每个季度的技术优化规划,去偿还技术债,技术债也是有利息的,因为利息的存在,技术债务不及时偿还的话,会在未来呈现出非线性增长,造成始料不及的损失。这里的技术规划包括如下几点:架构优化:一些结构不良、低内聚高耦合的代码则会使得哪怕是微小的需求变更或功能扩展都无从下手,修改的代价很可能超过了重写的代价。同样系统之间的耦合也需要重点去关注,遵循微服务化的原则,系统也要遵循单一职责原则,对于职责不清晰的系统去做解耦优化,进行一些模块化改造、服务隔离、公用服务抽象。性能优化:基于财年对于业务量、数据量的发展评估,根据目前系统服务的QPSRT,需要提前规划对系统性能进行一些升级策略,包括重点关注对一些慢接口、慢查询的优化。弹性与可靠性:系统提供的服务需要保障括数据一致性、幂等、防重攻击,同时也需要从熔断降级、异地多活的角度去考虑存在哪些问题,目前系统的SLA指标是否能够达到高可用,需要做哪些优化保障系统的高可用。可伸缩:应用服务是否保证无状态,关键节点发生故障能够快速转移、扩容,避免故障扩大化。总结大家不知道有没有类似的经历,某个时间段突然一些线上故障频发,各种技术债、业务债被业务方穷追猛打要求还债,如果出现这种现象很大程度这个TL已经失位了,这个团队失控了。也曾经有人跟我吐槽他的TL把活都分给他们,而TL自己什么都不干!这个技术TL真的什么都不干?曾经有一段时间我也在思考技术TL的核心职责到底是什么?技术TL应该具备哪些素质?首先技术说到底是为业务服务的,除非技术就是业务本身,必须体现它的商业价值。在很多公司里技术研发真的就成了实现其他部门需求的工具,我觉得这样的技术TL肯定是不合格的。首先它不能影响业务发展,需求提出方会经过很多转化,如果不是不假思索传递需求,整个过程会失真。第二个,我认为最最重要的是架构设计的能力,可能管理能力还次之。对于管理能力我认为最重要的是对团队的感知能力,因为一旦到了技术TL这个级别,不能脱离一线太远,业务细节可以不清楚,大的方向必须要明确。如果没有很细腻的感知能力,很多的决策会有偏差。如果他不是一个业务架构师,不是一个能给团队指明更好方向的人,他最终会沦为一个需求翻译器,产品经理说怎么做就怎么做。他更多的只是负责保证产品的质量、开发的速度,最终被肢解成一个很琐碎的人。一旦团队上了一定的规模,团队就会从单纯的需求实现走向团队运营,而运营是需要方向的,业务架构就是一个基于运营和数据的一种综合的能力。关于技术层面,技术TL需要具备如下素养:技术视野良好,解决问题能力与架构设计能力出色。技术TL要有良好的技术视野,不需要各种技术都样样精通,但是必须要所有涉猎,有所了解,对各种技术领域的发展趋势,主流非主流技术的应用场景要非常了解。知道在什么场景应用什么技术,业务发展到什么规模应该预先做哪些技术储备。产品架构的设计要有足够的弹性,既能够保证当前开发的高效率,又能够对未来产品架构的演进留出扩展的余地。动手能力要强,学习能力出色。技术TL并不需要自己亲自动手写代码,但是如有必要,自己可以随时动手参与第一线的编码工作,技术TL不能长期远离一线工作,自废武功,纸上谈兵。否则长此以往,会对技术的判断产生严重的失误。另外,技术TL也应该是一个学习能力非常出色的人,毕竟IT行业的技术更新换代速度非常快,如果没有快速学习能力,是没有资格做好技术TL的。技术TL除了管人和管事之外,其他还有很多事情要做包括建立团队研发文化、团队人才培养与建设、跨部门协调与沟通等,这样以要求技术TL也同时也需要具备良好的沟通和管理能力,以上观点仅是个人的一些思考和观点,仅供参考。本文作者:阿里技术 阅读原文本文来自云栖社区合作伙伴“ 阿里技术”,如需转载请联系原作者。 ...

February 28, 2019 · 1 min · jiezi

Android平台架构的介绍和源码下载

本篇文章为Android源码学习的第一章,主要讲述Android平台架构的分层,以及如何下载Android源码。Android平台架构介绍Android 是一种基于 Linux 的开放源代码软件栈,为广泛的设备和机型而创建。下图所示为 Android 平台的主要组件。从上图可以看出,Android系统大体可以分为6个层次,从下往上依次是:Linux内核层:Android 平台的基础是 Linux 内核。例如,Android Runtime (ART) 依靠 Linux 内核来执行底层功能,例如线程和低层内存管理。使用 Linux 内核可让 Android 利用主要安全功能,并且允许设备制造商为著名的内核开发硬件驱动程序。硬件抽象层 (HAL):硬件抽象层 (HAL) 提供标准界面,向更高级别的 Java API 框架显示设备硬件功能。HAL 包含多个库模块,其中每个模块都为特定类型的硬件组件实现一个界面,例如相机或蓝牙模块。当框架 API 要求访问设备硬件时,Android 系统将为该硬件组件加载库模块。Android Runtime:对于运行 Android 5.0(API 级别 21)或更高版本的设备,每个应用都在其自己的进程中运行,并且有其自己的 Android Runtime (ART) 实例。ART 编写为通过执行 DEX 文件在低内存设备上运行多个虚拟机,DEX 文件是一种专为 Android 设计的字节码格式,经过优化,使用的内存很少。编译工具链(例如 Jack)将 Java 源代码编译为 DEX 字节码,使其可在 Android 平台上运行。ART 的部分主要功能包括:预先 (AOT) 和即时 (JIT) 编译优化的垃圾回收 (GC)更好的调试支持,包括专用采样分析器、详细的诊断异常和崩溃报告,并且能够设置监视点以监控特定字段在 Android 版本 5.0(API 级别 21)之前,Dalvik 是 Android Runtime。如果您的应用在 ART 上运行效果很好,那么它应该也可在 Dalvik 上运行,但反过来不一定。Android 还包含一套核心运行时库,可提供 Java API 框架使用的 Java 编程语言大部分功能,包括一些 Java 8 语言功能。原生 C/C++ 库:许多核心 Android 系统组件和服务(例如 ART 和 HAL)构建自原生代码,需要以 C 和 C++ 编写的原生库。Android 平台提供 Java 框架 API 以向应用显示其中部分原生库的功能。例如,您可以通过 Android 框架的 Java OpenGL API 访问 OpenGL ES,以支持在应用中绘制和操作 2D 和 3D 图形。如果开发的是需要 C 或 C++ 代码的应用,可以使用 Android NDK 直接从原生代码访问某些原生平台库。Java API 框架:您可通过以 Java 语言编写的 API 使用 Android OS 的整个功能集。这些 API 形成创建 Android 应用所需的构建块,它们可简化核心模块化系统组件和服务的重复使用,包括以下组件和服务:丰富、可扩展的视图系统,可用以构建应用的 UI,包括列表、网格、文本框、按钮甚至可嵌入的网络浏览器资源管理器,用于访问非代码资源,例如本地化的字符串、图形和布局文件通知管理器,可让所有应用在状态栏中显示自定义提醒Activity 管理器,用于管理应用的生命周期,提供常见的导航返回栈内容提供程序,可让应用访问其他应用(例如“联系人”应用)中的数据或者共享其自己的数据开发者可以完全访问 Android 系统应用使用的框架 API。系统应用:Android 随附一套用于电子邮件、短信、日历、互联网浏览和联系人等的核心应用。平台随附的应用与用户可以选择安装的应用一样,没有特殊状态。因此第三方应用可成为用户的默认网络浏览器、短信 Messenger 甚至默认键盘(有一些例外,例如系统的“设置”应用)。系统应用可用作用户的应用,以及提供开发者可从其自己的应用访问的主要功能。例如,如果您的应用要发短信,您无需自己构建该功能,可以改为调用已安装的短信应用向您指定的接收者发送消息。从上图可以将Android平台划分为两层,一层是由C/C++编写的,可以称为Native层。另一层是由Java编写的,可以称为Framework层。这两层之间的联系是通过JNI进行连接。Android源码下载了解了Android平台架构之后,作为开发者学习源码,需要下载其源代码。在下载源代码之前,需要了解AOSP这个概念,AOSP是Android Open Source Project(Androi开源项目)的缩写,如果可以翻墙的话,可以按照AOSP官网 https://source.android.com/se… 这个地址上的步骤进行源码下载,如果不具备翻墙的条件,可以在清华大学开源软件镜像站 https://mirrors.tuna.tsinghua… 进行下载。步骤如下:安装 Repomkdir /binPATH=/bin:$PATHcurl https://storage.googleapis.com/git-repo-downloads/repo > ~/bin/repo## 如果上述 URL 不可访问,可以用下面的:## curl -sSL ‘https://gerrit-googlesource.proxy.ustclug.org/git-repo/+/master/repo?format=TEXT' |base64 -d > ~/bin/repochmod a+x ~/bin/repo建立工作目录mkdir WORKING_DIRECTORYcd WORKING_DIRECTORY初始化仓库repo init -u git://mirrors.ustc.edu.cn/aosp/platform/manifest## 如果提示无法连接到 gerrit.googlesource.com,可以编辑 ~/bin/repo,把 REPO_URL 一行替换成下面的:## REPO_URL = ‘https://gerrit-googlesource.proxy.ustclug.org/git-repo'## 如果需要某个特定的Android版本,则使用repo init -u git://mirrors.ustc.edu.cn/aosp/platform/manifest -b android-7.1.0_r1同步源码树(以后只需执行这条命令来同步)repo sync如果中间有网络断开的情况,则只需要执行repo sync继续同步即可。直到下载完Android源码。相关链接Android官方文档AOSP官网清华大学AOSP镜像地址中国科学技术大学开源软件镜像服务 ...

February 28, 2019 · 1 min · jiezi

【面试精选】关于大型网站系统架构你不得不懂的10个问题

该文已加入笔主的开源项目——JavaGuide(一份涵盖大部分Java程序员所需要掌握的核心知识的文档类项目),地址:https://github.com/Snailclimb/JavaGuide 。觉得不错的话,记得点个Star。下面这些问题都是一线大厂的真实面试问题,不论是对你面试还是说拓宽知识面都很有帮助。之前发过一篇8 张图读懂大型网站技术架构 可以作为不太了解大型网站系统技术架构朋友的入门文章。<!– MarkdownTOC –>1. 你使用过哪些组件或者方法来提升网站性能,可用性以及并发量2. 设计高可用系统的常用手段3. 现代互联网应用系统通常具有哪些特点?4. 谈谈你对微服务领域的了解和认识5. 谈谈你对 Dubbo 和 Spring Cloud 的认识(两者关系)6. 性能测试了解吗?说说你知道的性能测试工具?7. 对于一个单体应用系统,随着产品使用的用户越来越多,网站的流量会增加,最终单台服务器无法处理那么大的流量怎么办?8. 大表优化的常见手段9. 在系统中使用消息队列能带来什么好处?1) 通过异步处理提高系统性能2) 降低系统耦合性10. 说说自己对 CAP 定理,BASE 理论的了解CAP 定理BASE 理论参考<!– /MarkdownTOC –>1. 你使用过哪些组件或者方法来提升网站性能,可用性以及并发量提高硬件能力、增加系统服务器。(当服务器增加到某个程度的时候系统所能提供的并发访问量几乎不变,所以不能根本解决问题)使用缓存(本地缓存:本地可以使用JDK自带的 Map、Guava Cache.分布式缓存:Redis、Memcache.本地缓存不适用于提高系统并发量,一般是用处用在程序中。比如Spring是如何实现单例的呢?大家如果看过源码的话,应该知道,Spiring把已经初始过的变量放在一个Map中,下次再要使用这个变量的时候,先判断Map中有没有,这也就是系统中常见的单例模式的实现。)消息队列 (解耦+削峰+异步)采用分布式开发 (不同的服务部署在不同的机器节点上,并且一个服务也可以部署在多台机器上,然后利用 Nginx 负载均衡访问。这样就解决了单点部署(All In)的缺点,大大提高的系统并发量)数据库分库(读写分离)、分表(水平分表、垂直分表)采用集群 (多台机器提供相同的服务)CDN 加速 (将一些静态资源比如图片、视频等等缓存到离用户最近的网络节点)浏览器缓存使用合适的连接池(数据库连接池、线程池等等)适当使用多线程进行开发。2. 设计高可用系统的常用手段降级: 服务降级是当服务器压力剧增的情况下,根据当前业务情况及流量对一些服务和页面有策略的降级,以此释放服务器资源以保证核心任务的正常运行。降级往往会指定不同的级别,面临不同的异常等级执行不同的处理。根据服务方式:可以拒接服务,可以延迟服务,也有时候可以随机服务。根据服务范围:可以砍掉某个功能,也可以砍掉某些模块。总之服务降级需要根据不同的业务需求采用不同的降级策略。主要的目的就是服务虽然有损但是总比没有好;限流: 防止恶意请求流量、恶意攻击,或者防止流量超出系统峰值;缓存: 避免大量请求直接落到数据库,将数据库击垮;超时和重试机制: 避免请求堆积造成雪崩;回滚机制: 快速修复错误版本。3. 现代互联网应用系统通常具有哪些特点?高并发,大流量;高可用:系统7×24小时不间断服务;海量数据:需要存储、管理海量数据,需要使用大量服务器;用户分布广泛,网络情况复杂:许多大型互联网都是为全球用户提供服务的,用户分布范围广,各地网络情况千差万别;安全环境恶劣:由于互联网的开放性,使得互联网更容易受到攻击,大型网站几乎每天都会被黑客攻击;需求快速变更,发布频繁:和传统软件的版本发布频率不同,互联网产品为快速适应市场,满足用户需求,其产品发布频率是极高的;渐进式发展:与传统软件产品或企业应用系统一开始就规划好全部的功能和非功能需求不同,几乎所有的大型互联网网站都是从一个小网站开始,渐进地发展起来。4. 谈谈你对微服务领域的了解和认识现在大公司都在用并且未来的趋势都是 Spring Cloud,而阿里开源的 Spring Cloud Alibaba 也是 Spring Cloud 规范的实现 。我们通常把 Spring Cloud 理解为一系列开源组件的集合,但是 Spring Cloud并不是等同于 Spring Cloud Netflix 的 Ribbon、Feign、Eureka(停止更新)、Hystrix 这一套组件,而是抽象了一套通用的开发模式。它的目的是通过抽象出这套通用的模式,让开发者更快更好地开发业务。但是这套开发模式运行时的实际载体,还是依赖于 RPC、网关、服务发现、配置管理、限流熔断、分布式链路跟踪等组件的具体实现。Spring Cloud Alibaba 是官方认证的新一套 Spring Cloud 规范的实现,Spring Cloud Alibaba 是一套国产开源产品集合,后续还会有中文 reference 和一些原理分析文章,所以,这对于国内的开发者是非常棒的一件事。阿里的这一举动势必会推动国内微服务技术的发展,因为在没有 Spring Cloud Alibaba 之前,我们的第一选择是 Spring Cloud Netflix,但是它们的文档都是英文的,出问题后排查也比较困难, 在国内并不是有特别多的人精通。Spring Cloud Alibaba 由阿里开源组件和阿里云产品组件两部分组成,其致力于提供微服务一站式解决方案,方便开发者通过 Spring Cloud 编程模型轻松开发微服务应用。另外,Apache Dubbo Ecosystem 是围绕 Apache Dubbo 打造的微服务生态,是经过生产验证的微服务的最佳实践组合。在阿里巴巴的微服务解决方案中,Dubbo、Nacos 和 Sentinel,以及后续将开源的微服务组件,都是 Dubbo EcoSystem 的一部分。阿里后续也会将 Dubbo EcoSystem 集成到 Spring Cloud 的生态中。5. 谈谈你对 Dubbo 和 Spring Cloud 的认识(两者关系)具体可以看公众号-阿里巴巴中间件的这篇文章:独家解读:Dubbo Ecosystem - 从微服务框架到微服务生态Dubbo 与 Spring Cloud 并不是竞争关系,Dubbo 作为成熟的 RPC 框架,其易用性、扩展性和健壮性已得到业界的认可。未来 Dubbo 将会作为 Spring Cloud Alibaba 的 RPC 组件,并与 Spring Cloud 原生的 Feign 以及 RestTemplate 进行无缝整合,实现“零”成本迁移。在阿里巴巴的微服务解决方案中,Dubbo、Nacos 和 Sentinel,以及后续将开源的微服务组件,都是 Dubbo EcoSystem 的一部分。我们后续也会将 Dubbo EcoSystem 集成到 Spring Cloud 的生态中。6. 性能测试了解吗?说说你知道的性能测试工具?性能测试指通过自动化的测试工具模拟多种正常、峰值以及异常负载条件来对系统的各项性能指标进行测试。性能测试是总称,通常细分为:基准测试: 在给系统施加较低压力时,查看系统的运行状况并记录相关数做为基础参考负载测试:是指对系统不断地增加压力或增加一定压力下的持续时间,直到系统的某项或多项性能指标达到安全临界值,例如某种资源已经达到饱和状态等 。此时继续加压,系统处理能力会下降。压力测试: 超过安全负载情况下,不断施加压力(增加并发请求),直到系统崩溃或无法处理任何请求,依此获得系统最大压力承受能力。稳定性测试: 被测试系统在特定硬件、软件、网络环境下,加载一定业务压力(模拟生产环境不同时间点、不均匀请求,呈波浪特性)运行一段较长时间,以此检测系统是否稳定。后端程序员或者测试平常比较常用的测试工具是 JMeter(官网:https://jmeter.apache.org/)。Apache JMeter 是一款基于Java的压力测试工具(100%纯Java应用程序),旨在加载测试功能行为和测量性能。它最初被设计用于 Web 应用测试但后来扩展到其他测试领域。7. 对于一个单体应用系统,随着产品使用的用户越来越多,网站的流量会增加,最终单台服务器无法处理那么大的流量怎么办?这个时候就要考虑扩容了。《亿级流量网站架构核心技术》这本书上面介绍到我们可以考虑下面几步来解决这个问题:第一步,可以考虑简单的扩容来解决问题。比如增加系统的服务器,提高硬件能力等等。第二步,如果简单扩容搞不定,就需要水平拆分和垂直拆分数据/应用来提升系统的伸缩性,即通过扩容提升系统负载能力。第三步,如果通过水平拆分/垂直拆分还是搞不定,那就需要根据现有系统特性,架构层面进行重构甚至是重新设计,即推倒重来。对于系统设计,理想的情况下应支持线性扩容和弹性扩容,即在系统瓶颈时,只需要增加机器就可以解决系统瓶颈,如降低延迟提升吞吐量,从而实现扩容需求。如果你想扩容,则支持水平/垂直伸缩是前提。在进行拆分时,一定要清楚知道自己的目的是什么,拆分后带来的问题如何解决,拆分后如果没有得到任何收益就不要为了拆而拆,即不要过度拆分,要适合自己的业务。8. 大表优化的常见手段当MySQL单表记录数过大时,数据库的CRUD性能会明显下降,一些常见的优化措施如下:限定数据的范围: 务必禁止不带任何限制数据范围条件的查询语句。比如:我们当用户在查询订单历史的时候,我们可以控制在一个月的范围内。;读/写分离: 经典的数据库拆分方案,主库负责写,从库负责读;垂直分区: 根据数据库里面数据表的相关性进行拆分。 例如,用户表中既有用户的登录信息又有用户的基本信息,可以将用户表拆分成两个单独的表,甚至放到单独的库做分库。简单来说垂直拆分是指数据表列的拆分,把一张列比较多的表拆分为多张表。 如下图所示,这样来说大家应该就更容易理解了。垂直拆分的优点: 可以使得行数据变小,在查询时减少读取的Block数,减少I/O次数。此外,垂直分区可以简化表的结构,易于维护。垂直拆分的缺点: 主键会出现冗余,需要管理冗余列,并会引起Join操作,可以通过在应用层进行Join来解决。此外,垂直分区会让事务变得更加复杂;水平分区: 保持数据表结构不变,通过某种策略存储数据分片。这样每一片数据分散到不同的表或者库中,达到了分布式的目的。 水平拆分可以支撑非常大的数据量。 水平拆分是指数据表行的拆分,表的行数超过200万行时,就会变慢,这时可以把一张的表的数据拆成多张表来存放。举个例子:我们可以将用户信息表拆分成多个用户信息表,这样就可以避免单一表数据量过大对性能造成影响。水平拆分可以支持非常大的数据量。需要注意的一点是:分表仅仅是解决了单一表数据过大的问题,但由于表的数据还是在同一台机器上,其实对于提升MySQL并发能力没有什么意义,所以 水平拆分最好分库 。水平拆分能够 支持非常大的数据量存储,应用端改造也少,但 分片事务难以解决 ,跨界点Join性能较差,逻辑复杂。《Java工程师修炼之道》的作者推荐 尽量不要对数据进行分片,因为拆分会带来逻辑、部署、运维的各种复杂度 ,一般的数据表在优化得当的情况下支撑千万以下的数据量是没有太大问题的。如果实在要分片,尽量选择客户端分片架构,这样可以减少一次和中间件的网络I/O。下面补充一下数据库分片的两种常见方案:客户端代理: 分片逻辑在应用端,封装在jar包中,通过修改或者封装JDBC层来实现。 当当网的 Sharding-JDBC 、阿里的TDDL是两种比较常用的实现。中间件代理: 在应用和数据中间加了一个代理层。分片逻辑统一维护在中间件服务中。 我们现在谈的 Mycat 、360的Atlas、网易的DDB等等都是这种架构的实现。9. 在系统中使用消息队列能带来什么好处?《大型网站技术架构》第四章和第七章均有提到消息队列对应用性能及扩展性的提升。1) 通过异步处理提高系统性能如上图,在不使用消息队列服务器的时候,用户的请求数据直接写入数据库,在高并发的情况下数据库压力剧增,使得响应速度变慢。但是在使用消息队列之后,用户的请求数据发送给消息队列之后立即 返回,再由消息队列的消费者进程从消息队列中获取数据,异步写入数据库。由于消息队列服务器处理速度快于数据库(消息队列也比数据库有更好的伸缩性),因此响应速度得到大幅改善。通过以上分析我们可以得出消息队列具有很好的削峰作用的功能——即通过异步处理,将短时间高并发产生的事务消息存储在消息队列中,从而削平高峰期的并发事务。 举例:在电子商务一些秒杀、促销活动中,合理使用消息队列可以有效抵御促销活动刚开始大量订单涌入对系统的冲击。如下图所示:因为用户请求数据写入消息队列之后就立即返回给用户了,但是请求数据在后续的业务校验、写数据库等操作中可能失败。因此使用消息队列进行异步处理之后,需要适当修改业务流程进行配合,比如用户在提交订单之后,订单数据写入消息队列,不能立即返回用户订单提交成功,需要在消息队列的订单消费者进程真正处理完该订单之后,甚至出库后,再通过电子邮件或短信通知用户订单成功,以免交易纠纷。这就类似我们平时手机订火车票和电影票。2) 降低系统耦合性我们知道模块分布式部署以后聚合方式通常有两种:1.分布式消息队列和2.分布式服务。先来简单说一下分布式服务:目前使用比较多的用来构建SOA(Service Oriented Architecture面向服务体系结构)的分布式服务框架是阿里巴巴开源的Dubbo.如果想深入了解Dubbo的可以看我写的关于Dubbo的这一篇文章:《高性能优秀的服务框架-dubbo介绍》:https://juejin.im/post/5acadeb1f265da2375072f9c再来谈我们的分布式消息队列:我们知道如果模块之间不存在直接调用,那么新增模块或者修改模块就对其他模块影响较小,这样系统的可扩展性无疑更好一些。我们最常见的事件驱动架构类似生产者消费者模式,在大型网站中通常用利用消息队列实现事件驱动结构。如下图所示:消息队列使利用发布-订阅模式工作,消息发送者(生产者)发布消息,一个或多个消息接受者(消费者)订阅消息。 从上图可以看到消息发送者(生产者)和消息接受者(消费者)之间没有直接耦合,消息发送者将消息发送至分布式消息队列即结束对消息的处理,消息接受者从分布式消息队列获取该消息后进行后续处理,并不需要知道该消息从何而来。对新增业务,只要对该类消息感兴趣,即可订阅该消息,对原有系统和业务没有任何影响,从而实现网站业务的可扩展性设计。消息接受者对消息进行过滤、处理、包装后,构造成一个新的消息类型,将消息继续发送出去,等待其他消息接受者订阅该消息。因此基于事件(消息对象)驱动的业务架构可以是一系列流程。另外为了避免消息队列服务器宕机造成消息丢失,会将成功发送到消息队列的消息存储在消息生产者服务器上,等消息真正被消费者服务器处理后才删除消息。在消息队列服务器宕机后,生产者服务器会选择分布式消息队列服务器集群中的其他服务器发布消息。 备注: 不要认为消息队列只能利用发布-订阅模式工作,只不过在解耦这个特定业务环境下是使用发布-订阅模式的,比如在我们的ActiveMQ消息队列中还有点对点工作模式,具体的会在后面的文章给大家详细介绍,这一篇文章主要还是让大家对消息队列有一个更透彻的了解。这个问题一般会在上一个问题问完之后,紧接着被问到。“使用消息队列会带来什么问题?”这个问题要引起重视,一般我们都会考虑使用消息队列会带来的好处而忽略它带来的问题!10. 说说自己对 CAP 定理,BASE 理论的了解CAP 定理在理论计算机科学中,CAP定理(CAP theorem),又被称作布鲁尔定理(Brewer’s theorem),它指出对于一个分布式计算系统来说,不可能同时满足以下三点:一致性(Consistence) :所有节点访问同一份最新的数据副本可用性(Availability):每次请求都能获取到非错的响应——但是不保证获取的数据为最新数据分区容错性(Partition tolerance) : 分布式系统在遇到某节点或网络分区故障的时候,仍然能够对外提供满足一致性和可用性的服务。CAP仅适用于原子读写的NOSQL场景中,并不适合数据库系统。现在的分布式系统具有更多特性比如扩展性、可用性等等,在进行系统设计和开发时,我们不应该仅仅局限在CAP问题上。注意:不是所谓的3选2(不要被网上大多数文章误导了):大部分人解释这一定律时,常常简单的表述为:“一致性、可用性、分区容忍性三者你只能同时达到其中两个,不可能同时达到”。实际上这是一个非常具有误导性质的说法,而且在CAP理论诞生12年之后,CAP之父也在2012年重写了之前的论文。当发生网络分区的时候,如果我们要继续服务,那么强一致性和可用性只能2选1。也就是说当网络分区之后P是前提,决定了P之后才有C和A的选择。也就是说分区容错性(Partition tolerance)我们是必须要实现的。我在网上找了很多文章想看一下有没有文章提到这个不是所谓的3选2,用百度半天没找到了一篇,用谷歌搜索找到一篇比较不错的,如果想深入学习一下CAP就看这篇文章把,我这里就不多BB了:《分布式系统之CAP理论》 : http://www.cnblogs.com/hxsyl/p/4381980.htmlBASE 理论BASE 是 Basically Available(基本可用) 、Soft-state(软状态) 和 Eventually Consistent(最终一致性) 三个短语的缩写。BASE理论是对CAP中一致性和可用性权衡的结果,其来源于对大规模互联网系统分布式实践的总结,是基于CAP定理逐步演化而来的,它大大降低了我们对系统的要求。BASE理论的核心思想: 即使无法做到强一致性,但每个应用都可以根据自身业务特点,采用适当的方式来使系统达到最终一致性。也就是牺牲数据的一致性来满足系统的高可用性,系统中一部分数据不可用或者不一致时,仍需要保持系统整体“主要可用”。BASE理论三要素:基本可用: 基本可用是指分布式系统在出现不可预知故障的时候,允许损失部分可用性。但是,这绝不等价于系统不可用。 比如: ①响应时间上的损失:正常情况下,一个在线搜索引擎需要在0.5秒之内返回给用户相应的查询结果,但由于出现故障,查询结果的响应时间增加了1~2秒;②系统功能上的损失:正常情况下,在一个电子商务网站上进行购物的时候,消费者几乎能够顺利完成每一笔订单,但是在一些节日大促购物高峰的时候,由于消费者的购物行为激增,为了保护购物系统的稳定性,部分消费者可能会被引导到一个降级页面;软状态: 软状态指允许系统中的数据存在中间状态,并认为该中间状态的存在不会影响系统的整体可用性,即允许系统在不同节点的数据副本之间进行数据同步的过程存在延时;最终一致性: 最终一致性强调的是系统中所有的数据副本,在经过一段时间的同步后,最终能够达到一个一致的状态。因此,最终一致性的本质是需要系统保证最终数据能够达到一致,而不需要实时保证系统数据的强一致性。参考《大型网站技术架构》《亿级流量网站架构核心技术》《Java工程师修炼之道》https://www.cnblogs.com/pures…专注Java知识和面试技能分享!我已经整理好了一份Java 学习必备的书籍+视频+文档汇总,内容比较多,你可以在公众号后台回复关键“1”,我会免费无套路把这些都给你。 ...

February 27, 2019 · 2 min · jiezi

使用Netty,我们到底在开发些什么?

在java界,netty无疑是开发网络应用的拿手菜。你不需要太多关注复杂的nio模型和底层网络的细节,使用其丰富的接口,可以很容易的实现复杂的通讯功能。和golang的网络模块相比,netty还是太过臃肿。不过java类框架就是这样,属于那种离了IDE就无法存活的编码语言。最新的netty版本将模块分的非常细,如果不清楚每个模块都有什么内容,直接使用netty-all即可。单纯从使用方面来说,netty是非常简单的,掌握ByteBuf、Channel、Pipeline、Event模型等,就可以进行开发了。你会发现面试netty相关知识,没得聊。但Netty与其他开发模式很大不同,最主要的就是其异步化。异步化造成的后果就是编程模型的不同,同时有调试上的困难,对编码的要求比较高,因为bug的代价与业务代码的bug代价不可同日而语。但从项目来说,麻雀虽小五脏俱全,从业务层到服务网关,以及各种技术保障,包括监控和配置,都是需要考虑的因素。netty本身占比很小。本文将说明使用netty开发,都关注哪些通用的内容,然后附上单机支持100w连接的linux配置。本文并不关注netty的基础知识。协议开发网络开发中最重要的就是其通讯格式,协议。我们常见的protobuf、json、avro、mqtt等,都属于此列。协议有语法、语义、时序三个要素。我见过很多中间件应用,采用的是redis协议,而后端落地的却是mysql;也见过更多的采用mysql协议实现的各种自定义存储系统,比如proxy端的分库分表中间件、tidb等。我们常用的redis,使用的是文本协议;mysql等实现的是二进制协议。放在netty中也是一样,实现一套codec即可(继承Decoder或Encoder系列)。netty默认实现了dns、haproxy、http、http2、memcache、mqtt、redis、smtp、socks、stomp、xml等协议,可以说是很全了,直接拿来用很爽。一个可能的产品结构会是这样的,对外提供一致的外观,核心存储却不同:文本协议在调试起来是比较直观和容易的,但安全性欠佳;而二进制协议就需要依赖日志、wireshark等其他方式进行分析,增加了开发难度。传说中的粘包拆包,就在这里处理。而造成粘包的原因,主要是由于缓冲区的介入,所以需要约定双方的传输概要等信息,netty在一定程度上解决了这个问题。每一个想要开发网络应用的同学,心里都埋了一颗重新设计协议的梦想种子。但协议的设计可以说是非常困难了,要深耕相应业务,还要考虑其扩展性。如没有特别的必要,建议使用现有的协议。连接管理功能做Netty开发,连接管理功能是非常重要的。通信质量、系统状态,以及一些黑科技功能,都是依赖连接管理功能。无论是作为服务端还是客户端,netty在创建连接之后,都会得到一个叫做Channel的对象。我们所要做的,就是对它的管理,我习惯给它起名叫做ConnectionManager。管理类会通过缓存一些内存对象,用来统计运行中的数据。比如面向连接的功能:包发送、接收数量;包发送、接收速率;错误计数;连接重连次数;调用延迟;连接状态等。这会频繁用到java中concurrent包的相关类,往往也是bug集中地。但我们还需要更多,管理类会给予每个连接更多的功能。比如,连接创建后,想要预热一些功能,那这些状态就可以参与路由的决策。通常情况下,将用户或其他元信息也attach到连接上,能够多维度的根据条件筛选一些连接,进行批量操作,比如灰度、过载保护等,是一个非常重要的功能。管理后台可以看到每个连接的信息,筛选到一个或多个连接后,能够开启对这些连接的流量录制、信息监控、断点调试,你能体验到掌控一切的感觉。管理功能还能够看到系统的整个运行状态,及时调整负载均衡策略;同时对扩容、缩容提供数据依据。心跳检测应用协议层的心跳是必须的,它和tcp keepalive是完全不同的概念。应用层协议层的心跳检测的是连接双方的存活性,兼而连接质量,而keepalive检测的是连接本身的存活性。而且后者的超时时间默认过长,完全不能适应现代的网络环境。心跳就是靠轮训,无论是服务端,还是客户端比如GCM等。保活机制会在不同的应用场景进行动态的切换,比如程序唤起和在后台,轮训的策略是不一样的。Netty内置通过增加IdleStateHandler产生IDLE事件进行便捷的心跳控制。你要处理的,就是心跳超时的逻辑,比如延迟重连。但它的轮训时间是固定的,无法动态修改,高级功能需要自己定制。在一些客户端比如Android,频繁心跳的唤起会浪费大量的网络和电量,它的心跳策略会更加复杂一些。边界优雅退出机制Java的优雅停机通常通过注册JDK ShutdownHook来实现。Runtime.getRuntime().addShutdownHook();一般通过kill -15进行java进程的关闭,以便在进程死亡之前进行一些清理工作。注意:kill -9 会立马杀死进程,不给遗言的机会,比较危险。虽然netty做了很多优雅退出的工作,通过EventLoopGroup的shutdownGracefully方法对nio进行了一些状态设置,但在很多情况下,这还不够多。它只负责单机环境的优雅关闭。流量可能还会通过外层的路由持续进入,造成无效请求。我的通常做法是首先在外层路由进行一次本地实例的摘除,把流量截断,然后再进行netty本身的优雅关闭。这种设计非常简单,即使没有重试机制也会运行的很好,前提是在路由层需要提前暴露相关接口。异常处理功能netty由于其异步化的开发方式,以及其事件机制,在异常处理方面就显得异常重要。为了保证连接的高可靠性,许多异常需要静悄悄的忽略,或者在用户态没有感知。netty的异常会通过pipeline进行传播,所以在任何一层进行处理都是可行的,但编程习惯上,习惯性抛到最外层集中处理。为了最大限度的区别异常信息,通常会定义大量的异常类,不同的错误会抛出不同的异常。发生异常后,可以根据不同的类型选择断线重连(比如一些二进制协议的编解码紊乱问题),或者调度到其他节点。功能限制指令模式网络应用就该干网络应用的事,任何通讯都是昂贵的。在《Linux之《荒岛余生》(五)网络篇》中,我们谈到百万连接的服务器,广播一个1kb消息,就需要1000M的带宽,所以并不是什么都可以放在网络应用里的。 一个大型网络应用的合理的思路就是值发送相关指令。客户端在收到指令以后,通过其他方式,比如http,进行大型文件到获取。很多IM的设计思路就是如此。指令模式还会让通讯系统的扩展性和稳定性得到保证。增加指令可以是配置式的,立即生效,服务端不需要编码重启。稳定性保证网络应用的流量一般都是非常大的,并不适合全量日志的开启。应用应该只关注主要事件的日志,关注异常情况下的处理流程,日志要打印有度。网络应用也不适合调用其他缓慢的api,或者任何阻塞I/O的接口。一些实时的事件,也不应该通过调用接口吐出数据,可以走高速mq等其他异步通道。缓存可能是网络应用里用的最多的组件。jvm内缓存可以存储一些单机的统计数据,redis等存储一些全局性的统计和中间态数据。网络应用中会大量使用redis、kv、高吞吐的mq,用来快速响应用户请求。总之,尽量保持通讯层的清爽,你会省去很多忧虑。单机支持100万连接的Linux配置单机支持100万连接是可行的,但带宽问题会成为显著的瓶颈。启用压缩的二进制协议会节省部分带宽,但开发难度增加。和《LWP进程资源耗尽,Resource temporarily unavailable》中提到的ES配置一样,优化都有类似的思路。这份配置,可以节省你几天的时间,请收下!操作系统优化更改进程最大文件句柄数ulimit -n 1048576修改单个进程可分配的最大文件数echo 2097152 > /proc/sys/fs/nr_open修改/etc/security/limits.conf文件* soft nofile 1048576* hard nofile 1048576* soft nproc unlimitedroot soft nproc unlimited记得清理掉/etc/security/limits.d/*下的配置网络优化打开/etc/sysctl.conf,添加配置然后执行,使用sysctl生效#单个进程可分配的最大文件数fs.nr_open=2097152#系统最大文件句柄数fs.file-max = 1048576#backlog 设置net.core.somaxconn=32768net.ipv4.tcp_max_syn_backlog=16384net.core.netdev_max_backlog=16384#可用知名端口范围配置net.ipv4.ip_local_port_range=‘1000 65535’#TCP Socket 读写 Buffer 设置net.core.rmem_default=262144net.core.wmem_default=262144net.core.rmem_max=16777216net.core.wmem_max=16777216net.core.optmem_max=16777216net.ipv4.tcp_rmem=‘1024 4096 16777216’net.ipv4.tcp_wmem=‘1024 4096 16777216’#TCP 连接追踪设置net.nf_conntrack_max=1000000net.netfilter.nf_conntrack_max=1000000net.netfilter.nf_conntrack_tcp_timeout_time_wait=30#TIME-WAIT Socket 最大数量、回收与重用设置net.ipv4.tcp_max_tw_buckets=1048576# FIN-WAIT-2 Socket 超时设置net.ipv4.tcp_fin_timeout = 15总结netty的开发工作并不集中在netty本身,更多体现在保证服务的高可靠性和稳定性上。同时有大量的工作集中在监控和调试,减少bug修复的成本。深入了解netty是在系统遇到疑难问题时能够深入挖掘进行排查,或者对苛刻的性能进行提升。但对于广大应用开发者来说,netty的上手成本小,死挖底层并不会产生太多收益。它只是个工具,你还能让它怎样啊。0.jpeg

February 27, 2019 · 1 min · jiezi

Spark in action on Kubernetes - Playground搭建与架构浅析

前言Spark是非常流行的大数据处理引擎,数据科学家们使用Spark以及相关生态的大数据套件完成了大量又丰富场景的数据分析与挖掘。Spark目前已经逐渐成为了业界在数据处理领域的行业标准。但是Spark本身的设计更偏向使用静态的资源管理,虽然Spark也支持了类似Yarn等动态的资源管理器,但是这些资源管理并不是面向动态的云基础设施而设计的,在速度、成本、效率等领域缺乏解决方案。随着Kubernetes的快速发展,数据科学家们开始考虑是否可以用Kubernetes的弹性与面向云原生等特点与Spark进行结合。在Spark 2.3中,Resource Manager中添加了Kubernetes原生的支持,而本系列我们会给大家介绍如何用更Kubernetes的方式在集群中使用Spark进行数据分析。本系列不需要开发者有丰富的Spark使用经验,对着系列的逐渐深入,会穿插讲解使用到的Spark特性。搭建Playground很多的开发者在接触Hadoop的时候,被安装流程的复杂度打消了很多的积极性。为了降低学习的门槛,本系列会通过spark-on-k8s-operator作为Playground,简化大家的安装流程。spark-on-k8s-operator顾名思义是为了简化Spark操作而开发的operator,如果对operator不是很了解的开发者,可以先自行搜索了解下,理解operator能做什么可以快速帮你掌握spark-on-k8s-operator的要领。在讲解内部原理前,我们先将环境搭建起来,通过一个简单的demo,跑通整个的运行时环境。1. 安装spark-on-k8s-operator官方的文档是通过Helm Chart进行安装的,由于很多开发者的环境无法连通google的repo,因此此处我们通过标准的yaml进行安装。## 下载repogit clone git@github.com:AliyunContainerService/spark-on-k8s-operator.git## 安装crdkubectl apply -f manifest/spark-operator-crds.yaml ## 安装operator的服务账号与授权策略kubectl apply -f manifest/spark-operator-rbac.yaml ## 安装spark任务的服务账号与授权策略kubectl apply -f manifest/spark-rbac.yaml ## 安装spark-on-k8s-operator kubectl apply -f manifest/spark-operator.yaml 验证安装结果此时在spark-operator的命名空间下的无状态应用下,可以看到一个运行中的sparkoperator,表名此时组件已经安装成功,接下来我们运行一个demo应用来验证组件是否可以正常工作。2. Demo验证学习Spark的时候,我们运行的第一个任务是官方文档中介绍的圆周率运行的例子。今天我们换一种方式,通过Kubernetes的方式再运行一次。## 下发spark-pi任务kubectl apply -f examples/spark-pi.yaml 任务下发成功后,可以通过命令行观察任务的状态。## 查询任务kubectl describe sparkapplication spark-pi## 任务结果 Name: spark-piNamespace: defaultLabels: <none>Annotations: kubectl.kubernetes.io/last-applied-configuration: {“apiVersion”:“sparkoperator.k8s.io/v1alpha1”,“kind”:“SparkApplication”,“metadata”:{“annotations”:{},“name”:“spark-pi”,“namespace”:“defaul…API Version: sparkoperator.k8s.io/v1alpha1Kind: SparkApplicationMetadata: Creation Timestamp: 2019-01-20T10:47:08Z Generation: 1 Resource Version: 4923532 Self Link: /apis/sparkoperator.k8s.io/v1alpha1/namespaces/default/sparkapplications/spark-pi UID: bbe7445c-1ca0-11e9-9ad4-062fd7c19a7bSpec: Deps: Driver: Core Limit: 200m Cores: 0.1 Labels: Version: 2.4.0 Memory: 512m Service Account: spark Volume Mounts: Mount Path: /tmp Name: test-volume Executor: Cores: 1 Instances: 1 Labels: Version: 2.4.0 Memory: 512m Volume Mounts: Mount Path: /tmp Name: test-volume Image: gcr.io/spark-operator/spark:v2.4.0 Image Pull Policy: Always Main Application File: local:///opt/spark/examples/jars/spark-examples_2.11-2.4.0.jar Main Class: org.apache.spark.examples.SparkPi Mode: cluster Restart Policy: Type: Never Type: Scala Volumes: Host Path: Path: /tmp Type: Directory Name: test-volumeStatus: Application State: Error Message: State: COMPLETED Driver Info: Pod Name: spark-pi-driver Web UI Port: 31182 Web UI Service Name: spark-pi-ui-svc Execution Attempts: 1 Executor State: Spark - Pi - 1547981232122 - Exec - 1: COMPLETED Last Submission Attempt Time: 2019-01-20T10:47:14Z Spark Application Id: spark-application-1547981285779 Submission Attempts: 1 Termination Time: 2019-01-20T10:48:56ZEvents: Type Reason Age From Message —- —— —- —- ——- Normal SparkApplicationAdded 55m spark-operator SparkApplication spark-pi was added, Enqueuing it for submission Normal SparkApplicationSubmitted 55m spark-operator SparkApplication spark-pi was submitted successfully Normal SparkDriverPending 55m (x2 over 55m) spark-operator Driver spark-pi-driver is pending Normal SparkExecutorPending 54m (x3 over 54m) spark-operator Executor spark-pi-1547981232122-exec-1 is pending Normal SparkExecutorRunning 53m (x4 over 54m) spark-operator Executor spark-pi-1547981232122-exec-1 is running Normal SparkDriverRunning 53m (x12 over 55m) spark-operator Driver spark-pi-driver is running Normal SparkExecutorCompleted 53m (x2 over 53m) spark-operator Executor spark-pi-1547981232122-exec-1 completed此时我们发现任务已经执行成功,查看这个Pod的日志,我们可以到计算最终的结果为Pi is roughly 3.1470557352786765。至此,在Kubernetes上,已经跑通了第一个Job,接下来我们要来详解一下刚才这一波操作到底都做了些什么。Spark Operator的基础架构浅析这张图是Spark Operator的流程图,在上面的操作中,第一个步骤里面,实际上是将图中的中心位置蓝色的Spark Operator安装到集群中,Spark Opeartor本身即是是一个CRD的Controller也是一个Mutating Admission Webhook的Controller。当我们下发spark-pi模板的时候,会转换为一个名叫SparkApplication的CRD对象,然后Spark Operator会监听Apiserver,并将SparkApplication对象进行解析,变成spark-submit的命令并进行提交,提交后会生成Driver Pod,用简单的方式理解,Driver Pod就是一个封装了Spark Jar的镜像。如果是本地任务,就直接在Driver Pod中执行;如果是集群任务,就会通过Driver Pod再生成Exector Pod进行执行。当任务结束后,可以通过Driver Pod进行运行日志的查看。此外在任务的执行中,Spark Operator还会动态attach一个Spark UI到Driver Pod上,希望查看任务状态的开发者,可以通过这个UI页面进行任务状态的查看。最后在本文中,我们讨论了Spark Operator的设计初衷,如何快速搭建一个Spark Operator的Playground以及Spark Operator的基本架构与流程。在下一篇文章中,我们会深入到Spark Operator的内部,为大家讲解其内部的实现原理以及如何与Spark更无缝的集成。本文作者:莫源 阅读原文本文为云栖社区原创内容,未经允许不得转载。 ...

February 26, 2019 · 2 min · jiezi

微服务架构下,解决数据一致性问题的实践

随着业务的快速发展,应用单体架构暴露出代码可维护性差、容错率低、测试难度大和敏捷交付能力差等诸多问题,微服务应运而生。微服务的诞生一方面解决了上述问题,但是另一方面却引入新的问题,其中主要问题之一就是:如何保证微服务间的业务数据一致性。本文将通过一个商品采购的业务,来看看在Dubbo的微服务架构下,如何通过Fescar来保障业务的数据一致性。本文所述的例子中,Dubbo 和 Fescar 的注册配置服务中心均使用 Nacos。Fescar 0.2.1+ 开始支持 Nacos 注册配置服务中心。业务描述用户采购商品的业务,包含3个微服务:库存服务: 扣减给定商品的库存数量。订单服务: 根据采购请求生成订单。账户服务: 用户账户金额扣减。业务结构图如下:库存服务(StorageService)public interface StorageService { /** * deduct storage count / void deduct(String commodityCode, int count);}订单服务(OrderService)public interface OrderService { /* * create order / Order create(String userId, String commodityCode, int orderCount);}账户服务(AccountService)public interface AccountService { /* * debit balance of user’s account */ void debit(String userId, int money);}说明: 以上三个微服务均是独立部署。8个步骤实现数据一致性Step 1:初始化 MySQL 数据库(需要InnoDB 存储引擎)在 resources/jdbc.properties 修改StorageService、OrderService、AccountService 对应的连接信息。jdbc.account.url=jdbc:mysql://xxxx/xxxxjdbc.account.username=xxxxjdbc.account.password=xxxxjdbc.account.driver=com.mysql.jdbc.Driver# storage db configjdbc.storage.url=jdbc:mysql://xxxx/xxxxjdbc.storage.username=xxxxjdbc.storage.password=xxxxjdbc.storage.driver=com.mysql.jdbc.Driver# order db configjdbc.order.url=jdbc:mysql://xxxx/xxxxjdbc.order.username=xxxxjdbc.order.password=xxxxjdbc.order.driver=com.mysql.jdbc.DriverStep 2:创建 undo_log(用于Fescar AT 模式)表和相关业务表相关建表脚本可在 resources/sql/ 下获取,在相应数据库中执行 dubbo_biz.sql 中的业务建表脚本,在每个数据库执行 undo_log.sql 建表脚本。CREATE TABLE undo_log ( id bigint(20) NOT NULL AUTO_INCREMENT, branch_id bigint(20) NOT NULL, xid varchar(100) NOT NULL, rollback_info longblob NOT NULL, log_status int(11) NOT NULL, log_created datetime NOT NULL, log_modified datetime NOT NULL, ext varchar(100) DEFAULT NULL, PRIMARY KEY (id), KEY idx_unionkey (xid,branch_id)) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;DROP TABLE IF EXISTS storage_tbl;CREATE TABLE storage_tbl ( id int(11) NOT NULL AUTO_INCREMENT, commodity_code varchar(255) DEFAULT NULL, count int(11) DEFAULT 0, PRIMARY KEY (id), UNIQUE KEY (commodity_code)) ENGINE=InnoDB DEFAULT CHARSET=utf8;DROP TABLE IF EXISTS order_tbl;CREATE TABLE order_tbl ( id int(11) NOT NULL AUTO_INCREMENT, user_id varchar(255) DEFAULT NULL, commodity_code varchar(255) DEFAULT NULL, count int(11) DEFAULT 0, money int(11) DEFAULT 0, PRIMARY KEY (id)) ENGINE=InnoDB DEFAULT CHARSET=utf8;DROP TABLE IF EXISTS account_tbl;CREATE TABLE account_tbl ( id int(11) NOT NULL AUTO_INCREMENT, user_id varchar(255) DEFAULT NULL, money int(11) DEFAULT 0, PRIMARY KEY (id)) ENGINE=InnoDB DEFAULT CHARSET=utf8;说明: 需要保证每个物理库都包含 undo_log 表,此处可使用一个物理库来表示上述三个微服务对应的独立逻辑库。Step 3:引入 Fescar、Dubbo 和 Nacos 相关 POM 依赖 <properties> <fescar.version>0.2.1</fescar.version> <dubbo.alibaba.version>2.6.5</dubbo.alibaba.version> <dubbo.registry.nacos.version>0.0.2</dubbo.registry.nacos.version> </properties> <dependency> <groupId>com.alibaba.fescar</groupId> <artifactId>fescar-spring</artifactId> <version>${fescar.version}</version> </dependency> <dependency> <groupId>com.alibaba.fescar</groupId> <artifactId>fescar-dubbo-alibaba</artifactId> <version>${fescar.version}</version> <exclusions> <exclusion> <artifactId>dubbo</artifactId> <groupId>org.apache.dubbo</groupId> </exclusion> </exclusions> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>dubbo</artifactId> <version>${dubbo.alibaba.version}</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>dubbo-registry-nacos</artifactId> <version>${dubbo.registry.nacos.version}</version> </dependency>说明: 由于当前 apache-dubbo 与 dubbo-registry-nacos jar存在兼容性问题,需要排除 fescar-dubbo 中的 apache.dubbo 依赖并手动引入 alibaba-dubbo,后续 apache-dubbo(2.7.1+) 将兼容 dubbo-registry-nacos。在Fescar 中 fescar-dubbo jar 支持 apache.dubbo,fescar-dubbo-alibaba jar 支持 alibaba-dubbo。Step 4:微服务 Provider Spring配置分别在三个微服务Spring配置文件(dubbo-account-service.xml、 dubbo-order-service 和 dubbo-storage-service.xml )进行如下配置:配置 Fescar 代理数据源<bean id=“accountDataSourceProxy” class=“com.alibaba.fescar.rm.datasource.DataSourceProxy”> <constructor-arg ref=“accountDataSource”/></bean><bean id=“jdbcTemplate” class=“org.springframework.jdbc.core.JdbcTemplate”> <property name=“dataSource” ref=“accountDataSourceProxy”/></bean>此处需要使用 com.alibaba.fescar.rm.datasource.DataSourceProxy 包装 Druid 数据源作为直接业务数据源,DataSourceProxy 用于业务 SQL 的拦截解析并与 TC 交互协调事务操作状态。配置 Dubbo 注册中心 <dubbo:registry address=“nacos://${nacos-server-ip}:8848”/>配置 Fescar GlobalTransactionScanner<bean class=“com.alibaba.fescar.spring.annotation.GlobalTransactionScanner”> <constructor-arg value=“dubbo-demo-account-service”/> <constructor-arg value=“my_test_tx_group”/></bean>此处构造方法的第一个参数为业务自定义 applicationId,若在单机部署多微服务需要保证 applicationId 唯一。构造方法的第二个参数为 Fescar 事务服务逻辑分组,此分组通过配置中心配置项 service.vgroup_mapping.my_test_tx_group 映射到相应的 Fescar-Server 集群名称,然后再根据集群名称.grouplist 获取到可用服务列表。Step 5:事务发起方配置在 dubbo-business.xml 配置以下配置:配置 Dubbo 注册中心同 Step 4配置 Fescar GlobalTransactionScanner同 Step 4在事务发起方 service 方法上添加 @GlobalTransactional 注解@GlobalTransactional(timeoutMills = 300000, name = “dubbo-demo-tx”)timeoutMills 为事务的总体超时时间默认60s,name 为事务方法签名的别名,默认为空。注解内参数均可省略。Step 6:启动 Nacos-Server下载 Nacos-Server 最新 release 包并解压运行 Nacos-serverLinux/Unix/Macsh startup.sh -m standaloneWindowscmd startup.cmd -m standalone访问 Nacos 控制台:http://localhost:8848/nacos/index.html#/configurationManagement?dataId=&group=&appName=&namespace若访问成功说明 Nacos-Server 服务运行成功(默认账号/密码: nacos/nacos)Step 7:启动 Fescar-Server下载 Fescar-Server 最新 release 包并解压初始化 Fescar 配置进入到 Fescar-Server 解压目录 conf 文件夹下,确认 nacos-config.txt 的配置值(一般不需要修改),确认完成后运行 nacos-config.sh 脚本初始化配置。sh nacos-config.sh $Nacos-Server-IPeg:sh nacos-config.sh localhost 脚本执行最后输出 “init nacos config finished, please start fescar-server.” 说明推送配置成功。若想进一步确认可登陆Nacos 控制台 配置列表 筛选 Group=FESCAR_GROUP 的配置项。修改 Fescar-server 服务注册方式为 nacos进入到 Fescar-Server 解压目录 conf 文件夹下 registry.conf 修改 type=“nacos” 并配置 Nacos 的相关属性。 registry { # file nacos type = “nacos” nacos { serverAddr = “localhost” namespace = “public” cluster = “default” } file { name = “file.conf” }}type: 可配置为 nacos 和 file,配置为 file 时无服务注册功能nacos.serverAddr: Nacos-Sever 服务地址(不含端口号)nacos.namespace: Nacos 注册和配置隔离 namespacenacos.cluster: 注册服务的集群名称file.name: type = “file” classpath 下配置文件名运行 Fescar-serverLinux/Unix/Macsh fescar-server.sh $LISTEN_PORT $PATH_FOR_PERSISTENT_DATA $IP(此参数可选)Windowscmd fescar-server.bat $LISTEN_PORT $PATH_FOR_PERSISTENT_DATA $IP(此参数可选)服务端口 PATH_FOR_PERSISTENT_DATA: 事务操作记录文件存储路径(已存在路径)$IP(可选参数): 用于多 IP 环境下指定 Fescar-Server 注册服务的IPeg: sh fescar-server.sh 8091 /home/admin/fescar/data/运行成功后可在 Nacos 控制台看到 服务名 =serverAddr 服务注册列表:Step 8:启动微服务并测试修改业务客户端发现注册方式为 nacos同Step 7 中[修改 Fescar-server 服务注册方式为 nacos] 步骤启动 DubboAccountServiceStarter启动 DubboOrderServiceStarter启动 DubboStorageServiceStarter启动完成可在 Nacos 控制台服务列表 看到启动完成的三个 provider:启动 DubboBusinessTester 进行测试注意: 在标注 @GlobalTransactional 注解方法内部显示的抛出异常才会进行事务的回滚。整个 Dubbo 服务调用链路只需要在事务最开始发起方的 service 方法标注注解即可。通过以上8个步骤,我们实现了用户采购商品的业务中库存、订单和账户3个独立微服务之间的数据一致性。参考链接:本文 sample 地址: https://github.com/fescar-group/fescar-samples/tree/master/nacosFescar: https://github.com/alibaba/fescarDubbo: https://github.com/apache/incubator-dubboNacos: https://github.com/alibaba/nacos本文作者:清铭,社区昵称 slievrly,Fescar 开源项目发起人之一,阿里巴巴中件间 TXC/GTS 核心研发成员,长期从事于分布式中间件核心研发工作,在分布式事务领域有着较丰富的技术积累。有关 Fescar 的更多信息:分布式事务中间件 Fescar - RM 模块源码解读关于开源分布式事务中间件Fescar,我们总结了开发者关心的13个问题本文作者:中间件小哥阅读原文本文为云栖社区原创内容,未经允许不得转载。 ...

February 25, 2019 · 3 min · jiezi

一文看透浏览器架构

本文由云+社区发表作者:廖彩明在从事前端开发过程中,浏览器作为最重要的开发环境,浏览器基础是是前端开发人员必须掌握的基础知识点,它贯穿着前端的整个网络体系。对浏览器原理的了解,决定着编写前端代码性能的上限。浏览器作为JS的运行环境,学习总结下现代浏览器的相关知识前言经常听说浏览器内核,浏览器内核究竟是什么,以及它做了什么。我们将来了解下浏览器的主要组成部分、现代浏览器的主要架构、浏览器内核、浏览器内部是如何工作的1 浏览器现代浏览器结构如下:The browser’s main componentThe User Interface主要提供用户与Browser Engine交互的方法。其中包括:地址栏(address bar)、向前/退后按钮、书签菜单等等。浏览器除了渲染请求页面的窗口外的所有地方都属于The User InterfaceThe Browser Engine协调(主控)UI和the Rendering Engine,在他们之间传输指令。 提供对The Rendering Engine的高级接口,一方面它提供初始化加载Url和其他高级的浏览器动作(如刷新、向前、退后等)方法。另一方面Browser Engine也为User Interface提供各种与错误、加载进度相关的消息。The Rendering Engine为给定的URL提供可视化的展示。它解析JavaScript、Html、Xml,并且User Interface中展示的layout。其中关键的组件是Html解析器,它可以让Rendering Engine展示差乱的Html页面。 值得注意:不同的浏览器使用不同的Rendering Engine。例如IE使用Trident,Firefox使用Gecko,Safai使用Webkit。Chrome和Opera使用Webkit(以前是Blink)The Networking基于互联网HTTP和FTP协议,处理网络请求。网络模块负责Internet communication and security,character set translations and MIME type resolution。另外网络模块还提供获得到文档的缓存,以减少网络传输。为所有平台提供底层网络实现,其提供的接口与平台无关The JavaScript Interpreter解释和运行网站上的js代码,得到的结果传输到Rendering Engine来展示。The UI Backend用于绘制基本的窗口小部件,比如组合框和窗口。而在底层使用操作系统的用户界面方法,并公开与平台无关的接口。The Data Storage管理用户数据,例如书签、cookie和偏好设置等。2 主流浏览器的架构2.1 FireFoxFireFox的架构可以看到火狐浏览器的渲染引擎(Rendering Engine)使用的是Gecko;XML Parser解析器是Expat;Java Script解释器是Spider-Monkey(c语言实现)2.2 ChromeChrome的架构渲染引擎Rendering Engine使用的是WebKitXML Parser: libXML解析XML,libXSLT处理XSLTJS解释器使用C++实现的V8引擎,2.3 IEIE的架构渲染引擎主要是TridentScripting Engine有JScript和VBScript3 浏览器内核浏览器最重要或者说核心的部分是“Rendering Engine”,可大概译为“渲染引擎”,不过我们一般习惯将之称为“浏览器内核”。主要包括以下线程:3.1 浏览器 GUI 渲染线程,主要包括: HTML Parser 解析HTML文档,将元素转换为树结构DOM节点,称之为Content Tree CSS Parser 解析Style数据,包括外部的CSS文件以及在HTML元素中的样式,用于创建另一棵树,调用“Render Tree” Layout过程 为每个节点计算出在屏幕中展示的准确坐标 Painting 遍历Render Tree,调用UI Backend提供的接口绘制每个节点3.2 JavaScript 引擎线程JS引擎线程负责解析Javascript脚本,运行代码 JS引擎一直等待着任务队列中任务的到来,然后加以处理,一个Tab页(renderer进程)中无论什么时候都只有一个JS线程在运行JS程序GUI渲染线程与JS引擎线程是互斥的,所以如果JS执行的时间过长,这样就会造成页面的渲染不连贯,导致页面渲染加载阻塞a) 减少 JavaScript 加载对 DOM 渲染的影响(将 JavaScript 代码的加载逻辑放在 HTML 文件的尾部,减少对渲染引擎呈现工作的影响;b) 避免重排,减少重绘(避免白屏,或者交互过程中的卡顿;c) 减少 DOM 的层级(可以减少渲染引擎工作过程中的计算量;d) 使用 requestAnimationFrame 来实现视觉变化(一般来说我们会使用 setTimeout 或 setInterval 来执行动画之类的视觉变化,但这种做法的问题是,回调将在帧中的某个时点运行,可能刚好在末尾,而这可能经常会使我们丢失帧,导致卡顿)3.3 浏览器定时触发器线程浏览器定时计数器并不是由 JavaScript 引擎计数的, 因为 JavaScript 引擎是单线程的, 如果处于阻塞线程状态就会影响记计时的准确, 因此通过单独线程来计时并触发定时是更为合理的方案3.4 浏览器事件触发线程当一个事件被触发时该线程会把事件添加到待处理队列的队尾,等待 JavaScript 引擎的处理。这些事件可以是当前执行的代码块如定时任务、也可来自浏览器内核的其他线程如鼠标点击、AJAX 异步请求等,但由于 JavaScript 的单线程关系所有这些事件都得排队等待 JavaScript 引擎处理。3.5 浏览器 http 异步请求线程在 XMLHttpRequest 在连接后是通过浏览器新开一个线程请求, 将检测到状态变更时,如果设置有回调函数,异步线程就产生状态变更事件放到 JavaScript 引擎的处理队列中等待处理。4 以Chrome浏览器为例,演示浏览器内部如何工作上面铺垫了这么多理论,下面结合Chrome讲解当用户在地址栏上输入URL后,浏览器内部都做了写什么4.1 Chrome浏览器中的多进程打开Chrome 任务管理器,可以看到Chrome运行的进程各个进程的功能• Browser进程功能:Controls “chrome” part of the application including address bar, bookmarks, back and forward buttons. Also handles the invisible, privileged parts of a web browser such as network requests and file access.• GPU进程功能:Handles GPU tasks in isolation from other processes. It is separated into different process because GPUs handles requests from multiple apps and draw them in the same surface.• 第三方插件进程功能:Controls any plugins used by the website, for example, flash. 每个插件对应一个进程,当插件运行时创建• 浏览器渲染进程功能:Controls anything inside of the tab where a website is displayed. 默认每个标签页创建一个渲染引擎实例。• V8 Proxy resolver关于V8 Proxy resolver可查看code.google.comgroup.google.com https://groups.google.com/a/c...!topic/net-dev/73f9B5vFphI doc.google.comChrome支持使用代理脚本为给定的网址选择代理服务器,包含使用操作系统提供的代理解析程序的多个平台的回退实现。但默认情况下(iOS除外),它使用内置的解析V8执行代理脚本(V8 pac)。今天(截至2015年1月),V8 pac在浏览器进程中运行。这意味着浏览器进程包含一个V8实例,这是一个潜在的安全漏洞。在浏览器进程中允许V8还需要浏览器进程允许写入 - 执行页面。我们关于将V8 pac迁移到单独进程的建议包括为解析器创建Mojo服务,从实用程序进程导出该服务,以及从浏览器进程创建/连接到该进程。浏览器进程之间主要通过IPC (Inter Process Communication)通信4.2 Per-frame renderer processes - Site IsolationSite Isolation is a recently introduced feature in Chrome that runs a separate renderer process for each cross-site iframe. We’ve been talking about one renderer process per tab model which allowed cross-site iframes to run in a single renderer process with sharing memory space between different sites. Running a.com and b.com in the same renderer process might seem okay. The Same Origin Policy is the core security model of the web; it makes sure one site cannot access data from other sites without consent. Bypassing this policy is a primary goal of security attacks. Process isolation is the most effective way to separate sites. With Meltdown and Spectre, it became even more apparent that we need to separate sites using processes. With Site Isolation enabled on desktop by default since Chrome 67, each cross-site iframe in a tab gets a separate renderer process.每个iframe是单独的渲染进程此文已由腾讯云+社区在各渠道发布获取更多新鲜技术干货,可以关注我们腾讯云技术社区-云加社区官方号及知乎机构号 ...

February 25, 2019 · 2 min · jiezi

基于泛型编程的序列化实现方法

写在前面序列化是一个转储-恢复的操作过程,即支持将一个对象转储到临时缓冲或者永久文件中和恢复临时缓冲或者永久文件中的内容到一个对象中等操作,其目的是可以在不同的应用程序之间共享和传输数据,以达到跨应用程序、跨语言和跨平台的解耦,以及当应用程序在客户现场发生异常或者崩溃时可以即时保存数据结构各内容的值到文件中,并在发回给开发者时再恢复数据结构各内容的值以协助分析和定位原因。泛型编程是一个对具有相同功能的不同类型的抽象实现过程,比如STL的源码实现,其支持在编译期由编译器自动推导具体类型并生成实现代码,同时依据具体类型的特定性质或者优化需要支持使用特化或者偏特化及模板元编程等特性进行具体实现。Hello World#include <iostream>int main(int argc, char* argv[]){ std::cout << “Hello World!” << std::endl; return 0;}泛型编程其实就在我们身边,我们经常使用的std和stl命名空间中的函数和类很多都是泛型编程实现的,如上述代码中的std::cout即是模板类std::basic_ostream的一种特化namespace std{ typedef basic_ostream<char> ostream;}从C++的标准输入输出开始除了上述提到的std::cout和std::basic_ostream外,C++还提供了各种形式的输入输出模板类,如std::basic_istream, std::basic_ifstream,std::basic_ofstream, std::basic_istringstream,std::basic_ostringstream等等,其主要实现了内建类型(built-in)的输入输出接口,比如对于Hello World可直接使用于字符串,然而对于自定义类型的输入输出,则需要重载实现操作符>>和<<,如对于下面的自定义类class MyClip{ bool mValid; int mIn; int mOut; std::string mFilePath;};如使用下面的方式则会出现一连串的编译错误MyClip clip;std::cout << clip;错误内容大致都是一些clip不支持<<操作符并在尝试将clip转为cout支持的一系列的内建类型如void*和int等等类型时转换操作不支持等信息。为了解决编译错误,我们则需要将类MyClip支持输入输出操作符>>和<<,类似实现代码如下inline std::istream& operator>>(std::istream& st, MyClip& clip){ st >> clip.mValid; st >> clip.mIn >> clip.mOut; st >> clip.mFilePath; return st;}inline std::ostream& operator<<(std::ostream& st, MyClip const& clip){ st << clip.mValid << ’ ‘; st << clip.mIn << ’ ’ << clip.mOut << ’ ‘; st << clip.mFilePath << ’ ‘; return st;}为了能正常访问类对象的私有成员变量,我们还需要在自定义类型里面增加序列化和反序列化的友元函数(回忆一下这里为何必须使用友元函数而不能直接重载操作符>>和<<?),如friend std::istream& operator>>(std::istream& st, MyClip& clip);friend std::ostream& operator<<(std::ostream& st, MyClip const& clip);这种序列化的实现方法是非常直观而且容易理解的,但缺陷是对于大型的项目开发中,由于自定义类型的数量较多,可能达到成千上万个甚至更多时,对于每个类型我们则需要实现2个函数,一个是序列化转储数据,另一个则是反序列化恢复数据,不仅仅增加了开发实现的代码数量,如果后期一旦对部分类的成员变量有所修改,则需要同时修改这2个函数。同时考虑到更复杂的自定义类型,比如含有继承关系和自定义类型的成员变量class MyVideo : public MyClip{ std::list<MyFilter> mFilters;};上述代码需要转储-恢复类MyVideo的对象内容时,事情会变得更复杂些,因为还需要转储-恢复基类,同时成员变量使用了STL模板容器list与自定义类’MyFilter`的结合,这种情况也需要自己去定义转储-恢复的实现方式。针对以上疑问,有没有一种方法能减少我们代码修改的工作量,同时又易于理解和维护呢?Boost序列化库对于使用C++标准输入输出的方法遇到的问题,好在Boost提供了一种良好的解决方式,则是将所有类型的转储-恢复操作抽象到一个函数中,易于理解,如对于上述类型,只需要将上述的2个友元函数替换为下面的一个友元函数template<typename Archive> friend void serialize(Archive&, MyClip&, unsigned int const);友元函数的实现类似下面的样子template<typename A>void serialize(A &ar, MyClip &clip, unsigned int const ver){ ar & BOOST_SERIALIZATION_NVP(clip.mValid); ar & BOOST_SERIALIZATION_NVP(clip.mIn); ar & BOOST_SERIALIZATION_NVP(clip.mOut); ar & BOOST_SERIALIZATION_NVP(clip.mFilePath);}其中BOOST_SERIALIZATION_NVP是Boost内部定义的一个宏,其主要作用是对各个变量进行打包。转储-恢复的使用则直接作用于操作符>>和<<,比如// storeMyClip clip;······std::ostringstream ostr;boost::archive::text_oarchive oa(ostr);oa << clip;// loadstd::istringstream istr(ostr.str());boost::archive::text_iarchive ia(istr);ia >> clip;这里使用的std::istringstream和std::ostringstream即是分别从字符串流中恢复数据以及将类对象的数据转储到字符串流中。对于类MyFilter和MyVideo则使用相同的方式,即分别增加一个友元模板函数serialize的实现即可,至于std::list模板类,boost已经帮我们实现了。这时我们发现,对于每一个定义的类,我们需要做的仅仅是在类内部声明一个友元模板函数,同时类外部实现这个模板函数即可,对于后期类的成员变量的修改,如增加、删除或者重命名成员变量,也仅仅是修改一个函数即可。Boost序列化库已经足够完美了,但故事并未结束!在用于端上开发时,我们发现引用Boost序列化库遇到了几个挑战端上的编译资料很少,官方对端上编译的资料基本没有,在切换不同的版本进行编译时经常会遇到各种奇怪的编译错误问题Boost在不同的C++开发标准之间兼容性不够好,尤其是使用libc++标准进行编译链接时遇到的问题较多Boost增加了端上发行包的体积Boost每次序列化都会增加序列化库及版本号等私有头信息,反序列化时再重新解析,降低了部分场景下的使用性能基于泛型编程的序列化实现方法为了解决使用Boost遇到的这些问题,我们觉得有必要重新实现序列化库,以剥离对Boost的依赖,同时能满足如下要求由于现有工程大量使用了Boost序列化库,因此兼容现有的代码以及开发者的习惯是首要目标尽量使得代码修改和重构的工作量最小兼容不同的C++开发标准提供比Boost序列化库更高的性能降低端上发行包的体积为了兼容现有使用Boost的代码以及保持当前开发者的习惯,同时使用代码修改的重构的工作量最小,我们应该保留模板函数serialize,同时对于模板函数内部的实现,为了提高效率也不需要对各成员变量重新打包,即直接使用如下定义#define BOOST_SERIALIZATION_NVP(value) value对于转储-恢复的接口调用,仍然延续目前的调用方式,只是将输入输出类修改为alivc::text_oarchive oa(ostr);alivc::text_iarchive ia(istr);好了,到此为止,序列化库对外的接口工作已经做好,剩下的就是内部的事情,应该如何重新设计和实现序列化库的内部框架才能满足要求呢?先来看一下当前的设计架构的处理流程图比如对于转储类text_oarchive,其支持的接口必须包括explicit text_oarchive(std::ostream& ost, unsigned int version = 0);template <typename T> text_oarchive& operator<<(T& v);template <typename T> text_oarchive& operator&(T& v);开发者调用操作符函数<<时,需要首先回调到相应类型的模板函数serialize中template <typename T>text_oarchive& operator<<(T& v){ serialize(*this, v, mversion); return *this;}当开始对具体类型的各个成员进行操作时,这时需要进行判断,如果此成员变量的类型已经是内建类型,则直接进行序列化,如果是自定义类型,则需要重新回调到对应类型的模板函数serialize中template <typename T>text_oarchive& operator&(T& v){ basic_save<T>::invoke(*this, v, mversion); return *this;}上述代码中的basic_save::invoke则会在编译期完成模板类型推导并选择直接对内建类型进行转储还是重新回调到成员变量对应类型的serialize函数继续重复上述过程。由于内建类型数量有限,因此这里我们选择使模板类basic_save的默认行为为回调到相应类型的serialize函数中template <typename T, bool E = false>struct basic_load_save{ template <typename A> static void invoke(A& ar, T& v, unsigned int version) { serialize(ar, v, version); }};template <typename T>struct basic_save : public basic_load_save<T, std::is_enum<T>::value>{};这时会发现上述代码的模板参数多了一个参数E,这里主要是需要对枚举类型进行特殊处理,使用偏特化的实现如下template <typename T>struct basic_load_save<T, true>{ template <typename A> static void invoke(A& ar, T& v, unsigned int version) { int tmp = v; ar & tmp; v = (T)tmp; }};到这里我们已经完成了重载操作符&的默认行为,即是不断进行回溯到相应的成员变量的类型中的模板函数serialize中,但对于碰到内建模型时,我们则需要让这个回溯过程停止,比如对于int类型template <typename T>struct basic_pod_save{ template <typename A> static void invoke(A& ar, T const& v, unsigned int) { ar.template save(v); }};template <>struct basic_save<int> : public basic_pod_save<int>{};这里对于int类型,则直接转储整数值到输出流中,此时text_oarchive则还需要增加一个终极转储函数template <typename T>void save(T const& v){ most << v << ’ ‘;}这里我们发现,在save成员函数中,我们已经将具体的成员变量的值输出到流中了。对于其它的内建类型,则使用相同的方式处理,要以参考C++ std::basic_ostream的源码实现。相应的,对于恢复操作的text_iarchive的操作流程如下图测试结果我们对使用Boost以及重新实现的序列化库进行了对比测试,其结果如下代码修改的重构的工作非常小,只需要删除Boost的相关头文件,以及将boost相关命名空间替换为alivc,BOOST_SERIALIZATION_FUNCTION以及BOOST_SERIALIZATION_NVP的宏替换Android端下的发行包体积大概减少了500KB目前的消息处理框架中,处理一次消息的平均时间由100us降低到了25us代码实现约300行,更轻量级未来还能做什么由于当前项目的原因,重新实现的序列化还没有支持转储-恢复指针所指向的内存数据,但当前的设计框架已经考虑了这种拓展性,未来会考虑支持。总结泛型编程能够大幅提高开发效率,尤其是在代码重用方面能发挥其优势,同时由于其类型推导及生成代码均在编译期完成,并不会降低性能序列化对于需要进行转储-恢复的解耦处理以及协助定位异常和崩溃的原因分析具有重要作用利用C++及模板自身的语言特性优势,结合合理的架构设计,即易于拓展又能尽量避免过度设计参考资料https://www.ibm.com/developerworks/cn/aix/library/au-boostserialization/本文作者:lifesider阅读原文本文为云栖社区原创内容,未经允许不得转载。 ...

February 25, 2019 · 2 min · jiezi

深入 Nginx 之架构篇

前言最近在读 Nginx 相关的书籍,做一下读书笔记。Nginx 作为业界知名的高性能服务器,被广泛的应用。它的高性能正是由于其优秀的架构设计,其架构主要包括这几点:模块化设计、事件驱动架构、请求的多阶段异步处理、管理进程与多工作进程设计、内存池的设计,以下内容依次进行说明。模块化设计高度模块化的设计是 Nginx 的架构基础。在 Nginx 中,除了少量的核心代码,其他一切皆为模块。所有模块间是分层次、分类别的,Nginx 官方共有五大类型的模块:核心模块、配置模块、事件模块、HTTP 模块、mail 模块。它们之间的关系如下:在这 5 种模块中,配置模块和核心模块是与 Nginx 框架密切相关的。而事件模块则是 HTTP 模块和 mail 模块的基础。HTTP 模块和 mail 模块的“地位”类似,它们都是更关注于应用层面。事件驱动架构事件驱动架构,简单的说就是由一些事件发生源来产生事件,由事件收集器来收集、分发事件,然后由事件处理器来处理这些事件(事件处理器需要先在事件收集器里注册自己想处理的事件)。对于 Nginx 服务器而言,一般由网卡、磁盘产生事件,Nginx 中的事件模块将负责事件的收集、分发操作;而所有的模块都可能是事件消费者,它们首先需要向事件模块注册感兴趣的事件类型,这样,在有事件产生时,事件模块会把事件分发到相应的模块中进行处理。对于传统 web 服务器(如 Apache)而言,采用的所谓事件驱动往往局限在 TCP 连接建立、关闭事件上,一个连接建立以后,在其关闭之前的所有操作都不再是事件驱动,这时会退化成按顺序执行每个操作的批处理模式,这样每个请求在连接建立后都将始终占用着系统资源,直到关闭才会释放资源。这种请求占用着服务器资源等待处理的模式会造成服务器资源极大的浪费。如下图所示,传统 web 服务器往往把一个进程或线程作为时间消费者,当一个请求产生的事件被该进程处理时,直到这个请求处理结束时,进程资源都将被这一请求所占用。比较典型的例子如 Apache 同步阻塞的多进程模式就是这样的。传统 web 服务器处理事件的简单模型(矩形代表进程):Nginx 采用事件驱动架构处理业务的方式与传统的 web 服务器是不同的。它不使用进程或者线程来作为事件消费者,所谓的事件消费者只能是某个模块。只有事件收集、分发器才有资格占用进程资源,它们会在分发某个事件时调用事件消费模块使用当前占用的进程资源,如下图所示,该图中列出了 5 个不同的事件,在事件收集、分发者进程的一次处理过程中,这 5 个事件按照顺序被收集后,将开始使用当前进程分发事件,从而调用相应的事件消费者来处理事件。当然,这种分发、调用也是有序的。Nginx 处理事件的简单模型:由上图可以看出,处理请求事件时,Nginx 的事件消费者只是被事件分发者进程短期调用而已,这种设计使得网络性能、用户感知的请求时延都得到了提升,每个用户的请求所产生的事件会及时响应,整个服务器的网络吞吐量都会由于事件的及时响应而增大。当然,这也带来一定的要求,即每个事件消费者都不能有阻塞行为,否则将会由于长时间占用事件分发者进程而导致其他事件得不到及时响应,Nginx 的非阻塞特性就是由于它的模块都是满足这个要求的。请求的多阶段异步处理多阶段异步处理请求与事件驱动架构是密切相关的,也就是说,请求的多阶段异步处理只能基于事件驱动架构实现。多阶段异步处理就是把一个请求的处理过程按照事件的触发方式划分为多个阶段,每个阶段都可以由事件收集、分发器来触发。处理获取静态文件的 HTTP 请求时切分的阶段及各阶段的触发事件如下所示:这个例子中,该请求大致分为 7 个阶段,这些阶段是可以重复发生的,因此,一个下载静态资源请求可能会由于请求数据过大,网速不稳定等因素而被分解为成百上千个上图所列出的阶段。异步处理和多阶段是相辅相成的,只有把请求分为多个阶段,才有所谓的异步处理。当一个时间被分发到事件消费者中进行处理时,事件消费者处理完这个事件只相当于处理完 1 个请求的阶段。什么时候可以处理下一个阶段呢?这只能等待内核的通知,即当下一次事件出现时,epoll 等事件分发器将会获取到通知,然后去调用事件消费者进行处理。管理进程、多工作进程设计Nginx 在启动后,会有一个 master 进程和多个 worker 进程。master 进程主要用来管理worker 进程,包括接收来自外界的信号,向各 worker 进程发送信号,监控 worker 进程的运行状态以及启动 worker 进程。 worker 进程是用来处理来自客户端的请求事件。多个 worker 进程之间是对等的,它们同等竞争来自客户端的请求,各进程互相独立,一个请求只能在一个 worker 进程中处理。worker 进程的个数是可以设置的,一般会设置与机器 CPU 核数一致,这里面的原因与事件处理模型有关。Nginx 的进程模型,可由下图来表示:在服务器上查看 Nginx 进程:这种设计带来以下优点:1) 利用多核系统的并发处理能力现代操作系统已经支持多核 CPU 架构,这使得多个进程可以分别占用不同的 CPU 核心来工作。Nginx 中所有的 worker 工作进程都是完全平等的。这提高了网络性能、降低了请求的时延。2) 负载均衡多个 worker 工作进程通过进程间通信来实现负载均衡,即一个请求到来时更容易被分配到负载较轻的 worker 工作进程中处理。这也在一定程度上提高了网络性能、降低了请求的时延。3) 管理进程会负责监控工作进程的状态,并负责管理其行为管理进程不会占用多少系统资源,它只是用来启动、停止、监控或使用其他行为来控制工作进程。首先,这提高了系统的可靠性,当 worker 进程出现问题时,管理进程可以启动新的工作进程来避免系统性能的下降。其次,管理进程支持 Nginx 服务运行中的程序升级、配置项修改等操作,这种设计使得动态可扩展性、动态定制性较容易实现。内存池的设计为了避免出现内存碎片,减少向操作系统申请内存的次数、降低各个模块的开发复杂度,Nginx 设计了简单的内存池,它的作用主要是把多次向系统申请内存的操作整合成一次,这大大减少了 CPU 资源的消耗,同时减少了内存碎片。因此,通常每一个请求都有一个简易的独立内存池(如每个 TCP 连接都分配了一个内存池),而在请求结束时则会销毁整个内存池,把曾经分配的内存一次性归还给操作系统。这种设计大大提高了模块开发的简单些,因为在模块申请内存后不用关心它的释放问题;而且因为分配内存次数的减少使得请求执行的时延得到了降低。同时,通过减少内存碎片,提高了内存的有效利用率和系统可处理的并发连接数,从而增强了网络性能。 ...

February 23, 2019 · 1 min · jiezi

Conflux吐槽君:IOTA物联网电磁炉-让PoW的耗电没有遗憾

鉴于有不少小伙伴反映,觉得区块链技术圈乱象横生,鱼龙混杂,导致大家很难去辨识哪些是真正的技术。甚至有些人,打着说技术的名号,其实自己本身都没弄懂弄明白,只是懂个皮毛,就开始拿着各种技术专有名词去唬人。这样的现象,导致想好好学习技术知识的小伙伴们甚至会被混淆和误导,学到和接收到的是错误的信息。小编对于存在的这样的乱象也深感痛心,作为一支来自与清华姚班的公链团队,Conflux的小伙伴们,决定来帮助真正想学习技术的大家!推出《吐槽君小C》专栏,小C会用最直接,最犀利的言语来道出区块链项目技术的优势劣势,真正讲清楚技术,讲清楚技术之间的区别,让大家对技术和整个行业有更深刻的了解认知,本文就是Conflux吐槽君第一期~一个荒唐的故事几年前,打车平台激烈大战的时候,有这样一家创业公司横空出世,号称实现了零打车费,从根本上解决了人们出行中的痛点。而实现的方式是,让用户自己买辆车,然后自己给自己当司机。让服务需求方自己给自己提供服务,从而节省了服务费。这一想法让投资人非常惊讶,然后将创业者打出门去。上面这个故事是小C我编的。但在区块链这个圈子里,却真的有这样一个公链项目,凭借着区块链的技术认知门槛,编概念讲故事,号称解决了区块链+物联网的痛点。这个项目在区块链泡沫最高的时候,一度登上了市值榜TOP10。这就是小C今天的要和大家讲的项目:IOTA。IOTA是个啥?首先,IOTA是一个使用DAG账本结构的区块链系统。(注:DAG,Directed Acyclic Graph,中文全称“有向无环图”,所谓DAG结构,就是让每个区块或交易引用多个区块或交易作为父亲。这样所有的区块或交易之间的父子关系构成一个有向图。每个区块或交易必须引用比自己早的交易,因此,这些区块或交易的父子关系不可能出现循环。因此,这个结构被称为有向无环图) 它的账本数据结构叫做Tangle,翻译成中文就是“纠缠,混乱”的意思。没错,这个名字非常贴切。因为小C从研究IOTA的第一天开始,就被IOTA技术上各种奇葩不靠谱的方案绕晕了。IOTA的项目愿景非常美好:它通过无区块链,无交易费,无限可扩展,解决了物联网场景中各种痛点。这简直是重新定义了区块链啊。但是,如果深扒IOTA的技术原理,你会发现IOTA实现方案非常不靠谱。有多不靠谱呢?比对着excel喊“二百五,求和”还不靠谱。IOTA到底怎么不靠谱小C先来说说这个无限可扩展。在IOTA原始的设定中,所有的交易构成一个 DAG。任何人(或物联网设备)想发起交易,只需要引用其他两个交易就可以了。没有矿工,没有区块,没有矿工赚交易费,你发交易的速度有多快,IOTA的TPS就有多高。只要好人的交易总数足够多,它就是安全的。这简直太awesome了,攻击一个区块链系统从来没有像攻击IOTA那样简单。不需要屯币,不需要买矿机,我只要搞一台电脑不停地,每分每秒不停地发交易,让我的交易占据全网的50%以上,我就攻击成功了。IOTA 大概也意识到了这个问题(被大家抨击到不得不意识到这个问题)。于是IOTA后面改了,说每笔交易必须算一个 PoW,来防止女巫攻击带来的双花问题的。纳尼?说好的无限可扩展呢?有了PoW的IOTA真是妙不可言啊。要知道,IOTA应用场景是物联网设备,物联网设备跑PoW真是天才的想法啊。所谓的物联网设备,就包括现在最火的智能家居,比如智能插座,智能音箱,智能冰箱等。那什么样的物联网设备可以把PoW的优势发挥到淋漓尽致呢?机智的小编我,马上想到了物联网智能电磁炉!我简直迫不及待想买一个 IOTA 物联网智能电磁炉,每次打开电磁炉的时候,它就开始进行PoW运算,发出的热量也可以加热食品。当你的晚饭做好了,一笔 IOTA交易也就发出去了。不仅如此,这个IOTA电磁炉还能提高烹饪的安全系数。它通过占满你家网络的带宽,让你上不了网,杜绝你在烹饪的时候因为刷微信刷微博把房子点着。因为在IOTA中,发送每笔交易时,需要选择两笔交易作为父亲。这个要求看似简单,但你需要保证:这两笔交易的历史中没有非法交易,没有冲突的交易。这需要同步大量的历史,验证历史交易的正确性,处理冲突交易,并且保持与IOTA的DAG最新状态同步。如果你偷懒不同步,那你的交易可能就因为违反了一些规则被无效掉了。为了重新发起这笔交易,你只好再做一顿饭。在比特币中,矿工负责做PoW运算,负责同步、验证网络交易,并处理冲突,用户向矿工付交易费。IOTA重新定义了区块链,消灭了交易费,取而代之的是这些事情都得用户自己来做。当比特币的用户坐在餐桌上吃烤鸭的时候,IOTA的用户还蹲在后厨亲自养鸭子。小C认为,IOTA所谓的无交易费,本质上就是用从商品经济回到自然经济,这是倒退,不是创新。当然,由于这个实在太不合理,于是IOTA的社区就有了弥补的方案。有一个叫 IOTA PoWer的服务,它允许用户付一笔钱,将自己的交易PoW计算等任务外包。可是小C我仔细一想,这不就是用户发出一笔交易,然后付钱让矿工给我打包进区块吗?这个区块很特别,只能放一笔交易而已。由此可见,IOTA所谓的无区块链,不过是自欺欺人的宣传点罢了。对于上面荒诞的故事,IOTA的拥护者可能会不服,他们认为IOTA的PoW与比特币的PoW目的是不一样的,IOTA的PoW只是为了减少网络中的垃圾交易,不会给用户造成负担。那就让小C来带着大家,具体算一算IOTA 中PoW 的难度怎么设比较合理。首先,我们要算一下IOTA网络最高能跑到多少个TPS?如果IOTA每秒产生10000笔交易,网络带宽的局限性导致IOTA无法保证DAG账本在全网的同步。如果账本始终无法及时同步,那么不同的节点就可能在不同的分叉上越走越远,从此分道扬镳,共识不再。所以 IOTA的网络中,每秒 10000 笔交易,不能再多了。然后,我们要算一下IOTA的全网算力达到多少 TH/s 才算安全?全网算力达到多少 TH/s,一个普通的家用电脑,才能在一顿饭的时间里(1小时)发出一笔交易?一个Intel Core 2 Duo的算力大概是2.5MHash/s, 1小时内可以尝试9G次Hash尝试。9G次Hash尝试发出一笔交易,目前 IOTA主网的吞吐率只有5TPS,如果坏人有>45GHash/s的算力,那么他们就可以每秒产生>5笔交易,就可以在交易数量上占据主导,从而进行51%算力攻击。即使达到了10000 TPS,90THash/s依然可以进行51%算力攻击。 90THash/s是个什么概念呢?一个蚂蚁S9矿机的算力是13.5THash/s,七台蚂蚁矿机的算力就可以超过 90THash/s。哪怕普通用户算1小时才能发起一笔交易,七台S9蚂蚁矿机就能完成对IOTA的双花攻击。IOTA面临着一个选择:去让用户忍受更长的等待时间,还是让攻破IOTA的门槛更低?IOTA选哪个?IOTA哪个都不选,IOTA选择中心化!为了解决上述矛盾,IOTA网络中要额外使用一个中心化的Coordinator来定期的验证DAG和交易。这使得IOTA实际上变成了一个中心化的系统。IOTA声称,未来会取消这个中心化的 Coordinator。然而,基于上面的计算,即使网络带宽增加100倍,即使用户愿意忍受1小时才能发一笔交易,700台S9矿机依然能对IOTA发起双花攻击。与之相对应的是,比特币的全网算力大约是(50 EHash/s),相当于4000000台S9矿机。给IOTA的建议小C认为,摆在IOTA面前两条路,要么在中心化的道路上继续走下去,要么积极推广PoW外包方案。让专门的矿工来处理交易打包、PoW挖矿等事宜,让用户为矿工付费。摒弃“无交易费、无区块链、无限扩展”等这些不负责任的言辞。但是即使IOTA“改过自新”,接受了小C的建议,IOTA本质上还是一个1个区块只能包1笔交易的区块DAG。它违背了系统设计中最最通用的一个常识性的优化思想–batching,就是批量处理。这意味着元数据带来的开销会显著增加,同时会带来很多系统实现上的性能挑战。比如,当区块链系统的吞吐率达到每秒几千笔交易的时候,网络带宽通常会成为瓶颈。而交易就是区块链网络中主要需要传输的数据。如果每笔交易都附带许多DAG相关的元数据(例如对其它DAG结点的引用),那么对网络带宽的压力就会大大增加。另外,维护交易粒度的DAG也会大大增加本地计算的复杂度。IOTA的DAG中需要对每个交易结点维护一个累计权重,也就是所有直接或间接引用了该交易的交易个数。当一个新的交易被加入到DAG的尾部,所有它能够直接或间接引用到的交易的累计权重都要需要更新,这个复杂度是和交易的个数成正比的 。假设系统的吞吐率是1000TPS,那么系统从刚开始运行到1小时后,DAG中的交易个数就会达到360万。一天之后就会达到8600万。之后每笔新加入的交易都会带来接近1亿次的权重更新,而且这个复杂度会越来越大。小C有话说我们需要认清几个事实。吞吐率有限,是因为网络带宽有限。PoW的难度高,是为了避免轻而易举地被 51% 攻击。交易费的存在,让专职矿工来解决普通用户的需求。一个区块容纳多个交易的设计,提高了运行的效率。如果看不到这些背后的原理,却盲目地去掉限速,去掉交易费,去掉区块,然后用一个漏洞百出的底层技术,去设计产品方案,去讲一个所谓天方夜谭的故事,这样只会断送这个项目的未来。(注:如果代币是增发的,通胀本质上就是持币者向矿工付服务费。)欢迎关注我们的微信公众号:Conflux中文社区(Conflux-Chain)添加微信群管理员 Confluxgroup 回复“加群”加入 Conflux官方交流群

February 21, 2019 · 1 min · jiezi

Spring Cloud Alibaba基础教程:Nacos的集群部署

前情回顾:《Spring Cloud Alibaba基础教程:使用Nacos实现服务注册与发现》《Spring Cloud Alibaba基础教程:支持的几种服务消费方式》《Spring Cloud Alibaba基础教程:使用Nacos作为配置中心》《Spring Cloud Alibaba基础教程:Nacos配置的加载规则详解》《Spring Cloud Alibaba基础教程:Nacos配置的多环境管理》《Spring Cloud Alibaba基础教程:Nacos配置的多文件加载与共享配置》《Spring Cloud Alibaba基础教程:Nacos的数据持久化》继续说说生产环境的Nacos搭建,通过上一篇《Nacos的数据持久化》的介绍,我们已经知道Nacos对配置信息的存储原理,在集群搭建的时候,必须要使用集中化存储,比如:MySQL存储。下面顺着上一篇的内容,继续下一去。通过本文,我们将完成Nacos生产环境的搭建。集群搭建根据官方文档的介绍,Nacos的集群架构大致如下图所示(省略了集中化存储信息的MySQL):下面我们就来一步步的介绍,我们每一步的搭建细节。MySQL数据源配置对于数据源的修改,在上一篇《Nacos的数据持久》中已经说明缘由,如果还不了解的话,可以先读一下这篇再回来看这里。在进行集群配置之前,先完成对MySQL数据源的初始化和配置。主要分以下两步:第一步:初始化MySQL数据库,数据库初始化文件:nacos-mysql.sql,该文件可以在Nacos程序包下的conf目录下获得。第二步:修改conf/application.properties文件,增加支持MySQL数据源配置,添加(目前只支持mysql)数据源的url、用户名和密码。配置样例如下:spring.datasource.platform=mysqldb.num=1db.url.0=jdbc:mysql://localhost:3306/nacos?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=truedb.user=rootdb.password=更多介绍与思考,可见查看上一篇《Nacos的数据持久化》。集群配置在Nacos的conf目录下有一个cluster.conf.example,可以直接把example扩展名去掉来使用,也可以单独创建一个cluster.conf文件,然后打开将后续要部署的Nacos实例地址配置在这里。本文以在本地不同端点启动3个Nacos服务端为例,可以如下配置:127.0.0.1:8841127.0.0.1:8842127.0.0.1:8843注意:这里的例子仅用于本地学习测试使用,实际生产环境必须部署在不同的节点上,才能起到高可用的效果。另外,Nacos的集群需要3个或3个以上的节点,并且确保这三个节点之间是可以互相访问的。启动实例在完成了上面的配置之后,我们就可以开始在各个节点上启动Nacos实例,以组建Nacos集群来使用了。由于本文中我们测试学习采用了本地启动多实例的情况,与真正生产部署会有一些差异,所以下面分两种情况说一下,如何启动各个Nacos实例。本地测试本文中,在集群配置的时候,我们设定了3个Nacos的实例都在本地,只是以不同的端口区分,所以我们在启动Nacos的时候,需要修改不同的端口号。下面介绍一种方法来方便地启动Nacos的三个本地实例,我们可以将bin目录下的startup.sh脚本复制三份,分别用来启动三个不同端口的Nacos实例,为了可以方便区分不同实例的启动脚本,我们可以把端口号加入到脚本的命名中,比如:startup-8841.shstartup-8842.shstartup-8843.sh然后,分别修改这三个脚本中的参数,具体如下图的红色部分(端口号根据上面脚本命名分配):这里我们通过-Dserver.port的方式,在启动命令中,为Nacos指定具体的端口号,以实现在本机上启动三个不同的Nacos实例来组成集群。修改完3个脚本配置之后,分别执行下面的命令就可以在本地启动Nacos集群了:sh startup-8841.shsh startup-8842.shsh startup-8843.sh生产环境在实际生产环境部署的时候,由于每个实例分布在不同的节点上,我们可以直接使用默认的启动脚本(除非要调整一些JVM参数等才需要修改)。只需要在各个节点的Nacos的bin目录下执行sh startup.sh命令即可。Proxy配置在Nacos的集群启动完毕之后,根据架构图所示,我们还需要提供一个统一的入口给我们用来维护以及给Spring Cloud应用访问。简单地说,就是我们需要为上面启动的的三个Nacos实例做一个可以为它们实现负载均衡的访问点。这个实现的方式非常多,这里就举个用Nginx来实现的简单例子吧。在Nginx配置文件的http段中,我们可以加入下面的配置内容:这样,当我们访问:http://localhost:8080/nacos/的时候,就会被负载均衡的代理到之前我们启动的三个Nacos实例上了。这里我们没有配置upstream的具体策略,默认会使用线性轮训的方式,如果有需要,也可以配置上更为复杂的分发策略。这部分是Nginx的使用内容,这里就不作具体介绍了。这里提一下我在尝试搭建时候碰到的一个问题,如果您也遇到了,希望下面的说明可以帮您解决问题。错误信息如下:2019-02-20 16:20:53,216 INFO The host [nacos_server] is not valid Note: further occurrences of request parsing errors will be logged at DEBUG level.java.lang.IllegalArgumentException: The character [_] is never valid in a domain name. at org.apache.tomcat.util.http.parser.HttpParser$DomainParseState.next(HttpParser.java:926) at org.apache.tomcat.util.http.parser.HttpParser.readHostDomainName(HttpParser.java:822) at org.apache.tomcat.util.http.parser.Host.parse(Host.java:71) at org.apache.tomcat.util.http.parser.Host.parse(Host.java:45) at org.apache.coyote.AbstractProcessor.parseHost(AbstractProcessor.java:288) at org.apache.coyote.http11.Http11Processor.prepareRequest(Http11Processor.java:809) at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:384) at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66) at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:791) at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1417) at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) at java.lang.Thread.run(Thread.java:748)主要原因是,一开始在配置upstream的时候,用了nacos_server作为名称,而在Nacos使用的Tomcat版本中不支持_符号出现在域名位置,所以上面截图给出的upstream的名称是nacosserver,去掉了_符号。到这里,Nacos的集群搭建就完成了!我们可以通过Nginx配置的代理地址:http://localhost:8080/nacos/来访问Nacos,在Spring Cloud应用中也可以用这个地址来作为注册中心和配置中心的访问地址来配置。读者可以使用文末的代码示例来修改原来的Nacos地址来启动,看是否可以获取配置信息来验证集群的搭建是否成功。也可以故意的关闭某个实例,来验证Nacos集群是否还能正常服务。深入思考在Nacos官方文档的指引下,Nacos的集群搭建总体上还是非常顺畅的,没有什么太大的难度。但是值得思考的一个问题跟在上一篇中讲数据持久化的思考类似,作为一个注册中心和配置中心,Nacos的架构是否显得太过于臃肿?除了Nacos自身之外,还需要依赖更多的中间件来完成整套生产环境的搭建,相较于其他的可以用于服务发现与配置的中间件来说,就不那么有优势了。尤其对于小团队来说,这样的复杂度与成本投入,也是在选型的时候需要去考虑的。代码示例本文介绍内容的客户端代码,示例读者可以通过查看下面仓库中的alibaba-nacos-config-client项目:Github:https://github.com/dyc87112/SpringCloud-Learning/Gitee:https://gitee.com/didispace/SpringCloud-Learning/如果您对这些感兴趣,欢迎star、follow、收藏、转发给予支持!以下专题教程也许您会有兴趣Spring Boot基础教程【新版】Spring Cloud从入门到精通 ...

February 21, 2019 · 1 min · jiezi

Tensorflow源码解析1 -- 内核架构和源码结构

1 主流深度学习框架对比当今的软件开发基本都是分层化和模块化的,应用层开发会基于框架层。比如开发Linux Driver会基于Linux kernel,开发Android app会基于Android Framework。深度学习也不例外,框架层为上层模型开发提供了强大的多语言接口、稳定的运行时、高效的算子,以及完备的通信层和设备层管理层。因此,各大公司早早的就开始了深度学习框架的研发,以便能占领市场。当前的框架有数十种之多,主流的如下(截止到2018年11月)显然TensorFlow是独一无二的王者。第二名Keras,它是对TensorFlow或Theano接口的二次封装,严格意义上并不是一个独立的深度学习框架。TensorFlow目前也已经集成了Keras,使得安装了TensorFlow的用户就可以直接使用Keras了。TensorFlow之所以能够从数十种框架中脱颖而出,主要优点有出身高贵,是谷歌出品的。但其他很多框架出身也不差,例如PyTorch之于Facebook,MXNET之于Amazon2015年就开源了,比较早的俘获了一大批开发者。这个确实是tf的一大先发优势,但PyTorch的前身Caffe,以及MXNET开源时间都不晚,而且Caffe流行时间比tf早,后来才被赶超的。更有Theano这样的绝对老前辈。由此可见,软件开源是多么重要。目前流行的深度学习框架也基本都开源了。支持的开发语言多,支持Python Java Go C++等多种流行语言。相比某些框架,确实是优势很大。相比MXNET则小巫见大巫了。MXNET早期发展的一个主要方向就是前端多语言的支持,连MATLAB R Julia等语言都支持了。运行效率高。早期的时候,其实tf的运行效率比很多框架都要低一些的。安装容易,用户上手快,文档齐全,社区活跃。这个是tf的一个较大优势,特别是社区方面,也就是我们常说的生态优势。互联网头部集中效应十分明显,体现在开源软件上也是一样。这也是我认为最大的一个优势。总结起来,TensorFlow虽然每个方面都不是绝对领先的优势,但贵在每个方面都做的不错,因此最终能够一骑绝尘,独领风骚。学习Tensorflow框架内核,可以理解前端接口语言的支持,session生命周期,graph的构建、分裂和执行,operation的注册和运行,模块间数据通信,本地运行和分布式运行模式,以及CPU GPU TPU等异构设备的封装支持等。学习这些,对于模型的压缩 加速 优化等都是大有裨益的。2 TensorFlow系统架构TensorFlow设计十分精巧,基于分层和模块化的设计思想进行开发的。框架如下图整个框架以C API为界,分为前端和后端两大部分。前端:提供编程模型,多语言的接口支持,比如Python Java C++等。通过C API建立前后端的连接,后面详细讲解。后端:提供运行环境,完成计算图的执行。进一步分为4层运行时:分为分布式运行时和本地运行时,负责计算图的接收,构造,编排等。计算层:提供各op算子的内核实现,例如conv2d, relu等通信层:实现组件间数据通信,基于GRPC和RDMA两种通信方式设备层:提供多种异构设备的支持,如CPU GPU TPU FPGA等模型构造和执行流程TensorFlow的一大特点是,图的构造和执行相分离。用户添加完算子,构建好整图后,才开始进行训练和执行,也就是图的执行。大体流程如下图构建:用户在client中基于TensorFlow的多语言编程接口,添加算子,完成计算图的构造。图传递:client开启session,通过它建立和master之间的连接。执行session.run()时,将构造好的graph序列化为graphDef后,以protobuf的格式传递给master。图剪枝:master根据session.run()传递的fetches和feeds列表,反向遍历全图full graph,实施剪枝,得到最小依赖子图图分裂:master将最小子图分裂为多个Graph Partition,并注册到多个worker上。一个worker对应一个Graph Partition。图二次分裂:worker根据当前可用硬件资源,如CPU GPU,将Graph Partition按照op算子设备约束规范(例如tf.device(’/cpu:0’),二次分裂到不同设备上。每个计算设备对应一个Graph Partition。图运行:对于每一个计算设备,worker依照op在kernel中的实现,完成op的运算。设备间数据通信可以使用send/recv节点,而worker间通信,则使用GRPC或RDMA协议。3 前端多语言实现 - swig包装器TensorFlow提供了很多种语言的前端接口,使得用户可以通过多种语言来完成模型的训练和推断。其中Python支持得最好。这也是TensorFlow之所以受欢迎的一大原因。前端多语言是怎么实现的呢?这要归功于swig包装器。swig是个帮助使用C或者C++编写的软件能与其它各种高级编程语言进行嵌入联接的开发工具。在TensorFlow使用bazel编译时,swig会生成两个wrapper文件pywrap_tensorflow_internal.py:对接上层Python调用pywrap_tensorflow_internal.cc:对接底层C API调用。pywrap_tensorflow_internal.py 模块被导入时,会加载_pywrap_tensorflow_internal.so动态链接库,它里面包含了所有运行时接口的符号。而pywrap_tensorflow_internal.cc中,则注册了一个函数符号表,实现Python接口和C接口的映射。运行时,就可以通过映射表,找到Python接口在C层的实现了。4 tensorflow 源码结构TensorFlow源码基本也是按照框架分层来组织文件的。如下其中core为tf的核心,它的源码结构如下5 总结TensorFlow框架设计精巧,代码量也很大,我们可以从以下部分逐步学习TensorFlow内核架构和源码结构。先从全局上对框架进行理解。前后端连接的桥梁–Session,重点理解session的生命周期,并通过相关源码可以加深理解Python前端如何调用底层C实现。TensorFlow核心对象—Graph。图graph是TensorFlow最核心的对象,基本都是围绕着它来进行的。graph的节点为算子operation,边为数据tensor。TensorFlow图的节点 – Operation。operation是图graph的节点,承载了计算算子。TensorFlow图的边 – Tensor。Tensor是图graph的边,承载了计算的数据。TensorFlow本地运行时。TensorFlow分布式运行时。和本地运行时有一些共用的接口,但区别也很大。TensorFlow设备层。主要了解设备层的定义规范,以及实现。TensorFlow队列和并行运算。TensorFlow断点检查checkpoint,模型保存Saver,以及可视化tensorboard。这三个为TensorFlow主要的工具。本文作者:扬易阅读原文本文为云栖社区原创内容,未经允许不得转载。

February 20, 2019 · 1 min · jiezi

Perseus-BERT——业内性能极致优化的BERT训练方案【阿里云弹性人工智能】

一,背景——横空出世的BERT全面超越人类2018年在自然语言处理(NLP)领域最具爆炸性的一朵“蘑菇云”莫过于Google Research提出的BERT(Bidirectional Encoder Representations from Transformers)模型。作为一种新型的语言表示模型,BERT以“摧枯拉朽”之势横扫包括语言问答、理解、预测等各项NLP锦标的桂冠,见图1和图2。【图1】SQuAD是基于Wikipedia文章的标准问答数据库的NLP锦标。目前SQuAD2.0排名前十名均为基于BERT的模型(图中列出前五名),前20名有16席均是出自BERT 【图2】GLUE是一项通用语言理解评估的benchmark,包含11项NLP任务。BERT自诞生日起长期压倒性霸占榜首(目前BERT排名第二,第一为Microsoft提交的BIGBIRD模型,由于没有URL链接无从知晓模型细节,网传BIGBIRD的名称上有借鉴BERT BIG模型之嫌) 业内将BERT在自然语言处理的地位比作ResNet之于计算机视觉领域的里程碑地位。在BERT横空出世之后,所有的自然语言处理任务都可以基于BERT模型为基础展开。一言以蔽之,现如今,作为NLP的研究者,如果不了解BERT,那就是落后的科技工作者;作为以自然语言处理为重要依托的科技公司,如果不落地BERT,那就是落后生产力的代表。二,痛点——算力成为BERT落地的拦路虎BERT强大的原因在哪里?让我们拂去云霭,窥探下硝烟下的奥秘。BERT模型分为预训练模型(Pretrain)和精调模型(Finetune)。Pretrain模型为通用的语言模型。Finetune只需要在Pretrain的基础上增加一层适配层就可以服务于从问答到语言推理等各类任务,无需为具体任务修改整体模型架构,如图3所示。这种设计方便BERT预处理模型适配于各类具体NLP模型(类似于CV领域基于ImageNet训练的各种Backbone模型)。【图3】左图基于BERT pretrain的模型用于语句问答任务(SQuAD)的finetune模型,右图为用于句对分类(Sentence Pair Classification Tasks)的finetune模型。他们均是在BERT Pretrain模型的基础上增加了一层具体任务的适配层因此,BERT的强大主要归功于精确度和鲁棒性俱佳的Pretrain语言模型。大部分的计算量也出自Pretrain模型。其主要运用了以下两项技术,都是极其耗费计算资源的模块。1. 双向Transformer架构图4可见,与其他pre-training的模型架构不同,BERT从左到右和从右到左地同时对语料进行transformer处理。这种双向技术能充分提取语料的时域相关性,但同时也大大增加了计算资源的负担。【关于Transformer是Google 17年在NLP上的大作,其用全Attention机制取代NLP常用的RNN及其变体LSTM等的常用架构,大大改善了NLP的预测准确度。本文不展开,该兴趣的同学可以自行搜索一下】。【图4】Pretrain架构对比。其中OpenAI GPT采用从左到右的Transformer架构,ELMo采用部分从左到右和部分从右到左的LSTM的级联方式。BERT采用同时从左到右和从右到左的双向Transformer架构。1. 词/句双任务随机预测BERT预训练模型在迭代计算中会同时进行单词预测和语句预测两项非监督预测任务。其一,单词预测任务对语料进行随机MASK操作(Masked LM)。在所有语料中随机选取15%的单词作为Mask数据。被选中Mask的语料单词在迭代计算过程中80%时间会被掩码覆盖用于预测、10%时间保持不变、10%时间随机替换为其他单词,如图5所示。其二,语句预测任务(Next Sentence Prediction)。对选中的前后句A和B,在整个迭代预测过程中,50%的时间B作为A的真实后续语句(Label=IsNext),另外50%的时间则从语料库里随机选取其他语句作为A的后续语句(Label=NotNext),如图5所示【图5】词/句双任务随机预测输入语料实例。蓝框和红框为同一个语料输入在不同时刻的随机状态。对单词预测任务,蓝框中的“went”为真实数据,到了红框则被[MASK],红框中的“the” 则相反;对于语句预测任务,蓝框中的句组为真实的前后句,而红框中的句组则为随机的组合。这种随机选取的单词/语句预测方式在功能上实现了非监督数据的输入的功能,有效防止模型的过拟合。但是按比例随机选取需要大大增加对语料库的迭代次数才能消化所有的语料数据,这给计算资源带来了极大的压力。综上,BERT预处理模型功能需要建立在极强的计算力基础之上。BERT论文显示,训练BERT BASE 预训练模型(L=12, H=768, A=12, Total Parameters=110M, 1000,000次迭代)需要1台Cloud TPU工作16天;而作为目前深度学习主流的Nvidia GPU加速卡面对如此海量的计算量更是力不从心。即使是目前主流最强劲的Nvidia V100加速卡,训练一个BERT-Base Pretrain模型需要一两个月的时间。而训练Large模型,需要花至少四五个月的时间。花几个月训练一个模型,对于绝大部分在GPU上训练BERT的用户来说真是伤不起。三,救星——擎天云加速框架为BERT披荆斩棘阿里云弹性人工智能团队依托阿里云强大的基础设施资源打磨业内极具竞争力的人工智能创新方案。基于BERT的训练痛点,团队打造了擎天优化版的Perseus-BERT, 极大地提升了BERT pretrain模型的训练速度。在云上一台V100 8卡实例上,只需4天不到即可训练一份BERT模型。Perseus-BERT是如何打造云上最佳的BERT训练实践?以下干货为您揭秘Perseus-BERT的独门绝技。1. Perseus 统一分布式通信框架 —— 赋予BERT分布式训练的轻功Perseus(擎天)统一分布式通信框架是团队针对人工智能云端训练的痛点,针对阿里云基础设施极致优化的分布式训练框架。其可轻便地嵌入主流人工智能框架的单机训练代码,在保证训练精度的同时高效地提升训练的多机扩展性。擎天分布式框架的干货介绍详见团队另一篇文章《Perseus(擎天):统一深度学习分布式通信框架》。针对tensorflow代码的BERT,Perseus提供horovod的python api方便嵌入BERT预训练代码。基本流程如下:让每块GPU对应一个Perseus rank进程;对global step和warmup step做基于rank数的校准;对训练数据根据rank-id做划分;给Optimizer增加DistributeOptimizer的wrapper。值得注意的是,BERT源码用的自定义的Optimizer,在计算梯度时采用了以下apigrads = tf.gradients(loss, tvars)Perseus的DistributeOptimizer继承标准的Optimizer实现,并在compute_gradients api 上实现分布式的梯度更新计算。因此对grads获取做了如下微调grads_and_vars = optimizer.compute_gradients(loss, tvars)grads = list()for grad, var in grads_and_vars: grads.append(grad)2. 混合精度训练和XLA编译优化——提升BERT单机性能的内功混合精度在深度学习中,混合精度训练指的是float32和float16混合的训练方式,一般的混合精度模式如图6所示【图6】混合精度训练示例。在Forward+Backward计算过程中用float16做计算,在梯度更新时转换为float32做梯度更新。混合梯度对Bert训练带来如下好处,增大训练时的batch size和sequence_size以保证模型训练的精度。 目前阿里云上提供的主流的Nvidia显卡的显存最大为16GB,对一个BERT-Base模型在float32模式只能最高设置为sequence_size=256,batch_size=26。BERT的随机预测模型设计对sequence_size和batch_size的大小有一定要求。为保证匹配BERT的原生训练精度,需要保证sequece_size=512的情况下batch_size不小于16。Float16的混合精度可以保证如上需求。混合精度能充分利用硬件的加速资源。 NVidia从Volta架构开始增加了Tensor Core资源,这是专门做4x4矩阵乘法的fp16/fp32混合精度的ASIC加速器,一块V100能提供125T的Tensor Core计算能力,只有在混合精度下计算才能利用上这一块强大的算力。 受限于float16的表示精度,混合精度训练的代码需要额外的编写,NVidia提供了在Tensorflow下做混合精度训练的教程 。其主要思路是通过tf.variable_scope的custom_getter 参数保证存储的参数为float32并用float16做计算。 在BERT预训练模型中,为了保证训练的精度,Perseus-BERT没有简单的利用custom_getter参数,而是显式指定训地参数中哪些可以利用float16不会影响精度,哪些必须用float32已保证精度。我们的经验如下:Embedding部分要保证float32精度;Attetion部分可以利用float16加速;Gradients相关的更新和验证需要保证float32精度;非线性激活等模块需要保证float32精度。XLA编译器优化XLA是Tensorflow新近提出的模型编译器,其可以将Graph编译成IR表示,Fuse冗余Ops,并对Ops做了性能优化、适配硬件资源。然而官方的Tensorflow release并不支持xla的分布式训练,为了保证分布式训练可以正常进行和精度,我们自己编译了带有额外patch的tensorflow来支持分布式训练,Perseus-BERT 通过启用XLA编译优化加速训练过程并增加了Batch size大小。3. 数据集预处理的加速Perseus BERT 同时对文本预处理做的word embedding和语句划分做了并行化的优化。这里就不展开说明。四,性能——计算时间单位从月降低到天图7展示了Perseus BERT在P100实例上的性能,与开源主流的horovod相比,Peseus-BERT双机16卡的分布式性能是前者的5倍之多。目前某大客户已在阿里云P100集群上大规模上线了Perseus BERT,用10台4卡P100只需要2.5天即可训练完成业务模型,如果用开源的horovod(Tensorflow分布式性能优化版)大概需要1个月的时间。【图7】Bert在阿里云上P100实例的对比(实验环境Bert on P100; Batch size: 22 ;Max seq length: 256 ;Data type:float32; Tensorflow 1.12; Perseus: 0.9.1;Horovod: 0.15.2)为了和Google TPU做对比,我们量化了TPU的性能,性能依据如图8。一个Cloud TPU可计算的BERT-Base性能 256 (1000000/4/4/24/60/60) = 185 exmaples/s。 而一台阿里云上的V100 单机八卡实例在相同的sequence_size=512下, 通过Perseus-BERT优化的Base模型训练可以做到 680 examples/s,接近一台Cloud TPU的4倍性能。对一台Cloud TPU花费16天才能训练完的BERT模型,一台阿里云的V100 8卡实例只需要4天不到便可训练完毕。【图8】BERT Pretain在Google Cloud TPU上的性能依据五,总结——基于阿里云基础设施的AI极致性能优化弹性人工智能团队一直致力基于阿里云基础设施的AI极致性能优化的创新方案。Perseus-BERT就是一个非常典型的案例,我们在框架层面上基于阿里云的基础设施做深度优化,充分释放阿里云上基础资源的计算能力,让阿里云的客户充分享受云上的AI计算优势,让天下没有难算的AI。本文作者:笋江阅读原文本文为云栖社区原创内容,未经允许不得转载。 ...

February 19, 2019 · 1 min · jiezi

如何合理的规划jvm性能调优

JVM性能调优涉及到方方面面的取舍,往往是牵一发而动全身,需要全盘考虑各方面的影响。但也有一些基础的理论和原则,理解这些理论并遵循这些原则会让你的性能调优任务将会更加轻松。为了更好的理解本篇所介绍的内容。你需要已经了解和遵循以下内容:1、已了解jvm 垃圾收集器2、已了解jvm 性能监控常用工具3、能够读懂gc日志4、确信不为了调优而调优,jvm调优不能解决一切性能问题如果对这些不了解不建议读本篇文章。本篇文章基于jvm性能调优,结合jvm的各项参数对应用程序调优,主要内容有以下几个方面:1、jvm调优的一般流程2、jvm调优所要关注的几个性能指标3、jvm调优需要掌握的一些原则4、调优策略&示例一、性能调优的层次为了提升系统性能,我们需要对系统的各个角度和层次来进行优化,以下是需要优化的几个层次。从上面我们可以看到,除了jvm调优以外,还有其他几个层面需要来处理,所以针对系统的调优不是只有jvm调优一项,而是需要针对系统来整体调优,才能提升系统的性能。本篇只针对jvm调优来讲解,其他几个方面,后续再介绍。在进行jvm调优之前,我们假设项目的架构调优和代码调优已经进行过或者是针对当前项目是最优的。这两个是jvm调优的基础,并且架构调优是对系统影响最大的 ,我们不能指望一个系统架构有缺陷或者代码层次优化没有穷尽的应用,通过jvm调优令其达到一个质的飞跃,这是不可能的。另外,在调优之前,必须得有明确的性能优化目标, 然后找到其性能瓶颈。之后针对瓶颈的优化,还需要对应用进行压力和基准测试,通过各种监控和统计工具,确认调优后的应用是否已经达到相关目标。二、jvm调优流程调优的最终目的都是为了令应用程序使用最小的硬件消耗来承载更大的吞吐。jvm的调优也不例外,jvm调优主要是针对垃圾收集器的收集性能优化,令运行在虚拟机上的应用能够使用更少的内存以及延迟获取更大的吞吐量。当然这里的最少是最优的选择,而不是越少越好。1、性能定义要查找和评估器性能瓶颈,首先要知道性能定义,对于jvm调优来说,我们需要知道以下三个定义属性,依作为评估基础:吞吐量:重要指标之一,是指不考虑垃圾收集引起的停顿时间或内存消耗,垃圾收集器能支撑应用达到的最高性能指标。延迟:其度量标准是缩短由于垃圾啊收集引起的停顿时间或者完全消除因垃圾收集所引起的停顿,避免应用运行时发生抖动。内存占用:垃圾收集器流畅运行所需要 的内存数量。这三个属性中,其中一个任何一个属性性能的提高,几乎都是以另外一个或者两个属性性能的损失作代价,不可兼得,具体某一个属性或者两个属性的性能对应用来说比较重要,要基于应用的业务需求来确定。2、性能调优原则在调优过程中,我们应该谨记以下3个原则,以便帮助我们更轻松的完成垃圾收集的调优,从而达到应用程序的性能要求。1. MinorGC回收原则: 每次minor GC 都要尽可能多的收集垃圾对象。以减少应用程序发生Full GC的频率。2. GC内存最大化原则:处理吞吐量和延迟问题时候,垃圾处理器能使用的内存越大,垃圾收集的效果越好,应用程序也会越来越流畅。3. GC调优3选2原则: 在性能属性里面,吞吐量、延迟、内存占用,我们只能选择其中两个进行调优,不可三者兼得。3、性能调优流程以上就是对应用程序进行jvm调优的基本流程,我们可以看到,jvm调优是根据性能测试结果不断优化配置而多次迭代的过程。在达到每一个系统需求指标之前,之前的每个步骤都有可能经历多次迭代。有时候为了达到某一方面的指标,有可能需要对之前的参数进行多次调整,进而需要把之前的所有步骤重新测试一遍。另外调优一般是从满足程序的内存使用需求开始的,之后是时间延迟的要求,最后才是吞吐量的要求,要基于这个步骤来不断优化,每一个步骤都是进行下一步的基础,不可逆行之。以下我们针对每个步骤进行详细的示例讲解。在JVM的运行模式方面,我们直接选择server模式,这也是jdk1.6以后官方推荐的模式。在垃圾收集器方面,我们直接采用了jdk1.6-1.8 中默认的parallel收集器(新生代采用parallelGC,老生代采用parallelOldGC)。三、确定内存占用在确定内存占用之前,我们需要知道两个知识点:应用程序的运行阶段jvm内存分配1、运行阶段应用程序的运行阶段,我可以划分为以下三个阶段:1、初始化阶段 : jvm加载应用程序,初始化应用程序的主要模块和数据。2、稳定阶段:应用在此时运行了大多数时间,经历过压力测试的之后,各项性能参数呈稳定状态。核心函数被执行,已经被jit编译预热过。3、总结阶段:最后的总结阶段,进行一些基准测试,生成响应的策报告。这个阶段我们可以不关注。确定内存占用以及活跃数据的大小,我们应该是在程序的稳定阶段来进行确定,而不是在项目起初阶段来进行确定,如何确定,我们先看以下jvm的内存分配。2、jvm内存分配&参数jvm堆中主要的空间,就是以上新生代、老生代、永久代组成,整个堆大小=新生代大小 + 老生代大小 + 永久代大小。 具体的对象提升方式,这里不再过多介绍了,我们看下一些jvm命令参数,对堆大小的指定。如果不采用以下参数进行指定的话,虚拟机会自动选择合适的值,同时也会基于系统的开销自动调整。在设置的时候,如果关注性能开销的话,应尽量把永久代的初始值与最大值设置为同一值,因为永久代的大小调整需要进行FullGC 才能实现。3、计算活跃数据大小计算活跃数据大小应该遵循以下流程:如前所述,活跃数据应该是基于应用程序稳定阶段时,观察长期存活与对象在java堆中占用的空间大小。计算活跃数据时应该确保以下条件发生:1.测试时,启动参数采用jvm默认参数,不人为设置。2.确保Full GC 发生时,应用程序正处于稳定阶段。采用jvm默认参数启动,是为了观察应用程序在稳定阶段的所需要的内存使用。如何才算稳定阶段?一定得需要产生足够的压力,找到应用程序和生产环境高峰符合状态类似的负荷,在此之后达到峰值之后,保持一个稳定的状态,才算是一个稳定阶段。所以要达到稳定阶段,压力测试是必不可少的,具体如何如何对应用压力测试,本篇不过多说明,后期会有专门介绍的篇幅。在确定了应用出于稳定阶段的时候,要注意观察应用的GC日志,特别是Full GC 日志。GC日志指令: -XX:+PrintGCTimeStamps -XX:+PrintGCDetails -Xloggc:<filename>GC日志是收集调优所需信息的最好途径,即便是在生产环境,也可以开启GC日志来定位问题,开启GC日志对性能的影响极小,却可以提供丰富数据。必须得有FullGC 日志,如果没有的话,可以采用监控工具强制调用一次,或者采用以下命令,亦可以触发jmap -histo:live pid在稳定阶段触发了FullGC我们一般会拿到如下信息:从以上gc日志中,我们大概可以分析到,在发生fullGC之时,整个应用的堆占用以及GC时间,当然了,为了更加精确,应该多收集几次,获取一个平均值。或者是采用耗时最长的一次FullGC来进行估算。在上图中,fullGC之后,老年代空间占用在93168kb(约93MB),我们以此定为老年代空间的活跃数据。其他堆空间的分配,基于以下规则来进行。基于以上规则和上图中的FullGC信息,我们现在可以规划的该应用堆空间为:java 堆空间: 373Mb (=老年代空间93168kb4)新生代空间:140Mb(=老年代空间93168kb1.5)永久代空间:5Mb(=永久代空间3135kb1.5)老年代空间: 233Mb=堆空间-新生代看空间=373Mb-140Mb对应的应用启动参数应该为:java -Xms373m -Xmx373m -Xmn140m -XX:PermSize=5m -XX:MaxPermSize=5m四、延迟调优在确定了应用程序的活跃数据大小之后,我们需要再进行延迟性调优,因为对于此时堆内存大小,延迟性需求无法达到应用的需要,需要基于应用的情况来进行调试。在这一步进行期间,我们可能会再次优化堆大小的配置,评估GC的持续时间和频率、以及是否需要切换到不同的垃圾收集器上。1、系统延迟需求在调优之前,我们需要知道系统的延迟需求是那些,以及对应的延迟可调优指标是那些。应用程序可接受的平均停滞时间: 此时间与测量的Minor GC持续时间进行比较。可接受的Minor GC频率:Minor GC的频率与可容忍的值进行比较。可接受的最大停顿时间: 最大停顿时间与最差情况下FullGC的持续时间进行比较。可接受的最大停顿发生的频率:基本就是FullGC的频率。以上中,平均停滞时间和最大停顿时间,对用户体验最为重要,可以多关注。基于以上的要求,我们需要统计以下数据:MinorGC的持续时间;统计MinorGC的次数;FullGC的最差持续时间;最差情况下,FullGC的频率;2、优化新生代的大小比如如上的gc日志中,我们可以看到Minor GC的平均持续时间=0.069秒,MinorGC 的频率为0.389秒一次。如果,我们系统的设置的平均停滞时间为50ms,当前的69ms明显是太长了,就需要调整。我们知道新生代空间越大,Minor GC的GC时间越长,频率越低。如果想减少其持续时长,就需要减少其空间大小。如果想减小其频率,就需要加大其空间大小。为了降低改变新生代的大小对其他区域的最小影响。在改变新生代空间大小的时候,尽量保持老年代空间的大小。比如此次减少了新生代空间10%的大小,应该保持老年代和持代的大小不变化,第一步调优后的参数如下变化:java -Xms359m -Xmx359m -Xmn126m -XX:PermSize=5m -XX:MaxPermSize=5m新生代的大小有140m变为126,堆大小顺应变化,此时老年代是没有变化的。3、优化老年代的大小同上一步一样,在优化之前,也需要采集gc日志的数据。此次我们关注的是FullGC的持续时间和频率。上图中,我们可以看到FullGC 平均频率 =5.8sFullGC 平均持续时间=0.14s(以上为了测试,真实项目的fullGC 没有这么快)如果没有FullGC的日志,有办法可以评估么?我们可以通过对象提升率进行计算。对象提升率比如上述中启动参数中,我们的老年代大小=233Mb。那么需要多久才能填满老年代中这233Mb的空闲空间取决于新生代到老年代的提升率。每次提升老年代占用量=每次MinorGC 之后 java堆占用情况 减去 MinorGC后新生代的空间占用对象提升率=平均值(每次提升老年代占用量) 除以 老年代空间有了对象提升率,我们就可以算出填充满老年代空间需要多少次minorGC,大概一次fullGC的时间就可以计算出来了。比如:上图中:第一次minor GC 之后,老年代空间:13740kb - 13732kb =8kb第二次minor GC 之后,老年代空间:22394kb - 17905kb =4489kb第三次minor GC 之后,老年代空间:34739kb - 17917kb =16822kb第四次minor GC 之后,老年代空间:48143kb - 17913kb =30230kb第五次minor GC 之后,老年代空间:62112kb - 17917kb =44195kb老年代每次minorGC提升率4481kb 第二次和第一次minorGC之间12333kb 第3次和第2次minorGC之间13408kb 第4次和第3次minorGC之间13965kb 第5次和第4次minorGC之间我们可以测算出:每次minorGC 的平均提升为12211kb,约为12Mb上图中,平均minorGC的频率为 213ms/次提升率=12211kb/213ms=57kb/ms老年代空间233Mb ,占满大概需要2331024/57=4185ms 约为4.185s。FullGC的预期最差频率时长可以通过以上两种方式估算出来,可以调整老年代的大小来调整FullGC的频率,当然了,如果FullGC持续时间过长,无法达到应用程序的最差延迟要求,就需要切换垃圾处理器了。具体如何切换,下篇再讲,比如切换为CMS,针对CMS的调优方式又有会细微的差别。五、吞吐量调优经过上述漫长 调优过程,最终来到了调优的最后一步,这一步对上述的结果进行吞吐量测试,并进行微调。吞吐量调优主要是基于应用程序的吞吐量要求而来的,应用程序应该有一个综合的吞吐指标,这个指标基于真个应用的需求和测试而衍生出来的。当有应用程序的吞吐量达到或者超过预期的吞吐目标,整个调优过程就可以圆满结束了。如果出现调优后依然无法达到应用程序的吞吐目标,需要重新回顾吞吐要求,评估当前吞吐量和目标差距是否巨大,如果在20%左右,可以修改参数,加大内存,再次从头调试,如果巨大就需要从整个应用层面来考虑,设计以及目标是否一致了,重新评估吞吐目标。对于垃圾收集器来说,提升吞吐量的性能调优的目标就是就是尽可能避免或者很少发生FullGC 或者Stop-The-World压缩式垃圾收集(CMS),因为这两种方式都会造成应用程序吞吐降低。尽量在MinorGC 阶段回收更多的对象,避免对象提升过快到老年代。六、最后据Plumbr公司对特定垃圾收集器使用情况进行了一次调查研究,研究数据使用了84936个案例。在明确指定垃圾收集器的13%的案例中,并发收集器(CMS)使用次数最多;但大多数案例没有选择最佳垃圾收集器。这个比例占用在87%左右。JVM调优是一个系统而又复杂的工作,目前jvm下的自动调整已经做的比较优秀,基本的一些初始参数都可以保证一般的应用跑的比较稳定了,对部分团队来说,程序性能可能优先级不高,默认垃圾收集器已经够用了。调优要基于自己的情况而来。本文作者:wier_ali阅读原文本文为云栖社区原创内容,未经允许不得转载。 ...

February 18, 2019 · 1 min · jiezi

架构的“一小步”,业务的一大步

前言:谈到“架构”这两个字,会有好多的名词闪现,比如:分层架构、事件驱动架构、DDD、CQRS等。亦或者一堆的软件设计原则,如:KISS原则(Keep it Simple and Stupid)、SOLID原则(单一责任原则、开放封闭原则、里氏替换原则、接口分离原则、依赖导致原则)等。甚至如状态图、用例图、时序图、活动图等UML建模,GOF设计模式等。本文不会讨论这些架构概念,而是从闲鱼详情页这个业务场景出发,分析出当前的业务问题和痛点,然后通过一步步的架构推导设计,解决这些痛点。随着业务的发展,相信这些问题大家都会遇到。而解决问题的过程,或多或少的会用到上面的设计原则。一:老的业务架构 - MVC架构很多同学开始写业务的时候,基本都会先建表,然后生成CURD,最后再堆业务逻辑,从DAO->Manager->Service->Controller一路写到底。在业务小的时候,这种架构非常的简单实用,可以快速的开发上线。但随着业务发展,人员不断增加,老的架构难以支撑业务的发展,稳定性和效率受到极大挑战。蛮荒时代已过,精耕细作的时代到来,急需一种更合适的架构来支撑业务的发展。以闲鱼的详情页举例,在业务初期,详情的样式只有普通的开价宝贝一种,但随着业务的发展,演变出拍卖、免费送、租房、玩家等细分领域的商品详情页(我们将细分领域的业务命名为“垂直业务”)。 此时,还不断的在老的业务逻辑里添加新的业务逻辑,导致所有的详情业务逻辑堆在一起。于是乎,会出现下面的场景:1)今天A详情业务线的同学,加了段逻辑,挂了,影响了所有业务线的同学;2)B详情业务线的同学想做单独的监控、缓存、降级等,做不到啊,大家的逻辑在一起,改造成本太高;3)C详情业务线的同学本想只关注C详情业务逻辑,发现所有业务都在一起,不得不将所有业务都理清楚一遍;4)D详情业务线的同学发现前面的业务逻辑太复杂,为了将影响面减少到最小,找了一个认为最安全的地方,加了一段D详情业务的特殊处理。有人可能会问,堆逻辑正常的啊,加几行代码,业务就上线了,互联网提倡的敏捷开发,当然是怎么快怎么来。但敏捷开发 != 提需求 + 编码 + 发布,加几行代码交付业务上线,可能会带来眼前的收益,但一直这么下去,代码会越来越臃肿,没有设计和文档沉淀的系统,难以维护,出故障只是时间问题。二:新的业务架构 - 业务隔离 + 领域建模吉德林法则讲:把难题清清楚楚地写出来,便已经解决了一半。 老的架构的问题,归纳起来讲:1.业务没有做隔离,所有的垂直业务逻辑都堆在一起,互相影响。2.详情页业务足够的复杂,却没有统一的模型,形成统一的认知。因此,架构的设计方案就着重解决这两个问题。2.1 业务隔离架构推导与设计一个业务,有多种形态的实现,很容易对应到设计模式里的策略模式。最粗暴的方式,每个垂直业务都自己实现详情页。这种方式,业务虽然隔离了,但维护成本极高,添加一个通用的功能,所有业务都需要添加一遍。 因此需要将共性内容(不变的部分)抽象出来,将变化的部分由各个垂直业务去实现。这种方式,解决了业务的隔离,共性的内容统一维护,变化的部分由各个垂直业务独立维护。但此时,所有的业务团队还是在一个应用工程里写业务代码,会出现如下场景:1)开发阶段,各业务线都在这个应用里拉取一个分支进行开发,集成部署时,代码冲突难以避免。2)A业务线添加了一段自己业务线的逻辑,部署失败了,导致其它业务线也无法使用。3)N业务线不在自己的团队内,属于外部合作团队,如何添加该业务线的逻辑。这些场景存在的原因在于,业务代码虽然隔离了, 但人员的开发过程并没有隔离。有如下3中方法可供选择:a. 将共性的内容打成二方依赖包,每个垂直业务依赖这个二方包,进行独立应用开发。这种二方依赖的方法最常用,但在二方服务里添加一个通用功能的时候,要告知所有业务方都升级二方包,还要发版,升级的成本高。b. 垂直业务独立应用开发,然后将代码打成jar包,再集成到共性业务应用里,一起部署。该方法依赖关系跟方法a相反,但部署方式不够灵活。如果要实现垂直业务的独立部署,改造成本太高,需要做类隔离,budle隔离等。综合a和b的优点,将共性的业务独立部署,垂直业务既可以独立部署,也可以写在共性内容应用里。当调用某个垂直业务实现时,可以自动路由到具体的垂直业务实现(这个垂直业务实现可以是一个本地调用,也可以是一个远程调用)。这样,垂直业务的开发人员就可以在自己的应用中开发、部署、运维,解决开发人员的隔离问题。至此,业务的隔离,开发人员的隔离问题都已解决。但该架构方案显然不只有详情这一个场景可用,其他类似的业务场景也有相似的问题。因此,架构的代码不能与业务的代码耦合在一起,需要将架构的代码独立出来,形成通用的技术工具,以应用于所有类似的业务,业务开发应该只关心业务的事情。我们特地为此开发了一个多实现“业务隔离”路由工具,最终的隔离架构设计图如下:2.2.领域模型在详情页的使用隔离的问题解决了,再来谈谈详情页的领域建模。为何需要领域建模?好多java开发的同学,大都会遇到这样的问题:1)一门OO(面向对象)的语言,写出来的代码都没有OO的感觉,到像是过程式的代码,面向对象的思想基本没有使用到。2)虽然代码满足了业务需求,但从代码中,完全看不到业务领域的影子,业务领域和代码是脱节的。3)随着业务的越来越复杂,里面的依赖关系梳理起来非常困难,业务模块没有边界可言。为了不给后人挖坑,为了解决详情页复杂的逻辑,为了让代码更有范,为了让接手详情的同学都有统一的业务领域认知,因此决定对详情领域进行领域建模。Eric Evans的那本《领域驱动设计——软件核心复杂性应对之道》经典书籍大行其道十几年,网上关于领域建模的文章也是浩如烟海,自顶向下、自底向上、四色原型建模、问题空间领域模型抽象方法论也非常的多。但这些文章和书籍,要么谈论理论概念,要么谈论建模方式,对初学者来说,看完之后,还是写不出相应的代码。所以本文不在重复的去讲领域建模的概念,直接通过闲鱼详情页这个业务场景,讲述建模的步骤、DDD的代码展示,给读者一个更直观的参考。2.2.1 详情页领域建模闲鱼详情页是一个纯展示的页面,用一句话可以概括为,“详情页是包括:商品、卖家、买家、鱼塘、认证、互动等内容的信息聚合展示页” 。这里我们使用四色原型建模法进行建模。上面的这句话最骨干的内容为:详情页是一个“信息聚合展示页”(瞬间事件)。骨干内容定义好后,为了更好的描述详情页是什么,需要补充一些实体对象,详情页主要包含商品、卖家、买家、鱼塘这些实体(人-物-地点)。在此基础上,进一步的进行抽象,用户实体中,有卖家、买家这个角色存在;鱼塘实体中,又有塘主、塘民角色存在(塘主也是塘民,所以塘主应该继承自塘民)。加入角色后的模型如图11所示:最后,再把一些描述信息放进去有了模型的设计,再转为类图设计。根据模型的抽象,详情页是信息展示的聚合,因此它是个聚合根,包含了商品、卖家、买家、鱼塘这些实体信息。 商品信息描述里,又有视频、图片、文本、互动等信息。视频、图片可以抽象为媒体信息。使用UML设计出最终的类图,如图13所示2.2.2 DDD代码展示在实现详情页时,依据的是DDD中的定义。DDD中最主要的内容包括:entity、value object、aggregate、repository、factory和service (如图8所示), 以及Infrastructure, Domain, application和User Interface 分层结构,如图14所示:Infrastructure主要用于持久化数据的读取和写入;Domain为领域层,提供领域信息,这是业务的核心所在;Application是很薄的一层,没有业务逻辑,用来协调应用活动;User Interface负责用户信息展示。将这个分层结构映射到工程结构如图15所示。这里的Applicaiton层没有业务逻辑,只作为二方服务对外提供。此外,工程结构中没有写User Interface层,因为该应用是以二方服务提供,当然,如果提供REST服务,则可以写在这一层。多数的用户对MVC架构比较了解,因此,图16对比了DDD的分层架构和MVC的架构,以做参考。根据上文的模型抽象,领域对象主要有 ItemEntity, SellerEnity, BuyerEntity, FishPoolEntity,并通过详情页聚合根DetailAggregate聚合。在图15应用结构分层中,有3种类型的数据对象,DO对象表示持久化的数据对象, Entity为领域对象,DTO为对外的传输对象。首先通过领域层的Repository,调用基础设置层的Dao读取DO结构,再使用Convertor转为Entity领域对象。领域entity处理各自的领域业务逻辑,然后通过领域层的DetailService,对聚合根DetailAggregate进行整体详情页业务领域处理。最后转为DTO传输对象提供对外服务。三: 总结和思考本文从详情页业务出发,当业务越来越复杂时,如何做业务的隔离,做开发人员的隔离,以及如何通过领域建模,形成统一认知。给大家提供一个可行的参考。但没有任何一种架构可以适用于所有的场景,也没有任何一个架构是最优的,所谓架构,都在解决“边界”的问题。因此都需要从实际的业务场景出发,明确出问题的边界在哪里,要达到什么样的目标,再遵循一些基本的原则和方法,基本都能够设计出符合自己业务特性的架构。接下来将会给大家分享一篇从不同的视角出发,进行的业务架构设计。本文作者:闲鱼技术-绛曲阅读原文本文为云栖社区原创内容,未经允许不得转载。

February 18, 2019 · 1 min · jiezi

可应用于实际的14个NLP突破性研究成果(四)

摘要:最好的论文是可以直接走出实验室!NLP年度最佳应用论文大集锦!可应用于实际的14个NLP突破性研究成果(一) 可应用于实际的14个NLP突破性研究成果(二) 可应用于实际的14个NLP突破性研究成果(三)11.对序列建模的通用卷积和递归网络的实证评估作者:SHAOJIE BAI,J。ZICO KOLTER,VLADLEN KOLTUN论文摘要对于大多数深度学习实践者来说,序列建模与循环网络是同义词。然而,最近的研究结果表明,卷积架构在语音合成和机器翻译等任务上的表现优于循环网络。给定一个新的序列建模任务或数据集,应该使用哪种架构?我们对序列建模的一般卷积和循环架构进行了系统的评价。我们在广泛的标准任务中评估这些模型。我们的结果表明,一个简单的卷积架构在不同的任务和数据集上的表现优于LSTM等典型的循环网络。我们的结论是,需要重新考虑序列建模和循环网络之间的共同关联,卷积网络应该被视为序列建模任务的一个自然起点我们提供了相关代码:http://github.com/locuslab/TCN。总结本文的作者质疑了一个常见假设,即循环架构应该是序列建模任务的默认起点。他们的结果表明,时间卷积网络(TCN)在多个序列建模任务中明显优于长短期记忆网络(LSTMs)和门控循环单元网络等典型的循环架构。论文的核心思想是什么?1、时间卷积网络(TCN)是基于最近提出的最佳实践(如扩张卷积和残差连接)设计的,它在一系列复杂的序列建模任务中表现得明显优于通用的循环架构。2、TCN表现出比循环架构更长的记忆,因此更适合需要较长的历史记录的任务。关键成就是什么?在序列建模任务上提供了卷积架构和循环体系结构系统的比较。设计了卷积体系结构,它可以作为序列建模任务的方便且强大的起点。AI社区的对其评价?在使用RNN之前,一定要先从CNN开始。未来的研究领域是什么?为了提高TCN在不同序列建模任务中的性能,需要进一步精化架构和算法。可能应用的商业领域?引入TCN可以提高依赖于循环架构进行序列建模的AI系统的性能。其中包括以下任务:§机器翻译;§语音识别;§音乐和语音生成。你在哪里可以得到代码?1、如论文摘要所述,研究人员通过GitHub存储库提供了官方代码。2、你还可以查看PhilippeRémy提供的Keras实施的TCN。12.用于文本分类的通用语言模型微调-ULMFiT作者:JEREMY HOWARD和SEBASTIAN RUDER论文摘要迁移学习在计算机视觉方面取得了很多成功,但是同样的方法应用在NLP领域却行不通。所以我们提出了通用语言模型微调(ULMFiT),这是一种有效的转移学习方法,可以应用于NLP中的任何任务。该方法在6个文本分类任务上的性能明显优于现有的文本分类方法,在大部分的数据集上测试使得错误率降低了18-24%。此外,仅有100个标记样本训练的结果也相当不错。我们已经开源我们的预训练模型和代码。总结Howard和Ruder建议使用预先训练的模型来解决各种NLP问题。使用这种方法的好处是你无需从头开始训练模型,只需对原始模型进行微调。通用语言模型微调(ULMFiT)的方法优于最先进的结果,它将误差降低了18-24%。更重要的是,ULMFiT可以只使用100个标记示例,就能与10K标记示例中从头开始训练的模型的性能相匹配。论文的核心思想是什么?为了解决缺乏标记数据的难题,研究人员建议将转移学习应用于NLP问题。因此,你可以使用另一个经过训练的模型来解决类似问题作为基础,然后微调原始模型以解决你的特定问题,而不是从头开始训练模型。但是,这种微调应该考虑到几个重要的考虑因素:§不同的层应该进行不同程度地微调,因为它们捕获不同类型的信息。§如果学习速率首先线性增加然后线性衰减,则将模型的参数调整为任务特定的特征将更有效。§微调所有层可能会导致灾难性的遗忘;因此,从最后一层开始逐渐微调模型可能会更好。关键成就是什么?显著优于最先进的技术:将误差降低18-24%;所需的标记数据要少得多,但性能可以保障。AI社区对其的看法是什么?预先训练的ImageNet模型的可用性已经改变了计算机视觉领域,ULMFiT对于NLP问题可能具有相同的重要性。此方法可以应用于任何语言的任何NLP任务。未来的研究领域的方向是什么?改进语言模型预训练和微调。将这种新方法应用于新的任务和模型(例如,序列标记、自然语言生成、蕴涵或问答)。可能应用的商业领域?ULMFiT可以更有效地解决各种NLP问题,包括:§识别垃圾邮件、机器人、攻击性评论;§按特定功能对文章进行分组;§对正面和负面评论进行分类;§查找相关文件等你在哪里可以得到实现代码?Fast.ai提供ULMFiT的官方实施,用于文本分类,并作为fast.ai库的一部分。13.用非监督学习来提升语言理解,作者:ALEC RADFORD,KARTHIK NARASIMHAN,TIM SALIMANS,ILYA SUTSKEVER论文摘要自然语言理解包括各种各样的任务,例如文本蕴涵、问答、语义相似性评估和文档分类。虽然大量未标记的文本语料库很丰富,但用于学习这些特定任务的标记数据很少。我们证明,通过对多种未标记文本语料库中的语言模型进行生成预训练,然后对每项特定任务进行辨别性微调,可以实现这些任务的巨大收益。与以前的方法相比,我们在微调期间利用任务感知输入转换来实现有效传输,同时对模型架构进行最少的更改。我们证明了我们的方法在广泛的自然语言理解基准上的有效性。例如,我们在常识推理(Stories Cloze Test)上获得8.9%的性能改善,在问答(RACE)上达到5.7%,在文本蕴涵(MultiNLI)上达到1.5%。总结OpenAI团队建议通过在多种未标记文本语料库中预先训练语言模型,然后使用标记数据集对每个特定任务的模型进行微调,从而可以显著改善了语言理解。他们还表明,使用Transformer模型而不是传统的递归神经网络可以显著提高模型的性能,这种方法在所研究的12项任务中有9项的表现优于之前的最佳结果。论文的核心思想是什么?通过在未标记数据上学习神经网络模型的初始参数,然后使用标记数据使这些参数适应特定任务,结合使用无监督预训练和监督微调。通过使用遍历样式方法避免跨任务对模型体系结构进行大量更改:§预训练模型是在连续的文本序列上训练的,但是问题回答或文本蕴涵等任务具有结构化输入。§解决方案是将结构化输入转换为预先训练的模型可以处理的有序序列。使用Transformer模型而不是LSTM,因为这些模型提供了更加结构化的内存,用于处理文本中的长期依赖关系。取得了什么关键成就?对于自然语言推理(NLI)的任务,通过在SciTail上获得5%的性能改进和在QNLI上获得5.8%的性能改进。对于QA和常识推理的任务,表现优于以前的最佳结果-在Story Cloze上高达8.9%,在RACE上高达5.7%。通过在QQP上实现4.2%的性能改善,刷新了3个语义相似性任务中的2个的最新结果。对于分类任务,获得CoLA的45.4分,而之前的最佳结果仅为35分。AI社区对其看法是什么?该论文通过使用基于Transformer模型而非LSTM扩展了ULMFiT研究,并将该方法应用于更广泛的任务。“这正是我们希望我们的ULMFiT工作能够发挥作用的地方!”Jeremy Howard,fast.ai的创始人。未来的研究领域是什么?进一步研究自然语言理解和其他领域的无监督学习,以便更好地理解无监督学习的时间和方式。可能应用的商业领域?OpenAI团队的方法通过无监督学习增强了自然语言理解,因此可以帮助标记数据集稀疏或不可靠的NLP应用。 在哪里可以得到实现代码?Open AI团队在GitHub上的公开了代码和模型。14.语境化词向量解析:架构和表示,作者:MATTHEW E. PETERS,MARK NEUMANN,LUKE ZETTLEMOYER,WEN-TAU YIH论文摘要最近研究显示从预训练的双向语言模型(biLM)导出的上下文词表示为广泛的NLP任务提供了对现有技术的改进。然而,关于这些模型如何以及为何如此有效的问题,仍然存在许多问题。在本文中,我们提出了一个详细的实证研究,探讨神经结构的选择(例如LSTM,CNN)如何影响最终任务的准确性和所学习的表征的定性属性。我们展示了如何在速度和准确性之间的权衡,但所有体系结构都学习了高质量的上下文表示,这些表示优于四个具有挑战性的NLP任务的字嵌入。此外,所有架构都学习随网络深度而变化的表示,从基于词嵌入层的专有形态学到基于较低上下文层的局部语法到较高范围的语义。总之,这些结果表明,无人监督的biLM正在学习更多关于语言结构的知识。总结今年早些时候艾伦人工智能研究所的团队介绍了ELMo嵌入,旨在更好地理解预训练的语言模型表示。为此,他们精心设计了无监督和监督任务上广泛研究学习的单词和跨度表示。研究结果表明,独立于体系结构的学习表示随网络深度而变化。论文的核心思想是什么?预训练的语言模型大大提高了许多NLP任务的性能,将错误率降低了10-25%。但是,仍然没有清楚地了解为什么以及如何在实践中进行预训练。为了更好地理解预训练的语言模型表示,研究人员凭经验研究神经结构的选择如何影响:§直接终端任务准确性;§学习表示的定性属性,即语境化词表示如何编码语法和语义的概念。什么是关键成就?确认在速度和准确度之间存在权衡,在评估的三种架构中-LSTM,Transformer和Gated CNN:§LSTM获得最高的准确度,但也是最慢的;§基于Transformer和CNN的模型比基于LSTM的模型快3倍,但也不太准确。证明由预先训练的双向语言模型(biLM)捕获的信息随网络深度而变化:§深度biLM的词嵌入层专注于词形态,与传统的词向量形成对比,传统的词向量在该层也编码一些语义信息;§biLM的最低上下文层只关注本地语法;证明了biLM激活可用于形成对语法任务有用的短语表示。AI社区对其看法是什么?该论文在EMNLP 2018上发表。 “对我来说,这确实证明了预训练的语言模型确实捕获了与在ImageNet上预训练的计算机视觉模型相似的属性。”AYLIEN的研究科学家Sebastian Ruder。未来的研究领域是什么?使用明确的句法结构或其他语言驱动的归纳偏见来增强模型。 将纯无监督的biLM训练目标与现有的注释资源以多任务或半监督方式相结合。可能应用的商业领域?1、通过更好地理解预训练语言模型表示所捕获的信息,研究人员可以构建更复杂的模型,并增强在业务环境中应用的NLP系统的性能。本文作者:【方向】阅读原文本文为云栖社区原创内容,未经允许不得转载。

February 18, 2019 · 1 min · jiezi

分布式系统「伸缩性」大招之——「弹性架构」详解

如果第二次看到我的文章,欢迎下方扫码订阅我的个人公众号(跨界架构师)哟本文长度为3633字,建议阅读10分钟。坚持原创,每一篇都是用心之作~如果我们的开发工作真的就如搭积木一般就好了,轮廓分明,个个分开,坏了哪块积木换掉哪块就好了。但是,实际我们的工作中所面临的可能只有一块积木,而且还是一大块,要换得一起换,要修得一起修。Z哥在之前《分布式系统关注点(13)——「高内聚低耦合」详解》中提到的分层架构它可以让我们有意识的去做一些切分,但是换和修的难度还是根据切分的粒度大小来决定的。有更好的方式吗?这是显然的。事件驱动架构我们来换一个思维看待这个问题。不管是平时的系统升级也好、修复bug也好、扩容也好,其实就是一场“手术”。通过这场“手术”来解决当前面临的一些问题。那么分层架构好比只是将一个人的手、脚、嘴、鼻等分的清清楚楚,但是整体还是紧密的耦合在一起。怎么耦合的呢?我们人是靠“血液”的流动连接起来的。这就好比在分布式系统中通过rpc框架连接起不同的节点一样。但是软件与人不同,有2种不同的连接方式,除了「同步」的方式之外还有「异步」的方式。因为有些时候你不需要知道其他系统的执行结果,只要确保自己将其需要的数据传递给它了即可。恰巧有一种架构是这种模式的典型——事件驱动架构(简称EDA,Event Driven Architecture)。平时常见的MQ、本地消息表等运用于数据传递的中转环节,就是事件驱动架构的思想体现。事件驱动架构又细分为两种典型的实现方式,与Z哥之前在《分布式系统关注点(3)——「共识」的兄弟「事务」》中提到的Saga模式的2种实现方式类似,一种是中心化的、一种是去中心化的。下面Z哥来举个例子,让你看起来更容易理解一些。(例子仅为了阐述是怎么工作的,真正的实施中还需要考虑如何保证数据一致性等问题,这部分可以参考之前发表的系列文章,文末带传送门)传统的电商场景中,用户从购物车中点击“提交”按钮后,至少需要做这几件事:生成一笔订单、生成一笔支付记录、给订单匹配发货的快递公司。在这个场景下,中心化和去中心化有什么不同呢?中心化这种模式拥有一个“上帝”。但是“上帝”不会处理也不知道任何业务逻辑,它只编排事件。除了中心化之外,它还有什么特点呢?Z哥给它的定义是“3+2结构”。这种模式中存在3种类型的主体:事件生产者、“上帝”(调停者)、事件处理者。然后中间夹着两层队列,以此结构就能解耦。就像这样:事件生产者 –> 队列 –> “上帝”(调停者) –> 队列 –> 事件处理者。那么回上面的这个例子中,事件生产者CartService发出了一个“订单创建”事件,通过队列传递给调停者。然后调停者根据事先制定好的编排规则对事件进行相应的转换,也通过队列做二次分发,传递给事件处理者。可能你会问,这些好理解。但是,我之前也经常看到什么编排编排的,到底编排该怎么做呢?其实编排主要做两件事:「事件转换」和「事件发送」(对应「服务编排」类框架的「调用」)。「事件转换」实质就是给将要发送的事件对象的参数进行赋值。赋值的数据来源于哪呢?除了事件产生的源头带入的参数,还有持续累积的「上下文」,就如下图中这样的一个共享存储空间。可能你又会问,我怎么将多个事件处理者之间组合成一个上下文呢?通过一个全局唯一的标识即可,每次向“上帝”丢事件的时候把这个全局唯一标识带过去。题外话:一般来说,还会在一个全局唯一标识之下带一个内部唯一的「子流水号」,为了配合做接下去要讲到的「事件发送」。一是为了后续排查问题的时候清晰的知道这次调用产生的异常是从哪个上游系统来的。二是为了便于观测整个调用的逻辑是否符合编排时的预期。怎么做呢?通过一个x.x.x.x格式的序号。比如,串行就是1,2,3。分支和并行就是2.1,2.2。分支+串行的结合就是1,2,2.1,2.2,3。「事件发送」实质就是负责事件流转的逻辑控制,然后发往「事件处理者」去处理。它决定了是按顺序还是分支进行?是串行还是并行?到这就不再展开了,要不然就跑题了,我们下次再细聊这部分内容。再强调一下,「事件转换」和「事件发送」是你在实现“上帝”(调停者)功能的时候需要满足的最基本的两个功能哦。中心化最大的优势是让流程更加的“可见”了,同时也更容易去做一些监控类的东西,系统规模越大,这个优势产生的效果越明显。但是一个最基本的“上帝”(调停者)实现起来还需要考虑数据一致性问题,所以,会大大增加它的实现复杂度。因此,如果你面对的场景,业务没有特别庞大,并且是比较稳定的,或许用去中心化的方式也是不错的选择。去中心化这个模式由于没有了“上帝”,因此每个事件处理者需要知道自己的下一个事件处理器是什么?需要哪些参数?以及队列是哪个之类的东西。但是整体结构会变得简单很多,从“3+2结构”变成了“2+1结构”。结构简化背后的复杂度都跑到事件处理者开发人员编写的业务代码中去了。因为他需要自己去负责「事件转换」和「事件发送」这两个事情。嗯,改造成事件驱动架构之后,通过「队列」的解耦和异步的事件流转,系统的运转的确会更顺畅。但是有时候你可能想进行更细粒度的控制,因为一般情况下,一个service中会处理很多业务环节,不太会只存在一个对外接口、一条业务逻辑。在这样的情况下,很多时候你可能需要修改的地方仅仅是其中的一个接口。能不能只修改其中的一部分代码并且进行「热更新」呢?微内核架构(插件架构)就适合来解决这个问题。微内核架构顾名思义,微内核架构的关键是内核。所以需要先找到并明确内核是什么?然后将其它部分都视作“可拆卸”的部件。好比我们一个人,大脑就是内核,其它的什么都可以换,换完之后你还是你,但是大脑换了就不是你了。微内核架构整体上由两部分组成:核心系统和插件模块。核心系统内又包含了微内核、插件模块,以及内置的一些同样以插件形式提供的默认功能。其中,微内核主要负责插件的生命周期管理和控制插件模块。插件模块则负责插件的加载、替换和卸载。外部的插件如果要能够接入进来并顺利运行,前提先要有一个满足标准接口规范的实现。一个插件的标准接口至少会有这样的2个方法需要具体的插件来实现:public interface IPlugin{ /// <summary> /// 初始化配置 /// </summary> void InitializeConfig(Dictionary<string,string> configs); /// <summary> /// 运行 /// </summary> void Run(); …}最后,插件之间彼此独立,但核心系统知道哪里可以找到它们以及如何运行它们。 最佳实践知道了这两种具有“弹性”的架构模式,你该如何判断什么情况下需要搬出来用呢?Z哥带你来分析一下每一种架构的优缺点,就能发现它适用的场景。事件驱动架构它的优点是:通过「队列」进行解耦,使得面对快速变化的需求可以即时上线,而不影响上游系统。由于「事件」是一个独立存在的“标准化”沟通载体,可以利用这个特点衔接各种跨平台、多语言的程序。如果再进行额外的持久化,还能便于后续的问题排查。同时也可以对「事件」进行反复的「重放」,对处理者的吞吐量进行更真实的压力测试。更“动态”、容错性好。可以很容易,低成本地集成、再集成、再配置新的和已经存在的事件处理者,也可以很容易的移除事件处理者。轻松的做扩容和缩容。在“上帝”模式下,对业务能有一个“可见”的掌控,更容易发现流程不合理或者被忽略的问题。同时能标准化一些技术细节,如「数据一致性」的实现方式等。它的缺点是:面对不稳定的网络问题、各种异常,想要处理好这些以确保一致性,需要比同步调用花费很大的精力和成本。无法像同步调用一般,操作成功后即代表可以看到最新的数据,需要容忍延迟或者对延迟做一些用户体验上的额外处理。那么,它所适用的场景就是:对实时性要求不高的场景。系统中存在大量的跨平台、多语言的异构环境。以尽可能提高程序复用度为目的的场景。业务灵活多变的场景。需要经常扩容缩容的场景。微内核架构它的优点是:为递进设计和增量开发提供了方便。可以先实现一个稳固的核心系统,然后逐渐地增加功能和特性。和事件驱动架构一样,也可避免单一组件失效,而造成整个系统崩溃,容错性好。内核只需要重新启动这个组件,不致于影响其他功能。它的缺点是:由于主要的微内核很小,所以无法对整体进行优化。每个插件都各自管各自的,甚至可能是由不同团队负责维护。一般来说,为了避免在单个应用程序中的复杂度爆炸,很少会启用插件嵌套插件的模式,所以插件中的代码复用度会差一些。那么,它所适用的场景就是:可以嵌入或者作为其它架构模式的一部分。例如事件驱动架构中,“上帝”的「事件转换」就可以使用微内核架构实现。业务逻辑虽然不同,但是运行逻辑相同的场景。比如,定期任务和作业调度类应用。具有清晰的增量开发预期的场景。总结好了,我们总结一下。这次呢,Z哥向你介绍了「事件驱动架构」的两种实现模式和实现思路,以及「微内核架构」的实现思路。并且奉上了对这两种架构模式的优缺点与适用场景分析的最佳实践。希望对你有所启发。相关文章:分布式系统关注点(1)——初识数据一致性分布式系统关注点(2)——通过“共识”达成数据一致性分布式系统关注点(3)——「共识」的兄弟「事务」作者:Zachary出处:https://www.cnblogs.com/Zacha…如果你喜欢这篇文章,可以点一下文末的「赞」。这样可以给我一点反馈。: )谢谢你的举手之劳。▶关于作者:张帆(Zachary,个人微信号:Zachary-ZF)。坚持用心打磨每一篇高质量原创。欢迎扫描下方的二维码。定期发表原创内容:架构设计丨分布式系统丨产品丨运营丨一些思考。如果你是初级程序员,想提升但不知道如何下手。又或者做程序员多年,陷入了一些瓶颈想拓宽一下视野。欢迎关注我的公众号「跨界架构师」,回复「技术」,送你一份我长期收集和整理的思维导图。如果你是运营,面对不断变化的市场束手无策。又或者想了解主流的运营策略,以丰富自己的“仓库”。欢迎关注我的公众号「跨界架构师」,回复「运营」,送你一份我长期收集和整理的思维导图。

February 18, 2019 · 1 min · jiezi

用友云开发者中心助你上云系列之在线调试

现在,大家开始越来越多的谈论到高可用架构的互联网应用。什么是高可用?高可用HA(High Availability)是分布式系统架构设计中必须考虑的因素之一,它通常是指,通过设计减少系统不能提供服务的时间。当我们谈论服务高可用的时候,我们通常聚焦在高并发、大流量、高可用性等关键字,企业上云,这些问题也是不可避免的。互联网应用正在由单体应用架构演变为微服务架构,服务的拆分,使得部署在云的运行实例也指数级的增加。但是!测试再充分的服务,在线上运行起来后,都可能会出现问题。这些问题可能跟架构设计有关,也可能是为了快速响应用户需求在快速迭代中带来的BUG.这些缺陷如同大堤上的蚁穴,随时可能会引起线上服务的整体崩溃。在这种情况下,我们就需要研发人员能迅速定位问题,并将修复问题后的版本在用户无感知的情况下快速上线,将缺陷的负面影响最小化。而线上问题的快速定位无非从日志分析、性能监控、线上环境的远程调试等几个方面入手。不同的方式适用于不同状况,各有千秋。但在这些解决方案中,基于线上环境的远程调试往往能够迅速分析出原因并解决,问题的解决速度脱颖而出。什么是Java远程调试?Java远程调试的原理是两个Java VM之间通过debug协议进行通信,然后以达到远程调试的目的。两者之间可以通过socket进行通信,被debug程序的Java虚拟机在启动时开启debug模式,启动debug监听程序。JDWP是Java Debug Wire Protocol的缩写,它定义了调试器(debugger)和被调试的Java虚拟机(target vm)之间的通信协议。target vm中运行着我们希望要调试的程序,它与一般运行的Java虚拟机没有什么区别,只是在启动时加载了Agent JDWP从而具备了调试功能。而debugger就是我们熟知的调试器,它向运行中的target vm发送命令来获取 target vm运行时的状态和控制Java程序的执行。Debugger和target vm分别在各自的进程中运行,他们之间的通信协议就是JDWP。如何使用开发者中心进行在线调试?如果你已经使用了开发者中心部署应用(上云),那么,可以非常荣幸的告诉你,看完下面的步骤,只需几秒钟的配置,就可以解救你于水火之中。抛开一切烦恼,掏出你的笔记本电脑,准备开始具体的配置吧。操作步骤应用属性增加环境变量CATALINA_OPTS = -Xdebug -Xrunjdwp:transport=dt_socket,address=8000,server=y,suspend=n如图:应用增加调试端口,需和步骤1中的属性address=8000一致,如8000如图:保存并重启实例实例重启完毕后,点击需要远程调试的实例控制台在实例控制台中输入echo $PORT0,$PORT1,输出信息为应用放开的端口对应该实例的数组,PORT0对应8080端口,PORT1对应实例的8000端口(即远程调试使用的端口号)查看实例运行的主机配置开发工具IDE的远程调试信息为步骤6的IP地址和步骤5获得的端口至此,大功告成,你可以轻松的进行问题排查了。此过程也可以用于日常开发过程中的在线定位问题,面对众多的微服务,无需再烦恼了。

February 14, 2019 · 1 min · jiezi

无监控、不运维。运维系统架构设计附带思维导图

无监控、不运维运维行业有句话:“无监控、不运维”。是的,一点也不夸张,监控俗称“第三只眼”。没了监控,什么基础运维,业务运维都是“瞎子”。**开篇所以说监控是运维这个职业的第一步。尤其是在现在DevOps这么火的时候,用监控数据给自己撑腰,这显得更加必要。有人说运维是背锅侠,那么,有了监控,有了充足的数据,一切以数据说话,运维还需要背锅吗,所以作为一个运维工程师,如何构建一套监控系统是你的第一件工作。统一运维监控平台设计思路运维监控平台不是简单的下载一个开源工具,然后搭建起来就行了,它需要根据监控的环境和特点进行各种整合和二次开发,以达到与自己的需求完全吻合的程度。**那么下面就谈谈运维监控平台的设计思路。构建一个智能的运维监控平台,必须以运行监控和故障报警这两个方面为重点,将所有业务系统中所涉及的网络资源、硬件资源、软件资源、数据库资源等纳入统一的运维监控平台中,并通过消除管理软件的差别。数据采集手段的差别,对各种不同的数据来源实现统一管理、统一规范、统一处理、统一展现、统一用户登录、统一权限控制,最终实现运维规范化、自动化、智能化的大运维管理。架构设计智能的运维监控平台,设计架构从低到高可以分为6层,三大模块,如下图:设计架构从低到高可以分为6层数据收集层:位于最底层,主要收集网络数据、业务系统数据、数据库数据、操作系统数据等,然后将收集到的数据进行规范化并进行存储。数据展示层:位于第二层,是一个Web展示界面,主要是将数据收集层获取到的数据进行统一展示,展示的方式可以是曲线图、柱状图、饼状态等,通过将数据图形化,可以帮助运维人员了解一段时间内主机或网络的运行状态和运行趋势,并作为运维人员排查问题或解决问题的依据。数据提取层:位于第三层,主要是对从数据收集层获取到的数据进行规格化和过滤处理,提取需要的数据到监控报警模块,这个部分是监控和报警两个模块的衔接点。报警规则配置层:位于第四层,主要是根据第三层获取到的数据进行报警规则设置、报警阀值设置、报警联系人设置和报警方式设置等。报警事件生成层:位于第五层,主要是对报警事件进行实时记录,将报警结果存入数据库以备调用,并将报警结果形成分析报表,以统计一段时间内的故障率和故障发生趋势。用户展示管理层:**位于最顶层,是一个Web展示界面,主要是将监控统计结果、报警故障结果进行统一展示,并实现多用户、多权限管理,实现统一用户和统一权限控制。功能实现划分3大模块在这6层中,从功能实现划分,又分为三个模块,分别是数据收集模块、数据提取模块和监控报警模块,每个模块完成的功能如下:数据收集模块:此模块主要完成基础数据的收集与图形展示。数据收集的方式有很多种,可以通过SNMP实现,也可以通过代理模块实现,还可以通过自定义脚本实现。常用的数据收集工具有Cacti、Ganglia等。数据提取模块:此模板主要完成数据的筛选过滤和采集,将需要的数据从数据收集模块提取到监控报警模块中。可以通过数据收集模块提供的接口或自定义脚本实现数据的提取。监控报警模块:此模块主要完成监控脚本的设置、报警规则设置,报警阀值设置、报警联系人设置等,并将报警结果进行集中展现和历史记录。常见的监控报警工具有Nagios、Centreon等。思维导图

February 13, 2019 · 1 min · jiezi

Spring Cloud Alibaba基础教程:Nacos配置的多环境管理

前情回顾:《Spring Cloud Alibaba基础教程:使用Nacos实现服务注册与发现》《Spring Cloud Alibaba基础教程:支持的几种服务消费方式》《Spring Cloud Alibaba基础教程:使用Nacos作为配置中心》《Spring Cloud Alibaba基础教程:Nacos配置的加载规则详解》通过之前两篇对Nacos配置管理功能的介绍,已经学会了在Nacos中如何加入配置以及Spring Cloud应用如何通过配置来加载到对应的内容。接下来,我们讨论一个在使用配置中心时,都需要关注的一个问题:多环境的配置如何实现与管理?多环境管理在Nacos中,本身有多个不同管理级别的概念,包括:Data ID、Group、Namespace。只要利用好这些层级概念的关系,就可以根据自己的需要来实现多环境的管理。下面,我就来介绍一下,可以使用的几种实现方式:使用Data ID与profiles实现Data ID在Nacos中,我们可以理解为就是一个Spring Cloud应用的配置文件名。通过上一篇《Spring Cloud Alibaba基础教程:Nacos配置的加载规则详解》,我们知道默认情况下Data ID的名称格式是这样的:${spring.application.name}.properties,即:以Spring Cloud应用命名的properties文件。实际上,Data ID的规则中,还包含了环境逻辑,这一点与Spring Cloud Config的设计类似。我们在应用启动时,可以通过spring.profiles.active来指定具体的环境名称,此时客户端就会把要获取配置的Data ID组织为:${spring.application.name}-${spring.profiles.active}.properties。实际上,更原始且最通用的匹配规则,是这样的:${spring.cloud.nacos.config.prefix}-${spring.profile.active}.${spring.cloud.nacos.config.file-extension}。而上面的结果是因为${spring.cloud.nacos.config.prefix}和${spring.cloud.nacos.config.file-extension}都使用了默认值。动手试一试我们可以用《Spring Cloud Alibaba基础教程:使用Nacos作为配置中心》一文中的列子(可在文末仓库中获取)为基础,体验一下这种区分环境的配置方式。第一步:先在Nacos中,根据这个规则,创建两个不同环境的配置内容。比如:如上图,我们为alibaba-nacos-config-client应用,定义了DEV和TEST的两个独立的环境配置。我们可以在里面定义不同的内容值,以便后续验证是否真实加载到了正确的配置。第二步:在alibaba-nacos-config-client应用的配置文件中,增加环境配置:spring.profiles.active=DEV第三步:启动应用,我们可以看到日志中打印了,加载的配置文件:2019-01-30 15:25:18.216 INFO 96958 — [ main] o.s.c.a.n.c.NacosPropertySourceBuilder : Loading nacos data, dataId: ‘alibaba-nacos-config-client-DEV.properties’, group: ‘DEFAULT_GROUP’使用Group实现Group在Nacos中是用来对Data ID做集合管理的重要概念。所以,如果我们把一个环境的配置视为一个集合,那么也就可以实现不同环境的配置管理。对于Group的用法并没有固定的规定,所以我们在实际使用的时候,需要根据我们的具体需求,可以是架构运维上对多环境的管理,也可以是业务上对不同模块的参数管理。为了避免冲突,我们需要在架构设计之初,做好一定的规划。这里,我们先来说说如何用Group来实现多环境配置管理的具体实现方式。动手试一试第一步:先在Nacos中,通过区分Group来创建两个不同环境的配置内容。比如:如上图,我们为alibaba-nacos-config-client应用,定义了DEV环境和TEST环境的两个独立的配置,这两个匹配与上一种方法不同,它们的Data ID是完全相同的,只是GROUP不同。第二步:在alibaba-nacos-config-client应用的配置文件中,增加Group的指定配置:spring.cloud.nacos.config.group=DEV_GROUP第三步:启动应用,我们可以看到日志中打印了,加载的配置文件:2019-01-30 15:55:23.718 INFO 3216 — [main] o.s.c.a.n.c.NacosPropertySourceBuilder : Loading nacos data, dataId: ‘alibaba-nacos-config-client.properties’, group: ‘DEV_GROUP’使用Namespace实现Namespace在本系列教程中,应该还是第一次出现。先来看看官方的概念说明:用于进行租户粒度的配置隔离。不同的命名空间下,可以存在相同的Group或Data ID的配置。Namespace的常用场景之一是不同环境的配置的区分隔离,例如:开发测试环境和生产环境的资源(如配置、服务)隔离等。在官方的介绍中,就介绍了利用其可以作为环境的隔离使用,下面我们就来试一下吧!动手试一试第一步:先在Nacos中,根据环境名称来创建多个Namespace。比如:第二步:在配置列表的最上方,可以看到除了Public之外,多了几个刚才创建的Namepsace。分别在DEV和TEST空间下为alibaba-nacos-config-client应用创建配置内容:第三步:在alibaba-nacos-config-client应用的配置文件中,增加Namespace的指定配置,比如:spring.cloud.nacos.config.namespace=83eed625-d166-4619-b923-93df2088883a。这里需要注意namespace的配置不是使用名称,而是使用Namespace的ID。第四步:启动应用,通过访问localhost:8001/test接口,验证一下返回内容是否正确。这种方式下,目前版本的日志并不会输出与Namespace相关的信息,所以还无法以此作为加载内容的判断依据。深入思考上面我们分别利用Nacos配置管理功能中的几个不同纬度来实现多环境的配置管理。从结果上而言,不论用哪一种方式,都能够胜任需求,但是哪一种最好呢?第一种:通过Data ID与profile实现。优点:这种方式与Spring Cloud Config的实现非常像,用过Spring Cloud Config的用户,可以毫无违和感的过渡过来,由于命名规则类似,所以要从Spring Cloud Config中做迁移也非常简单。缺点:这种方式在项目与环境多的时候,配置内容就会显得非常混乱。配置列表中会看到各种不同应用,不同环境的配置交织在一起,非常不利于管理。建议:项目不多时使用,或者可以结合Group对项目根据业务或者组织架构做一些拆分规划。第二种:通过Group实现。优点:通过Group按环境讲各个应用的配置隔离开。可以非常方便的利用Data ID和Group的搜索功能,分别从应用纬度和环境纬度来查看配置。缺点:由于会占用Group纬度,所以需要对Group的使用做好规划,毕竟与业务上的一些配置分组起冲突等问题。建议:这种方式虽然结构上比上一种更好一些,但是依然可能会有一些混乱,主要是在Group的管理上要做好规划和控制。第三种:通过Namespace实现。优点:官方建议的方式,通过Namespace来区分不同的环境,释放了Group的自由度,这样可以让Group的使用专注于做业务层面的分组管理。同时,Nacos控制页面上对于Namespace也做了分组展示,不需要搜索,就可以隔离开不同的环境配置,非常易用。缺点:没有啥缺点,可能就是多引入一个概念,需要用户去理解吧。建议:直接用这种方式长远上来说会比较省心。虽然可能对小团队而言,项目不多,第一第二方式也够了,但是万一后面做大了呢?注意:不论用哪一种方式实现。对于指定环境的配置(spring.profiles.active=DEV、spring.cloud.nacos.config.group=DEV_GROUP、spring.cloud.nacos.config.namespace=83eed625-d166-4619-b923-93df2088883a),都不要配置在应用的bootstrap.properties中。而是在发布脚本的启动命令中,用-Dspring.profiles.active=DEV的方式来动态指定,会更加灵活!。参考资料Nacos官方文档代码示例本文示例读者可以通过查看下面仓库的中的alibaba-nacos-config-client项目:Github:https://github.com/dyc87112/SpringCloud-Learning/Gitee:https://gitee.com/didispace/SpringCloud-Learning/如果您对这些感兴趣,欢迎star、follow、收藏、转发给予支持!以下专题教程也许您会有兴趣Spring Boot基础教程Spring Cloud基础教程

February 1, 2019 · 1 min · jiezi

Spring Cloud Alibaba基础教程:使用Nacos作为配置中心

通过本教程的前两篇:《Spring Cloud Alibaba基础教程:使用Nacos实现服务注册与发现》《Spring Cloud Alibaba基础教程:支持的几种服务消费方式(RestTemplate、WebClient、Feign)》我们已经学会了,如何利用Nacos实现服务的注册与发现。同时,也介绍了在Spring Cloud中,我们可以使用的几种不同编码风格的服务消费方式。接下来,我们再来一起学习一下Nacos的另外一个重要能力:配置管理。简介Nacos除了实现了服务的注册发现之外,还将配置中心功能整合在了一起。通过Nacos的配置管理功能,我们可以将整个架构体系内的所有配置都集中在Nacos中存储。这样做的好处,在以往的教程中介绍Spring Cloud Config时也有提到,主要有以下几点:分离的多环境配置,可以更灵活的管理权限,安全性更高应用程序的打包更为纯粹,以实现一次打包,多处运行的特点(《云原声应用的12要素》之一)Nacos的配置管理模型与淘宝开源的配置中心Diamond类似,基础层面都通过DataId和Group来定位配置内容,除此之外还增加了很多其他的管理功能。快速入门下面我们通过一个简单的例子来介绍如何在Nacos中创建配置内容以及如何在Spring Cloud应用中加载Nacos的配置信息。创建配置第一步:进入Nacos的控制页面,在配置列表功能页面中,点击右上角的“+”按钮,进入“新建配置”页面,如下图填写内容:其中:Data ID:填入alibaba-nacos-config-client.propertiesGroup:不修改,使用默认值DEFAULT_GROUP配置格式:选择Properties配置内容:应用要加载的配置内容,这里仅作为示例,做简单配置,比如:didispace.title=spring-cloud-alibaba-learning创建应用第一步:创建一个Spring Boot应用,可以命名为:alibaba-nacos-config-client。第二步:编辑pom.xml,加入必要的依赖配置,比如:<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.0.5.RELEASE</version> <relativePath/> <!– lookup parent from repository –></parent><dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Finchley.SR1</version> <type>pom</type> <scope>import</scope> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-alibaba-dependencies</artifactId> <version>0.2.1.RELEASE</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies></dependencyManagement><dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.2</version> <optional>true</optional> </dependency></dependencies>上述内容主要三部分:parent:定义spring boot的版本dependencyManagement:spring cloud的版本以及spring cloud alibaba的版本,由于spring cloud alibaba还未纳入spring cloud的主版本管理中,所以需要自己加入dependencies:当前应用要使用的依赖内容。这里主要新加入了Nacos的配置客户端模块:spring-cloud-starter-alibaba-nacos-config。由于在dependencyManagement中已经引入了版本,所以这里就不用指定具体版本了。可以看到,这个例子中并没有加入nacos的服务发现模块,所以这两个内容是完全可以独立使用的第三步:创建应用主类,并实现一个HTTP接口:@SpringBootApplicationpublic class TestApplication { public static void main(String[] args) { SpringApplication.run(TestApplication.class, args); } @Slf4j @RestController @RefreshScope static class TestController { @Value("${didispace.title:}") private String title; @GetMapping("/test") public String hello() { return title; } }}内容非常简单,@SpringBootApplication定义是个Spring Boot应用;还定义了一个Controller,其中通过@Value注解,注入了key为didispace.title的配置(默认为空字符串),这个配置会通过/test接口返回,后续我们会通过这个接口来验证Nacos中配置的加载。另外,这里还有一个比较重要的注解@RefreshScope,主要用来让这个类下的配置内容支持动态刷新,也就是当我们的应用启动之后,修改了Nacos中的配置内容之后,这里也会马上生效。第四步:创建配置文件bootstrap.properties,并配置服务名称和Nacos地址spring.application.name=alibaba-nacos-config-clientserver.port=8001spring.cloud.nacos.config.server-addr=127.0.0.1:8848注意:这里必须使用bootstrap.properties。同时,spring.application.name值必须与上一阶段Nacos中创建的配置Data Id匹配(除了.properties或者.yaml后缀)。第五步:启动上面创建的应用。2019-01-27 18:29:43.497 INFO 93597 — [ main] o.s.c.a.n.c.NacosPropertySourceBuilder : Loading nacos data, dataId: ‘alibaba-nacos-config-client.properties’, group: ‘DEFAULT_GROUP'2019-01-27 18:29:43.498 INFO 93597 — [ main] b.c.PropertySourceBootstrapConfiguration : Located property source: CompositePropertySource {name=‘NACOS’, propertySources=[NacosPropertySource {name=‘alibaba-nacos-config-client.properties’}]}在启动的时候,我们可以看到类似上面的日志信息,这里会输出应用程序要从Nacos中获取配置的dataId和group。如果在启动之后,发现配置信息没有获取到的时候,可以先从这里着手,看看配置加载的目标是否正确。第六步:验证配置获取和验证动态刷新用curl或者postman等工具,访问接口: localhost:8001/test,一切正常的话,将返回Nacos中配置的spring-cloud-alibaba-learning。然后,再通过Nacos页面,修改这个内容,点击发布之后,再访问接口,可以看到返回结果变了。同时,在应用的客户端,我们还能看到如下日志:2019-01-27 18:39:14.162 INFO 93597 — [-127.0.0.1_8848] o.s.c.e.event.RefreshEventListener : Refresh keys changed: [didispace.title]在Nacos中修改了Key,在用到这个配置的应用中,也自动刷新了这个配置信息。参考资料Nacos官方文档Nacos源码分析代码示例本文示例读者可以通过查看下面仓库的中的alibaba-nacos-config-client项目:Github:https://github.com/dyc87112/SpringCloud-Learning/Gitee:https://gitee.com/didispace/SpringCloud-Learning/如果您对这些感兴趣,欢迎star、follow、收藏、转发给予支持!以下专题教程也许您会有兴趣Spring Boot基础教程Spring Cloud基础教程 ...

January 30, 2019 · 1 min · jiezi

鲜为人知的混沌工程,到底哪里好?

阿里妹导读:混沌工程属于一门新兴的技术学科,行业认知和实践积累比较少,大多数IT团队对它的理解还没有上升到一个领域概念。阿里电商域在2010年左右开始尝试故障注入测试的工作,希望解决微服务架构带来的强弱依赖问题。通过本文,你将了解到:为什么需要混沌工程,阿里巴巴在该领域的实践和思考、未来的计划。一、为什么需要混沌工程?(翻译自Chaos Engineering电子书)1.1 混沌工程与故障测试的区别混沌工程是在分布式系统上进行实验的学科, 目的是建立对系统抵御生产环境中失控条件的能力以及信心,最早由Netflix及相关团队提出。故障演练是阿里巴巴在混沌工程领域的产品,目标是沉淀通用的故障模式,以可控成本在线上重放,以持续性的演练和回归方式运营来暴露问题,不断推动系统、工具、流程、人员能力的不断前进。混沌工程、故障注入和故障测试在关注点和工具中都有很大的重叠。混沌工程和其他方法之间的主要区别在于,混沌工程是一种生成新信息的实践,而故障注入是测试一种情况的一种特定方法。当想要探索复杂系统可能出现的不良行为时,注入通信延迟和错误等失败是一种很好的方法。但是我们也想探索诸如流量激增,激烈竞争,拜占庭式失败,以及消息的计划外或不常见的组合。如果一个面向消费者的网站突然因为流量激增而导致更多收入,我们很难称之为错误或失败,但我们仍然对探索系统的影响非常感兴趣。同样,故障测试以某种预想的方式破坏系统,但没有探索更多可能发生的奇怪场景,那么不可预测的事情就可能发生。测试和实验之间可以有一个重要的区别。在测试中,进行断言:给定特定条件,系统将发出特定输出。测试通常是二进制态的,并确定属性是真还是假。严格地说,这不会产生关于系统的新知识,它只是将效价分配给它的已知属性。实验产生新知识,并经常提出新的探索途径。我们认为混沌工程是一种实验形式,可以产生关于系统的新知识。它不仅仅是一种测试已知属性的方法,可以通过集成测试更轻松地进行验证。混沌实验的输入示例:模拟整个区域或数据中心的故障。部分删除各种实例上的Kafka主题。重新创建生产中发生的问题。针对特定百分比的交易服务之间注入一段预期的访问延迟。基于函数的混乱(运行时注入):随机导致抛出异常的函数。代码插入:向目标程序添加指令和允许在某些指令之前进行故障注入。时间旅行:强制系统时钟彼此不同步。在模拟I/O错误的驱动程序代码中执行例程。在 Elasticsearch 集群上最大化CPU核心。混沌工程实验的机会是无限的,可能会根据分布式系统的架构和组织的核心业务价值而有所不同。1.2 实施混沌工程的先决条件要确定是否已准备好开始采用混沌工程,需要回答一个问题:你的系统是否能够适应现实世界中的事件,例如服务故障和网络延迟峰值?如果答案是“否”,那么你还有一些工作要做。混沌工程非常适合揭露生产系统中未知的弱点,但如果确定混沌工程实验会导致系统出现严重问题,那么运行该实验就没有任何意义。先解决这个弱点,然后回到混沌工程,它将发现你不了解的其他弱点,或者它会让你发现你的系统实际上是有弹性的。混沌工程的另一个基本要素是可用于确定系统当前状态的监控系统。1.3 混沌工程原则为了具体地解决分布式系统在规模上的不确定性,可以把混沌工程看作是为了揭示系统弱点而进行的实验。破坏稳态的难度越大,我们对系统行为的信心就越强。如果发现了一个弱点,那么我们就有了一个改进目标。避免在系统规模化之后问题被放大。以下原则描述了应用混沌工程的理想方式,这些原则来实施实验过程。对这些原则的匹配程度能够增强我们在大规模分布式系统的信心。二、阿里巴巴在混沌工程领域的实践:故障演练混沌工程属于一门新兴的技术学科,行业认知和实践积累比较少,大多数IT团队对它的理解还没有上升到一个领域概念。阿里电商域在2010年左右开始尝试故障注入测试的工作,开始的目标是想解决微服务架构带来的强弱依赖问题。后来经过多个阶段的改进,最终演进到 MonkeyKing(线上故障演练平台)。从发展轨迹来看,阿里的技术演进和Netflix的技术演进基本是同时间线的,每个阶段方案的诞生都有其独特的时代背景和业务难点,也可以看到当时技术的局限性和突破。2.1 建立一个围绕稳定状态行为的假说目前阿里巴巴集团范围内的实践偏向于故障测试,即在一个具体场景下实施故障注入实验并验证预期是否得到满足。这种测试的风险相对可控,坏处是并没有通过故障注入实验探索更多的场景,暴露更多的潜在问题,测试结果比较依赖实施人的经验。当前故障测试的预期比较两级分化,要么过于关注系统的内部细节,要么对于系统的表现完全没有预期,与混沌工程定义的稳态状态行为差异比较大。引起差异的根本原因还是组织形态的不同。2014年,Netflix团队创建了一种新的角色,叫作混沌工程师(Chaos Enigneer),并开始向工程社区推广。而阿里目前并没有一个专门的职位来实施混沌工程,项目目标、业务场景、人员结构、实施方式的不同导致了对于稳定状态行为的定义不太标准。2.2 多样化真实世界的事件阿里巴巴因为多元化的业务场景、规模化的服务节点及高度复杂的系统架构,每天都会遇到各式各样的故障。这些故障信息就是最真实的混沌工程变量。为了能够更体感、有效率地描述故障,我们优先分析了P1和P2的故障(P是阿里对故障等级的描述),提出一些通用的故障场景并按照IaaS层、PaaS层、SaaS层的角度绘制了故障画像。从故障的完备性角度来看,上述画像只能粗略代表部分已出现的问题,对于未来可能会出现的新问题也需要一种手段保持兼容。在更深入的进行分析之后,我们定义了另一维度的故障画像:任何故障,一定是硬件如IaaS层,软件如PaaS或SaaS的故障。并且有个规律,硬件故障的现象,一定可以在软件故障现象上有所体现。故障一定隶属于单机或是分布式系统之一,分布式故障包含单机故障。对于单机或同机型的故障,以系统为视角,故障可能是当前进程内的故障,比如:如FullGC,CPU飙高;进程外的故障,比如其他进程突然抢占了内存,导致当前系统异常等。同时,还可能有一类故障,是人为失误,或流程失当导致,这部分我们今天不做重点讨论。从故障注入实现角度,我们也是参照上述的画像来设计的。之前我们是通过Java字节码技术和操作系统层面的工具来分别模拟进程内和进程外的故障。随着Serverless、Docker等新架构、新技术的出现,故障实现机制和承接载体也将会有一些新的变化。2.3 在生产环境中运行实验从功能性的故障测试角度来看,非生产环境去实施故障注入是可以满足预期的,所以最早的强弱依赖测试就是在日常环境中完成的。不过,因为系统行为会根据环境和流量模式有所不同,为了保证系统执行方式的真实性与当前部署系统的相关性,推荐的实施方式还是在生产环境(仿真环境、沙箱环境都不是最好的选择)。很多同学恐惧在生产环境执行实验,原因还是担心故障影响不可控。实施实验只是手段,通过实验对系统建立信心是我们的目标。关于如何减少实验带来的影响,这点在"最小化爆炸半径"部分会有阐述。2.4 持续自动化运行实验2014年,线下环境的强弱依赖测试用例是默认在每次发布后自动执行的。2015年,开始尝试在线上进行自动化回归。不过发展到最近两年,手动实验的比例逐渐变高。原因也不复杂,虽然故障注入自动化了,业务验证的成本仍然比较高。在业务高速发展、人员变化较快的环境之下,保持一套相对完善的线上回归用例集对是见非常难的事情。虽然也出现了流量录制技术,不过因为混沌工程实验本身会打破系统已有的行为,基于入口和出口的流量比对的参考度就下降许多。为了解决测试成本问题,2017年初开始推进线上微灰度环境的建设。基于业务、比例来筛选特征流量,通过真实的流量来替换原来的测试流量,通过监控&报警数据来替代测试用例结果。目前已经有部分业务基于微灰度+故障演练的模式来做演练验证(比如:盒马APOS容灾演习)。因为故障演练之前是作为一个技术组件被嵌入到常态和大促的流程中,所以在系统构建自动化的编排和分析方面的产品度并不高。演练可视化编排和能力开放会是我们团队未来的一个重点,下文中的规划部分会有所阐述。2.5 最小化爆炸半径在生产中进行试验可能会造成不必要的客户投诉,但混沌工程师的责任和义务是确保这些后续影响最小化且被考虑到。对于实验方案和目标进行充分的讨论是减少用户影响的最重要的手段。但是从实际的实施角度看,最好还是通过一些技术手段去最小化影响。Chaos Engineering和Fault Injection Test的核心区别在于:是否可以进一步减小故障的影响,比如微服务级别、请求级别甚至是用户级别。在MonkeyKing演进的中期阶段,已经可以实现请求级别的微服务故障注入。虽然那个时候演练实施的主要位置在测试环境,但初衷也是为了减少因为注入故障而导致的环境不稳定问题。除了故障注入,流量路由和数据隔离技术也是减少业务影响的有效手段。三、未来的计划线上故障演练发展到今天是第三年,随着阿里安全生产的大环境、业务方的诉求、研发迭代模式的变化,以及大家对混沌工程的接受和认识程度的提高。集团的演练领域会向着未来的几个目标发力:建立高可用专家库,结构化提高应用容错能力(解决"稳定状态定义"的问题)建设故障注入实现标准,集团内开源,提升故障模拟的广度和深度(拓宽"多样化真实世界的事件"的广度)规模化覆盖核心业务(提升"在生产环境中运行实验"的规模)以产品化、平台化思路开放演练能力(探索"自动化运行实验"的方式)四、触手可及的混沌工程MonkeyKing已经提供商业化产品,欢迎在阿里云官网搜索“AHAS”,进行免费公测。地址:https://www.aliyun.com/product/ahas本文作者:中亭阅读原文本文来自云栖社区合作伙伴“阿里技术”,如需转载请联系原作者。

January 29, 2019 · 1 min · jiezi

阿里开源分布式事务解决方案 Fescar 全解析

广为人知的阿里分布式事务解决方案:GTS(Global Transaction Service),已正式推出开源版本,取名为“Fescar”,希望帮助业界解决微服务架构下的分布式事务问题,今天我们一起来深入了解。FESCAR on GitHubhttps://github.com/alibaba/fe…微服务倡导将复杂的单体应用拆分为若干个功能简单、松耦合的服务,这样可以降低开发难度、增强扩展性、便于敏捷开发。当前被越来越多的开发者推崇,系统微服务化后,一个看似简单的功能,内部可能需要调用多个服务并操作多个数据库实现,服务调用的分布式事务问题变的非常突出。分布式事务已经成为微服务落地最大的阻碍,也是最具挑战性的一个技术难题。 1. 什么是微服务化带来的分布式事务问题?首先,设想一个传统的单体应用(Monolithic App),通过 3 个 Module,在同一个数据源上更新数据来完成一项业务。很自然的,整个业务过程的数据一致性由本地事务来保证。随着业务需求和架构的变化,单体应用被拆分为微服务:原来的 3 个 Module 被拆分为 3 个独立的服务,分别使用独立的数据源(Pattern: Database per service)。业务过程将由 3 个服务的调用来完成。此时,每一个服务内部的数据一致性仍有本地事务来保证。而整个业务层面的全局数据一致性要如何保障呢?这就是微服务架构下面临的,典型的分布式事务需求:我们需要一个分布式事务的解决方案保障业务全局的数据一致性。2. Fescar 的发展历程阿里是国内最早一批进行应用分布式(微服务化)改造的企业,所以很早就遇到微服务架构下的分布式事务问题。2014 年,阿里中间件团队发布 TXC(Taobao Transaction Constructor),为集团内应用提供分布式事务服务。2016 年,TXC 经过产品化改造,以 GTS(Global Transaction Service)的身份登陆阿里云,成为当时业界唯一一款云上分布式事务产品,在阿云里的公有云、专有云解决方案中,开始服务于众多外部客户。2019 年起,基于 TXC 和 GTS 的技术积累,阿里中间件团队发起了开源项目 Fescar(Fast & EaSy Commit And Rollback, FESCAR),和社区一起建设这个分布式事务解决方案。TXC/GTS/Fescar 一脉相承,为解决微服务架构下的分布式事务问题交出了一份与众不同的答卷。2.1 设计初衷高速增长的互联网时代,快速试错的能力对业务来说是至关重要的:一方面,不应该因为技术架构上的微服务化和分布式事务支持的引入,给业务层面带来额外的研发负担。另一方面,引入分布式事务支持的业务应该基本保持在同一量级上的性能表现,不能因为事务机制显著拖慢业务。基于这两点,我们设计之初的最重要的考量就在于:对业务无侵入:这里的“侵入”是指,因为分布式事务这个技术问题的制约,要求应用在业务层面进行设计和改造。这种设计和改造往往会给应用带来很高的研发和维护成本。我们希望把分布式事务问题在 中间件 这个层次解决掉,不要求应用在业务层面做额外的工作。高性能:引入分布式事务的保障,必然会有额外的开销,引起性能的下降。我们希望把分布式事务引入的性能损耗降到非常低的水平,让应用不因为分布式事务的引入导致业务的可用性受影响。2.2 既有的解决方案为什么不满足?既有的分布式事务解决方案按照对业务侵入性分为两类,即:对业务无侵入的和对业务有侵入的。业务无侵入的方案既有的主流分布式事务解决方案中,对业务无侵入的只有基于 XA 的方案,但应用 XA 方案存在 3 个方面的问题:要求数据库提供对 XA 的支持。如果遇到不支持 XA(或支持得不好,比如 MySQL 5.7 以前的版本)的数据库,则不能使用。受协议本身的约束,事务资源的锁定周期长。长周期的资源锁定从业务层面来看,往往是不必要的,而因为事务资源的管理器是数据库本身,应用层无法插手。这样形成的局面就是,基于 XA 的应用往往性能会比较差,而且很难优化。已经落地的基于 XA 的分布式解决方案,都依托于重量级的应用服务器(Tuxedo/WebLogic/WebSphere 等),这是不适用于微服务架构的。侵入业务的方案实际上,最初分布式事务只有 XA 这个唯一方案。XA 是完备的,但在实践过程中,由于种种原因(包含但不限于上面提到的 3 点)往往不得不放弃,转而从业务层面着手来解决分布式事务问题。比如:基于可靠消息的最终一致性方案TCCSaga都属于这一类。这些方案的具体机制在这里不做展开,网上这方面的论述文章非常多。总之,这些方案都要求在应用的业务层面把分布式事务技术约束考虑到设计中,通常每一个服务都需要设计实现正向和反向的幂等接口。这样的设计约束,往往会导致很高的研发和维护成本。2.3 理想的方案应该是什么样子?不可否认,侵入业务的分布式事务方案都经过大量实践验证,能有效解决问题,在各种行业的业务应用系统中起着重要作用。但回到原点来思考,这些方案的采用实际上都是迫于无奈。设想,如果基于 XA 的方案能够不那么重,并且能保证业务的性能需求,相信不会有人愿意把分布式事务问题拿到业务层面来解决。一个理想的分布式事务解决方案应该:像使用本地事务一样简单,业务逻辑只关注业务层面的需求,不需要考虑事务机制上的约束。3. 原理和设计我们要设计一个对业务无侵入的方案,所以从业务无侵入的 XA 方案来思考:是否可以在 XA 的基础上演进,解决掉 XA 方案面临的问题呢?3.1 如何定义一个分布式事务?首先,很自然的,我们可以把一个分布式事务理解成一个包含了若干分支事务的全局事务。全局事务的职责是协调其下管辖的 分支事务 达成一致,要么一起成功提交,要么一起失败回滚。此外,通常分支事务本身就是一个满足 ACID 的本地事务。这是我们对分布式事务结构的基本认识,与 XA 是一致的。其次,与 XA 的模型类似,我们定义 3 个组件来协议分布式事务的处理过程。Transaction Coordinator (TC):事务协调器,维护全局事务的运行状态,负责协调并驱动全局事务的提交或回滚。Transaction Manager (TM):控制全局事务的边界,负责开启一个全局事务,并最终发起全局提交或全局回滚的决议。Resource Manager (RM):控制分支事务,负责分支注册、状态汇报,并接收事务协调器的指令,驱动分支(本地)事务的提交和回滚。一个典型的分布式事务过程:TM 向 TC 申请开启一个全局事务,全局事务创建成功并生成一个全局唯一的 XID。XID 在微服务调用链路的上下文中传播。RM 向 TC 注册分支事务,将其纳入 XID 对应全局事务的管辖。TM 向 TC 发起针对 XID 的全局提交或回滚决议。TC 调度 XID 下管辖的全部分支事务完成提交或回滚请求。至此,Fescar 的协议机制总体上看与 XA 是一致的。3.2 与 XA 的差别在什么地方?架构层次XA 方案的 RM 实际上是在数据库层,RM 本质上就是数据库自身(通过提供支持 XA 的驱动程序来供应用使用)。而 Fescar 的 RM 是以二方包的形式作为中间件层部署在应用程序这一侧的,不依赖与数据库本身对协议的支持,当然也不需要数据库支持 XA 协议。这点对于微服务化的架构来说是非常重要的:应用层不需要为本地事务和分布式事务两类不同场景来适配两套不同的数据库驱动。这个设计,剥离了分布式事务方案对数据库在 协议支持 上的要求。两阶段提交先来看一下 XA 的 2PC 过程。无论 Phase2 的决议是 commit 还是 rollback,事务性资源的锁都要保持到 Phase2 完成才释放。设想一个正常运行的业务,大概率是 90% 以上的事务最终应该是成功提交的,我们是否可以在 Phase1 就将本地事务提交呢?这样 90% 以上的情况下,可以省去 Phase2 持锁的时间,整体提高效率。这个设计,在绝大多数场景减少了事务持锁时间,从而提高了事务的并发度。当然,你肯定会问:Phase1 即提交的情况下,Phase2 如何回滚呢?3.3 分支事务如何提交和回滚?首先,应用需要使用 Fescar 的 JDBC 数据源代理,也就是 Fescar 的 RM。Phase1:Fescar 的 JDBC 数据源代理通过对业务 SQL 的解析,把业务数据在更新前后的数据镜像组织成回滚日志,利用本地事务 的 ACID 特性,将业务数据的更新和回滚日志的写入在同一个 本地事务中提交。这样,可以保证:任何提交的业务数据的更新一定有相应的回滚日志存在。基于这样的机制,分支的本地事务便可以在全局事务的 Phase1 提交,马上释放本地事务锁定的资源。Phase2:如果决议是全局提交,此时分支事务此时已经完成提交,不需要同步协调处理(只需要异步清理回滚日志),Phase2 可以非常快速地完成。如果决议是全局回滚,RM 收到协调器发来的回滚请求,通过 XID 和 Branch ID 找到相应的回滚日志记录,通过回滚记录生成反向的更新 SQL 并执行,以完成分支的回滚。3.4 事务传播机制XID 是一个全局事务的唯一标识,事务传播机制要做的就是把 XID 在服务调用链路中传递下去,并绑定到服务的事务上下文中,这样,服务链路中的数据库更新操作,就都会向该 XID 代表的全局事务注册分支,纳入同一个全局事务的管辖。基于这个机制,Fescar 是可以支持任何微服务 RPC 框架的。只要在特定框架中找到可以透明传播 XID 的机制即可,比如,Dubbo 的 Filter + RpcContext。对应到 Java EE 规范和 Spring 定义的事务传播属性,Fescar 的支持如下:PROPAGATION_REQUIRED:默认支持PROPAGATION_SUPPORTS:默认支持PROPAGATION_MANDATORY:应用通过 API 来实现PROPAGATION_REQUIRES_NEW:应用通过 API 来实现PROPAGATION_NOT_SUPPORTED:应用通过 API 来实现PROPAGATION_NEVER:应用通过 API 来实现PROPAGATION_REQUIRED_NESTED:不支持3.5 隔离性全局事务的隔离性是建立在分支事务的本地隔离级别基础之上的。在数据库本地隔离级别读已提交或以上的前提下,Fescar 设计了由事务协调器维护的 全局写排他锁,来保证事务间的写隔离,将全局事务默认定义在读未提交的隔离级别上。我们对隔离级别的共识是:绝大部分应用在 读已提交 的隔离级别下工作是没有问题的。而实际上,这当中又有绝大多数的应用场景,实际上工作在读未提交的隔离级别下同样没有问题。在极端场景下,应用如果需要达到全局的 读已提交,Fescar 也提供了相应的机制来达到目的。默认,Fescar 是工作在 读无提交 的隔离级别下,保证绝大多数场景的高效性。事务的 ACID 属性在 Fescar 中的体现是一个比较复杂的话题,我们会有专门的文章来深入分析,这里不做进一步展开。4. 适用场景分析前文所述的 Fescar 的核心原理中有一个重要前提:分支事务中涉及的资源,必须是支持ACID 事务的 关系型数据库。分支的提交和回滚机制,都依赖于本地事务的保障。所以,如果应用使用的数据库是不支持事务的,或根本不是关系型数据库,就不适用。另外,目前 Fescar 的实现还存在一些局限,比如:事务隔离级别最高支持到读已提交的水平,SQL 的解析还不能涵盖全部的语法等。为了覆盖 Fescar 原生机制暂时不能支持应用场景,我们定义了另外一种工作模式。上面介绍的 Fescar 原生工作模式称为 AT(Automatic Transaction)模式,这种模式是对业务无侵入的。与之相应的另外一种工作模式称为 MT(Manual Transaction)模式,这种模式下,分支事务需要应用自己来定义业务本身及提交和回滚的逻辑。4.1 分支的基本行为模式作为全局事务一部分的分支事务,除本身的业务逻辑外,都包含 4 个与协调器交互的行为:分支注册:在分支事务的数据操作进行之前,需要向协调器注册,把即将进行的分支事务数据操作,纳入一个已经开启的全局事务的管理中去,在分支注册成功后,才可以进行数据操作。状态上报:在分支事务的数据操作完成后,需要向事务协调器上报其执行结果。分支提交:响应协调器发出的分支事务提交的请求,完成分支提交。分支回滚:响应协调器发出的分支事务回滚的请求,完成分支回滚。4.2 AT 模式分支的行为模式业务逻辑不需要关注事务机制,分支与全局事务的交互过程自动进行。4.3 MT 模式分支的行为模式业务逻辑需要被分解为 Prepare/Commit/Rollback 3 部分,形成一个 MT 分支,加入全局事务。MT 模式一方面是 AT 模式的补充。另外,更重要的价值在于,通过 MT 模式可以把众多非事务性资源纳入全局事务的管理中。4.4 混合模式因为 AT 和 MT 模式的分支从根本上行为模式是一致的,所以可以完全兼容,即,一个全局事务中,可以同时存在 AT 和 MT 的分支。这样就可以达到全面覆盖业务场景的目的:AT 模式可以支持的,使用 AT 模式;AT 模式暂时支持不了的,用 MT 模式来替代。另外,自然的,MT 模式管理的非事务性资源也可以和支持事务的关系型数据库资源一起,纳入同一个分布式事务的管理中。4.5 应用场景的远景回到我们设计的初衷:一个理想的分布式事务解决方案是不应该侵入业务的。MT 模式是在 AT 模式暂时不能完全覆盖所有场景的情况下,一个比较自然的补充方案。我们希望通过 AT 模式的不断演进增强,逐步扩大所支持的场景,MT 模式逐步收敛。未来,我们会纳入对 XA 的原生支持,用 XA 这种无侵入的方式来覆盖 AT 模式无法触达的场景。5. 扩展点5.1 微服务框架的支持事务上下文在微服务间的传播需要根据微服务框架本身的机制,订制最优的,对应用层透明的解决方案。有兴趣在这方面共建的开发者可以参考内置的对 Dubbo 的支持方案,来实现对其他微服务框架的支持。5.2 所支持的数据库类型因为 AT 涉及 SQL 的解析,所以在不同类型的数据库上工作,会有一些特定的适配。有兴趣在这方面共建的开发者可以参考内置的对 MySQL 的支持方案,来实现对其他数据库的支持。5.3 配置和服务注册发现支持接入不同的配置和服务注册发现解决方案。比如:Nacos、Eureka、ZooKeeper 等。5.4 MT 模式的场景拓展MT 模式的一个重要作用就是,可以把非关系型数据库的资源,通过 MT 模式分支的包装,纳入到全局事务的管辖中来。比如,Redis、HBase、RocketMQ 的事务消息等。有兴趣在这方面共建的开发者可以在这里贡献一系列相关生态的适配方案。5.5 事务协调器的分布式高可用方案针对不同场景,支持不同的方式作为事务协调器 Server 端的高可用方案。比如,针对事务状态的持久化,可以是基于文件的实现方案,也可以是基于数据库的实现方案;集群间的状态同步,可以是基于 RPC 通信的方案,也可以是基于高可用 KV 存储的方案。6. Roadmap蓝图绿色部分是已经开源发布出来的,黄色 部分是将在后续版本中由阿里发布出来的,蓝色部分是我们和社区共建生态部分:对不同数据库的支持,开发者可以参考 MySQL 的实现。对不同微服务框架的支持,开发者可以参考 Dubbo 的实现。对 MQ、NoSQL 的支持,开发者可以参考 TCC 的实现。配置和服务注册发现:开发者通过少量的工作可以接入任何可以提供这类服务的框架。当然,非 蓝色 的部分也非常欢迎社区参与进来,贡献更优的解决方案。另外,XA 作为分布式事务的标准,是一个完备的分布式事务解决方案不可或缺的,远景的规划中,我们一定需要把 XA 的支持加入进来。初步的版本规划v0.1.0:微服务框架支持: Dubbo数据库支持: MySQL基于 Spring AOP 的 Annotation事务协调器: 单机版本v0.5.x:微服务框架支持: Spring CloudMT 模式支持 TCC 模式事务的适配动态配置和服务发现事务协调器: 高可用集群版本v0.8.x:Metrics控制台: 监控/部署/升级/扩缩容v1.0.0:General Availability: 生产环境适用v1.5.x:数据库支持: Oracle/PostgreSQL/OceanBase不依赖 Spring AOP 的 Annotation热点数据的优化处理机制RocketMQ 事务消息纳入全局事务管理NoSQL 纳入全局事务管理的适配机制支持 HBase支持 Redisv2.0.0:支持 XA当然,项目迭代演进的过程,我们最重视的是社区的声音,路线图会和社区充分交流及时进行调整。相关链接:FESCAR on GitHub:https://github.com/alibaba/fe… GTS on Aliyun:https://help.aliyun.com/produ…本文作者:amber涂南阅读原文本文为云栖社区原创内容,未经允许不得转载。 ...

January 29, 2019 · 2 min · jiezi

Spring Cloud Alibaba基础教程:支持的几种服务消费方式

通过《Spring Cloud Alibaba基础教程:使用Nacos实现服务注册与发现》一文的学习,我们已经学会如何使用Nacos来实现服务的注册与发现,同时也介绍如何通过LoadBalancerClient接口来获取某个服务的具体实例,并根据实例信息来发起服务接口消费请求。但是这样的做法需要我们手工的去编写服务选取、链接拼接等繁琐的工作,对于开发人员来说非常的不友好。所以接下来,我们再来看看除此之外,还支持哪些其他的服务消费方式。使用RestTemplate在之前的例子中,已经使用过RestTemplate来向服务的某个具体实例发起HTTP请求,但是具体的请求路径是通过拼接完成的,对于开发体验并不好。但是,实际上,在Spring Cloud中对RestTemplate做了增强,只需要稍加配置,就能简化之前的调用方式。比如:@EnableDiscoveryClient@SpringBootApplicationpublic class TestApplication { public static void main(String[] args) { SpringApplication.run(TestApplication.class, args); } @Slf4j @RestController static class TestController { @Autowired RestTemplate restTemplate; @GetMapping("/test") public String test() { String result = restTemplate.getForObject(“http://alibaba-nacos-discovery-server/hello?name=didi”, String.class); return “Return : " + result; } } @Bean @LoadBalanced public RestTemplate restTemplate() { return new RestTemplate(); }}可以看到,在定义RestTemplate的时候,增加了@LoadBalanced注解,而在真正调用服务接口的时候,原来host部分是通过手工拼接ip和端口的,直接采用服务名的时候来写请求路径即可。在真正调用的时候,Spring Cloud会将请求拦截下来,然后通过负载均衡器选出节点,并替换服务名部分为具体的ip和端口,从而实现基于服务名的负载均衡调用。关于这种方式,可在文末仓库查看完整代码示例。而对于这种方式的实现原理,可以参考我之前写的这篇文章的前半部分:Spring Cloud源码分析(二)Ribbon使用WebClientWebClient是Spring 5中最新引入的,可以将其理解为reactive版的RestTemplate。下面举个具体的例子,它将实现与上面RestTemplate一样的请求调用:@EnableDiscoveryClient@SpringBootApplicationpublic class TestApplication { public static void main(String[] args) { SpringApplication.run(TestApplication.class, args); } @Slf4j @RestController static class TestController { @Autowired private WebClient.Builder webClientBuilder; @GetMapping("/test”) public Mono<String> test() { Mono<String> result = webClientBuilder.build() .get() .uri(“http://alibaba-nacos-discovery-server/hello?name=didi”) .retrieve() .bodyToMono(String.class); return result; } } @Bean @LoadBalanced public WebClient.Builder loadBalancedWebClientBuilder() { return WebClient.builder(); }}可以看到,在定义WebClient.Builder的时候,也增加了@LoadBalanced注解,其原理与之前的RestTemplate时一样的。关于WebClient的完整例子也可以通过在文末的仓库中查看。使用Feign上面介绍的RestTemplate和WebClient都是Spring自己封装的工具,下面介绍一个Netflix OSS中的成员,通过它可以更方便的定义和使用服务消费客户端。下面也举一个具体的例子,其实现内容与上面两种方式结果一致:第一步:在pom.xml中增加openfeign的依赖:<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId></dependency>第二步:定义Feign客户端和使用Feign客户端:@EnableDiscoveryClient@SpringBootApplication@EnableFeignClientspublic class TestApplication { public static void main(String[] args) { SpringApplication.run(TestApplication.class, args); } @Slf4j @RestController static class TestController { @Autowired Client client; @GetMapping("/test") public String test() { String result = client.hello(“didi”); return “Return : " + result; } } @FeignClient(“alibaba-nacos-discovery-server”) interface Client { @GetMapping("/hello”) String hello(@RequestParam(name = “name”) String name); }}这里主要先通过@EnableFeignClients注解开启扫描Spring Cloud Feign客户端的功能;然后又创建一个Feign的客户端接口定义。使用@FeignClient注解来指定这个接口所要调用的服务名称,接口中定义的各个函数使用Spring MVC的注解就可以来绑定服务提供方的REST接口,比如下面就是绑定alibaba-nacos-discovery-server服务的/hello接口的例子。最后,在Controller中,注入了Client接口的实现,并调用hello方法来触发对服务提供方的调用。关于使用Feign的完整例子也可以通过在文末的仓库中查看。深入思考如果之前已经用过Spring Cloud的读者,肯定会这样的感受:不论我用的是RestTempalte也好、还是用的WebClient也好,还是用的Feign也好,似乎跟我用不用Nacos没啥关系?我们在之前介绍Eureka和Consul的时候,也都是用同样的方法来实现服务调用的,不是吗?确实是这样,对于Spring Cloud老手来说,就算我们更换了Nacos作为新的服务注册中心,其实对于我们应用层面的代码是没有影响的。那么为什么Spring Cloud可以带给我们这样的完美编码体验呢?实际上,这完全归功于Spring Cloud Common的封装,由于在服务注册与发现、客户端负载均衡等方面都做了很好的抽象,而上层应用方面依赖的都是这些抽象接口,而非针对某个具体中间件的实现。所以,在Spring Cloud中,我们可以很方便的去切换服务治理方面的中间件。代码示例本文示例读者可以通过查看下面仓库:Github:https://github.com/dyc87112/SpringCloud-Learning/Gitee:https://gitee.com/didispace/SpringCloud-Learning/其中,本文的几种示例可查看下面的几个项目:alibaba-nacos-discovery-server:服务提供者,必须启动alibaba-nacos-discovery-client-resttemplate:使用RestTemplate消费alibaba-nacos-discovery-client-webclient:使用WebClient消费alibaba-nacos-discovery-client-feign:使用Feign消费如果您对这些感兴趣,欢迎star、follow、收藏、转发给予支持!以下专题教程也许您会有兴趣Spring Boot基础教程Spring Cloud基础教程 ...

January 29, 2019 · 1 min · jiezi

Auto-Keras与AutoML:入门指南

摘要: 不会机器学习?不会人工智能?没关系!自动化程序来了!在本教程中,你将学习如何使用Auto-Keras(Google的AutoML的开源替代品)来实现自动化机器学习和深度学习。目前来说,深度学习从业者在数据集上训练神经网络时,主要正在尝试优化和平衡两个目标:1.定义适合数据集性质的神经网络体系结构;2.在许多实验中调整一组超参数,这将导致模型具有高精度并能够推广到训练和测试集之外的数据。需要调整的典型超参数包括优化算法(SGD,Adam等),学习速率和学习速率调度以及正则化等。根据数据集和具体问题,深度学习专家可以进行数十到数百次实验,以找到神经网络架构和超参数之间的平衡,这些实验通常需要计算数百到数千小时。刚刚提到的这种模式仅适用于专家,那非深度学习专家呢?这就需要Auto-Keras和AutoML:Auto-Keras和AutoML的最终目标是通过使用自动神经架构搜索(NAS)算法降低进入机器学习和深度学习的门槛。Auto-Keras和AutoML使非深度学习专家能够以最小的深度学习领域知识或实际数据来训练他们自己的模型。具有最小机器学习专业知识的程序员可以使用AutoML和Auto-Keras并应用这些算法,只需很少的努力即可实现最先进的性能。听起来好得令人难以置信?也许你需要好好阅读这篇文章的其余部分以找出原因。Auto-Keras和AutoML:入门指南在本博文的第一部分中,我们将讨论自动机器学习(AutoML)和神经架构搜索(NAS),这种算法使得AutoML在应用于神经网络和深度学习时成为可能。我们还将简要讨论Google的AutoML,这是一套工具和库,允许具有有限机器学习专业知识的程序员在自己的数据上训练高精度模型。当然,谷歌的AutoML是一种专有算法,AutoML的另一种选择是开源Auto-Keras、它是围绕Keras和PyTorch而构建。然后,我将向你展示如何使用Auto-Keras自动训练网络以及评估它。什么是自动机器学习(AutoML)?Auto-Keras是Google AutoML的替代品。它可以帮助你自动训练模型,几乎不需要干预。对于新手深度学习从业者来说,它们是很好的选择。在无监督学习之外,非专家的自动机器学习被认为是机器学习的“圣杯”。想象一下通过以下方式自动创建机器学习模型的能力:1.安装库/使用Web界面;2.将库/接口指向你的数据;3.自动训练数据模型而无需调整参数/需要深入了解为其提供动力的算法;一些公司正试图创建这样的解决方案,其中一个就是谷歌的AutoML。Google AutoML使非常有限的机器学习经验的开发人员和工程师能够自动在他们自己的数据集上训练神经网络。谷歌的底层AutoML算法是迭代的:1.在训练集上训练网络;2.在测试集上评估网络;3.修改神经网络架构;4.调整超参数;5.重复上述过程;使用AutoML的程序员或工程师不需要定义他们自己的神经网络架构或调整超参数,AutoML会自动为他们做这件事。神经架构搜索(NAS)使AutoML成为可能神经架构搜索(NAS)在搜索CIFAR-10的最佳CNN架构时,通过这些图表生成了一个模型。Google的AutoML和Auto-Keras都采用了一种称为神经架构搜索(NAS)的算法。根据你的输入数据集,神经架构搜索算法将自动搜索最佳架构和相应参数。神经架构搜索基本上是用一组自动调整模型的算法取代深度学习工程师/从业者!在计算机视觉和图像识别的背景下,神经架构搜索算法将:1.接受输入训练数据集;2.优化并找到称为“单元”的架构构建块,然后让这些单元自动学习,这可能看起来类似于初始化,残留或激活微架构;3.不断训练和搜索“NAS搜索空间”以获得更优化的单元;如果AutoML系统的用户是经验丰富的深度学习从业者,那么他们可能会决定:1.在训练数据集的一个非常小的子集上运行NAS;2.找到一组最佳的架构构建块/单元;3.获取这些单元并手动定义在体系结构搜索期间找到的更深层次的网络版本;4.使用自己的专业知识和最佳实践,在完整的培训集上训练网络;这种方法是全自动机器学习解决方案与需要专家深度学习实践者的解决方案之间的混合体,通常这种方法比NAS自己训练的模型性能更好。Auto-Keras:谷歌AutoML的开源替代品在Auto-Keras包是由在德克萨斯州A&M大学数据实验室团队开发。Auto-Keras是Google AutoML的开源替代品。Auto-Keras依然是利用神经架构搜索,但应用“网络态射”(在更改架构时保持网络功能)以及贝叶斯优化,以指导网络态射以实现更高效的神经网络搜索。你可以在Jin等人的2018年出版物Auto-Keras:Efficient Neural Architecture Search with Network Morphism中找到Auto-Keras框架的全部细节。安装Auto-Keras:正如Auto-Keras GitHub存储库所述,Auto-Keras处于“预发布”状态-它现在还不是正式版本。其次,Auto-Keras需要Python 3.6并且只与Python 3.6兼容。如果你使用的*是3.6以外的任何其他版本的Python,你将无法使用Auto-Keras软件包。如果你想要检查Python版本,只需使用以下命令:python –version如果你有Python 3.6,你可以使用pip安装Auto-Keras:pip install tensorflow # or tensorflow-gpupip install keraspip install autokeras使用Auto-Keras实现我们的训练脚本:让我们继续使用Auto-Keras实现我们的训练脚本,打开train_auto_keras.py文件并插入以下代码:# import the necessary packagesfrom sklearn.metrics import classification_reportfrom keras.datasets import cifar10import autokeras as akimport osdef main(): # initialize the output directory OUTPUT_PATH = “output"首先,我们在第2-5行导入必要的包:如前所述,我们将使用scikit-learn的classification_report来计算我们将在输出文件中保存的统计信息。我们将使用CIFAR-10数据集,因为它已经被内置到keras.datasets。然后是导入import依赖项-autokeras,我已经将它用AK的简写代替。该os模块是必需的,因为我们会在建立输出文件的路径时,在各种操作系统上容纳路径分隔符。我们在第7行定义脚本的主要功能,由于Auto-Keras和TensorFlow处理线程的方式,我们需要将代码包装在main函数中。有关更多详细信息,请参阅此GitHub问题线程。现在让我们初始化Auto-Keras的训练时间列表:# initialize the list of training times that we’ll allow # Auto-Keras to train for TRAINING_TIMES = [ 60 * 60, # 1 hour 60 * 60 * 2, # 2 hours 60 * 60 * 4, # 4 hours 60 * 60 * 8, # 8 hours 60 * 60 * 12, # 12 hours 60 * 60 * 24, # 24 hours ]上述代码是限定了一组训练-TIMES,包括[1,2,4,8,12,24]小时。我们将使用Auto-Keras来探索更长的训练时间对精确度的影响。让我们加载CIFAR-10数据集并初始化类名:# load the training and testing data, then scale it into the # range [0, 1] print("[INFO] loading CIFAR-10 data…”) ((trainX, trainY), (testX, testY)) = cifar10.load_data() trainX = trainX.astype(“float”) / 255.0 testX = testX.astype(“float”) / 255.0 # initialize the label names for the CIFAR-10 dataset labelNames = [“airplane”, “automobile”, “bird”, “cat”, “deer”, “dog”, “frog”, “horse”, “ship”, “truck”]我们的CIFAR-10数据被加载并存储在第25行的训练/测试分组中。随后,我们将这个数据缩放到[0,1]的范围。接着我们会初始化我们的类labelNames,这10个类包含在CIFAR-10中。请注意,标签在这里很重要。现在让我们开始循环遍历我们的TRAINING_TIMES,每次都使用Auto-Keras:# loop over the number of seconds to allow the current Auto-Keras # model to train for for seconds in TRAINING_TIMES: # train our Auto-Keras model print("[INFO] training model for {} seconds max…".format( seconds)) model = ak.ImageClassifier(verbose=True) model.fit(trainX, trainY, time_limit=seconds) model.final_fit(trainX, trainY, testX, testY, retrain=True) # evaluate the Auto-Keras model score = model.evaluate(testX, testY) predictions = model.predict(testX) report = classification_report(testY, predictions, target_names=labelNames) # write the report to disk p = os.path.sep.join(OUTPUT_PATH, “{}.txt”.format(seconds)) f = open(p, “w”) f.write(report) f.write("\nscore: {}".format(score)) f.close()上面的代码块是今天脚本的核心。在第35行,我们在每个TRAINING_TIMES上定义了一个循环,我们在其中做以下操作:初始化我们的模型(AK.ImageClassifier),并让训练开始。请注意,我们并没有实例化一个特定对象的CNN类,我们也没有调整超参数。因为Auto-Keras会为我们处理所有这些。一旦达到时间限制,请采用Auto-Keras找到的最佳模型和参数+重新训练模型。评估和构建分类报告。将分类报告与准确度分数一起写入磁盘,以便我们评估更长训练时间的影响。我们将为每个TRAINING_TIMES重复此过程。最后,我们将检查并启动执行的主线程:# if this is the main thread of execution then start the process (our# code must be wrapped like this to avoid threading issues with# TensorFlow)if name == “main”: main()这里我们检查确保这是执行的主线程,然后是主函数。仅仅60行代码,我们就完成了使用CIFAR-10示例脚本编写Auto-Keras,但是我们还没有完成……使用Auto-Keras训练神经网络让我们继续使用Auto-Keras训练我们的神经网络。请确保使用本教程的“下载”部分下载源代码。从那里打开终端,导航到下载源代码的位置,然后执行以下命令:$ python train_auto_keras.py[INFO] training model for 3600 seconds max… Preprocessing the images.Preprocessing finished.Initializing search.Initialization finished.+———————————————-+| Training model 0 |+———————————————-+Using TensorFlow backend.No loss decrease after 5 epochs.Saving model.+————————————————————————–+| Model ID | Loss | Metric Value |+————————————————————————–+| 0 | 4.816269397735596 | 0.5852 |+————————————————————————–++———————————————-+| Training model 1 |+———————————————-+Using TensorFlow backend.Epoch-14, Current Metric - 0.83: 28%|██████▊ | 110/387 [01:02<02:46, 1.67 batch/s]Time is out.[INFO] training model for 86400 seconds max… Preprocessing the images.Preprocessing finished.Initializing search.Initialization finished.+———————————————-+| Training model 0 |+———————————————-+Using TensorFlow backend.No loss decrease after 5 epochs….+———————————————-+| Training model 21 |+———————————————-+Using TensorFlow backend.No loss decrease after 5 epochs.+————————————————————————–+| Father Model ID | Added Operation |+————————————————————————–+| | to_deeper_model 16 ReLU || 16 | to_wider_model 16 64 |+————————————————————————–+Saving model.+————————————————————————–+| Model ID | Loss | Metric Value |+————————————————————————–+| 21 | 0.8843476831912994 | 0.9316000000000001 |+————————————————————————–++———————————————-+| Training model 22 |+———————————————-+Using TensorFlow backend.Epoch-3, Current Metric - 0.9: 80%|████████████████████▊ | 310/387 [03:50<00:58, 1.31 batch/s]Time is out.No loss decrease after 30 epochs.在这里你可以看到我们的脚本正在指示Auto-Keras执行六组实验。在NVIDIA K80 GPU上,总训练时间为3天多一点。Auto-Keras的结果:使用Auto-Keras通常是一个非常耗时的过程。使用Auto-Keras进行训练可在8-12小时范围内为CIFAR-10生成最佳型号。在上图中,你可以看到训练时间(x轴)对使用Auto-Keras的总体准确度(y轴)的影响。较短的训练时间,即1小时和2小时,大约可以达到73%的准确性。一旦我们训练4小时,我们就能达到高达93%的准确率。训练8-12小时,我们就能获得95%的精确度了。超过8-12小时的训练不会提高我们的准确度,这意味着我们已达到饱和点并且Auto-Keras无法进一步优化。Auto-Keras和AutoML值得吗?Auto-Keras值得吗?这无疑是行业向前迈出的一大步,对那些没有深入学习领域知识的人尤其有用。在无监督学习之外(从未标记数据自动学习模式),非专家的自动机器学习被认为是机器学习的“圣杯”。Google的AutoML和开源Auto-Keras软件包都试图将机器学习带给大众,即使是没有关键性技术的经验的程序员。虽然Auto-Keras在CIFAR-10上工作得相当好,但是我使用我之前关于深度学习,医学图像和疟疾检测的文章进行了第二组实验。我使用简化的ResNet架构获得了97.1%的准确率,该架构花费了不到一小时的时间进行训练。然后我让Auto-Keras在相同的数据集上运行24小时-结果只有96%的准确度,低于我自己定义的架构。但不管怎样,谷歌的AutoML和Auto-Keras都是向前迈出的一大步。本文作者:【方向】阅读原文本文为云栖社区原创内容,未经允许不得转载。 ...

January 28, 2019 · 2 min · jiezi

终于等到你!阿里正式向 Apache Flink 贡献 Blink 源码

阿里妹导读:如同我们去年12月在 Flink Forward China 峰会所约,阿里巴巴内部 Flink 版本 Blink 将于 2019 年 1 月底正式开源。今天,我们终于等到了这一刻。阿里资深技术专家大沙,将为大家详细介绍本次开源的Blink主要功能和优化点,希望与业界同仁共同携手,推动Flink社区进一步发展。Blink简介Apache Flink是德国柏林工业大学的几个博士生和研究生从学校开始做起来的项目,早期叫做Stratosphere。2014年,StratoSphere项目中的核心成员从学校出来开发了Flink,同时将Flink计算的主流方向定位为流计算,并在同年将Flink捐赠Apache,后来快速孵化成为Apache的顶级项目。现在Flink是业界公认的最好的大数据流计算引擎。阿里巴巴在2015年开始尝试使用Flink。但是阿里的业务体量非常庞大,挑战也很多。彼时的Flink不管是规模还是稳定性尚未经历实践,成熟度有待商榷。为了把这么大的业务体量支持好,我们不得不在Flink之上做了一系列的改进,所以阿里巴巴维护了一个内部版本的Flink,它的名字叫做Blink。基于Blink的计算平台于2016年正式上线。截至目前,阿里绝大多数的技术部门都在使用Blink。Blink一直在阿里内部错综复杂的业务场景中锻炼成长着。对于内部用户反馈的各种性能、资源使用率、易用性等诸多方面的问题,Blink都做了针对性的改进。虽然现在Blink在阿里内部用的最多的场景主要还是在流计算,但是在批计算场景也有不少业务上线使用了。例如,在搜索和推荐的算法业务平台中,它使用Blink同时进行流计算和批处理。Blink被用来实现了流批一体化的样本生成和特征抽取这些流程,能够处理的特征数达到了数千亿,而且每秒钟处理数亿条消息。在这个场景的批处理中,我们单个作业处理的数据量已经超过400T,并且为了节省资源,我们的批处理作业是和流计算作业以及搜索的在线引擎运行在同样的机器上。所以大家可以看到流批一体化已经在阿里巴巴取得了极大的成功,我们希望这种成功和阿里巴巴内部的经验都能够带回给社区。Blink开源的背景其实从我们选择Flink的第一天开始我们就一直和社区紧密合作。过去的这几年我们也一直在把阿里对Flink 的改进推回社区。从2016年开始我们已经将流计算SQL的大部分功能,针对runtime的稳定性和性能优化做的若干重要设计都推回了社区。但是Blink本身发展迭代的速度非常快,而社区有自己的步伐,很多时候可能无法把我们的变更及时推回去。对于社区来说,一些大的功能和重构,需要达成共识后,才能被接受,这样才能更好地保证开源项目的质量,但是同时就会导致推入的速度变得相对较慢。经过这几年的开发迭代,我们这边和社区之间的差距已经变得比较大了。Blink 有一些很好的新功能,比如性能优越的批处理功能,在社区的版本是没有的。在过去这段时间里,我们不断听到有人在询问Blink的各种新功能。期望Blink尽快开源的呼声越来越大。我们一直在思考如何开源的问题,一种方案就是和以前一样,继续把各种功能和优化分解,逐个和社区讨论,慢慢地推回Flink。但这显然不是大家所期待的。另一个方案,就是先完整的尽可能的多的把代码开源,让社区的开发者能够尽快试用起来。第二个方案很快收到社区广大用户的支持。因此,从2018年年中开始我们就开始做开源的相关准备。经过半年的努力,我们终于把大部分Blink的功能梳理好,开源了出来。Blink开源的方式我们把代码贡献出来,是为了让大家能先尝试一些他们感兴趣的功能。Blink永远不会单独成为一个独立的开源项目来运作,他一定是Flink的一部分。开源后我们期望能找到办法以最快的方式将Blink merge到Flink中去。Blink开源只有一个目的,就是希望 Flink 做得更好。Apache Flink 是一个社区项目,Blink以什么样的形式进入 Flink 是最合适的,怎么贡献是社区最希望的方式,我们都要和社区一起讨论。在过去的一段时间内,我们在Flink社区征求了广泛的意见,大家一致认为将本次开源的Blink代码作为Flink的一个branch直接推回到Apache Flink项目中是最合适的方式。并且我们和社区也一起讨论规划出一套能够快速merge Blink到Flink master中的方案(具体细节可以查看Flink社区正在讨论的FLIP32)。我们期望这个merge能够在很短的时间内完成。这样我们之后的Machine Learning等其他新功能就可以直接推回到Flink master。相信用不了多久,Flink 和 Blink 就完全合二为一了。在那之后,阿里巴巴将直接使用Flink用于生产,并同时协助社区一起来维护Flink。本次开源的Blink的主要功能和优化点本次开源的Blink代码在Flink 1.5.1版本之上,加入了大量的新功能,以及在性能和稳定性上的各种优化。主要贡献包括,阿里巴巴在流计算上积累的一些新功能和性能的优化,一套完整的(能够跑通全部TPC-H/TPC-DS,能够读取Hive meta和data)高性能Batch SQL,以及一些以提升易用性为主的功能(包括支持更高效的interactive programming, 与zeppelin更紧密的结合, 以及体验和性能更佳的Flink web)。未来我们还将继续给Flink贡献在AI,IoT以及其他新领域的功能和优化。更多的关于这一版本Blink release的细节,请参考Blink代码根目录下的README.md文档。下面,我来分模块介绍下Blink主要的新的功能和优化点。Runtime为了更好的支持batch processing,以及解决阿里巴巴大规模生产场景中遇到的各种挑战,Blink对Runtime架构、效率、稳定性方面都做了大量改进。在架构方面,首先Blink引入了Pluggable ShuffleArchitecture,开发者可以根据不同的计算模型或者新硬件的需要实现不同的shuffle策略进行适配。此外Blink还引入新的调度架构,容许开发者根据计算模型自身的特点定制不同调度器。为了优化性能,Blink可以让算子更加灵活的chain在一起,避免了不必要的数据传输开销。在Pipeline Shuffle模式中,使用了ZeroCopy减少了网络层内存消耗。在BroadCast Shuffle模式中,Blink优化掉了大量的不必要的序列化和反序列化开销。此外,Blink提供了全新的JM FailOver机制,JM发生错误之后,新的JM会重新接管整个JOB而不是重启JOB,从而大大减少了JM FailOver对JOB的影响。最后,Blink也开发了对Kubernetes的支持。不同于Standalone模式在Kubernetes上的拉起方式,在基于Flink FLIP6的架构上基础之上,Blink根据job的资源需求动态的申请/释放Pod来运行TaskExecutor,实现了资源弹性,提升了资源的利用率。SQL/TableAPISQL/TableAPI架构上的重构和性能的优化是Blink本次开源版本的一个重大贡献。首先,我们对SQL engine的架构做了较大的调整。提出了全新的Query Processor(QP), 它包括了一个优化层(Query Optimizer)和一个算子层(Query Executor)。这样一来,流计算和批计算的在这两层大部分的设计工作就能做到尽可能的复用。另外,SQL和TableAPI的程序最终执行的时候将不会翻译到DataStream和DataSet这两个API上,而是直接构建到可运行的DAG上来,这样就使得物理执行算子的设计不完全依赖底层的API,有了更大的灵活度,同时执行代码也能够被灵活的codegen出来。唯一的一个影响就是这个版本的SQL和TableAPI不能和DataSet这个API进行互相转换,但仍然保留了和DataStream API互相转换的能力(将DataStream注册成表,或将Table转成DataStream后继续操作)。未来,我们计划把dataset的功能慢慢都在DataStream和TableAPI上面实现。到那时DataStream和SQL以及tableAPI一样,是一个可以同时描述bounded以及unbounded processing的API。除了架构上的重构,Blink还在具体实现上做了较多比较大的重构。首先,Blink引入了二进制的数据结构BinaryRow,极大的减少了数据存储上的开销以及数据在序列化和反序列化上计算的开销。其次,在算子的实现层面,Blink在更广范围内引入了CodeGen技术。由于预先知道算子需要处理的数据的类型,在QP层内部就可以直接生成更有针对性更高效的执行代码。Blink的算子会动态的申请和使用资源,能够更好的利用资源,提升效率,更加重要的是这些算子对资源有着比较好的控制,不会发生OutOfMemory 的问题。此外,针对流计算场景,Blink加入了miniBatch的执行模式,在aggregate、join等需要和state频繁交互且往往又能先做部分reduce的场景中,使用miniBatch能够极大的减少IO,从而成数量级的提升性能。除了上面提到的这些重要的重构和功能点,Blink还实现了完整的SQL DDL,带emit策略的流计算DML,若干重要的SQL功能,以及大量的性能优化策略。有了上面提到的诸多架构和实现上的重构。Blink的SQL/tableAPI在功能和性能方面都取得了脱胎换骨的变化。在批计算方面,首先Blink batch SQL能够完整的跑通TPC-H和TPC-DS,且性能上有着极大的提升。如上图所示,是这次开源的Blink版本和spark 2.3.1的TPC-DS的benchmark性能对比。柱状图的高度代表了运行的总时间,高度越低说明性能越好。可以看出,Blink在TPC-DS上和Spark相比有着非常明显的性能优势。而且这种性能优势随着数据量的增加而变得越来越大。在实际的场景这种优势已经超过 Spark的三倍。在流计算性能上我们也取得了类似的提升。我们线上的很多典型作业,它的性能是原来的3到5倍。在有数据倾斜的场景,以及若干比较有挑战的TPC-H query,流计算性能甚至得到了数十倍的提升。除了标准的Relational SQL API。TableAPI在功能上是SQL的超集,因此在SQL上所有新加的功能,我们在tableAPI也添加了相对应的API。除此之外,我们还在TableAPI上引入了一些新的功能。其中一个比较重要是cache功能。在批计算场景下,用户可以根据需要来cache计算的中间结果,从而避免不必要的重复计算。它极大的增强了interactive programming体验。我们后续会在tableAPI上添加更多有用的功能。其实很多新功能已经在社区展开讨论并被社区接受,例如我们在tableAPI增加了对一整行操作的算子map/flatMap/aggregate/flatAggregate(Flink FLIP29)等等。Hive的兼容性我们这次开源的版本实现了在元数据(meta data)和数据层将Flink和Hive对接和打通。国内外很多公司都还在用 Hive 在做自己的批处理。对于这些用户,现在使用这次Blink开源的版本,就可以直接用Flink SQL去查询Hive的数据,真正能够做到在Hive引擎和Flink引擎之间的自由切换。为了打通元数据,我们重构了Flink catalog的实现,并且增加了两种catalog,一个是基于内存存储的FlinkInMemoryCatalog,另外一个是能够桥接Hive metaStore的HiveCatalog。有了这个HiveCatalog,Flink作业就能读取Hive的metaData。为了打通数据,我们实现了HiveTableSource,使得Flink job可以直接读取Hive中普通表和分区表的数据。因此,通过这个版本,用户可以使用Flink SQL读取已有的Hive meta和data,做数据处理。未来我们将在Flink上继续加大对Hive兼容性的支持,包括支持Hive特有的query,data type,和Hive UDF等等。Zeppelin for Flink为了提供更好的可视化和交互式体验,我们做了大量的工作让Zeppelin能够更好的支持Flink。这些改动有些是在Flink上的,有些是在Zeppelin上的。在这些改动全部推回Flink和Zeppelin社区之前,大家可以使用这个Zeppelin image(具体细节请参考Blink代码里的docs/quickstart/zeppelin_quickstart.md)来测试和使用这些功能。这个用于测试的Zeppelin版本,首先很好的融合和集成了Flink的多种运行模式以及运维界面。使用文本SQL和tableAPI可以自如的查询Flink的static table和dynamic table。此外,针对Flink的流计算的特点,这一版Zeppelin也很好的支持了savepoint,用户可以在界面上暂停作业,然后再从savepoint恢复继续运行作业。在数据展示方面,除了传统的数据分析界面,我们也添加了流计算的翻牌器和时间序列展示等等功能。为了方便用户试用,我们在这一版zeppelin中提供3个built-in的Flink tutorial的例子: 一个是做StreamingETL的例子, 另外两个分别是做Flink Batch,Flink Stream的基础样例。Flink Web我们对Flink Web的易用性与性能等多个方面做了大量的改进,从资源使用、作业调优、日志查询等维度新增了大量功能,使得用户可以更方便的对Flink作业进行运维。在资源使用方面,新增了Cluster、TaskManager与Job三个级别的资源信息,使得资源的申请与使用情况一目了然。作业的拓扑关系及数据流向可以追溯至 Operator 级别,Vertex 增加了InQueue,OutQueue等多项指标,可以方便的追踪数据的反压、过滤及倾斜情况。TaskManager 和 JobManager 的日志功能得到大幅度加强,从Job、Vertex、SubTask 等多个维度都可以关联至对应日志,提供多日志文件访问入口,以及分页展示查询和日志高亮功能。另外,我们使用了较新的Angular 7.0 对Flink web进行了全面重构,页面运行性能有了一倍以上的提升。在大数据量情况下也不会发生页面卡死或者卡顿情况。同时对页面的交互逻辑进行了整体优化,绝大部分关联信息在单个页面就可以完成查询和比对工作,减少了大量不必要的跳转。未来的规划Blink迈出了全面开源的第一步,接下来我们会和社区合作,尽可能以最快的方式将Blink的功能和性能上的优化merge回Flink。本次的开源版本一方面贡献了Blink多年在流计算的积累,另一方面又重磅推出了在批处理上的成果。接下来,我们会持续给Flink社区贡献其他方面的功能。我们期望每过几个月就能看到技术上有一个比较大的亮点贡献到社区。下一个亮点应该是对机器学习的支持。要把机器学习支持好,有一系列的工作要做,包括引擎的功能,性能,和易用性。这里面大部分的工作我们已经开发完成,并且很多功能都已经在阿里巴巴内部服务上线了。除了技术上创新以及新功能之外,Flink的易用性和外围生态也非常重要。我们已经启动了若干这方面的项目,包括Python以及Go等多语言支持,Flink集群管理,Notebook,以及机器学习平台等等。这些项目有些会成为Flink自身的一部分贡献回社区,有些不是。但它们都基于Flink,是Flink生态的一个很好的补充。独立于Flink之外的那些项目,我们都也在认真的考虑开源出来。总之,Blink在开源的第一天起,就已经完全all-in的融入了Flink社区,我们希望所有的开发者看到我们的诚意和决心。未来,无论是功能还是生态,我们都会在Flink社区加大投入,我们也将投入力量做 Flink 社区的运营,让 Flink 真正在中国、乃至全世界大规模地使用起来。我们衷心的希望更多的人加入,一起把Apache Flink开源社区做得更好!本文作者:大沙阅读原文本文来自云栖社区合作伙伴“阿里技术”,如需转载请联系原作者。 ...

January 28, 2019 · 1 min · jiezi

一位技术校招生在支付宝的成长笔记

哪有那么多的“逆袭”,唯有努力与坚持,机会就会在前方。鲁直,1989年生,本科毕业于浙江工业大学,之后被校招进阿里巴巴。虽然,今年刚刚30岁,但他已是蚂蚁金服SOFA中间件开源负责人。看到这个开头,是不是觉得我们要向大家讲述一个普通程序员励志“逆袭”的故事?不,并不是这样。前4年,他的人生剧本和别人并没有什么不同但机会总是留给有准备的人“当时就是不想考研究生,而刚好阿里给的offer又能让我在杭州‘活’下去。”鲁直推了推眼镜,淡淡地说。2009年,鲁直报名参加了阿里和浙江工业大学校企合作的实习项目,经过1年的实习期,他在毕业季里成功拿下了B2B团队的offer。最初的时候,鲁直对于业务架构根本谈不上了解,只是每天重复着很普通,甚至是略微枯燥的代码工作。在当时,鲁直的工作就是做产品的研发以及业务系统的开发。每天想着的是建模和现在的业务模型是否匹配,IE6下能不能兼容……和大多数踏出校门、初入职场的大学生没什么不同。鲁直的生活和职业几乎谈不上计划,更谈不上梦想。但是,努力和幸运,让鲁直的人生轨迹逐渐发生变化。“当时的主管对我们说,因为我们刚进公司不久,在技术方面还需要更多的提升。”于是,鲁直就一头扎进开源代码的研究与分析中。在那时,业界的开源意识并不像现在这般普及,但鲁直他们组织的“半民间”开源兴趣小组却坚持了近2年的时间,一帮技术新人相互陪伴着学习开源,看代码,互相指出不足。不断的学习让鲁直对于中间件的兴趣日渐浓厚,他很想在这一领域进行尝试。终于,机会来了!有个同事提议推出一个研发效率提升工具,并被当时的技术主管知道了,他给了鲁直和这个同事一个月的时间把这个工具做出来,而且先不用管业务的事儿。于是,两个人用了一个月的时间,最终拿到结果:一款研发效率提升工具。从看书自学,到组成小团队一起研究代码,再到这次的实操,鲁直在B2B团队3年时间,想清楚了自己究竟要什么。“当时,就认定了自己想要去做中间件”,鲁直说,“而且阿里也有完备的人员流动机制。”于是,鲁直作出了一个重要的决定——从B2B团队转岗到蚂蚁金服中间件SOFA团队。那个属于鲁直的机会终于来了。在SOFA中间件团队5年的挑战与成长学习使人进步如愿以偿,鲁直进入了蚂蚁金服中间件SOFA团队,但这并不意味着是一片坦途。“更忙了,也更充实了;更有趣了,但挑战也更大了。”鲁直略带兴奋地告诉笔者,转岗后,他感受最明显的是角色发生了变化。“之前在业务团队的时候,我只需要具备业务视角即可。但是中间件不一样,需要充分考虑用户的感受。中间件的用户都是研发人员,我需要考量他们的使用场景和习惯等,甚至是在单词拼写以及命名规范等细节。”鲁直说,他必须要较真,因为程序员很多时间都花在变量命名上。随着对中间件的深入,鲁直发现,自己进入了“Hard”模式,之前那些认知看上去都不太管用,甚至有一些可笑。正是基于这种警醒,鲁直知道,不断学习才是自己唯一可选的路。于是,鲁直一头扎进书海,到处找中间件相关的书籍,从最底层的基础理论学起;然后将这些理论知识应用于实际的工作中。为此,鲁直主动要求做很多的支持工作。一段时间之后,鲁直很快就了解了所负责的中间件产品的细节,并快速地积累了解决问题的经验。“这段经历还是蛮有意思的。如果当时只是一味地读死书,而没有将其用于工作中,我想我可能没有那么大的提升。”鲁直感慨到。如果说学习让鲁直感到了愉悦,那么在中间件团队工作期间,收获的“痛苦”又是什么?——“你不知道,项目进度带来的压力真心大。”鲁直说。2016年双11,鲁直所在的SOFA团队负责弹性架构的改造,但其中一个非常老的协议却成了弹性架构下的“bug”。“都知道双11那种紧张的气氛,跟打仗没什么区别。”鲁直说,“架构改造的工作当时因为这个‘bug’而停滞了,整个团队不仅周末连续加班,身体疲惫不已;心理的压力更大。”然而,除了迎难而上,别无它途。鲁直和小伙伴们一起不断对协议进行深入的分析,不断地定制针对性的修复方案,终于让业务顺利升级中间件,平稳地支持了双11。“当时真的是身心俱疲,可以说是非常痛苦了。但最终,我们还是完成了任务。”鲁直说着,镜片后闪过一丝坚定的眼神。在鲁直看来,在越困难的时期,越需要逼自己一把,所谓破釜沉舟,大概如此吧。“SOFA这个名字的来历还挺有意思的,是我们的CTO鲁肃取的名字,里面包含两层意思,一是按照当时的技术趋势,要做面向服务的架构,即Service Oriented Architecture,但加入了金融业务,所以是ServiceOriented Fabric Architecture;二是希望能够像‘沙发’一样,让工程师可以非常爽地工作。”2018年4月,可以让工程师们非常爽的SOFA正式开源了!“现在,SOFA在蚂蚁金服有将近2000个应用,是在蚂蚁业务场景下被不断验证和锤炼的一套框架。”鲁直表示,“把SOFA开源出去,让更多的人使用,对于SOFA未来的发展极具意义。”鲁直告诉笔者,开源的意义就是给技术的发展装上轮子。9年阿里轨迹,一个普通又特别的“码农”越自律越自由程序员的头发,一直是一个不太好玩的老梗。尽管鲁直的头发仍然浓密,但还是能看到在危险边缘疯狂试探的发际线。尽管团队的小伙伴称其为“鲁大师”,但鲁直一直强调自己不过是个平凡的“码农”。“如果哪天,我在阿里的成长完全停滞了,那也就是我离开的时候了。”鲁直悠悠地说到。从大学毕业就在这家公司,9年,是一份执着的坚持。他认为,自己之所以能在阿里巴巴有所成,是因为自己很幸运,在工作中找到了自己的热爱,于是,所有的辛苦都不再是前行的负重,而是助推力。对于中间件的喜欢,以及阿里巴巴和蚂蚁金服提供的阔大舞台,让自己不断面对挑战,不断去学习,不断地成长。鲁直喜欢跑步,即便是天气再冷也会跑个5公里;而且他也喜欢马拉松,陆续坚持了8年之久。在作息时间方面,鲁直也有着“严格”的标准,他要求自己尽量在12点之前睡觉。“熬夜对身体真的不好,而且我跑步也是为了锻炼身体,但这些都其实是我对自己的一些要求。”鲁直说。不管作息规律也好,跑步也好,都可以视作是鲁直对自己的严格自律。鲁直在用自己的行动诠释“越自律越自由”。那些对开源有兴趣的小伙伴们,鲁直给出了自己的建议。“参与开源,一个错别字也是开始。根据对项目了解的深入程度,可以从找错别字、命名规范等找错开始,由浅入深,再去提出Issue、提交Bug。相信所有的开源项目维护者都会非常地欢迎大家一起参与、多提一些意见。”最后,鲁直引用他最喜欢的程序员Jamie Zanwinski的一句话与大家共勉:痛苦造就性格。在舒适的状态下,很多的人表现是差不多的,但是在逆境中,一些人内心非常深处的想法和力量才能被充分发挥出来。SOFA是什么?SOFA(Scalable OpenFinancial Architecture),蚂蚁金服自主研发的金融级分布式中间件,包含了构建金融级云原生架构所需的各个组件,包括微服务研发框架,RPC 框架,服务注册中心,分布式定时任务,限流/熔断框架,分布式链路追踪,分布式高可用消息队列,分布式事务框架等组件。简单来说,SOFA就是包含一整套组件的金融级分布式中间件。诞生于支付宝第2代技术系统的服务化,最开始只有一套框架,后来逐渐形成了一整套完整组件。SOFA和传统金融架构的区别1、传统的金融IT架构一般采取集中式,通过购入大型机小型机解决数据问题,拓展性弱且机器成本高昂。2、SOFA则采取分布式的架构,在高并发交易处理能力、强一致性、秒级容灾和弹性伸缩上都有突出的表现。譬如面对双11流量洪峰时,完全可以准备PC级的服务器去支撑,弹性伸缩。本文作者:越自律越自由阅读原文本文来自云栖社区合作伙伴“阿里技术”,如需转载请联系原作者。

January 25, 2019 · 1 min · jiezi

微服务不是全部,只是特定领域的子集

大家都在学SpringCloud,貌似学会了SC就牛逼哄哄,感觉不得了的样子。但微服务,在整个企业级应用中,只占了一小部分。微服务引入的问题比解决的问题还要多,你会遇到各种各样的bottleneck。微服务解决的是计算节点的问题,然而根源却在存储节点。当业务规模变得越来越庞大,存储、编码、管理都会成为问题。接下来我们谈一些放之四海而皆准的道理,不需要贴上"XX公司最佳实践"之类的标签。下面是一张因数据扩张引出的微服务相关的图,简约但不简单。中小型公司只要有这些元素,就能玩的很好;大点的公司,因为规模太大,每个组件都会遇到瓶颈,所谓的专项的优化并不能脱离它的本质。那我们开始。注意,这张图仅是主要数据路径,一个子集,其他的包括CDN、通讯层等,不在此列。这张图并不包含某个特定领域的具体架构,属于一个整体性的概括。我们从数据库容量的瓶颈说起,看一下微服务在其中的比重。数据库用户数据要存储,就存在数据库。过去这么多年,NoSQL并不能消除开发人员的恐惧,所以,MySQL之类还是大多数公司的首选存储。假设你的业务增长的很好,这个就有意思多了。项目开始,你的sql玩的越6,那么给后人埋的坑,越多。因为sql的功能太丰富了,一不小心,就炫技了。你会发现,林子越大,对sql的规范要求越高。一些官宣的特性,在公司内是严格禁止的。市场发展很好,终于来报应了。以前的技巧变成了现在的累赘。慢查询、全文扫描,招招毙命。想要加缓存,结果发现无从下手;想要分库分表,结果发现表关系错综复杂。小表和宽表所以第一步,还是得去填坑。一个超过3个表的联合查询业务,大概率是不合理的。在加缓存和分库分表之前,还是得重新设计一下数据表。忘掉什么数据库范式,我们将存在两类表:小表和宽表。小表提供了最基本的数据,可能一个简单的KV就完成了。一些联合查询,是直接可以在程序里进行循环拼接的。程序里循环1000次10毫秒的查询,比单次查询耗费6秒要强的多。这就是分布式系统的特点,小耗时的批量查询,比hang在那里更加有生命力。宽表通过冗余的方式,提供了某个重要功能常用的分析数据。这种表的字段一般都特别多,在写入时通过拼接获取冗余数据,一般用在读多写少的场景。完成了这一步,接下来的工作才能进行。分库分表在《“分库分表" ?选型和流程要慎重,否则会失控》中,详细的说明了分库分表的选型,这里浅谈一下过程。分库分表很可能会引入某一种中间件,因为仅仅将数据库分开还不行。HA,FailOver等特性,是同时需要的。分库分为垂直分和水平分。垂直面向的是业务拆分,即将一部分表按照业务逻辑独立到其他库中;水平面向的是容量,即通过分库分表的模式使数据有一个扩张的途径。数据一定要有一个可以度量的切分维度,否则就过于分散,或者过于倾斜,影响后续的处理。数据同步有分就有合,比如某些报表业务需要全量的数据。不同业务通过共享数据库来共享数据不得不说是个非常蠢的主意。这个时候就需要一些数据同步工具。数据同步组件可以说是一个公司的必备组件。有基于最后更新时间的高延迟同步工具,也有基于binlog的低延迟同步工具。有的公司为了稳定,还会有所谓的多机房同步。 数据同步最怕异常,因为大多数同步都有顺序性要求。一切运行良好的时候,大家皆大欢喜;一旦出现异常,就需要其他手段来保证异常期间的数据同步和延迟。这都是些脏活,自动化有时候会适得其反,监控是第一位的。分层的数据存储可以预见的是,即使你分库分表了,还是能很快达到瓶颈。分库分表后,你的一些统计功能可能还用不了了,在一些传统的管理系统上,这是硬伤。一个分层的数据存储层是必要的。你的一些业务,可能一个分支走的是MySQL,换了另外一个条件就成了ES。不同的DB做不同的事情。RDBMS只做原是数据的存储和查询,是扁平快的数据通道;特定的单机高性能DB,做一些汇聚和科学计算;分布式的类RT的存储,用来存储一些中等规模的数据,并提供一些中延迟的搜索功能;海量的存储系统,存储系统所有的历史记录,并提供离线分析功能。不要想着某一类存储解决所有的问题,那是骗人的。存储部分的复杂性不是普通的微服务能够相比的。 是谁保证了分层的数据存储设计呢?除了一部分通过MQ分发数据的业务,还是得靠我们的数据同步组件。缓存但DB的压力实在是太大了,我们不得不考虑缓存。缓存不能乱用,有两个原则:一个是缓存不能侵入业务,也就是不能带有业务逻辑;一个是缓存的命中率要高,否则适得其反。缓存是对高并发、高速接口的补充,是系统稳定性的必要不充分条件。除了Redis等外置的缓存集群,jvm内缓存也是一个比较重要的场所。缓存的存在是因为I/O设备的缓慢,通常放在内存中,断电后即消失。缓存涉及到源数据库和缓存数据库之间的数据同步。通常,更新源库时,会同时删掉缓存中相关的就数据,这样在下次读取的时候,能够读取到最新的数据。缓存限制最大的就是其容量问题,而且都贵的很。假如业务模式固定,一些kv存储使用LevelDB或者HBase等方案,会显著节约成本。模块化是时候将工程模块化了,毕竟上百个程序员共享一个代码库,风险已经很大了。模块化通常会按照业务线进行拆分。比如,支付模块和报表模块的拆分。模块拆分后,相似的模块会共享数据库。但更多的是通过冗余数据来解决,这样能将业务解耦,一部分出现问题,另一部分能够运行良好。好比你隔壁出了杀人案你第二天还能正常去上班。模块之间要找到一种交互方式,比如使用HttpClient、OkHttp等。重要的是统一,统一了以后就有一个高大上的名字了:RPC。一个小模块很有可能会发展为一个大的业务线,也有可能无人问津。MQ模块化之间另一种共享数据或者数据交互的方式就是MQ。除了有削峰等功效,MQ更多改变的是一种交互模式,一种对业务的解耦。Kafka几乎每个公司都在用,最高能有几十万的吞吐量。RabbitMQ、RocketMQ等,更多用在可靠性要求非常高的场景,但比较耗机器。MQ资源一般都要求绝对的高可靠,作为基础设施,一旦出问题,将带来非常大的事故。设计的时候要考虑异常情况下的数据处理流向,以及MQ恢复后的补偿策略。MQ集群设计的比较小一些才合理,避免不同业务,不同可靠性级别的消息互相影响。MQ在业务上和功能上要相互隔离,做到最小服务集合。为了避免MQ当机对正常业务产生影响,非重要链路上的MQ不能阻塞业务的正常进行,这种消息通常通过异步线程发送。微服务我们已经使用消息和模块化,将系统拆分成了多个工程。将这些工程使用统一的方式管理起来,统一其交互模式和在上面的治理,就是微服务的范畴。微服务就是一个多模块项目规范化的过程。非规范的服务与微服务体系,是要共存一段时间的,如何保证新旧服务的替换,是一个管理上的问题。功能组件根据SpringCloud的描述,一个服务想要被发现,需要将自己注册到通用的注册中心,其他服务可以从同一个地方,获取它的实例,进而调用。而真正产生调用的功能,就是RPC的功能。RPC要考虑一系列比如超时、重拾、熔断等功能。在某些访问量非常大的节点,可能还要考虑预热。RPC要能产生一些统计性数据,比如TPS、QPS、TP值等,很显然SpringCloud是缺乏的,我们要借助外部系统进行分析。在外部请求流转到内部之前,需要经过一层网关的处理。像一些通用的操作,比如权限、限流、灰度等,就可以在网关层处理。服务治理微服务最重要的特色就是其治理功能。服务治理的依据就是监控信息。通过统计每次调用的大小、耗时、分布,能够得出服务的大体拓扑。通常以下信息最有用:1、QPS,时间序列的qps分布,最高区间qps2、平均响应时间,接口的平均响应时间,最大耗时和最小耗时3、TP值分布,90%,99%等请求是在x耗时内完成通过以上信息能够对服务进行画像。是扩容、缩容、专项治理的数据依据。微服务引出的另外一个问题就是调用链,即某个请求的真实路径。分布式环境下的问题排查,会非常的困难,调用链能够帮助研发快速定位问题,并帮助理解业务的数据流向。服务治理的目的就是找到不合理的请求和分布,比如某个接口耗时太长;某个接口请求量大,需要加缓存;某个功能依赖链条过长,需要业务优化等。服务治理要借助大量的外部分析工具,更多通用的业务模型,需要大数据平台的支持。我们把监控/报警也放在服务治理的部分,在《这么多监控组件,总有一款适合你》中,我们详细的讨论了监控部分的技术选择方案。日志微服务产生的另外一个问题就是日志太过分散。一个核心的业务可能有上百个实例,你不可能打开100个终端去看日志。这就涉及到日志的收集。日志归集功能就是把分散的日志集合到一个地方,它的主要挑战就是数据量。通常日志分为两部分,一部分是全量的,可以通过定时同步等方式,备份到日志堡垒机或者hdfs中;一部分是过滤后的日志,比如一些异常信息,集中在某一个处理平台中进行报警。很多研发喜欢将用户行为数据输出到日志文件中,这部分日志被收集后,会通过流计算或者离线计算,得到一些推荐和模型。日志信息进入了大数据处理的范畴,我们不过多描述。持续集成如果一个上点规模的公司,技术团队有什么值得一做的系统,那么发布系统算一个。《发布系统有那么难么?》中,谈了一种可能的模式。发布系统就是给一堆脚本包了一张方便的皮。一些流程性工具、发布验证、CI/CD功能,很容易能够添加到自己的发布系统中。很多微服务推广的文章中,谈到虚拟化(Docker)等,其实不是必须的。虚拟化减少了服务编排的时间,能够方便的进行扩容和缩容,但对监控、日志收集、网络拓扑等,要求比较高。建议是整个体系中的最后一步而不是第一步。你的系统是否灵活,还与公司的文化环境相关。如果上个线走审批流程就需要一两周,那么做一个敏捷的持续集成系统就不是那么必要了。基础设施基础设施更多指的是运维体系,这是支撑整个系统健康发展的基石。我倾向于基础运维和基础架构不分家,因为它们的模式和文化,是一个公司研发环境的基石。另外一些基础组件,比如配置中心、调度中心、分布式锁管理等,都对可靠性有较高的要求。END这套体系看着简单,也有固定的解决方案。但问题就在于,许多公司从成立玩到倒闭,玩了那么多年,还是没玩好。真是可怜。

January 25, 2019 · 1 min · jiezi

用友云开发者中心,你应该知道的那些事

2018开发者中心产品不断进行架构升级优化,同时也在不断完善产品能力,目前已支撑内部大量云产品的运行,下面给大家介绍一下新增的几大能力:一、一体化的计算资源管理1.提供资源池使用率看板,资源池的内存分配和实际使用率对比情况,内存消耗情况一目了然,基于这个数据,可以更好的优化每个应用的内存分配,防止资源浪费。提供资源池监控大盘,详细的展示资源池中CPU、内存、磁盘使用率情况,历史的波动情况等,有利于全局的了解每台主机的实际工作负载,可以根据负载情况,动态调配应用的实例数。对于高负载主机,也能够直观发现,作为决策数据,及时扩容IaaS资源。可以按资源池或按主机维度,查看所有部署的应用列表,查找应用非常迅速便捷。点击操作按钮,可以直接跳转到应用管理页面,方便的查看应用的详细状态。提供主机以及资源池等计算资源的在线申请,再也不用人肉的方式通过邮件申请资源了。二、以应用为中心,以产品线、产品为组织管理方式开发者中心秉承以应用为中心的理念,打造开发、运维、测试一体化平台。支持创建产品线、产品、应用三个维度部署应用,并提供产品视图维度和环境视图维度进行精细化管理。有利于从全局的视角,了解应用的部署情况和依赖情况。产品维度视图环境维度视图三、支持多套环境的持续交付流水线针对开发环境、测试环境、灰度环境、生产环境以及其他自定义环境,可以为每个应用配置持续集成流水线。整个流水线涵盖了CI/CD的主要过程,包括代码构建、测试、生成镜像、执行部署等环节。自动化测试方面支持代码静态检查、安全检查、代码质量分析,单元测试、接口测试、UI测试、冒烟测试、流程测试等不同测试任务,并可以输出产品质量分析报告。

January 24, 2019 · 1 min · jiezi

阿里毕玄:程序员如何提升自己的硬实力

从业余程序员到职业程序员程序员刚入行时,我觉得最重要的是把自己培养成职业的程序员。我的程序员起步比同龄人都晚了很多,更不用说现在的年轻人了。我大学读的是生物专业,在上大学前基本算是完全没接触过计算机。军训的时候因为很无聊,我和室友每天跑去学校的机房玩,我现在还印象很深刻,我第一次走进机房的时候,别人问,你是要玩windows,还是dos,我那是完全的一抹黑。后来就只记得在机房一堆人都是在练习盲打,军训完,盲打倒是练的差不多了,对计算机就这么产生了浓厚的兴趣,大一的时候都是玩组装机,捣鼓了一些,对计算机的硬件有了那么一些了解。到大二后,买了一些书开始学习当时最火的网页三剑客,学会了手写HTML、PS的基本玩法之类的,课余、暑假也能开始给人做做网站什么的(那个时候做网站真的好赚钱),可能那样过了个一年左右,做静态的网页就不好赚钱了,也不好找实习工作,于是就开始学asp,写些简单的CRUD,做做留言板、论坛这些动态程序,应该算是在这个阶段接触编程了。毕业后加入了深圳的一家做政府行业软件的公司,一个非常靠谱和给我空间的Leader,使得自己在那几年有了不错的成长,终于成了一个职业的程序员。通常来说,业余或半职业的程序员,多数是1个人,或者很小的一个团队一起开发,使得在开发流程、协作工具(例如jira、cvs/svn/git等)、测试上通常会有很大的欠缺,而职业的程序员在这方面则会专业很多。另外,通常职业的程序员做的系统都要运行较长的时间,所以在可维护性上会特别注意,这点我是在加入阿里后理解更深的。一个运行10年的系统,和一个写来玩玩的系统显然是有非常大差别的。这块自己感觉也很难讲清楚,只能说模模糊糊有个这样的概念。通常在有兴趣的基础上,从业余程序员跨越到成为职业程序员我觉得不会太难。编程能力的成长作为程序员,最重要的能力始终是编程能力,就我自己的感受而言,我觉得编程能力的成长主要有这么几个部分:1、编程能力初级:会用编程,首先都是从学习编程语言的基本知识学起的,不论是什么编程语言,有很多共同的基本知识,例如怎么写第一个Hello World、if/while/for、变量等,因此我比较建议在刚刚开始学一门编程语言的时候,看看编程语言自己的一些文档就好,不要上来就去看一些高阶的书。我当年学Java的时候上来就看Think in Java、Effective Java之类的,真心好难懂。除了看文档以外,编程是个超级实践的活,所以一定要多写代码,只有这样才能真正熟练起来。这也是为什么我还是觉得在面试的时候让面试者手写代码是很重要的,这个过程是非常容易判断写代码的熟悉程度的。很多人会说由于写代码都是高度依赖IDE的,导致手写很难,但我绝对相信写代码写了很多的人,手写一段不太复杂的、可运行的代码是不难的。即使像我这种三年多没写过代码的人,让我现在手写一段不太复杂的可运行的Java程序,还是没问题的,前面N年的写代码生涯使得很多东西已经深入骨髓了。我觉得编程能力初级这个阶段对于大部分程序员来说都不会是问题,勤学苦练,是这个阶段的核心。2、编程能力中级:会查和避免问题除了初级要掌握的会熟练的使用编程语言去解决问题外,中级我觉得首先是提升查问题的能力。在写代码的过程中,出问题是非常正常的,怎么去有效且高效的排查问题,是程序员群体中通常能感受到的大家在编程能力上最大的差距。解决问题能力强的基本很容易在程序员群体里得到很高的认可。在查问题的能力上,首先要掌握的是一些基本的调试技巧,好用的调试工具,在Java里有JDK自带的jstat、jmap、jinfo,不在JDK里的有mat、gperf、btrace等。工欲善其事必先利其器,在查问题上是非常典型的,有些时候大家在查问题时的能力差距,有可能仅仅是因为别人比你多知道一个工具而已。除了调试技巧和工具外,查问题的更高境界就是懂原理。一个懂原理的程序员在查问题的水平上和其他程序员是有明显差距的。我想很多的同学应该能感受到,有些时候查出问题的原因仅仅是因为有效的工具,知其然不知其所以然。我给很多阿里的同学培训过Java排查问题的方法,在这个培训里,我经常也会讲到查问题的能力的培养最主要的也是熟练,多尝试给自己写一些会出问题的程序,多积极的看别人是怎么查问题的,多积极的去参与排查问题,很多最后查问题能力强的人多数仅仅是因为“无他,但手熟尔”。我自己排查问题能力的提升主要是在2009年和2010年。那两年作为淘宝消防队(处理各种问题和故障的虚拟团队)的成员,处理了很多的故障和问题。当时消防队还有阿里最公认的技术大神——多隆,我向他学习到了很多排查问题的技巧。和他比,我排查问题的能力就是初级的那种。印象最深刻的是一次我们一起查一个应用cpu us高的问题,我们两定位到是一段代码在某种输入参数的时候会造成cpu us高的原因后,我能想到的继续查的方法是去生产环境抓输入参数,然后再用参数来本地debug看是什么原因。但多隆在看了一会那段代码后,给了我一个输入参数,我拿这个参数一运行,果然cpu us很高!这种case不是一次两次。所以我经常和别人说,我是需要有问题场景才能排查出问题的,但多隆是完全有可能直接看代码就能看出问题的,这是本质的差距。除了查问题外,更厉害的程序员是在写代码的过程就会很好的去避免问题。大家最容易理解的就是在写代码时处理各种异常情况,这里通常也是造成程序员们之间很大的差距的地方。写一段正向逻辑的代码,大部分情况下即使有差距,也不会太大,但在怎么很好的处理这个过程中有可能出现的异常上,这个时候的功力差距会非常明显。很多时候一段代码里处理异常逻辑的部分都会超过正常逻辑的代码量。我经常说,一个优秀程序员和普通程序员的差距,很多时候压根就不需要看什么满天飞的架构图,而只用show一小段的代码就可以。举一个小case大家感受下。当年有一个严重故障,最后查出的原因是输入的参数里有一个是数组,把这个数组里的值作为参数去查数据库,结果前面输入了一个很大的数组,导致从数据库查了大量的数据,内存溢出了,很多程序员现在看都会明白对入参、出参的保护check,但类似这样的case我真的碰到了很多。在中级这个阶段,我会推荐大家尽可能的多刻意的去培养下自己这两个方面的能力,成为一个能写出高质量代码、有效排查问题的优秀程序员。3、编程能力高级:懂高级API和原理就我自己的经历而言,我是在写了多年的Java代码后,才开始真正更细致的学习和掌握Java的一些更高级的API,我相信多数Java程序员也是如此。我算是从2003年开始用Java写商业系统的代码,但直到在2007年加入淘宝后,才开始非常认真地学习Java的IO通信、并发这些部分的API。尽管以前也学过也写过一些这样的代码,但完全就是皮毛。当然,这些通常来说有很大部分的原因会是工作的相关性,多数的写业务系统的程序员可能基本就不需要用到这些,所以导致会很难懂这些相对高级一些的API,但这些API对真正的理解一门编程语言,我觉得至关重要。在之前的程序员成长路线的文章里我也讲到了这个部分,在没有场景的情况下,只能靠自己去创造场景来学习好。我觉得只要有足够的兴趣,这个问题还是不大的,毕竟现在有各种开源,这些是可以非常好的帮助自己创造机会学习的,例如学Java NIO,可以自己基于NIO包一个框架,然后对比Netty,看看哪些写的是不如Netty的,这样会非常有助于真正的理解。在学习高级API的过程中,以及排查问题的过程中,我自己越来越明白懂编程语言的运行原理是非常重要的,因此我到了后面的阶段开始学习Java的编译机制、内存管理、线程机制等。对于我这种非科班出身的而言,学这些会因为缺乏基础更难很多,但这些更原理性的东西学会了后,对自己的编程能力会有质的提升,包括以后学习其他编程语言的能力,学这些原理最好的方法我觉得是先看看一些讲相关知识的书,然后去翻看源码,这样才能真正的更好的掌握,最后是在以后写代码的过程中、查问题的过程中多结合掌握的原理,才能做到即使在N年后也不会忘。在编程能力的成长上,我觉得没什么捷径。我非常赞同1万小时理论,在中级、高级阶段,如果有人指点或和优秀的程序员们共事,会好非常多。不过我觉得这个和读书也有点像,到了一定阶段后(例如高中),天分会成为最重要的分水岭,不过就和大部分行业一样,大部分的情况下都还没到拼天分的时候,只需要拼勤奋就好。系统设计能力的成长除了少数程序员会进入专深的领域,例如Linux Kernel、JVM,其他多数的程序员除了编程能力的成长外,也会越来越需要在系统设计能力上成长。通常一个编程能力不错的程序员,在一定阶段后就会开始承担一个模块的工作,进而承担一个子系统、系统、跨多领域的更大系统等。我自己在工作的第三年开始承担一个流程引擎的设计和实现工作,一个不算小的系统,并且也是当时那个项目里的核心部分。那个阶段我学会了一些系统设计的基本知识,例如需要想清楚整个系统的目标、模块的划分和职责、关键的对象设计等,而不是上来就开始写代码。但那个时候由于我是一个人写整个系统,所以其实对设计的感觉并还没有那么强力的感觉。在那之后的几年也负责过一些系统,但总体感觉好像在系统设计上的成长没那么多,直到在阿里的经历,在系统设计上才有了越来越多的体会。(点击文末阅读原文,查看:我在系统设计上犯过的14个错,可以看到我走的一堆的弯路)。在阿里有一次做分享,讲到我在系统设计能力方面的成长,主要是因为三段经历,负责专业领域系统的设计 -> 负责跨专业领域的专业系统的设计 -> 负责阿里电商系统架构级改造的设计。第一段经历,是我负责HSF。HSF是一个从0开始打造的系统,它主要是作为支撑服务化的框架,是个非常专业领域的系统,放在整个淘宝电商的大系统来看,其实它就是一个很小的子系统,这段经历里让我最深刻的有三点:1).要设计好这种非常专业领域的系统,专业的知识深度是非常重要的。我在最早设计HSF的几个框的时候,是没有设计好服务消费者/提供者要怎么和现有框架结合的,在设计负载均衡这个部分也反复了几次,这个主要是因为自己当时对这个领域掌握不深的原因造成的;2). 太技术化。在HSF的阶段,出于情怀,在有一个版本里投入了非常大的精力去引进OSGi以及去做动态化,这个后来事实证明是个非常非常错误的决定,从这个点我才真正明白在设计系统时一定要想清楚目标,而目标很重要的是和公司发展阶段结合;3). 可持续性。作为一个要在生产环境持续运行很多年的系统而言,怎么样让其在未来更可持续的发展,这个对设计阶段来说至关重要。这里最low的例子是最早设计HSF协议的时候,协议头里竟然没有版本号,导致后来升级都特别复杂;最典型的例子是HSF在早期缺乏了缺乏了服务Tracing这方面的设计,导致后面发现了这个地方非常重要后,全部落地花了长达几年的时间;又例如HSF早期缺乏Filter Chain的设计,导致很多扩展、定制化做起来非常不方便。第二段经历,是做T4。T4是基于LXC的阿里的容器,它和HSF的不同是,它其实是一个跨多领域的系统,包括了单机上的容器引擎,容器管理系统,容器管理系统对外提供API,其他系统或用户通过这个来管理容器。这个系统发展过程也是各种犯错,犯错的主要原因也是因为领域掌握不深。在做T4的日子里,学会到的最重要的是怎么去设计这种跨多个专业领域的系统,怎么更好的划分模块的职责,设计交互逻辑,这段经历对我自己更为重要的意义是我有了做更大一些系统的架构的信心。第三段经历,是做阿里电商的异地多活。这对我来说是真正的去做一个巨大系统的架构师,尽管我以前做HSF的时候参与了淘宝电商2.0-3.0的重大技术改造,但参与和自己主导是有很大区别的,这个架构改造涉及到了阿里电商众多不同专业领域的技术团队。在这个阶段,我学会的最主要的:1). 子系统职责划分。在这种超大的技术方案中,很容易出现某些部分的职责重叠和冲突,这个时候怎么去划分子系统,就非常重要了。作为大架构师,这个时候要从团队的职责、团队的可持续性上去选择团队;2). 大架构师最主要的职责是控制系统风险。对于这种超大系统,一定是多个专业领域的架构师和大架构师共同设计,怎么确保在执行的过程中对于系统而言最重要的风险能够被控制住,这是我真正的理解什么叫系统设计文档里设计原则的部分。设计原则我自己觉得就是用来确保各个子系统在设计时都会遵循和考虑的,一定不能是虚的东西,例如在异地多活架构里,最重要的是如何控制数据风险,这个需要在原则里写上,最基本的原则是可接受系统不可用,但也要保障数据一致,而我看过更多的系统设计里设计原则只是写写的,或者千篇一律的,设计原则切实的体现了架构师对目标的理解(例如当时异地多活这个其实开始只是个概念,但做到什么程度才叫做到异地多活,这是需要解读的,也要确保在技术层面的设计上是达到了目标的),技术方案层面上的选择原则,并确保在细节的设计方案里有对于设计原则的承接以及执行;3). 考虑问题的全面性。像异地多活这种大架构改造,涉及业务层面、各种基础技术层面、基础设施层面,对于执行节奏的决定要综合考虑人力投入、机器成本、基础设施布局诉求、稳定性控制等,这会比只是做一个小的系统的设计复杂非常多。系统设计能力的成长,我自己觉得最重要的一是先在一两个技术领域做到专业,然后尽量扩大自己的知识广度。例如除了自己的代码部分外,还应该知道具体是怎么部署的,部署到哪去了,部署的环境具体是怎么样的,和整个系统的关系是什么样的。像我自己,是在加入基础设施团队后才更加明白有些时候软件上做的一个决策,会导致基础设施上巨大的硬件、网络或机房的投入,但其实有可能只需要在软件上做些调整就可以避免,做做研发、做做运维可能是比较好的把知识广度扩大的方法。第二点是练习自己做tradeoff的能力,这个比较难,做tradeoff这事需要综合各种因素做选择,但这也是所有的架构师最关键的,可以回头反思下自己在做各种系统设计时做出的tradeoff是什么。这个最好是亲身经历,听一些有经验的架构师分享他们选择背后的逻辑也会很有帮助,尤其是如果恰好你也在同样的挑战阶段,光听最终的架构结果其实大多数时候帮助有限。技术Leader我觉得最好是能在架构师的基础上,后续注重成长的方面还是有挺大差别,就不在这篇里写了,后面再专门来写一篇。程序员金字塔我认为程序员的价值关键体现在作品上,被打上作品标签是一种很大的荣幸,作品影响程度的大小我觉得决定了金字塔的层次,所以我会这么去理解程序员的金字塔。当然,要打造一款作品,仅有上面的两点能力是不够的,作品里很重要的一点是对业务、技术趋势的判断。希望作为程序员的大伙,都能有机会打造一款世界级的作品,去为技术圈的发展做出贡献。由于目前IT技术更新速度还是很快的,程序员这个行当是特别需要学习能力的。我一直认为,只有对程序员这个职业真正的充满兴趣,保持自驱,才有可能在这个职业上做好,否则的话是很容易淘汰的。作者简介:毕玄,2007年加入阿里,十多年来主要从事在软件基础设施领域,先后负责阿里的服务框架、Hbase、Sigma、异地多活等重大的基础技术产品和整体架构改造。本文作者:云效鼓励师阅读原文本文为云栖社区原创内容,未经允许不得转载。

January 24, 2019 · 1 min · jiezi

Spark in action on Kubernetes - Playground搭建与架构浅析

前言Spark是非常流行的大数据处理引擎,数据科学家们使用Spark以及相关生态的大数据套件完成了大量又丰富场景的数据分析与挖掘。Spark目前已经逐渐成为了业界在数据处理领域的行业标准。但是Spark本身的设计更偏向使用静态的资源管理,虽然Spark也支持了类似Yarn等动态的资源管理器,但是这些资源管理并不是面向动态的云基础设施而设计的,在速度、成本、效率等领域缺乏解决方案。随着Kubernetes的快速发展,数据科学家们开始考虑是否可以用Kubernetes的弹性与面向云原生等特点与Spark进行结合。在Spark 2.3中,Resource Manager中添加了Kubernetes原生的支持,而本系列我们会给大家介绍如何用更Kubernetes的方式在集群中使用Spark进行数据分析。本系列不需要开发者有丰富的Spark使用经验,对着系列的逐渐深入,会穿插讲解使用到的Spark特性。搭建Playground很多的开发者在接触Hadoop的时候,被安装流程的复杂度打消了很多的积极性。为了降低学习的门槛,本系列会通过spark-on-k8s-operator作为Playground,简化大家的安装流程。spark-on-k8s-operator顾名思义是为了简化Spark操作而开发的operator,如果对operator不是很了解的开发者,可以先自行搜索了解下,理解operator能做什么可以快速帮你掌握spark-on-k8s-operator的要领。在讲解内部原理前,我们先将环境搭建起来,通过一个简单的demo,跑通整个的运行时环境。1. 安装spark-on-k8s-operator官方的文档是通过Helm Chart进行安装的,由于很多开发者的环境无法连通google的repo,因此此处我们通过标准的yaml进行安装。## 下载repogit clone git@github.com:AliyunContainerService/spark-on-k8s-operator.git## 安装crdkubectl apply -f manifest/spark-operator-crds.yaml ## 安装operator的服务账号与授权策略kubectl apply -f manifest/spark-operator-rbac.yaml ## 安装spark任务的服务账号与授权策略kubectl apply -f manifest/spark-rbac.yaml ## 安装spark-on-k8s-operator kubectl apply -f manifest/spark-operator.yaml 验证安装结果此时在spark-operator的命名空间下的无状态应用下,可以看到一个运行中的sparkoperator,表名此时组件已经安装成功,接下来我们运行一个demo应用来验证组件是否可以正常工作。2. Demo验证学习Spark的时候,我们运行的第一个任务是官方文档中介绍的圆周率运行的例子。今天我们换一种方式,通过Kubernetes的方式再运行一次。## 下发spark-pi任务kubectl apply -f examples/spark-pi.yaml 任务下发成功后,可以通过命令行观察任务的状态。## 查询任务kubectl describe sparkapplication spark-pi## 任务结果 Name: spark-piNamespace: defaultLabels: <none>Annotations: kubectl.kubernetes.io/last-applied-configuration: {“apiVersion”:“sparkoperator.k8s.io/v1alpha1”,“kind”:“SparkApplication”,“metadata”:{“annotations”:{},“name”:“spark-pi”,“namespace”:“defaul…API Version: sparkoperator.k8s.io/v1alpha1Kind: SparkApplicationMetadata: Creation Timestamp: 2019-01-20T10:47:08Z Generation: 1 Resource Version: 4923532 Self Link: /apis/sparkoperator.k8s.io/v1alpha1/namespaces/default/sparkapplications/spark-pi UID: bbe7445c-1ca0-11e9-9ad4-062fd7c19a7bSpec: Deps: Driver: Core Limit: 200m Cores: 0.1 Labels: Version: 2.4.0 Memory: 512m Service Account: spark Volume Mounts: Mount Path: /tmp Name: test-volume Executor: Cores: 1 Instances: 1 Labels: Version: 2.4.0 Memory: 512m Volume Mounts: Mount Path: /tmp Name: test-volume Image: gcr.io/spark-operator/spark:v2.4.0 Image Pull Policy: Always Main Application File: local:///opt/spark/examples/jars/spark-examples_2.11-2.4.0.jar Main Class: org.apache.spark.examples.SparkPi Mode: cluster Restart Policy: Type: Never Type: Scala Volumes: Host Path: Path: /tmp Type: Directory Name: test-volumeStatus: Application State: Error Message: State: COMPLETED Driver Info: Pod Name: spark-pi-driver Web UI Port: 31182 Web UI Service Name: spark-pi-ui-svc Execution Attempts: 1 Executor State: Spark - Pi - 1547981232122 - Exec - 1: COMPLETED Last Submission Attempt Time: 2019-01-20T10:47:14Z Spark Application Id: spark-application-1547981285779 Submission Attempts: 1 Termination Time: 2019-01-20T10:48:56ZEvents: Type Reason Age From Message —- —— —- —- ——- Normal SparkApplicationAdded 55m spark-operator SparkApplication spark-pi was added, Enqueuing it for submission Normal SparkApplicationSubmitted 55m spark-operator SparkApplication spark-pi was submitted successfully Normal SparkDriverPending 55m (x2 over 55m) spark-operator Driver spark-pi-driver is pending Normal SparkExecutorPending 54m (x3 over 54m) spark-operator Executor spark-pi-1547981232122-exec-1 is pending Normal SparkExecutorRunning 53m (x4 over 54m) spark-operator Executor spark-pi-1547981232122-exec-1 is running Normal SparkDriverRunning 53m (x12 over 55m) spark-operator Driver spark-pi-driver is running Normal SparkExecutorCompleted 53m (x2 over 53m) spark-operator Executor spark-pi-1547981232122-exec-1 completed此时我们发现任务已经执行成功,查看这个Pod的日志,我们可以到计算最终的结果为Pi is roughly 3.1470557352786765。至此,在Kubernetes上,已经跑通了第一个Job,接下来我们要来详解一下刚才这一波操作到底都做了些什么。Spark Operator的基础架构浅析这张图是Spark Operator的流程图,在上面的操作中,第一个步骤里面,实际上是将图中的中心位置蓝色的Spark Operator安装到集群中,Spark Opeartor本身即是是一个CRD的Controller也是一个Mutating Admission Webhook的Controller。当我们下发spark-pi模板的时候,会转换为一个名叫SparkApplication的CRD对象,然后Spark Operator会监听Apiserver,并将SparkApplication对象进行解析,变成spark-submit的命令并进行提交,提交后会生成Driver Pod,用简单的方式理解,Driver Pod就是一个封装了Spark Jar的镜像。如果是本地任务,就直接在Driver Pod中执行;如果是集群任务,就会通过Driver Pod再生成Exector Pod进行执行。当任务结束后,可以通过Driver Pod进行运行日志的查看。此外在任务的执行中,Spark Operator还会动态attach一个Spark UI到Driver Pod上,希望查看任务状态的开发者,可以通过这个UI页面进行任务状态的查看。最后在本文中,我们讨论了Spark Operator的设计初衷,如何快速搭建一个Spark Operator的Playground以及Spark Operator的基本架构与流程。在下一篇文章中,我们会深入到Spark Operator的内部,为大家讲解其内部的实现原理以及如何与Spark更无缝的集成。本文作者:莫源阅读原文本文为云栖社区原创内容,未经允许不得转载。 ...

January 23, 2019 · 2 min · jiezi

用友云平台,真正的云原生架构,加速云应用落地

数字化经济的出现,企业需要通过新技术实现数字化转型,完成企业管理和业务模式变革。而云计算是数字化中尤为重要且能够更快实现的技术手段。真正的云应用必须是基于云原生架构的,PaaS是一个重要的步骤,因为这是云原生的第一接触点。基于云原生架构的PaaS平台于企业客户、于生态伙伴而言,都是真正上云的必要支撑!用友公司聚焦企业服务领域近30年的时间,用友云基于新一代信息技术,构建数字化商业的基础设施,为企业提供2.0版智能化企业云服务,解决企业上云的“最后一公里”问题,让云计算在千家万户企业真正落地。用友云在新技术新架构上的优势主要沉淀在用友云平台上,可以说是整个用友云的“技术担当”。作为PaaS平台,它向下连接IaaS,向上生长SaaS、BaaS,纵向还要打通DaaS, 将企业服务的很多特征、基础能力、数据能力、应用能力集成在一个平台之内。因此,要问用友云的技术先进性如何?是否可以承载企业上云的期望?可以从用友云平台身上找到一些答案。云原生风格架构,业务上云赋能云原生平台可以理解为,以云计算相关的云原生技术为基础的落地平台。用友云平台基于云原生架构的基础,赋能所有云成为真正的云架构平台。它包含了三个层面的云原生技术,这也是用友云平台云架构的基础构成 :一,DevOps平台。提供开发运维一体化平台,解决业务敏捷响应,产品快速发布的问题,支撑微服务架构下应用监控,自动化运维管理。它能够让整个开发和运维过程变成连续的、自动化的过程,形成持续集成、持续交付、快速迭代;二,容器云平台。容器技术是一种全新的,更深层次的虚拟化技术。提供基于容器的运行时引擎,基于Mesos和Kubernets的容器调度方案,解决开发、测试、运行环境统一、服务快速部署,运行期服务管理、调度的问题。提供物理机、虚拟机、私有云、共有云统一接入的能力,屏蔽基础设施层的复杂性;三,微服务治理平台。它颠覆了传统的SOA,打破了中心化的理念,可以自动发现服务并连接,使服务间可以做更灵活的组合。提供微服务架构编程模型和最佳实践,提供基于服务日志的全链路监控、统计和分析。用友云平台的云原生架构有三大特点:首先,它是成体系的,体系和平台功能都很完整;其次,覆盖了企业所需的大部分应用场景,包括各行业和各领域应用;第三,它是可落地的,且落地完整度较高。用友云平台上已经运营着财务、采购、支付等领域云,及政务、能源、建筑等行业云。同时,用友已经为中国建筑集团、海底捞集团、国家开发银行、中信集团等搭建了中建云、餐饮云、中信云等,具备完善的云平台定制部署经验。用友云平台中有一个开发者中心,是云原生的最好体现。它作为用友云连接云上业务及服务的纽带,提供了完备的应用开发、运行、运维、运营支撑能力。上云的应用可一键上架到云市场,能够打通与SaaS 服务、基础数据服务及API 市场的连接。基于开发者中心可以将“客户、产品、交付”的理念通过云的方式轻松的实践。ISV 开发的应用还可以通过云市场具备持续变现的能力。智能化移动应用建设,开发能力赋能如果说云原生架构是解决了开发者的效率问题,那么接下来要提到的内容则是主要解决开发能力问题。今天,主流技术向物联、智能化发展,从PC互联到移动互联到万物互联,历史在快速演进。用友移动平台(Moli)作为下一代泛终端的一体化解决方案,是涵盖跨泛设备开发运、智能化、IoT 安全接入、用户行为分析、运维运营、管理监控等能力的基于新技术、新架构、新模式的技术平台。Moli移动应用建设,全面支持人脸识别、语音交互、混合现实等移动领先技术。可以为生态伙伴带来地图服务、AR服务、通讯服务等基础能力;实景导航、识图互动、在线客服、轨迹查询等业务组件;物流监控、门店查询、商超导航、设备维修、协同办公等业务模板;O2O商城应用、物流管理应用、商超门户应用、CRM等业务应用;商户点评、智慧交通、安全认证、AR广告等行业平台。构建API经济,数据服务赋能当今领先的企业都在进行数字转型,专注于API 经济。通过API经济解决方案,企业能够充分利用其大部分数据,创建一流的客户体验并开启新的收入渠道。APILink是用友提供的API市场、API网关及云服务产品。里面收录了所有用友云API,用友ERP API,同时ESB开发的API发布到API市场。同时收录了第三方API,包括电商类、安全类、支付类、其他SaaS API、人工智能API等。和第三方API市场做融合,相互接入,给API服务商提供专区服务。还可以与用友云市场交易对接,通过调用次数及流量等方式进行收费及与提供商进行利润分成。目前,已经有众多API伙伴入住用友云市场,生成全新的合作与盈利模式。如微赞与用友云平台无缝集成、融合推出企业直播多场景服务“云直播”;小能科技与用友云的融合产品“云客服”,能够高效解决企业和用户之间的沟通场景;E签宝与用友云的融合产品“云合同”能够为用友云在销售、采购、人力、办公等场景提供电子合同、电子签章服务,让商业及管理过程变得简单可信。这种合作模式,能够将线下的经营优势扩展到线上,并赋能伙伴。帮助伙伴实现商品上架、销售、在线服务及销售全过程管理。

January 23, 2019 · 1 min · jiezi

关于公司架构管控的思考

假想背景:现状是,各子系统的新建及重大迭代都会形式化地走架构审批流程,但应用架构是否设计以及是否合理,信息技术部门不能掌握。而架构规划部门的架构师人屈指可数,面对总人数达数百人的开发团队所负责的几十子系统、每个月数十个迭代特性,无法做到直接帮助开发团队详尽的进行架构设计。由此提出:架构审批流程不代表架构设计、架构规划部门要加强架构管控。要做好架构管控,需要能够回答几个问题:架构管控的目的是什么?架构管控的目标是什么?架构管控需要管控什么内容?如何进行管控?一、目的一个稳定发展、创新发展的企业,支援业务发展的信息系统的稳定与效率同等重要。架构管控的目的,要指导各团队技术负责人设计出合理的系统,能够满足稳定与开发效率的要求,能够满足功能与非功能的需求,能够考虑到各级相关者的意见;并且还要有考察开发过程及运营过程的机制,以确定最终交付的软件系统复合架构设计及开展架构设计的持续改善工作。二、制定目标为了达到这些我们架构管控的目标又是什么呢?发布一份指导意见?发布一份制度说明?发布一份评分表?我认为这些应该归属于如何进行管控,而不是目标。我们需要梳理现状,找出主要矛盾,量化主要矛盾,形成目标(SMART原则别忘记~~)(一)、主要生产问题、客户投诉及分类从客户反馈中可以抓住主要矛盾。(二)、信息技术方面的主要矛盾外购产品 vs 二次改造早期从外部采购的产品一般会使用比较老旧的开发框架,进行二次改造困难,常带来较多故障,并且开发效率低下。系统解耦 vs 互相影响分布式带来较好的伸缩性等非功能特性的同时,也带来了复杂度 —— 系统间相互影响较难控制,给设计和开发增大了难度。开发团队对科技公共平台的不熟悉 vs 强制使用业务数据模型混乱 vs 新需求5、控制 vs 创新(三)、形成架构管控目标控制新增外购系统的架构方案的合理性、梳理既存外购系统的架构、提升开发效率。降低分布式系统的开发难度、提升分布式系统的交付质量。降低科技公共平台的使用难度。引导、规范新技术的引入。

January 22, 2019 · 1 min · jiezi

入职一家大公司,应该选择新业务还是老业务?

新入职一家公司,你是想接手一个新的业务还是交接一个老业务呢?我来说说我的思考!新业务还是老业务?前提在一家BAT这样的大公司,从技术角度来想会有什么新业务吗?大概率是很难遇到的。新人刚入公司基本也是从老员工手里接手一些老的业务,旧的代码,这些代码有着这样那样的问题,技术栈陈旧,架构不灵活,无法满足新业务,历史遗留问题多,新需求还不断。该怎么办呢?新业务好吗?自己去独立负责一块没有的业务,从头开始,对于一个高级工程师来说,这样的业务往往比较小,或者并不受重视,从头做起是简单的,简单的由你来做,有什么挑战呢?大公司普遍有着创新者的窘境,所以从技术角度来说并没有什么新业务或者新技术,比如从0搭建一个react全家桶难吗?想必并没有什么挑战。去做新业务也许只是你的杏仁核在作怪,这是一种寻求确定感的自我意识驱动。改别人的代码往往并不能带来一种掌控力和确定感,缺失这种感觉往往会让你陷入自我焦虑,尤其是持续性的超负荷填坑,会让你产生生理抗拒。从零开始的业务往往是不成熟的,需求不明确的,是摸着石头过河,很难有全局甚至宏观的把握。初始设计的架构很难说能保持多久。新业务会出成绩吗?对于一个开发来说,业务做的好坏从来都是基本盘,那是产品经理的kpi,开发应该关注的是通过业务沉淀出的能力。新是很难做到深的,而深才是能力。一个前景巨大的新业务,你的上级会把他交给你吗?其他老员工早就看到了,还能轮得到你?老业务不好吗?一个需求爆炸的老业务,说明他依然具有很大的增长性。在大公司里一个需求旺盛的老业务,是被时间证明具有很高价值的。他牵扯的人也会更多,他们都是利益共同体,而这些人会让他变大,变茂盛。技术栈陈旧,架构不合理,说明他是一个可以从架构和顶层思维解决的问题,而这种思维才是具有挑战性的。也是从一个工程师想让架构师转变的好场景。历史遗留问题多,让参与其中的每个人都感受过他的痛处,如果你能解决,将获得更多的正反馈。代码陈旧与不合理往往带来系统稳定的问题,而解决系统稳定性在大公司是非常关键的指标。如何让老业务代码焕发新生机?你可能首先想到的是重构。但重构是推翻了重来吗?你应该重点关注以下几点稳定性开发效率提升代码学习成本降低,便于扩大开发团队规模工程化工具顶层设计思维该怎么做?完整的理清系统现有的业务逻辑,画一张大图,清晰的说明白。预期未来一段时间的需求,添加其中。发现并罗列其中的问题,尤其是对你的合作方带来的问题。设计解决方案,向相关各方持续输出迭代自己的方案。出一张新的架构图。突出体现新方案带来的业务价值,比如稳定性提升,人效提升,销量提升,投诉率降低,体验提升等。渐进式的重构代码,老需求不动新需求采用新架构,并逐渐替换老业务逻辑,千万不要一上来就重做,重在设计不在代码整理和重写。沉淀技术能力。具体操作尽量快的梳理现有业务逻辑,边做新需求边熟悉。反复与产品经理以及后端同学同步和完善这张大图。对于新需求的接入排期,给自己留足时间。对于一些改动较大的需求选择性说服合作方暂且搁置。一点一点的输出新方案,向合作方表现出相当强的重构意愿,赢得他们的支持。得到支持的目的是让你获得足够的时间来重构代码。提高自己思考的维度,回到需求的原点,了解真正的需求是什么,要解决什么问题,防止遇到老代码业务逻辑与需求脱离变形问题。回到需求原点来设计业务架构。软件设计是一个非常专业的知识领域,有很多总结好的套路和方法,需要花时间学习。用引擎这个概念来思考和拆分业务,而不是传统的页面,组件。一个软件可以包含多个引擎,而每个引擎之间相对独立,通过数据做流转和连接。数据,模型,逻辑分离。清晰的编码规范和思路,让别人在你的框架约束下写代码,让代码整洁又可控。能力沉淀,通过这次重构,有哪些技术能力沉淀下来,能批量解决什么样的一类问题。核心关注点能力型组织不拘泥于任何业务,他是一个批量解决问题的引擎。业务提效能力沉淀总结作为一个技术人员完成业务需求永远都是基本盘,能力的提升才是最重要的。而能力中最重要的是软件设计能力(架构和视野)和深入研究能力(技术深度和专业性)。作为工程师,你需要把握三项能力。宏观视野(扩大知识面,比如了解编程范式,设计模式,不同语言特性,行业前沿状态等)中观套路(大公司能给你的思考方式方法,规章制度,文化,管理经验等)微观体感(自己在实践中摸索的原则和感觉)欢迎访问我的blog: http://yondu.vip

January 20, 2019 · 1 min · jiezi

阿里大规模数据中心性能分析

郭健美,阿里巴巴高级技术专家,目前主要从事数据中心的性能分析和软硬件结合的性能优化。CCF 系统软件专委和软件工程专委的委员。曾主持国家自然科学基金面上项目、入选上海市浦江人才计划A类、获得 ACMSIGSOFT “杰出论文奖”。担任 ICSE'18NIER、ASE'18、FSE'19 等重要会议程序委员会委员。*数据中心已成为支撑大规模互联网服务的标准基础设施。随着数据中心的规模越来越大,数据中心里每一次软件(如 JVM)或硬件(如 CPU)的升级改造都会带来高昂的成本。合理的性能分析有助于数据中心的优化升级和成本节约,而错误的分析可能误导决策、甚至造成巨大的成本损耗。本文整理自阿里巴巴高级技术专家郭健美在 2018 年 12 月 GreenTea JUG Java Meetup上的分享,主要介绍阿里大规模数据中心性能监控与分析的挑战与实践。大家好,很高兴有机会与 Java 社区的开发者交流。我的研究领域在软件工程,主要集中在系统配置和性能方面。软件工程一个比较常见的活动是找 bug,当然找 bug 很重要,但后来也发现,即便 bug-free 的程序也会被人配置错,所以就衍生出了软件配置问题。很多软件需要配置化,比如 Java 程序或 JVM 启动时可以配置很多参数。通过配置,一套软件可以灵活地提供各种定制化的功能,同时,这些配置也会对软件整体性能产生不同的影响。当然这些还在软件配置方面,来了阿里以后,我有机会把这方面工作扩展到了硬件,会更多地结合硬件比如 CPU,来看系统的配置变更和升级改造对性能、可靠性以及业务上线效果的影响。今天主要谈谈我在这方面的一点工作。阿里最有代表性的事件是“双 11”。这里还是用的去年的数据,因为今年有些数据还没出来。左上角是双十一的销售额,去年大概是 253 亿美金,比美国同期 Thanksgiving、Black Friday、Cyber Monday 加起来的销售额还要多。当然这是从业务层面去看数据,技术同学会比较关注右边的数据,去年双十一的交易峰值达到 32.5 万笔/秒、支付峰值达到 25.6 万笔/秒。对于企业来说,这么高的峰值性能意味着什么?意味着成本!我们之所以关注性能,就是希望通过持续的技术创新,不断地提高性能、同时节省成本。双十一零点的峰值性能不是一个简单的数字,其背后需要一个大规模数据中心来支撑。 简单来说,阿里的基础架构的上层是各种各样的应用,比如淘宝、天猫、菜鸟、钉钉,还有云计算和支付宝等,这也是阿里的一个特色,即具有丰富的业务场景。底层是上百万台机器相连的大规模数据中心,这些机器的硬件架构不同、分布地点也不同,甚至分布在世界各地。中间这部分我们称之为中台,最贴近上层应用的是数据库、存储、中间件以及计算平台,然后是资源调度、集群管理和容器,再下面是系统软件,包括操作系统、JVM 和虚拟化等。中台这部分的产品是衔接社区与企业的纽带。这两年阿里开源了很多产品,比如 Dubbo、PouchContainer 等,可以看出阿里非常重视开源社区,也非常重视跟开发者对话。现在很多人都在讲开源社区和生态,外面也有各种各样的论坛,但是像今天这样与开发者直接对话的活动并不是那么多,而推动社区发展最终还是要依赖开发者。这样大规模的基础架构服务于整个阿里经济体。从业务层面,我们可以看到 253 亿美金的销售额、32.5 万笔交易/秒这样的指标。然而,这些业务指标如何分解下来、落到基础架构的各个部分就非常复杂了。比如,我们在做 Java 中间件或 JVM 开发时,都会做性能评估。大部分技术团队开发产品后都会有个性能提升指标,比如降低了 20% 的 CPU 利用率,然而这些单个产品的性能提升放到整个交易链路、整个数据中心里面,占比多少?对数据中心整体性能提升贡献多少?这个问题很复杂,涉及面很广,包括复杂关联的软件架构和各种异构的硬件。后面会提到我们在这方面的一些思考和工作。阿里的电商应用主要是用 Java 开发的,我们也开发了自己的 AJDK,这部分对 OpenJDK 做了很多定制化开发,包括:融入更多新技术、根据业务需要及时加入一些 patches、以及提供更好的 troubleshooting 服务和工具。大家也知道,今年阿里入选并连任了 JCPEC 职位,有效期两年,这对整个 Java 开发者社区、尤其是国内的 Java 生态都是一件大事。但是,不是每个人都了解这件事的影响。记得之前碰到一位同仁,提到 JCPEC 对阿里这种大业务量的公司是有帮助,对小公司就没意义了。其实不是这样的,参选 JCPEC 的时候,大公司、小公司以及一些社区开发者都有投票资格,小公司或开发者有一票,大公司也只有一票,地位是一样的。很多国外的小公司更愿意参与到社区活动,为什么?举个简单例子,由于业务需要,你在 JVM 8 上做了一个特性,费了很大的力气开发调试完成、业务上线成功,结果社区推荐升级到 JVM11 上,这时你可能又需要把该特性在 JVM 11 上重新开发调试一遍,可能还要多踩一些新的坑,这显然增加了开发代价、拉长了上线周期。但如果你能影响社区标准的制定呢?你可以提出将该特性融入社区下一个发布版本,有机会使得你的开发工作成为社区标准,也可以借助社区力量完善该特性,这样既提高了技术影响力也减少了开发成本,还是很有意义的。过去我们做性能分析主要依赖小规模的基准测试。比如,我们开发了一个 JVM 新特性, 模拟电商的场景,大家可能都会去跑SPECjbb2015 的基准测试。再比如,测试一个新型硬件,需要比较 SPEC 或 Linpack 的基准测试指标。这些基准测试有必要性,因为我们需要一个简单、可复现的方式来衡量性能。但基准测试也有局限性,因为每一次基准测试都有其限定的运行环境和软硬件配置,这些配置设定对性能的影响可能很大,同时这些软硬件配置是否符合企业需求、是否具有代表性,都是需要考虑的问题。阿里的数据中心里有上万种不同的业务应用,也有上百万台分布在世界各地的不同服务器。当我们考虑在数据中心里升级改造软件或硬件时,一个关键问题是小规模基准测试的效果是否能扩展到数据中心里复杂的线上生产环境?举个例子,我们开发了 JVM 的一个新特性,在 SPECjbb2015 的基准测试中看到了不错的性能收益,但到线上生产环境灰度测试的时候,发现该特性可以提升一个 Java 应用的性能、但会降低另一个 Java 应用的性能。同时,我们也可能发现即便对同一个 Java 应用,在不同硬件上得到的性能结果大不相同。这些情况普遍存在,但我们不可能针对每个应用、每种硬件都跑一遍测试,因而需要一个系统化方法来估计该特性对各种应用和硬件的整体性能影响。对数据中心来说,评估每个软件或硬件升级的整体性能影响非常重要。比如,“双11”的销售额和交易峰值,业务层面可能主要关心这两个指标,那么这两个指标翻一倍的时候我们需要买多少台新机器?需要多买一倍的机器么?这是衡量技术能力提升的一个手段,也是体现“新技术”对“新商业”影响的一个途径。我们提出了很多技术创新手段,也发现了很多性能提升的机会,但需要从业务上也能看出来。为了解决上面提到的问题,我们开发了 SPEED 平台。首先是估计当前线上发生了什么,即 Estimation,通过全域监控采集数据,再进行数据分析,发现可能的优化点。比如,某些硬件整体表现比较差,可以考虑替换。然后,我们会针对软件或硬件的升级改造做线上评估,即 Evaluation。比如,硬件厂商推出了一个新硬件,他们自己肯定会做一堆评测,得到一组比较好的性能数据,但刚才也提到了,这些评测和数据都是在特定场景下跑出来的,这些场景是否适合用户的特定需求?没有直接的答案。通常,用户也不会让硬件厂商到其业务环境里去跑评测。这时候就需要用户自己拿这个新硬件做灰度测试。当然灰度规模越大评测越准确,但线上环境都直接关联业务,为了降低风险,实际中通常都是从几十台甚至几台、到上百台、上千台的逐步灰度。SPEED 平台要解决的一个问题就是即便在灰度规模很小时也能做一个较好的估计,这会节约非常多的成本。随着灰度规模增大,平台会不断提高性能分析质量,进而辅助用户决策,即 Decision。这里的决策不光是判断要不要升级新硬件或新版软件,而且需要对软硬件全栈的性能有一个很好的理解,明白什么样的软硬件架构更适合目标应用场景,这样可以考虑软硬件优化定制的方向。比如,Intel 的 CPU 从 Broadwell 到 Skylake,其架构改动很大,但这个改动的直接效果是什么?Intel 只能从基准测试中给答案,但用户可能根据自己的应用场景给出自己的答案,从而提出定制化需求,这对成本有很大影响。最后是 Validation,就是通常规模化上线后的效果来验证上述方法是否合理,同时改进方法和平台。数据中心里软硬件升级的性能分析需要一个全局的性能指标,但目前还没有统一的标准。Google 今年在 ASPLOS 上发表了一篇论文,提出了一个叫 WSMeter 的性能指标,主要是基于 CPI 来衡量性能。在 SPEED 平台里,我们也提出了一个全局性能指标,叫资源使用效率 RUE。基本思想很简单,就是衡量每个单位 Work Done 所消耗的资源。这里的 Work Done 可以是电商里完成的一个 Query,也可以是大数据处理里的一个 Task。而资源主要涵盖四大类:CPU、内存、存储和网络。通常我们会主要关注 CPU 或内存,因为目前这两部分消费了服务器大部分的成本。RUE 的思路提供了一个多角度全面衡量性能的方法。举个例子,业务方反映某台机器上应用的 response time 升高了,这时登录到机器上也看到 load 和 CPU 利用率都升高了。这时候你可能开始紧张了,担心出了一个故障,而且很可能是由于刚刚上线的一个新特性造成的。然而,这时候应该去看下 QPS 指标,如果 QPS 也升高了,那么也许是合理的,因为使用更多资源完成了更多的工作,而且这个资源使用效率的提升可能就是由新特性带来的。所以,性能需要多角度全面地衡量,否则可能会造成不合理的评价,错失真正的性能优化机会。下面具体讲几个数据中心性能分析的挑战,基本上是线上碰到过的具体问题,希望能引起大家的一些思考。首先是性能指标。可能很多人都会说性能指标我每天都在用,这有什么好说的。其实,真正理解性能指标以及系统性能本身并不是那么容易。举个例子,在数据中心里最常用的一个性能指标是 CPU 利用率,给定一个场景,数据中心里每台机器平均 CPU 利用率是 50%,假定应用需求量不会再增长、并且软件之间也不会互相干扰,那么是否可以把数据中心的现有机器数量减半呢?这样,理想情况下 CPU 利用率达到 100% 就可以充分利用资源了,是否可以这样简单地理解 CPU 利用率和数据中心的性能呢?肯定不行。就像刚才说的,数据中心除了 CPU,还有内存、存储和网络资源,机器数量减半可能很多应用都跑不起来了。再举个例子,某个技术团队升级了其负责的软件版本以后,通过线上测试看到平均 CPU 利用率下降了 10%,因而声明性能提升了 10%。这个声明没有错,但我们更关心性能提升以后是否能节省成本,比如性能提升了 10%,是否可以把该应用涉及的 10%的机器关掉?这时候性能就不应该只看 CPU 利用率,而应该再看看对吞吐量的影响。所以,系统性能和各种性能指标,可能大家都熟悉也都在用,但还需要更全面地去理解。刚才提到 SPEED 的 Estimation 会收集线上性能数据,可是收集到的数据一定对吗?这里讲一个 Hyper-Threading 超线程的例子,可能对硬件了解的同学会比较熟悉。超线程是 Intel 的一个技术,比如我们的笔记本,一般现在都是双核的,也就是两个hardwarecores,如果支持超线程并打开以后,一个 hardware core 就会变成两个 hardware threads,即一台双核的机器会有四个逻辑 CPU。来看最上面一张图,这里有两个物理核,没有打开超线程,两边 CPU 资源都用满了,所以从任务管理器报出的整台机器平均 CPU 利用率是 100%。左下角的图也是两个物理核,打开了超线程,每个物理核上有一个 hardwarethread 被用满了,整台机器平均 CPU 利用率是 50%。再看右下角的图,也是两个物理核,也打开了超线程,有一个物理核的两个hardware threads 都被用满了,整台机器平均 CPU 利用率也是 50%。左下角和右下角的 CPU 使用情况完全不同,但是如果我们只是采集整机平均 CPU 利用率,看到的数据是一样的!所以,做性能数据分析时,不要只是想着数据处理和计算,还应该注意这些数据是怎么采集的,否则可能会得到一些误导性的结果。数据中心里的硬件异构性是性能分析的一大挑战,也是性能优化的一个方向。比如这里左边的 Broadwell 架构,是 Intel 过去几年服务器 CPU 的主流架构,近几年在推右边的 Skylake 架构,包含最新的 Cascade Lake CPU。Intel 在这两个架构上做了很大的改动,比如,Broadwell 下访问内存还是保持多年的环状方式,而到了 Skylake 改为网格状方式。再比如,L2 Cache 到了Skylake 上扩大了四倍,通常来说这可以提高 L2 Cache 的命中率,但是 cache 越大也不代表性能就一定好,因为维护 cache coherence 会带来额外的开销。这些改动有利有弊,但我们需要衡量利和弊对整体性能的影响,同时结合成本来考虑是否需要将数据中心的服务器都升级到 Skylake。了解硬件的差异还是很有必要的,因为这些差异可能影响所有在其上运行的应用,并且成为硬件优化定制的方向。现代互联网服务的软件架构非常复杂,比如阿里的电商体系架构,而复杂的软件架构也是性能分析的一个主要挑战。举个简单的例子,图中右边是优惠券应用,左上角是大促主会场应用,右下角是购物车应用,这三个都是电商里常见的业务场景。从 Java 开发的角度,每个业务场景都是一个 application。电商客户既可以从大促主会场选择优惠券,也可以从购物车里选择优惠券,这是用户使用习惯的不同。从软件架构角度看,大促主会场和购物车两个应用就形成了优惠券应用的两个入口,入口不同对于优惠券应用本身的调用路径不同,性能影响也就不同。所以,在分析优惠券应用的整体性能时需要考虑其在电商业务里的各种错综复杂的架构关联和调用路径。像这种复杂多样的业务场景和调用路径是很难在基准测试中完全复现的,这也是为什么我们需要做线上性能评估。这是数据分析里著名的辛普森悖论,在社会学和医学领域有很多常见案例,我们在数据中心的性能分析里也发现了。这是线上真实的案例,具体是什么 App 我们不用追究。假设还用前面的例子,比如 App 就是优惠券应用,在大促的时候上线了一个新特性 S,灰度测试的机器占比为 1%,那么根据 RUE 指标,该特性可以提升性能 8%,挺不错的结果。但是如果优惠券应用有三个不同的分组,分组假设就是刚才提到的不同入口应用,那么从每个分组看,该特性都降低了应用的性能。同样一组数据、同样的性能评估指标,通过整体聚集分析得到的结果与通过各部分单独分析得到的结果正好相反,这就是辛普森悖论。既然是悖论,说明有时候应该看总体评估结果,有时间应该看部分评估结果。在这个例子里面,我们选择看部分评估、也就是分组上的评估结果,所以看起来这个新特性造成了性能下降,应该继续修改并优化性能。所以,数据中心里的性能分析还要预防各种可能的数据分析陷阱,否则可能会严重误导决策。最后,还有几分钟,简单提一下性能分析师的要求。这里通常的要求包括数学、统计方面的,也有计算机科学、编程方面的,当然还有更重要的、也需要长期积累的领域知识这一块。这里的领域知识包括对软件、硬件以及全栈性能的理解。其实,我觉得每个开发者都可以思考一下,我们不光要做功能开发,还要考虑所开发功能的性能影响,尤其是对数据中心的整体性能影响。比如,JVM 的 GC 开发,社区里比较关心 GC 暂停时间,但这个指标与 Java 应用的 response time 以及所消耗的 CPU 资源是什么关系,我们也可以有所考虑。当然,符合三块要求的候选人不好找,我们也在总结系统化的训练流程,欢迎对系统性能有兴趣的同学加入我们。本文作者:amber涂南阅读原文本文为云栖社区原创内容,未经允许不得转载。 ...

January 17, 2019 · 2 min · jiezi

高可用、弹性动态的金融级移动架构在蚂蚁金服的演进之路

摘要: 支付宝作为国民级应用,当前全球用户已经超过 10 亿,提供了超过 200 项以上的服务,而崩溃率始终维持在万分之五以下,而且每天支付宝都上线新的功能和改进。做到今天这样的成绩,并不容易,是经过长时间的实践经验积累下来的。导语本文基于重岳在 2018 年 Arch Summit 北京站的分享内容进行总结,希望通过本篇文章介绍近些年来支付宝在移动端架构的上演进和思考,期冀能给读者们带来些许帮助。支付宝作为国民级应用,当前全球用户已经超过 10 亿,提供了超过 200 项以上的服务,而崩溃率始终维持在万分之五以下,而且每天支付宝都上线新的功能和改进。做到今天这样的成绩,并不容易,是经过长时间的实践经验积累下来的。支付宝的架构演进主要经历了三个阶段,如果用比喻的话,可以分为独木舟、战列舰和航空母舰三个阶段。独木舟时代支付宝刚推出移动端时,它的结构非常之简单,除了一些工具组件被划分为模块,业务代码都是糅合在一起。刚开始并没有太大问题,但是当我们的研发人员迅速增长时,问题开始变得棘手起来,仅仅举几个例子便可见一斑。研发同学晚上提交的可以运行的代码,到第二天早上来更新一下就完全不能用,原因是其他不相干团队提交代码覆盖或者污染了自己的代码。临近发布点的时候,通常是最忙的,但不是忙着赶功能,而是忙着解决合并代码产生的各种问题,不仅浪费时间,还耽误测试同学的宝贵时间。即使最后勉强发布了,稳定性和性能也是非常糟糕的,因为各个模块只管自己的,没有统一的规范,也缺乏统一的监控。最令 Android 开发头痛的是 65535 的问题,彼时 Google 还没有推出 multi-dex 的方案。这些严重的问题让我们的产品研发迭代变得无法持续下去,因此我们决定来一次彻底的重构,于是步入了战列舰时代。战列舰时代当设计新一代的客户端架构时,我们从三个方向进行思考:团队协作、研发效率、性能与稳定。团队协作方面,我们希望整个架构分层合理,基础层面,将通用能力下沉,为更多的上层业务服务,避免重复创造轮子;业务层面,各个业务团队能够独立开发管理,不会对不相关的业务造成影响。基于这个初衷,我们形成了下图这样的架构:整个客户端架构总共分成四层:业务层、服务层、组件层、框架层。业务层:只需专注于业务逻辑与界面的实现,当需要调用如支付这样的通用能力时,研发同学直接使用下层提供的服务能力,不需自己开发,如此能够保证核心能力有收口,方便监控。服务层:常用模块,如登录、支付、营销等,它们不仅自己是业务,也向其他业务提供自己的服务,我们将此类模块归类到服务层。组件层:这一层提供的是客户端通用能力,如安全、网络、多媒体、存储这些,它们提供稳定的接口给上层使用者,同时不断优化自身内部的性能和稳定性,作为客户端的基石,它们至关重要。框架层:最为关键的部分,包括容器、微应用、服务框架以及 Pipeline,客户端的微应用化、启动管理都依赖框架层的运作。我们将服务层、组件层和框架层合称为 mPaaS,即移动端上的 PaaS 服务。这些 PaaS 服务可以复用,我们不仅在支付宝里使用它们,也在其他集团应用,如蚂蚁财富、网商银行等中使用。业务分治要实现业务分治,最好的方式就在代码上能够进行隔离,大家不必在同一个 Codebase 中开发,避免代码合并冲突的现象,这个通常在 Android 上通常可以 aar 的方式来实现,但是可惜的是我们重构的时候 aar 还没出来,而且即使有 aar,也存在打包时间随代码体积增大线性增长的问题。我们的解决方案借鉴 OSGi 的概念,将整个客户端以 Bundle 为单位划分,每个 Bundle 可以包含自己的代码、页面和资源。读者可能会想,这究竟和 aar 有什么分别呢?其实区别很大!首先,Bundle 里的代码部分是已编译的 dex,当编译 apk 时,我们只需要合并 dex 即可,不需要像 aar 那样将 class 编译成 dex 再进行合并,这样大大节省了打包时间;其次,Bundle 是可以独立运行于自己的 ClassLoader 中的,并且我们可以通过壳代理的方式加载 Activity 等基础组件,使得动态下发业务成为可能;最后,Bundle 里还包含微应用、服务和 Pipeline 相关的配置信息,框架会根据这些信息启动相应的组件。mPaaS 的服务,即 Service 类似于 Spring 框架中的 Service,它对外提供接口服务,而使用者不需要知道如何初始化服务的实例以及生命周期管理,这些完全由框架来托管。使用者只需要知道目标服务接口类的方法参数即可,调用时通过框架提供的 API 来获取实例。对于服务的发布者来说,他在自己的 bundle 中声明接口类以及实现接口类派生的实例类,并注册相关信息到 bundle 的 manifest 文件中。这种做法的本质思想是 Inversion of Control,减少类之间的复杂依赖,避免繁琐的初始化工作。以依赖接口的方式进行开发,能够解除服务使用者对服务提供者的依赖,在服务提供者尚未完全开发完成时,使用者可以完全以 mock 的方式来模拟服务,而不需要修改自己的业务代码,当然,前提是双方协商好服务接口的协议。支付宝中的页面非常多,直接启动 Activity 或者 ViewController 对我们来说远远不够,我们选择在它们上面增加 MicroApp,即微应用的概念。微应用具备唯一的应用 ID,在框架中标识自己的存在。微应用具有统一的入口,根据使用方传入的字典参数来管理 Activity 或 ViewController。这样能够带来很多好处:只要应用 ID 和参数协议不变,使用方不需担心目标应用内部重构带来的影响,直接使用 Activity 或者 ViewController 类名造成的引用泛滥的问题不复存在。微应用的 ID 和字典参数特性,很容易生成 URL,从而实现外部应用使用 URL 跳转应用内页面。从数据的角度,我们可以按业务维度来统计用户行为数据。微应用的概念不仅适用于原生页面,同样也适用于 H5 和小程序。注册为 H5 或者小程序类型的应用 ID,框架会自动将启动过程 delegate 给 H5 或者小程序容器,而使用者完全不必关心应用 ID 对应的应用类型。综上所述,微应用化和服务接口所赋予的特性极大提高团队间协作效率,各研发小组之间的依赖更加简单,可以各行其道,更关注于自身服务的打造建设。性能优化我们一方面在架构上作出重大改变来提高研发效率,另一方面也在不断的进行性能优化,改善用户体验。我们主要从三个层面来着手:框架层面制定统一开发规范,业务方使用统一的线程池、存储、网络等组件,并按需进行加载,避免不必要的启动和耗时操作。引入 Pipeline 机制,业务模块如需在应用启动时进行初始化工作,必须使用 Pipeline。框架依据业务优先级确定业务初始化实际。利用 AOP 切面,对常用路径进行耗时统计,追踪性能瓶颈。基础指标对于常用指标,如闪退、ANR、内存、存储、电量、流量等,进行长期追踪。我们能够明确获悉每个版本之间这些指标上的差异,并进行采样分析,定位并解决问题。向下突破我们不仅仅在应用层面进行优化,同时也向下探索性能提升的可能性。在这方面,我们也收获颇丰,比如在 Android 上某些系统版本,通过在启动阶段禁用 GC 的方式获得 20%~30% 的启动时间缩减;在 iOS 上,利用系统本身的 Background Fetch 机制提高进程活跃时间,实现应用秒起。航母时代随着移动支付的不断普及,面对海量的用户和业务需求,高可用、弹性动态成为支付宝客户端更为艰巨的挑战。支付宝作为集支付、金融、生活为一体的服务平台,需要能够快速稳定的发布服务和引入第三方服务,同时对于用户的反馈和诉求必须能够积极迅速的响应。动态研发模式我们在研发模式上作出改变以业务快速迭代的要求,业务逐步由原生页面向 Web 混合页面迁移。原有的研发模式能够很好的满足团队协作的要求,但是随着业务规模的不断增大,代码量相应膨胀导致安装包太大,在iOS上一度超过代码段上限,无法通过 AppStore 审核,另外基于集中时间点的迭代发布,通常是一个月发布一个版本,远不能满足业务的更新速度要求。相较于原生应用开发,Web应用的优势非常明显:只需要一套代码,Web 应用可以在 iOS 和 Android 客户端中运行,能够相对减少人员的投入。每个用户日常使用的功能仅仅是支付宝庞大平台中的一小部分,H5 应用可以做到动态下发,因此可以消除冗余的存储,降低包大小。近些年来 React Native,Weex 等动态渲染引擎在社区非常活跃,但经过小范围的应用以及考虑到 Web 技术的不断发展以及其在业界公认的地位,我们最终还是选择 Web 技术作为动态研发模式的基础。Web 应用迭代摆脱了客户端集中时间点发布的束缚,各业务线迭代计划变得自主可控。打磨 Web 体验尽管 Web 应用优势明显,但在移动端上的短板也是显而易见的,它提供的用户体验、性能以及能力上的限制与原生应用有相当大的差距。为了弥补这些差距,我们做了大量的改进,主要在以下几个方面:前后端分离,我们将页面资源离线化,这样节省了资源请求消耗的时间,使得页面打开速度提升明显,解决了在网络环境较差下容易出现白屏的问题。同时,数据请求使用 native 网络通道,可优化的空间更大,安全性更高。差量更新,客户端更新某业务应用版本时,不需下载完整的新版本资源包,而是下载由发布平台根据客户端本地安装版本计算生成的体积更小的差量包,这样不仅能够节省带宽和流量,也提升了业务更新的速度。推拉结合,解决业务最新版本覆盖率的问题,每次发布新版本时,业务可主动触发消息到客户端,客户端收到通知后会更新该业务应用版本。同时,客户端会定时去检查服务端是否有版本发布,这样能够保证版本发布后大多数用户在短时间内获得最新的应用。容错补偿,客户端可能由于网络、安全或者存储权限等原因,不能使用或者及时获得离线包,这种情况我们也考虑进来了。我们在发布离线资源时,发布平台会自动生成对应的在线 URL 并配置到应用信息中,当客户端加载 Web 应用时发现离线包不可用,会立刻启用该url加载内容,能够最大程度保证业务可用性。Android 独立浏览器内核,Android 碎片化的问题自其诞生之初业已存在,而且目前看上去没有得以解决的迹象。不同系统、不同厂商中的浏览器内核同样存在差异,这导致层出不穷的兼容性问题令研发同学头疼不已,这也违背 Web 一统天下的愿景。为了彻底解决并掌控这些问题,我们引入了独立的 UC 浏览器内核并集成在应用中,这样所有的问题都集中到UC团队解决,变得非常可控,根据数据统计,使用 UC 浏览器内核后浏览器相关的闪退和 ANR 有明显的下降。同时,安全上出现的漏洞,我们可以在第一时间修复并发布,远比厂商升级更有效率。Web 应用全方位监控,资源加载异常、JS执行异常、白屏、加载耗时等性能数据会被收集上报至后台,可以及时发现异常。小程序我们不仅自身提供各种各样的服务,也需要引入第三方服务来服务更多的人群,以往我们只能引入简单的第三方 H5 页面,它们只能使用支付宝提供的少量功能,而且开发人员能力的差异导致用户体验不是很理想。小程序将支付宝的能力全面开放出来,从开发到测试皆有完整的 IDE 等工具链支持,同时 DSL 简单易用,对于第三方来说,能够快速开发上线一款体验和功能比以往更强大的小程序。本文作者:josephjin阅读原文本文为云栖社区原创内容,未经允许不得转载。 ...

January 15, 2019 · 1 min · jiezi

阿里开发者们的第17个感悟:无细节不设计,无设计不架构

2015年12月20日,云栖社区上线。2018年12月20日,云栖社区3岁。阿里巴巴常说“晴天修屋顶”。在我们看来,寒冬中,最值得投资的是学习,是增厚的知识储备。所以社区特别制作了这个专辑——分享给开发者们20个弥足珍贵的成长感悟,50本书单。多年以后,再回首2018-19年,留给我们自己的,除了寒冷,还有不断上升的技术能力与拼搏后的成就感。云栖社区钉钉技术讨论群,已有5000+开发者。云栖社区2019年1月30+场活动预告【持续更新,欢迎加入】 学习,是一种氛围。*1月14日,无细节不设计,无设计不架构。这是我们送给开发者的第17个感悟。项籍,阿里巴巴新零售供应链平台服务决策平台负责人。在专家页中如此介绍自己:“多年互联网开发经验,从事业务开发、平台开发、架构设计、云计算、APM等领域。目前专注于供应链方向的解决方案治理和服务交易域”。作为问答频道活跃的达人,欢迎交流讨论。阿里陈帅(项籍):无细节不设计,无设计不架构阿里巴巴新零售供应链平台服务决策平台负责人没有恶心的业务和应用,只有恶心的设计。只有程序员自己能把自己当成资源,多关注总结和沉淀。工程师的使命是使世界更加优雅和飘逸。推荐的书单《运筹学》《模式识别》《Java并发编程实战》《平台革命》本文作者:云篆阅读原文本文为云栖社区原创内容,未经允许不得转载。

January 14, 2019 · 1 min · jiezi