http://mp.weixin.qq.com/s?__biz=MzA5Nzc4OTA1Mw==&mid=411003246&idx=1&sn=304831a15d8fae89f2d5481c7419838c&scene=1&srcid=0405a9I8yatOoaq7cec9LOK3#wechat_redirect
自从 2014 年“微服务架构”这个概念首次提出以来,在业界就引发了一股对微服务架构的激烈探讨,大家对它的意义褒贬不一,所以我想借此机会给大家简单分享一下我所理解的微服务架构,主要内容会包括:为什么需要微服务架构?微服务架构是什么?微服务架构有哪些特点?如何搭建微服务架构?此外,我还会为大家展示我们公司目前搭建的微服务架构的应用案例,希望我的分享会给大家带来一点帮助。
背景介绍今天我给大家分享的主题是“微服务架构”。坦率地说,我其实并不是微服务方面的专家,只是非常喜欢这个架构,通过自己的学习与实践,也算稍微总结了一点知识吧,所以想借此机会为大家做一下分享,也许讲得不够深入或者有错误的地方,还请大家多多指教,我们共同探讨。
好了,还是先给大家做一下自我介绍吧,否则我讲完了,大家可能还不知道我是谁,哈哈!(自我介绍部分比较长,喜欢直接高潮的同学请自觉跳过)
我叫黄勇,一名在上海工作了十年的武汉人。2006 年计算机专业毕业,喜欢写代码,也喜欢学习与分享。
毕业那年我被我们计算机学院的院长推荐到上海来工作,这家公司是他大学同学创办的,这是一家初创型公司,我刚加入的时候,公司只有 3 个人(包括老板和前台)。我在这里一干就是 4 年,从一个名什么都不会的毕业生,到一名能够带领团队成功完成项目的主管,在这里我学到了很多在大公司里很难学到的东西。
由于公司的需要,我慢慢地远离了自己喜爱的技术,变成了一名披着技术外衣的销售(售前人员),每天和我打交道最多的就是客户,我需要给他们写方案,给他们做 demo,请他们吃饭,和他们建立良好的关系;下班还要请他们吃饭、洗脚、泡温泉,可以想象,那时的我过得并不快乐。
当时我感觉这不是自己想要的工作,于是我坚决地选择了离开,去寻找能够让我在技术方面得到成长的企业。离开后不久就加入了一家大型外企,开始沉下心来做架构,开始研究 SOA 与大型企业应用整合,在这里我学习到了规范化的工作方式,以及跨团队协作的能力,当然也学会了用英语和国外的同事们交流。
也许所有的外企都一样,干的时间长了,就觉得自己在养老,尤其当我看到身边的同事们没事做了就开始逛淘宝和打游戏,我就对自己的将来非常担忧。我觉得自己不能这样安于现状,于是我开始在“开源中国”网站上写自己的技术博客,体会积累与分享的快乐,与此同时,我还写了一款名为 Smart 的开源框架。慢慢地,技术博客写了很多篇,开源框架也吸引来众多关注者。
后来我离开了这家外企,加入了一家互联网公司继续做架构,后来这家公司又被阿里巴巴收购,我就莫名其妙地成为了一名阿里巴巴系统架构师,做大数据应用架构,从此开始就穿梭在西溪园区与上海魔都。我把这一切都归结于幸运,更幸运的是,有一位出版社的编辑老师找到了我,他给了我一次写书的机会,我就用了 4 个月的时间写了自己人生中第一本书《架构探险》,没想到这本书销量还不错,半年左右就重印了 4 次,已经卖了 10000 多本。
阿里巴巴的工作氛围和同事们都很好,但我喜欢按照自己的想法做事情,也许我的性格确实不太适合在阿里巴巴工作吧,于是去年我选择了离开,随后就加入了一家名为特赞(tezign.com)的创业型公司,从此开始学着做 CTO,其实我并不知道怎样才能做好这个岗位,只能说一边学一边做吧,如果将来有机会,我非常愿意向大家再分享一下我做 CTO 的体会。
这是我的第一个开源项目:Smart Framework。开发该框架是为了:加速基于 Java 的中小型 Web 应用程序的开发,让开发人员将更多的精力集中到业务上,而无需过多地关心底层技术细节;推广国内开源事业的发展,吸引更多有想法并且有开源奉献精神的朋友,一起共同探讨,并分享自己的经验;对于个人而言,我想结交更多志同道合的朋友,将来有机会能够一起做点事情。博客地址:http://my.oschina.net/huangyong/blog/158380,源码地址:http://git.oschina.net/huangyong/smart-framework。
这是我的第一本书《架构探险》,这本书全面地介绍了 Smart 框架的架构设计与开发过程,希望这本书对喜欢写框架的读者有所帮助,也希望会有更多的人都能贡献自己的开源框架。当时我有幸邀请了“开源中国”创始人“红薯”先生为本书作序,听说这也是他的处女序,这本书既是我的第一次也是他的第一次。
顺便给大家透露一下,现在我正在写《架构探险 2》,这本书将围绕“微服务架构”进行描述,目的是让大家学会如何搭建一款轻量级微服务架构,预计这本书将在今年第三季度末与大家见面。
这是我现在所在的公司:特赞(Tezign),官方网站:www.tezign.com,我们提供的是一个为客户精确且便捷地对接最优秀设计师的互联网平台,也就是说,我们让客户找到自己最想要的设计师,同时也让设计师找到自己最想做的项目。该平台是一个基于 SaaS 的软件服务,在技术上涉及到大数据、云计算、人工智能、机器学习、数据挖掘等方面。
正文下面我们将从这6个方面进行展开,聊聊我所理解的微服务架构。
1、为什么需要微服务架构
自从 Martin Fowler(福勒)提出了 Micro Service(微服务)的概念后,业界就卷起了一股关于微服务的热潮,大家谈论多年的 SOA(Service-Oriented Architecture,面向服务的架构)终于有了新的解决方案,人们不再需要笨重的 ESB(Enterprise Service Bus,企业服务总线),一个崭新的轻量级 SOA 架构 MSA(Micro Service Architecture,微服务架构)伴随着容器技术,正向我们携手走来。
微服务架构(MSA)的出现绝对不是偶然的,传统应用架构的不合理,产生了新的架构模式,这类现象再正常不过了。那么,传统应用架构究竟有哪些问题呢?下面我们将为大家做一个简单的分析。
这是一个经典的 Java Web 应用程序(简称 Webapp),它包括 Web UI 部分,还包括若干业务模块,就像这里出现的 Module A、Module B、Module C 等。
Web UI 与这些 Module 封装在一个 war 包中,需要将此 war 包部署到 Web Server(例如 Tomcat)上才能运行,该应用程序会连接到 Database(例如 MySQL)上操纵数据。
当系统运行过程中,通过监控程序发现,Module A 与 Module B 都需要消耗 10% 的系统资源,加起来才占总系统资源的 20%,而 Module C 却要占用 80% 的系统资源。运行一段时间后,Module C 就会成为整个系统的瓶颈,从而将会降低系统的性能。
那么,如何才能解决这类问题呢?人们想到了一个简单的办法。
只需将这个应用程序复制一份,一模一样的程序,将其部署到另一台 Web Server 上,下方还是连接到同样的 Database,只是在这些 Web Server 的上方架设一台 Load Balancer(负载均衡器,简称 LB)。
请求会首先发送到 LB 上,通过 LB 上的路由算法(例如轮询或哈希),将请求转发到后面具体的 Web Server 上,这类请求转发技术被称为 Reverse Proxy(反向代理)。
由于进入 LB 的请求(流量)被均衡到下方各台 Web Server 中了,流量得到了分摊,负载得到了均衡,因此该技术也称为 Load Balance(负载均衡)。
如果流量加大,我们还可以继续水平扩展更多的 Web Server,该架构理论上可以无限扩展,只要 LB 扛得住巨大的流量就行。
通过以上技术方案,轻松地将负载进行了均衡,一定程度上缓解了流量对 Web Server 的压力,但此时却造成了大量的系统资源浪费,比如对系统资源暂用率不高的 Module A 与 Module B 也进行了水平扩展,其实我们真心只想对 Module C 进行水平扩展而已。
除了水平扩展方案带来的系统资源浪费以外,实际上传统应用架构还有其它的问题,下面我们继续讨论。
传统应用架构实际上是一个 Monolith(单块架构),因为整个应用都封装在一个 Webapp 中,就像是巨石一块,无法拆分,我们所做的水平扩展也只是在扩展一块块的巨石。为了便于表达,我们不妨将单块架构搭建的应用简称为“单块应用”。
我们部署单块应用的时候,同样也会遇到许多麻烦,比如:
修改了一个 Module(可能只是修改了一行代码),就需要部署整个应用。
部署整个应用所消耗的时间与对系统带来的性能开销都是非常多的。
此外,对于 Java Web 应用而言,打包在 war 包里的代码一般都是 class 文件,也就意味着,我们的单块应用只是基于 Java 语言开发的,无法将该应用中某个 Module 通过其它开发语言来实现(假如我们不考虑在 JVM 上运行动态语言的情况下),也许其它开发语言实现某个模块会更加合适,这样就会产生技术选型单一的问题。
综上所述,传统应用架构存在以下问题:
系统资源浪费
部署效率太低
技术选型单一
当然,传统应用架构的问题还远远不止这些。当业务变得越来越复杂,应用会变得越来越臃肿,个头越来越大,而且无法瘦身。于是,人们找到了新的思路来解决传统应用架构的问题,这就是微服务架构。
那么,微服务架构究竟与传统应用架构有何区别呢?
2、微服务架构是什么?
微服务架构从字面来理解就是:许多微小的服务搭建的应用架构。这里面涉及到了许多问题,比如:
服务需要多微才能叫微服务?
如何管理越来越多的微服务?
客户端怎样调用这些微服务?
我们带着这些问题,进入下面的讨论,首先我们来看看如何定义微服务架构。
当福勒大神提出微服务架构这个概念时,同时他也为微服务架构提出了几条要求,也就是说,当我们的应用满足以下要求时,才能称为微服务架构,具体要求包括:
根据业务模块划分服务种类
每个服务可独立部署且相互隔离
通过轻量级 API 调用服务
服务需保证良好的高可用性
我们简单地分析一下:首先根据产品业务功能模块来划分微服务种类,也就是说,我们需要按照业务功能去划分,这是“垂直划分”,然而在代码层面进行划分,这是“水平划分”。而且每个微服务客户独立部署,还需要相互隔离,也就是说,服务之间是没有任何干扰的,可将每个服务放入独立的进程中运行,因为进程之间是完全隔离的。客户端通过轻量级 API 来调用微服务,比如可通过基于 HTTP 或 RPC 的方式来调用,目的是为了降低调用所产生的性能开销。微服务需要确保高可用性,不能长时间无法响应,需要提供多个“后补队员”,在某个微服务出现故障时,可以自动调用其中一个正常工作的微服务。
微服务架构颠覆了传统应用架构的模式,若不定义良好的交付流程与开发模式,则很难让微服务架构发挥出真正的价值,下面我们先来看看微服务架构的交付流程。
1)交付流程
使用微服务架构开发应用程序,我们实际上是针对一个个微服务进行设计、开发、测试、部署,因为每个服务之间是没有彼此依赖的,大概的交付流程就像上图这样。
在设计阶段,架构师将产品功能拆分为若干微服务,为每个微服务设计 API 接口(例如 REST API),需要给出 API 文档,包括 API 的名称、版本、请求参数、响应结果、错误代码等信息。在开发阶段,开发工程师去实现 API 接口,也包括完成 API 的单元测试工作,在此期间,前端工程师会并行开发 Web UI 部分,可根据 API 文档造出一些假数据(我们称为“mock 数据”),这样一来,前端工程师就不必等待后端 API 全部开发完毕,才能开始自己的工作了。
在测试阶段,前后端工程师分别将自己的代码部署到测试环境上,测试工程师将针对测试用例进行手工或自动化测试,随后产品经理将从产品功能上进行验收。在部署阶段,运维工程师将代码部署到预发环境,测试工程师再次进行一些冒烟测试,当不再发现任何问题时,经技术经理确认,运维工程师将代码部署到生产环境,这一系列的部署过程都需要做到自动化,才能提高工作效率。
在以上交付流程中,开发、测试、部署这三个阶段可能都会涉及到对代码行为的控制,我们还需要制定相关开发模式,以确保多人能够良好地协作。
2)开发模式
无论使用传统应用架构,还是微服务架构,我们都需要定义良好的开发模式。经验表明,我们需要善用代码版本控制系统。就拿 Git 来说,它很好地支持了多分支代码版本,我们需要利用这个特性来提高开发效率,上图就是一款经典的分支管理规范。
最稳定的代码放在 master 分支上(相当于 SVN 的 trunk 分支),我们不要直接在 master 分支上提交代码,只能在该分支上进行代码合并操作,例如将其它分支的代码合并到 master 分支上。
我们日常开发中的代码需要从 master 分支拉一条 develop 分支出来,该分支所有人都能访问,但一般情况下,我们也不会直接在该分支上提交代码,代码同样是从其它分支合并到 develop 分支上去。
当我们需要开发某个特性时,需要从 develop 分支拉出一条 feature 分支,例如 feature-1 与 feature-2,在这些分支上并行地开发具体特性。
当特性开发完毕后,我们决定需要发布某个版本了,此时需要从 develop 分支上拉出一条 release 分支,例如 release-1.0.0,并将需要发布的特性从相关 feature 分支一同合并到 release 分支上,随后将针对 release 分支部署测试环境,测试工程师在该分支上做功能测试,开发工程师在该分支上修改 bug。待测试工程师无法找到任何 bug 时,我们可将该 release 分支部署到预发环境,再次验证以后,均无任何 bug,此时可将 release 分支部署到生产环境。待上线完成后,将 release 分支上的代码同时合并到 develop 分支与 master 分支,并在 master 分支上打一个 tag,例如 v1.0.0。
当生产环境发现 bug 时,我们需要从对应的 tag 上(例如 v1.0.0)拉出一条 hotfix 分支(例如 hotfix-1.0.1),并在该分支上做 bug 修复。待 bug 完全修复后,需将 hotfix 分支上的代码同时合并到 develop 分支与 master 分支。
对于版本号我们也有要求,格式为:x.y.z,其中,x 用于有重大重构时才会升级,y 用于有新的特性发布时才会升级,z 用于修改了某个 bug 后才会升级。针对每个微服务,我们都需要严格按照以上开发模式来执行。
我们已经对微服务架构的概念、交付流程、开发模式进行了描述,下面我们大致归纳一下微服务有哪些特点。
3、微服务架构有哪些特点?
微服务架构相对于传统应用架构有着显著的特点,同时微服务架构也对我们带来了一定的挑战,我们先从它的特点开始说起。
1. 粒度微小
微服务的粒度是根据业务功能来划分的,对于某些复杂的业务来说,可能粒度较大,对于相对简单的业务而言,可能粒度较小。总之,微服务的粒度可大可小,但往往我们更希望它尽可能的小,但又不希望微服务之间有任何的依赖,因此粒度的划分是非常考验架构师水平的事情。
2. 责任单一
我们需要确保每个微服务只做一件事情,也就是我们经常提到的“单一职责原则”,该原则对微服务的划分提供了指导方针。
3. 隔离性好
每个微服务相互隔离,且互不影响。也就是说,每个服务运行在自己的进程中。众所周知,进程之间是隔离的,是安全的,而进程内部或线程之间资源共享的。换句话说,一个微服务出了问题,不会影响到其它微服务受到任何影响。
4. 管理容易
随着业务功能不断增多,微服务的数量也会逐渐增加,我们需要对微服务提供自动化部署与监控预警的能力,才能更加高效地管理微服务。
微服务架构的特点非常明显,可能还有很多,但同时微服务架构也给我们带来了许多挑战。
1. 运维要求较高
运维工程师除了需要使用自动化技术来部署微服务以外,还需要对整个微服务系统进行有效的监控,并保障系统的高可用性。可见,微服务架构的引入会带来运维成本的上升。
2. 分布式复杂性
微服务架构的本质还是一个分布式架构,一位每个微服务可以部署在任意的机器上。对于分布式系统而言,网络延迟、系统容错、分布式事务等问题都会对我们带来很大的挑战。
3. 部署依赖性较强
对于业务复杂的情况,可能存在多个微服务共同完成一件事情,微服务之间虽然没有相互调用,但可能会有调用的顺序性要求,业务上的依赖性,导致了部署的依赖性,从而在某一时间点,同一微服务可能具备多个版本。
4. 通讯成本较高
既然微服务是隔离在自己的进程中运行的,从客户端调用微服务,需要跨进程间调用,而进程间的调用一定比进程内的调用更加消耗资源,带来通讯成本上的开销。
4、如何搭建微服务架构?
可见,微服务架构的要求还是相当高的,不仅仅对技术,而且对运维都有很高的要求,我们需要设计出一款简单易用的微服务架构来满足自身的需求,下面用一张图来描述一下我们对微服务架构的愿景。
我们不妨从下往上来理解这张图。
底层部署了一系列的 Service,每个 Service 可能有自己的 DB,或者多个 Service 共用一个 DB,且同一个 Service 可部署多个。当 Service 启动时,会自动将其信息注册到 Service Registry(服务注册表)中,比如:每个服务的 IP 与端口。当 Web UI 上发出请求时,该请求会发送到 Service Gateway(服务网关)中,Service Gateway 读取请求数据,并从 Service Registry 中获取对应 Service 的信息(IP 与端口),最后 Service Gateway 主动去调用下面对应的 Service。整个过程就是这样,其中 Service Registry 与 Service Gateway 担当了重要的角色。
可能大家会认为 Service Gateway 将成为一个中心,可能会造成单点故障。没错,完全有这个可能,所以我们需要将它做得越薄越好,所以我们在技术选型上,需要谨慎考虑。
此外,对于 Service Registry 的高可用性也有很高的要求,它不仅需要在每个 Service 启动时提供“服务注册”,还需要在 Service Gateway 处理每个请求时提供“服务发现”。如果它失效了,整个系统将无法工作。
看来搭建微服务架构确实需要在技术选型上做一些考究,需要找到最适合的“演员”把这场“戏”演好。
我们可使用 Spring Boot 作为微服务开发框架,Spring Boot 拥有嵌入式 Tomcat,可直接运行一个 jar 包来发布微服务,此外它还提供了一系列“开箱即用”的插件,可大量提高我们的开发效率,我们也可以去扩展更多的插件。
在发布微服务时,可连接 ZooKeeper,注册微服务,实现“服务注册”,实际上 ZooKeeper 中有一个名为 ZNode 的内存树状模型,树上的节点用于存放微服务的配置信息。使用 Node.js 处理浏览器发送的请求,在 Node.js 中连接 ZooKeeper,发现服务配置,实现“服务发现”,有大量的 Node.js 的 ZooKeeper 客户端可以完成这个任务。
通过 Node.js 将请求转发到 Tomcat 上,实现“反向代理”,同样也有大量的 Node.js 库,我们可以自由选择。Node.js 的“单线程模型”且“非阻塞异步式 I/O”特性,通过“事件循环”的方式来支撑大量的高并发请求,此外 Node.js 原生也提供了集群特性,可确保高可用性。
为了实现微服务自动化发布,我们可通过 Jenkins 搭建自动化发布框架,并使用 Docker 实现微服务的容器化。
综上所述,微服务架构技术选型如下:
微服务开发框架:Spring Boot
微服务注册表:ZooKeeper
微服务网关:Node.js
微服务自动化发布:Jenkins
微服务容器:Docker
除了以上技术选型以外,实际上还有其它可选择的方案,比如 Netflix 公司开源的微服务技术栈:
Netflix:http://netflix.github.io/
Spring 官方在 Spring Boot 的基础上,封装了 Netflix 相关组件,提供了一个名为 Spring Cloud 的开源项目:
Spring Cloud:http://projects.spring.io/spring-cloud/
就连曾经的 JBoss 也推出了自己的微服务框架 WildFly Swarm:
WildFly Swarm:http://wildfly-swarm.io/
当然,JavaEE 官方也提供了自己的微服务框架 KumuluzEE:
KumuluzEE:https://ee.kumuluz.com/
以上仅为 Java 相关的微服务技术选型,其它开发语言也有自己的微服务技术栈。
5、我开源的微服务框架
下面我想推荐两款自己开源的微服务框架,一款可用于搭建 REST API 服务端,另一款可用于搭建分布式 RPC 服务框架,在我曾经的工作中也大量地使用过这两款框架,所以想借此机会推荐给大家。
这是我曾经开源的一款 REST API 框架,项目地址:http://git.oschina.net/huangyong/api,对此框架我也写过一篇文章:http://my.oschina.net/huangyong/blog/521891。
这是我曾经开源的一款分布式 RPC 框架,项目地址:http://git.oschina.net/huangyong/rpc,对此框架我也写过一篇文章:http://my.oschina.net/huangyong/blog/361751。
6、微服务架构应用案例
最后,我想借助我们特赞公司的微服务架构,为大家简单地分享一下微服务架构的应用案例。
我们的架构师首先对产品功能进行垂直划分,定义出一系列的微服务,每个微服务提供某一方面的特性。开发人员使用 Spring Boot 框架去实现每个微服务的业务细节,并对外提供 REST API。在每个微服务启动时,框架会自动将其基本信息(比如:IP 与端口)注册到 TSR 中,TSR 是我们基于 ZooKeeper 开发的服务注册中心。每个微服务在运行过程中将相关信息推送至 TSM,该系统用于监控每个微服务的运行状况。上层应用通过 TSG 进行服务发现与反向代理,调用相应的微服务提供的 REST API。整个架构非常轻量级,我们拒绝选择复杂的技术来解决简单的问题。目前我们已经开发了上 100 多个微服务,并在 TSG、TSR、TSM 的支持下稳定地运行,当然整个架构还有大量的优化空间。
总结我们从传统应用架构所产生的种种问题开始,讲到微服务架构的由来与概念,以及微服务架构的特点与挑战。我们提出了一种轻量级微服务架构设计,以及实现该架构的开源项目,此外还有其它开源组织提供的微服务架构技术选型。
我们坚信微服务将会成为新一代 SOA 的解决方案,并伴随着容器技术一起改变计算机软件行业的未来!
微服务的春天正向我们走来,大家准备好了吗?
互动问答问题:像所有业务都在一个工程的项目,应该如何进行微服务化改造 ?
建议将业务按照功能进行划分,在不影响功能的前提下,进行逐步重构。
问题:微服务的部署形式,一般什么架构 ?
一般都是分布式架构。
问题:微服务与SOA什么区别?
可以把 SOA 理解成一种架构风格,微服务理解为 SOA 的一种落地方案,我认为微服务是轻量级的 SOA。
问题:微服务拆分的粒度是什么?
粒度可大可小,可以是 API 级别,也可以是模块级别,一切根据具体业务功能进行划分。
问题:请问如何开始一套基于微服务的分布式系统的设计和开发?
如果是一个新应用,我们可以根据产品功能进行模块划分,尽可能地将模块细化,并定义每个模块的 API 接口,让每个 API 只做一件事情,此外,借助我今天推荐的轻量级框架,可快速搭建一个微服务架构。
问题:既有系统的服务重构成微服务的标准和原则有哪些?
只要能满足我刚才讲到的微服务架构的四大条件即可,但不要为了微服务而去微服务。
感谢志愿者田光、攀爬的蜗牛、Bendy PAN、qiaoliang、王旭林、cloes、Max、朱熙文对本文的整理和编辑。本文是老X聊架构系列文章的第十二篇,聊聊架构社群将会邀请国内顶级的架构师与大家探讨实战中的架构经验,欢迎关注『聊聊架构』公众号并回复『干货』获取入群方式。