首页 > 精选 > SFDC 杭州开发者大会分享之微服务实践之路

SFDC 杭州开发者大会分享之微服务实践之路

【编者注】本文为阿里巴巴技术专家马昕曦(桃谷)在 SegmentFault 2016 杭州开发者大会上的演讲文稿整理,内容来自讲师的个人微信公众号「 次灵均阁」。

开场白

大家,下午好!这个时间点,老师们讲得辛苦,朋友也听得兴奋,欢迎大家拨冗参加鄙人的分享 ,感激涕零。要感谢的人太多,不能一一列举,首先,感谢国家,然后,再感谢在场的各位。之前我还很担心,如果我的分享在上午场的话,讲得不好怎么办?到了这个点彻底放心了,因为大家想退票都难咯。

今天非常荣幸与各位业界精英一起探讨前沿技术 。上月本人有幸被邀请前往厦门,参加互联网大会 ,做了相同主题的演讲,分享了“微服务”实践的经验。

可能大家有人看过我上场的演讲稿。不过由于招商局系大会的组织方,属于国有企业,有点段子不好说。告诉大家一个好消息和坏消息,好消息是,为了答谢广大“衣食父母”的错爱,本人的每次演讲都是“私人定制”,奉献给大家 。

坏消息则是前面的各位老师讲得太好了,多少让我有点自惭形愧。所以我打算改变一下演讲风格,讲点不让播的,大家轻松轻松,就图一乐。本次准备匆忙,可能不那么长,可能没有办法让您高潮跌宕。或许没有那么大,可能无法让你合不拢腿。这里的”长”是指的时间,那里的“大”是说的笑声。

希望这场会议不仅是技术交流,还是人文课堂,更是成人再教育。

以上的各位老师都是老司机,直奔主题。本人比较委婉一点,开场之前,来点前戏,请允许本人做一下自我介绍。

自我介绍

  • 姓名

也许大家已看过我的简介,请允许我再次向您自我介绍。鄙人的姓“马”,名“昕曦”,一个中国几乎唯一的人名。

  • 职业

就职于阿里巴巴,目前主要负责微服务技术实施和推广,重点关注云计算、微服务以及软件架构等领域。

  • 工作

我用十个字来概括工作内容,“互联网,意淫大数据”。

为什么说互联网呢?互联网源于技术,用于屌丝。啪啪啪地敲键盘,撸啊撸地写代码。小撸怡情,大撸伤身,不撸伤心,强撸飞灰烟灭。左手右手,一个慢动作。右手左手,慢动作重播。这动作,给你快乐,你有没有爱上我。

那“意淫大数据”做何解释呢?通俗地讲,想得太多,实践太少。这种感觉有点像,套路姿势都知道,就缺马子泡。

  • 笔名来历

作为一个文学青年,都会给自己张罗一个笔名,而我的笔名则来源于伟大的爱国诗人屈原的作品《离骚》,其辞句为“名余曰正则兮,字余曰灵均 ”。在这十一个字之中,有两个名可取。一是“正则 ”,二是“灵均”,不过“正则”二字,听起来就像个技术屌丝,所以选了“灵均 ”。由于屈原是楚辞鼻祖,文学斐然,相比起来,如同皓月与萤火虫,故名“次灵均”。

  • 花名来历

或许大家都知道,在阿里巴巴的企业文化里,每位入职的员工都要求取一个“花名”,而本人阿里的花名是“桃谷”。我的花名来自金庸先生的武侠小说《笑傲江湖》中人物“桃谷六仙”。虽然我也技能傍身啊,但是我非常讨厌人家称我为桃谷老师。

  • 桃谷(德艺双馨)

每当他人听到我的花名时,大多会发出贱贱的微笑?但是我觉得纳闷,后来搜索之后发现,原来是这样(如图所示):

同是天涯卖艺人,为什么她能名利双收,而我却默默无闻呢?何况我”码“上功夫轻车熟路,她不过炕上功夫炉火纯青。当我冷静后,得到一个结论,”写代码,没门路;要致富,先脱裤“,一个自取其“RU”,一个有求必“YING”,这是多么痛彻的领悟 。

这页面太美,不能停留太久。以免男同胞们全身发软,就剩下一个地方硬。待会大家都面红耳赤,不好意思站起身来。

我想大家已经差不多也热了热身。接下来,我马上要一本正经地往下讲了。

主题部分

上月去厦门所做的微服务分享,内容上多少略显“诗”态,以思想层面为主。然而大伙对微服务的热衷和理解让我颇感意外,希望本次分享变得“干”“诗”结合。今天大多数老师讲得太“硬”了,比较起来,我的就“软”了,我是说演讲内容。

议题分为四大部分:“What”、“Why”、“How” 以及 “Q&A”。

What

“是非之心,知之端也”

孟夫子有言,人要有四心,即“是非之心”、“恻隐之心”、“羞恶之心”、“恭敬之心”。是非之心,“知”之端也,因此,明白“是”与“非”让人活得明白。

这两年微服务作为一个非常新的技术,各种理论流派试图从不同的角度去阐述其概念和优势,我一开始是拒绝的,因为我没有”Duang“的一下想清楚。个人感性地认知是,姿势不对,纯靠意会。理性的看法则是,在思想上,那些布道师们并未达到一致。经过参考各家思想之后,得到了一些自己的领悟,我分享给大家。

微服务是什么?

微服务是一种细粒度(Fine-Grain)的SOA

或许在座的高朋了解过其概念。个人认为,与其说微服务是一种技术,不如将其定义为一种架构,而架构则是“技”的实现与“术”的策略相辅相成。“术”的策略需要分析使用场景,进行合理地划分业务边界,实现“业以类聚”,然而“技”的实现则通过特定的技术在实现业务逻辑之时,更多的考虑实现过程中的效率性、测试的便利性、维护的可持续性,达到“技以群分”的目的。

由此而论,我个人偏好将其定义为:“微服务是一种细粒度的SOA”。

这样定义的好处在于,没必要去重复地“抹黑”“单体应用”(Monolithic,也有人翻译成“巨石应用”),缘于SOA技术的衍化过程中早已提及。那么,细粒度更多的体现在“取其精华,去其糟粕”。

SOA 又是什么?

SOA = Service-Oriented Architecture

SOA 中文定义是面向服务架构,它并非是今日的重点,请原谅我不能花大篇幅来加以阐述。我用“点到为止”的方式描述SOA具备哪些特征,以及相关的技术。

SOA 有什么?

特征

  • 面向服务( Service-Oriented )

  • 松耦合(Loose-Coupling)

  • 模块化(Modular)

  • 分布式计算(Distributed Computing)

  • 平台无关性(Independent Platform)

  • 集中管理(Center Government)

技术

  • Web Services

Web Services 技术演进的目的在于解决分布式计算中,统一异构系统的服务调用的通讯协议。前期的Web Services有XML-PRC、WSDL、SOAP等技术,不但解决了Windows平台COM+以及Java 平台RMI无法跨平台的问题,而且使用了可读性强的本文协议替代了复杂的二进制协议,如CORBA技术。现代的WebServices 技术主要代表有REST等。

  • Message Queue

Message Queue 技术设计的目的主要有两个方面,从架构上来说,消息队列服务帮助系统之间依赖关系解耦;从技术上来看,消息队列为系统提供异步处理的能力,解决了并发同步调用导致资源消耗过集中和过快等问题,将上下游系统的数据结构提供了统一的传输介质。

  • ESB

ESB 则是 SOA 集大成实现。

SOA 不是什么?

SOA ≠ Monolithic

SOA 不但不是Monolithic,而且是要解决Monolithic,Monolithic 个人偏好翻译成“单体应用”,也被翻译成“巨石应用”。

Monolithic 是什么?


故宫


朋友可能觉得奇怪,故宫与“单体应用”有什么关系?故宫是帝王居住和办公的场所,。华夏民族,自秦朝的“三公九卿制”,还是隋朝的“三省六部制”,以及明清的“内阁制度”,。


近两千年来,虽然王朝不断更迭,这个制度一直被沿用,并且没有出现大的诟病。可是,1793年,英国勋爵马戛尔尼出使中国,代表英皇为乾隆皇帝祝寿,也负有促成中英通商的使命。虽然当时的中国笼罩在“乾隆盛世”的光环下,不过在马戛尔尼看来中国无论从科技还是社会制度上,均处于相对落后的阶段。《左传》有言:“民之多幸,国之不幸”,当时的大多数国民视英国为“蛮夷”,不与商贸往来。五十年后,中英鸦片战争爆发,1840年,,它不但打击中华名族,而且“打醒”了大和民族。明治维新后的日本,屡屡挑战中国的东亚地位,直到中日甲午战争失利。1895年《马关条约》签订,割台湾,赔巨款。但仍有康有为等不愿放弃,联名千人“公车上书”,。,行政不力,,无法做到“因地制宜”。


我想说的是,?而微服务应用则更像“多权分立”的“自治”政府,各个“自治”政府之间在“联邦”的架构下“分工”和“协作”。

Why?

“学而不思则罔”

为什么要微服务?

  • 效率的需要

应用进行微服务化后,规模和体积变得更加轻量级,在编译、打包、分发、部署等环节节约了时间,开发上效率提升。

  • 质量的需要

微服务应用面向持续集成友好,自动化编译、单元和集成测试用例执行和回归,提高应用整体质量。

  • 稳定的需要

当应用大而全时,往往牵一发而动全身,其中一个服务出现问题,整体受到牵动效应。整体稳定性得不到保证,因此,经过微服务化后,应用由原来的服务内部组装到服务自由组合,一旦关联服务存在问题,整体应用可以选择性地降级或熔断等措施,待问题服务恢复,一切照常执行。

  • 运维的需要

微服务应用具备自动化编译、打包、分发、部署和运维的能力。传统的应用不但需要开发、还需要测试和运维人员,微服务应用实现后,将理想化的全栈(Full-Stack)工程师变为可能。

  • 成长的需要

微服务能够更好,更快地适配新技术,比如目前流行的Apache Kafka。而工程人员需要接触新的技术,为未来可能的技术选型做好准备。我的建议在一些不那么重要的微服务应用中,可以尝试一些新的技术,在其提供的功能与实际需要之间,找到一些自己的理解,也是自我成长的需要。

为什么不必微服务?

论语有言:“子绝四:‘毋意、毋必、毋固、毋我’。”,简单地说,不要臆断,不要固执,不要自我感觉良好,也有什么是必定的。那么,在微服务实践过程中,哪些因素可以不必微服务呢?请注意用词,这里说的是“不必”,不是“不要”。

  • 场景单一

当应用的场景单一时,没有必要非得微服务,因为它本身就是微服务,例如一些静态的通告页面。

  • 逻辑简单

当应用逻辑简单时,同样也违背了微服务的初衷,因为微服务是为了解决复杂业务逻辑而衍生,因此这种情况下也不必实施微服务。

  • 业务渐逝

首先,我解释一下“渐逝”,也就是逐渐消逝的意思。当应用所关注的业务趋于消逝状态时,尽管有实施的空间,但无实施的必要。因为这样的应用随时可能不复存在,好比没有必要去对BB机或者短信业务大张旗鼓的重构一般。

  • “老成持重”

老成持重的原意是形容人做事情老练和沉稳。这里我引用了这个成语,是为了方便记忆,需要将其拆开,单独解释。

“老”是指年老的应用,多久算得上年老呢?个人经验,应用服役年龄超过三年以上。

“成”则表示应用的规模已成形,业务上几乎不再变化,比如通知应用。

“持”说明应用的场景还将持续较长时间。

“重”表示应用所处的位置举足轻重,不能随时重构,比如交易应用。

当应用符合其中一条以上的特征时,该应用不必实行微服务。

  • 技术盲从

这一点是我最为关注,也是最担心朋友触犯的。我们同为工程人员,对技术的追求毋容置疑,可是千万不能因为技术而技术,新的技术推出或是解决现有问题,或是提供便利性,可是也有夸大其词的成分。理性地评估和谨慎地实施,更是我们更要关注的地方。技术困难挑战聪明才智,理智对待则考验情绪控制。

进阶阅读

网络
http://microservices.io/
http://martinfowler.com/articles/microservices.html

书籍
《Microservice Architecture》, Irakli Nadareishvili

文稿
《2016.11.19 微服务实践之路(厦门)演讲稿》 (具体请查看微信公众号「次灵均阁」)

以上推荐的网络资源以及书籍可能大家已阅,不过我主要是推荐我上月去厦门的演讲稿,之所以把它放在最后,目的确实想突出,“后其身而身先”(老子)嘛。: D

How

前面提到的部分是“What”和“Why”,接下来,进入“How”的部分,顾名思义,就是怎么做,如何做的意思。

“多见阙殆,慎行其余”

以上两句处于孔子的学生子张请教孔子关于如何干好工,孔子的回答是:“多闻阙疑,慎言其余,则寡尤。多见阙殆,慎行其余,则寡悔。言寡尤,行寡悔,禄在其中矣”。儒家经典总在告诫我们,言行需谨慎,如临深渊、如履薄冰,战战兢兢。个人认为将此等思想放诸四海而皆准,在微服务的实践过程中,同样需要谨慎因应。

怎么实现微服务

怎么样实现微服务,我想从以下三个方面来说明:

  • 心态

  • 技术

  • 思想

心态

  • “子路有闻,未之能行,唯恐有闻”

句中的开头二字“子路”,是一个人名。孔子门徒三千,七十二贤,最著名的是“孔门十哲”,其中就包括子路。子路,也就是仲由,字子路。整句话的意思是说,子路听到新的知识或者道理,没有付诸于实践,又担心新的知识或道理的出现。这句话能很好地反应当今这个浮躁的互联网时代,看似科技突飞猛进,新的技术层出不穷,而实践不力,导致首鼠两端的心态。凡是他人掌握了新的技术,自己却没有,就觉得不如人,反之亦然。我想告诉大家的是,微服务并不是新的技术,而是新的思路,只不过咨询发达,加上基础的沉淀,让老的技术或理论在新的时代能够“飞入寻常百姓家”。

  • “不患无位,患所以立”

当微服务被广泛地被业界认可和接受时,或许你总会担心在何处实践,因此,在心态上,需要做到不要担心它花落谁家,更要放平心态,思考它为什么存在的理由。

  • “攻乎异端,斯害也已”

当你或你的团队在推广微服务过程中,你得首先做好被挑战甚至是攻击的准备,据不完全统计,世界上有5%的人,是因为反对而反对的人。但是反对负面情绪可能会印象其他50%的人。由此前提之后,还需具备攻击“”的能力,这样就能达到“斯害也已”(这种危害也可以被消灭)。

  • “过则勿惮改”

最后一种心态则是不要怕犯错,错了不要忌惮改正。作为工程人员,实施的过程中不出错是不可能的,除非不去做。不要畏惧犯错,犯错也是更好地缩小内心期望和现实情况的鸿沟,不犯错就没有成长的空间,因此,不怕错,也不忌改正。

前面的部分用了不少诗词,接下来就不会那么“诗”了,来点“干”的,也是今天的技术重头戏。马上进入技术的部分。

技术

技术上,在阿里微服务的实践过程中也不能免俗,基本上也是以下三个套路:

  • Docker

  • DDD

  • Middleware(Java)

Docker

在阿里巴巴集团技术体系中,自行研发与Docker兼容的AliDocker,并且提供了一些其他能力和辅助工具。本人相对这块不是特别熟悉,如果大家需要进一步的了解,可以考虑后续加入“微服务技术交流”群中,与我的同事一同讨论和交流,这里只能做一些简单地介绍。

  • 测试环境:AliDocker + ECS(阿里云)

  • 生成环境:AliDocker + 物理机

DDD

DDD是Domain Driven Design(领域驱动设计)的简写,该技术源于Eric Evans 在其名著《Domain Driven Design》。从年代来看,已是相当老的设计方法论了。它作为微服务重要的理论依据,如今又如“凤凰涅槃”一般,重新进入软件领域的视野。DDD的三大实施策略在具体微服务实践过程中,取二舍一。当然,整个DDD的理论并不限于此,个人理解,DDD好像是一个传说,大家都听说过,但是谁也没有见到过。,目前仍未到时候。

  • 有界上下文(Bounded Context)

有界上下文的思想,个人认为是在《设计模式》中的“单职责原则”进一步发展而言。其实也体现了东西方文化的差异,,和古希腊城邦的“”的民治思想。微服务则属于“权力分立”思想的范畴。在微服务实践过程中,确定应用边界是必要的,也是困难的。必要性反应在系统职责划分,要简约、清晰,不耦合。困难性则体现在重构过程不是一蹴而就,而是循序渐进,同时,应用还伴随着业务发展而同步开发,其间的困难是可预知的。虽然过程是痛苦的,但是也不得不去做。

  • 持续集成(Continuous integration)

持续集成是继承了TDD(Test Driven Development,测试驱动开发)的思想,对应形成规模的公司而言,基本上都部署了持续集成的环境,在阿里则是Aone 系统来统筹。一些流行的开源软件,如GitLab、Jenkins(Hudson)等。


  • 上下文映射(Context Map)

以上两个策略均在实践中被采纳,那么上下文映射(Context Map)则被舍弃,舍弃的原因并不在于其不合理,而是难以驾驭。例如,用户服务提供用户的模型,其中包括了姓名、生日、电话等。可是下游系统,需要仅仅需要用户的姓名信息,而实际情况,用户服务无法提供这么细粒度的服务,那么不得不在中间做一层上下文映射,将两者不再直接关联。这种情况貌似还看不出端倪,可是为服务化后,服务数量众多,其映射环节基本上不可控制,下游系统配合改动也是代价颇高,因此,在实践过程中,还是保持原有的调用关系。尽量做到改造过程中,减低错误率。

Middleware

中间件是微服务实施过程中不可或缺的一个环节,实现中间件的编程语言可以任意,不过目前市场上最为流行还属Java。经刚才粗略的统计,在座的朋友们从事Java居多,本人恰好也相对熟悉这个领域。接下来,我们一同来探讨,Java 中间件在微服务实践过程中的措施。由于时间的关系,无法做到一一列举,因此,以下每个小节均有实例说明。

  • Spring

  • Spring Boot

  • Spring Cloud

  • Spring Cloud Stream

  • Spring Boot DevOps

Spring

  • Annotation驱动

在微服务实践的过程中,中间件部门向各条业务线的开发推广,用Annotation驱动的方式替代过去XML配置的方式:


Annotation驱动方式

在Spring 3.1 以及更好的版本中,提供了大量的Annotation作为XML配置的替代一下方式(现场统计,基本上没有人知道这种方式):


XML配置方式

工程人员相对XML的方式更为熟悉,以上XML配置了是Spring WebMVC的一些组件Bean。实际上,除了@EnableWebMvc以外,还提供了很多@EnableXXX的替代方式,例如@EnableAsync、@EnableAspectJAutoProxy等。在实施过程中,很多开发人员错误的认为这些是Spring Boot的带来的便利,其实不然。

Spring Boot

在 Spring Boot 推广实施过程中,除了以上Annotation重构方式以外,我想在前端渲染引擎选型评估方面谈谈自己的心得和体会,建议大家时刻保持怀疑的态度,一家之言,仅供参考。

渲染引擎

Thymeleaf(Spring 推荐)

优点:HTML结构化、UI友好,表达式功能强大

  • HTML结构化、UI友好
    Thymeleaf 设计初衷就是针对UI友好,让开发人员在编辑模板页面时,遵循标准HTML结构。

  • 表达式功能强大
    不但兼容标准 OGNL 表达式,而且也支持Spring 表达。Spring 表达式为Spring 3 之后推出的重要功能提供动态的执行程序的能力。

缺点:编码略微繁琐、性能一般、扩展复杂

  • 编码略微繁琐
    没有比较不存在优劣,Thymeleaf 在编辑过程中相对繁琐,相比较于Velocity和JSP而言。

  • 性能一般
    最明显的缺点是,性能着实一般,因此,不建议用在访问过频繁的页面,比如宝贝详情页面。

  • 扩展复杂
    Thymeleaf 元素标签相对比较复杂。
    以下为 Thymeleaf 模板页面的内容,其中“th”为Thymeleaf 标签(tag)的命名空间(namespace):


Thymeleaf 模板页面

Velocity(广泛应用)

优点:性能良好、易于扩展、事件处理、配置灵活

  • 性能良好
    相比较于 Thymeleaf 而言,Velocity的性能良好。

  • 易于扩展
    在扩展性方面,Velocity提供宏(Marco)扩展,实现代码复用。

  • 事件处理
    开发人员可能对于事件处理上相对陌生,我简单地介绍以下,Velocity 提”org.apache.velocity.app.event.EventHandler”接口,其中典型代表为:”org.apache.velocity.app.event.ReferenceInsertionEventHandler”接口,主要用于拦截引用插入前的事件。

  • 配置灵活
    也是Velocity显著特点,提供了大量灵活的配置项,方便开发人员设置,例如配置模板位置、字符编码等。

缺点:HTML结构化不友好、发展停滞

  • HTML结构化不友好

    HTML结构化不友好,由于Velocity模板的语法特点并非HTML结构化友好,指令(Directive)以及宏(Marco)均直接在页面非标签区域植入,比如 #set 这种写法。

  • 发展停滞
    Velocity 1.7 版本自2010年以来,不再更新,因此,Spring 4.3 版本(或者Spring Boot 1.4)开始,将Velocity支持标记为Deprecated。


常规Velocity模板


Velocity宏(Marco)


Velocity 指令(Directive)

JSP(Java EE标准)

优点:编码灵活、兼容性好、性能优秀、多种页面结构化

  • 编码灵活
    较以上两种模板引擎,JSP编码方式更为灵活,其中包括:

  • Scriptlets
    早期类PHP脚本语法,即在JSP页面中直接添加 Java 代码,这种编程模式称为 Scriptlets ,其对应的J2EE(当时还称作J2EE,即现在的Java EE)设计模型为Model 1。

  • EL(Express Language)
    由于Scriptlets编程模式在页面上植入太多的 Java 代码,代码既难以复用,维护成本又相当巨大。JSP 2.0 规范引入了EL(Express Language)1.0 规范,随后该能力被用在J2EE设计模式中,逐步发展成 Model 2 以及 MVC ,JSP页面不再负责数据组装等逻辑,而是仅承载页面渲染的作用(当然还是具备 Scriptlets 能力,只是不推荐使用这种方式)。

  • 兼容性好
    JSP属于Java EE规范,因此Java EE均提供了实现,比如 Tomcat、Jetty、WebLogic 等等。因此,JSP 具备天然性兼容,不需要额外引入其他资源。

  • 性能优秀
    JSP属于解释编译型模板语言,无论是 Scriptlets 还是 EL 均可以翻译成 Java 源文件,然后将 Java 源文件编译成 Java Class 文件,再经过容器加载并且执行相关方法调用(可参考org.apache.jasper.servlet.JspServlet)。

  • 多种页面结构化
    这个特点是很多国内 Java 工程人员不太关注的特性,通常将JSP页面结构定格在HTML,实际上,它的页面结构格式可以设置成更为严格的XHTML,甚至是XML。顺便提一句,Thymeleaf 也具备该能力,而 Velocity 不具备。因此,在我看来,JSP 并不是太落伍,而是太超前。

缺点:限制表达式(EL)、扩展繁琐、规约较多、Servlet强依赖

  • 限制表达式(EL)
    EL 的实现是OGNL 表达式的子集,仅实现了简单地数据读取和逻辑运行。类似于 Bean 方法调用这样的高级语法,需要配合 JSF 这样的Web技术来配合( JSF 叫座不叫好的 Web 框架 )。

  • 扩展繁琐
    JSP 扩展主要是JSP 标签扩展,JSP 标签扩展被很多人视为反模式,我倒不怎么认为,但是对其配置上倒是颇为复杂,举个例子,每个 Tag 的属性需要绑定一个对应的实现类属性,并且类型复杂,功能各异,比如 IterationTag 和 BodyTag 的作用存在一定的区别。

  • 规约较多
    JSP 除了tag lib的规约以外,还有jsp-property-group 等,我用一段web.xml中的配置为例:

      <jsp-config>      
     <taglib>          <taglib-uri>http://tae-sdk.taobao.com/taglibs/sdk</taglib-uri>          <taglib-location>/META-INF/config/taglibs/sdk-web-1.0.tld</taglib-location>      </taglib>      <jsp-property-group>          <url-pattern>*.jsp</url-pattern>          <page-encoding>GBK</page-encoding>          <include-coda>/WEB-INF/jsp/coda/footer.jspf</include-coda>          <trim-directive-whitespaces>true</trim-directive-whitespaces>      </jsp-property-group>  </jsp-config>
  • Servlet 强依赖
    JSP 对于 Servlet API 是强依赖的,主要执行逻辑与Servlet 相同( init 方法、service 方法以及 destroy 方法 ),在现代化的Java Web 编程模式中,基本上屏蔽了Servlet API接口,比如 Spring WebMVC 中的@RequestParam用于获取请求参数,去取代Servlet API中的javax.servlet.http.HttpServletRequest#getParameter(String)方法,因为该方法仅返回 String 类型,如要转化成 Integer 类型,不得不调用 Integer#valueOf(String)方法进行转化。再则,目前流行的HTTP 2 Web服务器 ,Undertow 并不兼容 Servlet API 方案,因此 Spring Boot 官方文档说明有一段特别说明:


Spring Boot 官方文档说明

Spring Boot 部分点到为止,会后可以进一步交流,接下来,进入Spring Cloud的部分。

Spring Cloud

Spring Cloud 官方提供了基本功能描述,其中包括:分布式/版本化配置(Distributed/versioned configuration)、注册与发现(Registry and Discovery)、路由(Routing)、服务调用(Service-to-service calls)、负载均衡(Load balancing)、短路( Circuit Break )以及分布式消息(Distributed messaging)。技术点不少,这里我选取了分布式配置为例。详细描述,我已在《2016.11.19 微服务实践之路(厦门) 演讲稿》中提到,请大家会后参考。

  • 分布式配置

Spring Framework 3.1 开始,提供了一个新的接口:org.springframework.core.env.Environment,该接口的标准实现中组合了 org.springframework.core.env.PropertySources 对象(组合了多个org.springframework.core.env.PropertySource 对象),利用这个对象可以方便地 resolve Property。同时,PropertySources 可以追加新的 org.springframework.core.env.PropertySource 对象。因此,Spring Cloud 提供了一个定位器 org.springframework.cloud.bootstrap.config.PropertySourceLocator 能够便利地追加org.springframework.core.env.PropertySource 对象到org.springframework.core.env.PropertySources 对象中。

结合Alibaba 内部分布式配置管理中间件 Diamond(类似于ZooKeeper),部分实现逻辑如下:


部分实现逻辑

具体使用则是通过@Value的方式获取配置内容中的Property,将其关联到对象字段中,如下图:



字段与配置项映射代码

在ArchimedesProperties上方,有一个@RefreshScope的注解,这个注解的用途是通知 Spring Cloud,如果配置项发生变更后,变更后的属性值将会同步到对象的字段值上。

下一张图所示,配置内容监听器的实现,符合现代Annotation 驱动的方式,将配置项的内容转化成需要的类型:


监听配置内容类型装换

Spring Cloud 部分完结,下一个环节进入 Spring Cloud Stream。


Spring Cloud Stream

在Martin Fowler的名著《Enterprise Integration Patterns》(企业整合模式 )中提到过(Channel)的概念,Spring Cloud Stream 付诸于实践,提供抽象实现。这种抽象实现的好处在于对应用透明,应用不再强制绑定在某种具体技术上,对它而言,Spring Cloud Stream 为其建立管道(Channel),其中有两个概念被涉及:Source(发送端)和Sink(接收端)。

类似于 Kafka 消息中间件,Alibaba 也自主研发了一套Message Queue,名叫 MetaQ ,早一阵子提交到开源社区 Apache 上,与 Kalfa 为同级的项目,很了不起。无论是 Kafka 还是 MetaQ 都有自带的API,为了增加应用依赖透明性,针对 MetaQ 做了Spring Cloud Stream 的适配,如下图所示:


Source(发送端)发送消息实例代码


Sink(接收器)消费消息实例代码

以上代码相当简单,与JMS中的消息订阅模式类似。

前面三小节均为实现部分,最后一个技术小节,继续讨论一下针对 Spring Boot 的 DevOps。

Spring Boot DevOps

  • 整体架构


Archimedes 整体架构图

每个微服务应用均有一个应用名,通过接入 Eureka Client ,向注册中心 Eureka Server 注册。Eureka Server保存所有注册应用的信息,这些信息被 Archimedes 通过Eureka Client 提供 REST 接口获取,将获取的应用列表并发地获取他们的Endpoint 和 Metrics信息。同时 Archimedes 也提供了REST API 接口,暴露应用元信息给 Archimedes Dashboard 提供页面展示。将需要的Metrics信息存放时序数据库,比如OpenTSDB。再通过OpenTSDB的HTTP API进行查询,最后将查询结果显示在监控页面中。

  • 线程管理

Archimedes Dashboard 提供了图形化的线程管理,如下单实例线程总数时序图所示:


单实例线程总数时序图

下图所示,其功能类似于JStack,将具体线程运行的状态以及堆栈详细列出:


活动线程堆栈信息

  • 内存管理

JVM 的内存管理相对比较复杂,不但包括内存部分,内存池、和相关垃圾回收的算法。其中JVM 内存有包括:Jjava 内存使用、堆使用、以及非堆使用。

在 Archimedes Dashboard 中,将几者结合起来,集中展示。


整体内存使用情况以及垃圾回收


垃圾回收前后对比


内存池使用详情

  • 日志管理

个人认为日志管理是独创,虽然Spring Admin 也提供了日志切换的能力,不过它不具备多种日志实现一同切换的能力,其中适配了四种流行的日志框架:Java Logging、Log4j、Log4j2 以及 Logback。


log4j 日志调控


Logback 日志调控

Archimedes 中会自动识别应用所使用的日志框架,虽然不推荐一个应用中使用多套日志框架,可是现实情况不得不一并思考,比如有些二方jar包中存在的独立的日志处理。

思想

聊完了技术,下面来谈谈思想方面的实现,我总结为三大点:

  • 少谈”敏捷”

国外很多流派在“吹嘘”,敏捷已死。不好我觉得有些夸张的成分,但是也无需过度的实施,借鉴一点即可。

  • 推崇”简洁”

简洁很重要,牢记“Simple is beautiful”。微服务系统设计越简洁越好,这里简洁不是简单。

  • 学习“狄仁杰”

这点可能很多朋友觉得非常突兀,和狄仁杰有什么关系。这里这么描述主要是狄阁老总问李元芳:“元芳,你怎么看?”。这种不耻下问的精神,知道我们来学习。狄仁杰并非事事明察,也需要李元芳这样的武夫分析和提点,能够达到破案的目的,有为何不可呢?

朋友们,你们怎么看?

(全篇完)

友情链接