更多精彩内容请关注我们
服务设计会影响到业务需求是否被正确、高效地实现,良好的服务设计能够帮助领域专家与开发人员之间,以及团队内部进行高效、准确的沟通。良好的实现则能缩短服务上线的周期,并提升可扩展性及可维护性。
在微服务架构设计的过程中,架构设计、接口设计需要和代码库一样,使用版本化机制管理起来。同时,作为独立的服务,应该能够在本地运行,并且要有完善并且容易理解的文档,方便团队成员快速上手。在本书的第3章中,笔者已经阐述了服务划分、服务内部实现、通信机制等内容,在本节中,我们将重点探讨服务设计与实现过程中的相关实践。
5.3.1 架构即代码
当探索整个系统的服务设计时,我们总会求助于它的架构图。单体应用架构下,功能以组件/模块化的形式存在,比较容易在一张架构图上体现出来。而在微服务架构下,服务数量多,很难以一种完整的状态体现在架构图上。
另外,系统的架构图通常都是使用Visio等类似的二进制工具绘制而成的,保存为二进制文件,维护起来不太方便。
在笔者的微服务实践中,通常的思路是使用Graphviz工具,基于dot语言来描述架构图,并将其保存为SVG、PNG,或者PDF之类的格式。同时,这些dot语言代码可以放在微服务的代码库中,以版本化的方式保存起来,任何的架构变动都能有效地反映到代码库中。Graphviz的安装非常简单,在Mac系统下通过brew install graphviz安装,在Windows系统下可以下载软件包安装。
譬如,假设我们现在需要为一个社交网站绘制架构图,前端的Web应用通过API Gateway请求照片、聊天、朋友服务,则其代码实现如下,架构示意图如图5-4所示。
digraph architecture {
rankdir=LR;
... # 节点定义如api_gateway、photo等,形状设置、填充颜色等
subgraph front_app {
front -> {api_gateway};
}
subgraph api_gateway {
api_gateway ->{photo, chat, friend};
}
subgraph microservices {
photo -> {database};
chat -> {database,cache};
friend -> {database,weibo_api};
}
subgraph dbs {
cache -> database;
}
}
图5-4 用Graphviz生产的架构图
使用Graphviz实现架构图,代码很容易理解。也可以直接使用GraphvizGUI的工具,实时看到修改的结果,非常方便。类似的工具还有Mermaid(https://github.com/knsv/mermaid),其也是一个类似的工具,而DSL更加简洁一些。除此之外,有些在线工具,如draw.io、gliffy,也都是不错的绘制微服务架构图的工具。
5.3.2 接口即代码
当接触一个新的服务时,我们往往要花一些时间去学习服务提供的 API,并通过案例了解用法。通常这样的API接口介绍,都是记录在文档中,而这样的文档往往得不到很好的更新与维护。在微服务架构下,随着服务数量增加,接口变化频繁,对应的接口管理也变得更加困难。
在笔者实现微服务的过程中,通常是通过Swagger这种工具可视化REST API的规范。通过SwagerEditor,能方便地定义API的详细信息、HTTP请求方法,以及请求响应等内容,如图5-5所示。
图5-5 Swagger案例
另外,可以将Swagger生成的YAML保存在微服务的代码库中,其相当于将接口的文档以版本化的方式管理起来;如果是使用Java实现的服务,也可以引入swagger-springmvc插件,其内嵌了Swagger-UI,直接访问即可查看服务的API接口信息。
在本书的实战篇中,笔者将介绍ServiceComb框架,它支持通过类Swagger的契约文件定义接口,使用方便,同时也达到了将接口定义版本化管理的目的。
5.3.3 本地运行服务
开发人员可以直接将单体应用在本地运行起来,进行端到端的功能验证。在微服务架构下,服务虽然能独立启动,但是要在本地进行端到端的验证,可能需要启动依赖的服务、数据库等。同时,微服务可能采用不同的技术实现,准备和维护这些服务的运行环境也有一定的时间成本。笔者通常会使用Docker/docker-compose的方式,结合自动化的脚本来解决微服务在本地运行的问题。
对于纯前端的工程,可以使用如npmstart这样的方式直接启动服务,依赖的服务可以配置为测试环境或者预生产环境,如果没有写操作,甚至都可以使用生产环境。如果服务不支持跨站请求,那么可能需要利用Docker/docker-compose在本地启动依赖的微服务、修改配置,并支持跨站请求。
对于后端工程,在本地运行服务的需求主要有两个,一个是在IDE中调试代码,还有一个就是验证开发的功能是否满足需求。有时在本地运行端到端的测试,也需要在本地启动微服务以及关联的服务。比如在一个 Java 的微服务开发过程中,笔者为团队准备了两个docker-compose的YAML文件来组织服务在本地的构建与运行,分别用于为IDE调试和本地功能自验。比如下面的debug.yml文件,用来组织微服务依赖的注册中心、数据库和redis的环境:
version:"2"
services:
servicecenter:
image:service-center
network_mode:"host"
logging:
driver:"none"
redis:
image: redis:4.0.2-alpine
network_mode:"host"
postgre:
image: postgres:9.3-alpine
network_mode:"host"
这里直接的容器都直接使用了host网络模型,从而避免了额外的link配置。启动包含本地代码修改的微服务的compose.yml文件如下:
version:"2"
services:
application:
build:
context: ./
environment:
...
network_mode:"host"
servicecenter:
image: service-center
network_mode:"host"
logging:
driver:"none"
redis:
image: redis:4.0.2-alpine
network_mode:"host"
postgre:
image: postgres:9.3-alpine
network_mode:"host"
用两个简单的shell脚本包装,用来启动调试环境的脚本:
#!/bin/bash
#debug.sh
docker stop $(docker ps -q)
docker-compose -f debug.yml up -d
本地启动所有相关服务的脚本:
#!/bin/bash
#compose.sh
docker stop $(docker ps -q)
docker-compose -f compose.yml up -d
通过在本地启动调试和自验的环境,可以很方便的在本地调试、验证功能,以及在本地运行端到端的测试,让开发人员可以及早自测功能,保证实现以满足需求。
5.3.4 OnePage文档
采用微服务意味着拥抱快速变化,这种快速变化反映在技术栈、架构、人员的变化,如何提升这种变化的可见性,如何让新人或者不熟悉服务的人能快速了解、上手微服务,也是微服务实施面临的一个挑战。
通过将服务相关的开发、测试、环境的基本信息记录在文档中,并和服务的代码库保存在一起,降低微服务的学习成本。通常笔者将这类文档称为“OnePage文档”。
OnePage文档的内容通常包括如下部分:
服务综述。包括服务的名称、服务提供的基本功能,服务的消费者以及服务提供的API。同时,记录服务的维护者信息,包括姓名、邮箱、电话号码等,确保能在服务出现异常时第一时间联系到维护者。
服务SLA。描述服务的可用性,明确提示不可用的时间段。如周一至周五(6:00~23:59)
与架构相关。描述服务依赖的组件、其他服务、数据库等,同时也体现数据的流向。一般笔者使用Grapviz工具完成这些依赖的表示。
运行环境。描述环境相关信息。如测试环境、预生产环境、生产环境等的访问地址以及访问的方式,如登录秘钥的获取方式。
与开发相关。描述开发相关信息。如何配置开发环境、本地启动、调试、基本开发流程等。
与测试相关。描述测试相关信息。如测试的策略、如何运行测试、覆盖率标准等。
流水线相关。描述持续交付相关信息。如持续集成地址、构建包存储地址等信息。
与部署相关。描述部署相关的信息,通常包括但不限于如何部署到不同环境、部署后的功能验证方式。
与运维相关。如监控、报警访问地址,不同环境的日志搜索的索引、监控面板、部署的工程、服务器访问的SSH信息、健康检查的接口等。同时也可以包括如何实施灾备的指导。
常见的问题链接。系统存在一些已知的问题,短时间内无法或者没有计划修复,可以列出来。
通常笔者会用MarkDown格式来记录这样的文档,并以README.md的形式保存在微服务的代码库中。这样任何人访问代码库时都可以快速了解该服务完整的信息。
组织良好、内容充实的OnePage文档,可以帮助我们快速上手一个新的系统,并且以最短的时间找到解决问题的思路和方法。另外,由于代码与文档在同一代码库中,对于像接口、架构等变更,也能有效保证代码与文档同步更新,较低维护成本。
5.3.5 前后端分离
系统有时需要提供界面完成与用户的交互,那么当后台服务化后,用户界面的部分如何处理呢?常见的处理机制有两种:
由服务实现界面,返回HTML/CSS。系统通过IFrame嵌套,JavaScript获取HTML,并以动态渲染的方式完成页面的集成。这种方式能让团队负责端到端的业务实现,包括UI的维护等,但它存在一些缺点:
难以保证界面的统一性。由于界面的不同部分来自于不同的服务,需要团队协作来保持样式的一致。
难以实现复杂的交互。对于复杂的交互,如搜索框输入后自动刷新,服务端很难在UI片段中提供这种能力。
难以支持多客户端。对于多元化的客户端,这些UI片段无法直接重用,即使是采用混合的方式在原生应用中嵌入HTML,也很难保证良好的用户体验和兼容性。
微服务中包含UI的方式也称作微前端(MicroFrontends),ThoughtWorks在2016年的技术雷达中首次提出了这个术语,不过目前仍处于评估阶段,因此只建议综合评估后再决定是否使用。
采用前后端分离,后端微服务负责业务或数据接口,前端的页面请求各个后端服务API,聚合数据并展现,完成交互逻辑。
前后端分离综述
前后端分离的优点有以下几个:
职责清晰。前端负责界面渲染、交互及用户体验。后端负责提供数据接口,权限控制等。由于前后端需要使用的资源等级不一致,后端可能需要更多的计算资源,可以在系统运行时对后端独立进行伸缩。
维护成本降低。对于前端来说,由于只包含HTML、CSS或JavaScripts部署只是文件的替换。通过目前主流的前端框架,可以非常快速地定位及发现问题的所在,客户端的问题不再需要后台人员参与及调试,代码重构及可维护性增强。
开发效率提升。可以采用优秀的框架,提高开发效率,后端只关注接口设计及逻辑开发,无须关注页面渲染。
性能提升。前端页面不再通过服务器渲染返回,而是直接通过文件服务器返回,速度更快。同时,通过前端路由的配置,可以实现页面的按需加载。笔者曾经对一家互联网企业的主站做前后端分离,页面加载速度从耗时12秒,降低到了3秒。
在使用前后端分离时,需要注意以下问题:
适配不同客户端。通过BFF(Backend for Frontends)的模式,为不同客户端提供不同形式的接口。
前后端协作。可以使用Mock接口,为前端提供数据,也可以使用契约测试,保证前后端的接口一致。
跨域问题。可以在后端统一配置跨域规则,降低前端跨域请求带来的复杂度。
SEO问题。把SEO需要的内容放在前端的HTML中,后端微服务只返回数据。
前后端分离案例
笔者经历的一个前后端分离的案例:系统需要增加一个单独的页面来收集用户信息,在具体实现时采用了前后端分离的策略,前端提供交互,后端提供数据。其中前端采用Grunt作为构建框架,Karma作为单元测试框架,Phantomjs作为功能测试框架,同时引入了契约测试来保证API的一致性。后端微服务基于Twitter的开源框架Finagle实现。其前端工程的基本架构如图5-6所示。
前端直接以静态文件的方式部署在S3上。部署非常方便,直接通过Nodejs的aws-sdk即可完成。不过需要注意的是,保证index.html最后上传,CSS/JavaScript等资源文件先上传,以防止index.html加载时资源文件还没有上传。
通过Nagios做可用性检查。因为S3是文件服务器,无法在上面部署agent提供监控数据。在前端工程的对应文件路径/diangnostic/status/nagios下加入供Nagios检查的JSON文件,Nagios检查访问该路径就可以知道网站的是否可用,如果出错则推送错误消息到PagerDuty,再由PageDuty推送到值班的运维。
图5-6 部署在S3上的前端工程基本架构
前端的访问日志上传到Splunk。S3的访问日志会保存到另一个S3存储桶中,通过Splunk可以从该存储桶中读取到相关的访问日志,方便统计和问题追踪。
使用CDN。使用Akamai缓存前端页面和静态资源文件,提升页面加载速度。
后端的API架构是典型的在EC2上部署的架构,即“ELB+EC2+ASG”,这里不再赘述。
上面的例子将前端代码部署在AWSS3文件服务器上,也可以选择将其部署在其他公有云的文件服务中(如华为云的OBS服务)。自建机房可以选择在Nginx、Haproxy等HTTP服务器上部署前端代码。
5.3.6 微服务与安全
当越来越多的个人数据保存在服务器端、云服务上时,这些数据的安全就变得尤为重要。对于企业来说,出现安全问题除了会造成经济损失,也会对业务稳定性和用户信心造成重大打击。相比单体应用,微服务架构下的安全更加重要,因为它面临着更多新的挑战,除了身份认证与鉴权之外,还包括如下两方面的挑战:
微服务本身的安全。比如在API设计时如何有效地防止信息泄露、密码策略等。
基础设施的安全。分布式系统的网络更加复杂,对应的网络安全保护难度增大,比如如何防止DDoS攻击,防止恶意的网站数据窃取等。系统规模增长对应会带来服务器数量的增长,修复操作系统的漏洞的维护挑战很大。
除此之外,微服务的交付过程通常采用持续集成,也需要考虑在这个过程中的安全,还有在自动化部署、配置管理等方面也需要注意安全。
微服务实现时的安全
在世界质量报告(WorldQuality Report)中曾提到,大部分(约80%)的安全问题都出现在应用层。所以微服务在设计实现的时候,要特别注意安全方面的问题,尤其是在OWASPTop 10中提到的常见安全问题。
2017年最新的OWASP Top 10中最常见的应用安全问题包括注入、失效的身份认证、敏感信息泄露、XML外部实体(XXE)、失效的访问控制、安全配置错误、跨站脚本(XSS)、不安全的反序列化、使用含有已知漏洞的组件以及不足的日志记录和监控。
很多微服务开发框架,都提供了与安全相关的组件或者功能,比如在SpringSecurity、Rails中集成了CSRF防范的功能,通过引入这些组件或者功能,可以对微服务起到最基本的保护作用。
除利用框架支持的功能外,在微服务设计实现还可以采取以下措施来增强安全性:
通过prepared statement来减少SQL注入的风险。
API的返回内容要做到信息量最少,不要返回额外的信息,防止被别人利用。
对于有资源从属关系的请求,比如/students/60/classes/10,需要注意检查学生和班级的从属关系,保证访问没有失去控制。
通过添加一些HTTP响应中的安全header来提升安全性,如X-Frame-OpKons:deny来防止点击劫持,X-XSS-ProtecKon: 1;mode=block激活浏览器自己的XSS防御功能等。
编码实现时,遵从统一的安全编码规范。
保证第三方依赖安全
微服务的技术异构性给我们带来了技术选择的自由,使用不同语言(Java、Python、Nodejs、Ruby)和框架来实现服务。而其带来的一个问题是各种不同的第三方依赖迅速膨胀,任一依赖出现安全问题都会威胁服务本身的安全。所以,掌握微服务都有哪些第三方依赖很重要,这样才能在发现安全漏洞时及时找到使用该类库的微服务并更新以解决漏洞。
笔者曾经针对不同的语言定制过依赖收集的插件(如Java、Scala的Maven插件、Nodejs模块等),将它们引入到微服务的依赖中,并在持续集成流水线上执行对应的任务,将依赖以JSON的形式导出并发布到文件存储服务中。这些JSON文件会包含微服务的信息,以及第三方依赖列表、版本号等。实际上利用了语言的构建工具列举依赖的功能,如 mvndependency:tree,解决并循环依赖可能导致的性能问题,合入微服务相关信息即可。
这样的好处在于,当有第三方类库出现安全漏洞时,可以迅速地从这些JSON文件中找到微服务是否用到这些类库,目前的版本是否存在问题。如果需要更新,哪个微服务需要更新,1 分钟内就可以做出决策。然后将升级的任务划分到团队中,提交代码、自动化部署之后就可以完成漏洞的更新。
密码策略
最近几年国内出现了好几次拖库事件,因为网站未对用户的密码加密,导致用户信息泄露。这种情况下,用户得知信息泄露的时间滞后,很难在利益受损前更新密码。
一种应对的策略是采用加密哈希函数(CryptographicHash Function)加密用户密码后保存到数据库。比如MySQL的PASSWORD函数就采用了md5/sha-1(和MySQL的版本相关)的单向散列函数进行密码加密。好处是即便数据库被拖库,采用暴力破解或者字典攻击的方式很难或者需要花费比较长的时间才能获得用户的明文密码,这就给用户争取了重新设置密码的时间,修复安全问题。
当然,攻击者可以加密哈希函数预先计算值并生成彩虹表(RainbowTable)。攻击者如果猜到了哈希函数的算法,比如MySQL用md5或者sha-1,黑客就可以以空间换时间的方式,先计算出密码的哈希值,然后反查密码,随着这个表的增长,破解的难度可能会降低,时间也会减少,最快可以在O(1)的时间复杂度内破解密码。
要增加破解的难度,让我们能在密码泄露时多争取点时间,其中的一种方式是给密码中加点“盐”(salt),在生成密码的哈希值时,加入一个随机的字符串,然后保存在数据库中。这样对于相同的密码而言,在数据库中的保存的记录也是不同的。对于使用彩虹表破解的攻击者来说,因为需要猜测混合salt的算法,破解的成本很高。同样,暴力破解也变得不太可能。
在密码比较时,计算用户输入的哈希值,然后和数据库中去掉salt的部分记录比较,就可以验证是否是合法用户了。我们以Python下的bcrypt为例:
>>> hashed_password = bcrypt.hashpw("password",bcrypt.gensalt())
>>> print hashed_password
$2b$12$K947InrSXM6XvNoErbAcj.K5YQ/OSVvJ802MxSWNgXdrjmru8Grs2
这是用Blowfish密码生成的哈希值字符串再进行base64编码的结果,共分为4个部分,第一部分$2b$表明这是bcrypt格式的哈希;第二部分是成本(cost)值,默认是12;第三部分是22位的字符串,也就是salt的值;剩下的部分就是密码哈希后的base64编码的值。在比较的时候,只需要把哈希后的密码当作salt传进去就可以了。
Blowfish是一个symmetric-key块分组密码,对称性key的意思用同样的加密秘钥去加密解密,就像谍战片中用相同的密码本解密消息。块分组的意思就是将明文分为固定长度的块,用秘钥分别加密后再拼起来,并且密文应该和明文的长度相同。
另外一种加强密码的强度的方式是给密码撒一把“胡椒”(pepper),简单来说就是在微服务中配置特殊的字符串,将用户的密码和这个字符串一起哈希,这样可以变相地增强简单密码的强度,如下所示:
>>> bcrypt.hashpw("password*{abcd&",bcrypt.gensalt())
'$2b$12$2dVYv2o5vw6uMYe2IT9V9uWfIR2zdkpKDagNRZ8eFOpS4nyNHJuz.'
*{abcd&就是pepper,它以配置的形式保存在服务器上,主要针对的场景是数据库暴露,但是应用服务器安全,可以拖延字典攻击的时间,给用户争取足够的时间更改密码。
这里笔者使用Python代码介绍了如何在密码中以“撒盐”和“胡椒”的方式进行操作,实际上主流的语言,如Java等都有这些算法的实现,可以直接使用。
保证微服务基础设施的安全
在基础设施方面,与微服务安全相关的主要是网络、服务器以及容器安全。网络方面主要是做好隔离和访问控制,服务器的安全方面是需要主动监测并且及时修复漏洞,容器方面主要考虑权限、资源控制。
网络安全:
通过CDN防护攻击。通常我们会使用CDN做缓存静态资源,但是一些CDN提供了安全方面的功能,比如Akamai提供了WAF和Site Shield的功能。WAF可以帮助识别一些攻击,如SQL注入等,但是价格不便宜。Site Shield可以告诉Akamai缓存的边缘节点的IP地址,这样在微服务前面的负载均衡器中可以将这些IP地址加入到白名单中,也就是说只允许来自这些边缘服务器的tcp请求。同时,在负载均衡器上可以阻止所有的UDP请求,这样可以防止黑客直接攻击源服务器,而CDN有足够多的资源来抵挡黑客的攻击。通过基础设施即代码,可以比较方便地以自动化的方式更新这个白名单。这些边缘节点的IP地址的变化比较小,所以整体的维护成本也不高。
做好网络隔离。比如将微服务的实例运行在私有网络中(可以通过NAT访问外网),而负载均衡器运行在公有网络中。不同团队、业务的微服务,划分到不同的网络中。
全站HTTPS。虽然HTTPS会造成性能下降,但是目前软硬件优化的手段已经很成熟了,比如硬件加速、TLS会话恢复、TCP Fast Open、TLS压缩等。2010年Google的Gmail已经开始默认使用HTTPS,SSL/TLS计算只占CPU不到1%的负载,以及不到2%的网络资源,没有使用硬件加速。
PKI管理。全站HTTPS的一个难点是PKI的管理,因为对于不同的微服务,我们会使用不同的证书(IntermediateCA)。而对于需要双向验证的场景,还需要客户端的证书(ClientSide Certificate)。笔者所在的团队最早使用运维提供的脚本来统一生成证书,同时版本化管理生成的代码,通过RatticDB来管理密钥。后来为了降低维护成本,采用了AWS提供商的证书服务Certificate Manager。如果不使用云提供商的服务,还可以考虑使用如Vault这样的工具来做PKI和密钥的管理。此外,必须对每个微服务证书的有效性进行检查。
服务器的安全:
可以通过主动扫描、入侵检测、做好SSH密钥管理等方式来保证。
漏洞扫描。使用诸如SecurityCenter这样的工具来扫描服务器,查看操作系统是否存在安全漏洞,如果出现漏洞,在基础镜像中修复该漏洞,并通知负责微服务的团队,采用在“5.7.5不可变部署”介绍的方式更新。
主动安全检测。如使用OSSEC进行入侵检测,通过日志采集工具收集检测的日志,并在日志服务器上配置报警规则,当检测到入侵时发出警报,然后启动安全应对流程。
密钥管理。对于部署不同微服务的服务器,使用不同的SSH密钥去访问,防止一个服务器被入侵,影响其他的服务器。密钥可以通过专门的工具管理起来,如RatticDB或者Vault,这些系统对接LDAP后,可以以比较小的代价实现对密钥的访问控制。如果采用了在“5.7部署管理实践”中提到的好的实践,甚至可以不需要SSH到服务器上就能获取想了解的内容,比如日志信息等,所以SSH服务并非必须的服务,可以关闭,这样节省了密钥管理的成本。
容器安全:
容器中运行的微服务进程不要使用root用户启动。
容器运行时可设置为对宿主机的文件系统只读。容器运行时,如果需要通过挂载的方式读取宿主机的文件,在挂载时设置为只读。对于需要写到文件系统的内容如日志,可以通过事件流发送到日志转发工具中。
限制容器运行能使用的资源,防止它占用过多资源影响宿主机上运行的其他容器。
在宿主机上通过Selinux或者AppArmor做更严格的访问权限控制。
加强DockerRegistry的安全,可以参考“通过安全加固的Docker Registry去管理镜像”中实现的方式。
其他安全方面的实践
鉴于安全的重要性,应当在微服务的整个生命周期中都嵌入对安全的考量。比如在微服务的设计过程中,需要安全专家的参与,考虑架构的安全性,在实现的过程中也需要考虑编码的安全性,此外还有测试、部署维护等方面。这样的实践也被称为安全内建(BuildSecurity In)。
做到安全内建,除了上面介绍的部分,还需要在以下方面考虑安全问题:
开发过程。通过LDAP、OKTA等工具做统一身份验证,既给予开发人员足够但有限的权限,同时定时更换密码(如一个月一次)。
测试过程。可以将安全测试作为自动化测试的一部分集成到持续集成流水线中。比如用Zap、Brakeman等工具对微服务的代码进行扫描,看看代码是否存在安全漏洞,如SQL注入漏洞等。
部署过程。加密,诸如密码等关键配置,只有在服务器上部署前才解密,并且过程不可见。
生产环境运行过程。通过主动扫描,或者付费给第三方的白帽子组织扫描,发现应用的安全风险,并在黑客找到漏洞之前修复。
在微服务架构下,安全是需要重点考虑的因素。在处理安全问题时,要兼顾业务交付的速度,合理地安排安全问题修复的优先级,通过良好的实践,如不可变部署、基于镜像部署等方式,降低安全问题修复的成本。从而实现业务交付和安全的双赢。
往期回顾
新特性解读 | Apache ServiceComb Toolkit 0.1.0发布
Apache ServiceComb 服务网格与微服务开发框架融合实践
《微服务架构与实践(第2版)》是在第1版的基础之上,基于作者近年来对服务化改造的实战经验和思考,并结合业界的技术趋势进行的一次体系化的精进。全书共分为基础篇、策略篇和实践篇,剖析了微服务架构理论、微服务实施的参考模型、最佳实践以及基于真实案例的实战。
本书不仅适合架构师、开发人员以及技术管理者阅读,也适合正在尝试向微服务架构迁移的团队或者个人。
当当购买链接:
http://product.dangdang.com/27863700.html
ServiceStage:提供微服务的开发、构建、发布、监控及运维等一站式解决方案。
https://www.huaweicloud.com/product/servicestage.html
Apache ServiceComb:业界首个Apache 微服务解决方案,致力于帮助企业、用户和开发者将应用轻松微服务化上云,实现对微服务应用的高效运维管理。
http://servicecomb.apache.org/cn/docs/join_the_community/
本文为作者原创文章,未经作者允许不得转载。
必须要赞一个!!