【揭秘】一个小团队真正能落地的微服务架构实践

来都来了 2019-03-29 13:11:18 ⋅ 958 阅读

编者的话

微服务是否真的适合小团队这里不多做争辩。但是透过现象看本质,随着产品版本的不断迭代、业务复杂度的提高最终都会导致单体应用越来越庞大,总会超过单体架构的负荷。那么使用微服务分而治之就成为一个不得不面对的问题。所以这么庞大的单体应用拆分出多个小应用也更符合这种分治的思想。虽然这些不是小团队能够考虑到的事情,但是如果能在产品的初期阶段能够规划好产品的架构体系那么在慢慢演变的过程中会越来越顺手,团队的战斗力也打造的越来越强。

一、背景

公司的背景是提供SaaS服务,初期是对于客户的定制开发以及私有化部署。经过两年多的发展,公司产品受到客户的欢迎并且慢慢蜕变到平台化的产品,技术架构也从单体架构到微服务架构迁移。

1、单体应用

起步的时候开发人员只有2、3人,并没有考虑微服务之类的(多余)。但是整体架构采用了SPA式的前后端分离法,单纯的从物理层做区分(认为只要是客户端的就是前端,服务器端的就是后端),这种分法不能满足前后端分离的需求,认为从技术职责上划分才能满足目前我们的使用场景。

由于团队资源有限后端人员往往担任前端的一些开发任务,所以采用了如下职责划分:
前端:负责View和Controller层。
后端:只负责Model层,业务处理/数据等。

优点:可以做url design,我们可以根据场景决定在服务端同步渲染,还是根据view层数据输出json数据,我们还可以根据表现层需求很容易的做Bigpipe,Comet,Socket等等,完全是需求决定使用方式。
缺点:需要前端来写Controller,以Java语言开发为例,需要前端学会Java开发,这样在处理复杂的业务逻辑的产品里双方都有Java 代码方面的重叠。

服务器部署上,采用Nginx代理前端HTML资源,在接收请求时根据路径反向代理到服务端口达到实现业务目的,如下图所示:



采用RESTful Api和Json搭建前后台交互



备注:后台提供一组设计原则和约束条件,接口通过swagger生成文档进行接口测试和联调。

2、开发过程遇到的问题

2.1 半持续集成
由于团队成员之间没有共事过的经历,对于开发模式、质量管控和开发流程都需要重新开始制定。针对这种情况开发初期没有进行引入非常完整的集成测试体系,主要是针对接口进行单元测试(Unit Test)、编写测试用例和人工Review。

2.2 引进Jenkins持续集成工具
Jenkins功能包括:
1、持续的软件版本发布/测试项目。
2、监控外部调用执行的工作。

两种启动方式

第一种:
切换到jenkins.war存放的目录,输入如下命令:
$ java -jar jenkins.war
如果需要修改端口可以使用如下命令:
$ java -jar jenkins.jar--httpPort=8081
然后在浏览器中输入localhost:8081,localhost可以是本机的ip,也可以是计算机名。就可以打开jenkins。
第二种:
解压tomcat到某个目录,如/usr/local,进入tomcat下的/bin目录,启动tomcat
将jenkins.war文件放入tomcat下的webapps目录下,启动tomcat时,会自动在webapps目录下建立jenkins目录,在地址栏上需要输入localhost:8080/jenkins。

Jenkins持续集成



执行步骤:

  • 开发人员提交代码进入gerrit中;

  • Jenkins被触发开始编译代码并执行集成测试;

  • 完成后生成测试报告;

  • 测试通过再由reviewer进行代码Review;

在单体应用时代这样的CI架构已经足够好用,由于有集成测试的覆盖,在保持API兼容性的前提下进行代码重构都将变得更有信心。

三、微服务时代

1 服务拆分原则
“独立,独立,再独立?”先忘记这句话吧!想象是美好的,显示却很骨感。以下拆分方案可以给大家一点参考,有好的经验也可以留言分享。

1.1 公共库的初始化拆分
我们把公共的库都放在common里面,这里面包括了log,config,errors等基础库,还有redis,mysql,mongodb等db的连接池初始化,还有rpc的连接池初始化,这里或者用grpc或者用户自己基于go自带的rpc的二次封装等。还有trace等用于追踪请求方便日志查询的基本库。

这些基础库是我们做微服务的必备,在搭建一个新项目的时候,前期需求讨论评审完成后,编码前期,我们会先把这些公共库的初始化工作都做了,比如db的一些连接池初始化不同项目稍微有一些不同。rpc等连接池代码基本都是能复用的。其他的公共库,直接拖到新项目里就能开搞,大大的规范了代码质量和减少开发周期。

1.2 根据业务职责拆分
其实微服务的拆分最根本是一些代码职责的拆分和抽象,这一步和我们模块化的时候思路是一样的。我们将按照要开发的业务功能拆分为不同的项目,而负责不同功能的研发人员就可以在自己的代码项目上进行开发,从而解决了大家无法在开发阶段并行开发的苦恼。


如上图所示,可以拆分为用户中心、产品中心和订单中心等,支撑整体业务的基础服务业可以相应的进行拆分。

1.3 各组件之间接口的定义(重点讲)
公共库和各个业务职责搞清楚后,接下来还不要着急写代码,我们先把各个组件之间接口定义清楚。不然各自写各自的,最后还是一团乱麻。
先做到以下几点:
1.3.1 接口协议选型。

- 现在微服务流行采用的http协议restful接口(语言无关)。
- RMI远程接口调用(Java语言支持)。
- 大数据传递采用文件离线下载的方式(FTP)。
- 状态数据(如果进度条)放在Redis中共享缓存。
- 数据库共享。一般来说微服务的数据库是隔离的,不同微服务不允许直接访问彼此的数据库。如涉及大数据有性能问题时可特殊考虑。

备注:如果为防止数据被人抓包分析,需要有相对应的加解密处理方案。

1.3.2 定义接口内容。
接口内容包含接口名称(url)、输入参数、返回值、错误码。一个典型的restful接口内容定义如下:


备注:code:100代表成功,message:描述说明,result:返回详细信息可以一般是json格式

1.3.3 明确接口性能。
接口性能包括:接口单次响应时间、单次查询返回记录条数和每秒支持调用次数等。数据量比较大的查询接口一把都会设计成分页查询,需要定义好单次查询返回的最大记录条数。

微服务接口的支撑能力是有限的,必须定义好单位时间内允许的最大请求次数(超过请求次数就不响应或者返回错误码),否则海量的请求一下涌过来,服务就挂了。对于特殊的服务,还会根据实际情况设定一天的请求次数上限等。

1.3.4 做好接口管理。
上面说了要做那么多事情那么能不能用好并且是持续的用好,接口管理是非常重要的。
接口管理包括:接口版本管理、接口权限管理、接口管控等;

为什么要做接口版本管理?
大家都知道同一个接口随着产品的不断迭代、需求的不断变更都可能面临接口升级(不管是新增还是兼容)。但是不管怎么升级都需要兼容旧的业务使用,为了管理好就需要通过版本号来解决。例如:在URL中带上不同的版本号,需要使用新特性的可以调用新版本的接口;不使用新特性的可以仍然沿用旧版本接口。

为什么要做接口权限管理?
对外发布的接口都需要做权限控制,未授权的服务是不允许访问的。可以采用在接口的header参数中加上加密的token作为权限认证。

后续当整个系统越来越庞大复杂后,各微服务发布的接口需要做可视化管理,包含服务的注册、发布、调用、下线都需要在统一的运维平台上操作。
为什么要做接口管控?
前面提到的接口版本管理对接口不同版本的兼容处理是不可能不限支持下去的。发布旧版本接口的下线公告到期后,如果在监控平台上发现旧版本接口已无人调用就可以下线了,如果还有人调用则可以通知他进行限期整改。

1.4 开始分工写自己的组件
这样就可以分配任务编写代码啦。每个开发人员都是相对独立的开发,并且接口也定义好了,公共库也都已经初始化完毕,然后开发就是完全并行了。编写完之后,自己的组件可以依靠单元测试,做一些基本的测试。然后联调即可。

2 技术框架选择
来看一下经典的微服务架构图:



主要包含11大核心组件,分别是:

核心支撑组件

  • 服务网关Zuul

  • 服务注册发现Eureka+Ribbon

  • 服务配置中心Apollo

  • 认证授权中心Spring Security OAuth

  • 服务框架Spring MVC/Boot

监控反馈组件

  • 数据总线Kafka

  • 日志监控ELK

  • 调用链监控CAT

  • Metrics监控KairosDB

  • 健康检查和告警ZMon

  • 限流熔断和流聚合Hystrix/Turbine

看到这里是不是想说:“尼玛,这是几个人小团队能玩起来的?确定不是让我们996 变 007 吗?”,我也想说我们也不是用的这个,一般是给别人吹牛用的,哈哈哈哈!
我们来看下面这张技术架构图,大家会好理解许多。


这张图大部分业务都通用,根据团队自身情况去选择技术来满足业务需求。

四、总结

还是那句话,技术栈没有好坏之分,只有适合一说。本文推荐的技术栈主要基于我个人的实践和总结,但是未必适合所有场景,毕竟每个企业的上下文各不相同。作为架构师你可以参考我推荐的技术栈,但不可拘泥照搬,你必须在深入理解分布系统原理的基础上,再结合企业实际场景灵活应用。
在整个互联网基础技术平台体系中,还有消息,任务,数据访问层,发布系统,容器云平台,分布式事务,分布式一致性,测试,CI/CD等其它重要主题,请大家持续关注“IT实战联盟”公众号。

最后送上整理的业务架构图,希望对大家有所帮助!


贡献者

  • IT实战联盟-Line


---------------END----------------

后续的内容同样精彩

长按关注“IT实战联盟”哦




全部评论: 0

    我有话说:

    架构实战篇:一个可供中小团队参考服务架构技术栈

    作者近年一直一线互联网公司(携程,拍拍贷等)开展服务架构实践,根据我个人一线实践经验和我平时对Spring Cloud调研,我认为Spring Cloud技术栈中有些组件离生产级开发尚有

    DDD 服务实战

    PS:让我们把DDD思想真正落地,从数据库设计到代码实战演练,从电商、在线订餐 到智慧医疗全方位展示如何运用DDD 在服务+人工智能、嵌入式+物联网项目中进行业务建模、系统规划与设计实践

    架构实战篇:认识一下服务架构

    服务一个新兴软件架构,就是把一个大型单个应用程序和服务拆分为数十个支持服务

    码云推荐:一个优秀分布式spring boot/Spring Cloud API限流框架,特别适合服务架构

    一个优秀分布式spring boot/Spring Cloud API限流框架,特别适合服务架构.

    服务架构若干常用设计模式

    在我们选择了用服务架构来设计、交付数字化应用后,因服务架构本身所带来一些共性问题。

    精品推荐:服务架构下静态数据通用缓存机制

    在分布式系统中,特别是最近很火服务架构下,有没有或者总结出一个业务静态数据通用缓存处理机制或方案,这篇文章将结合一些实际研发经验,尝试理清其中存在关键问题以及探寻通用解决之道。

    老板逼你上服务了吗?

    “ 这些年软件设计规模越来越庞大,业务需求也越来越复杂,针对系统性能、高吞吐率、高稳定性、高扩展等特性提出了更高要求。   图片来自 Pexels可以说业务需求是软件架构能力

    【分享】一次单体架构改造成服务架构拆分实践

    从5个方面设计这次服务拆分方案,以及经验总结!

    「转载」服务分布式架构中,如何实现日志链路跟踪?

    背景 开发排查系统问题用得最多手段就是查看系统日志,在分布式环境中一般使用ELK来统一收集日志,但是在并发大时使用日志定位问题还是比较麻烦,我们来看下面图     上图

    程序实战篇:如何解决https域名问题 ?

    开发自己程序绕不开https问题,为了程序中调用我们自己API服务请打开看一看吧!!!

    字节跳动 | 服务架构中如何优雅重试?

    背景 在服务架构中,一个大系统被拆分成多个服务服务之间大量 RPC 调用,经常可能因为网络抖动等原因导致 RPC 调用失败,这时候使用重试机制可以提高请求最终成功率,减少故障影响,让系统

    程序实现商品数量加减

    这是一个程序原生代码实现数量加减demo,主要是用于商品购物车或者商品详情修改数量使用

    程序电商实战-购物车(上)

    好久没更新程序电商实战文章了,是因为最近一直做整体架构调整,一些准备工作也是比较耗费时间。在这几天将会有新版 程序电商教程推出.......

    【开源资讯】JWCloud 专业版 v1.0.0 发布,基于 SpringCloud 研发服务框架

    简介 JavaWeb_Cloud 服务平台是一款基于 SpringCloud 框架研发分布式微服务框架,主要使用技术栈包括: SpringCloud、Vue、ElementUI

    服务架构:搭建网站扫码登录功能设计

    信扫码登录大家都是应用比较多登录方式了,现在大购物网站像京东、淘宝等都支持使用APP扫码登录网站了。今天就用APP扫码登录网站实例来举例说明服务架构搭建过程。

    程序实战篇:商品属性联动选择(案例)

    本期程序实战篇来做一个电商网站经常用到-商品属性联动选择效果,素材参考了一点

    服务架构学习笔记(一):重新认识服务

    服务(Microservice)是服务化思路一种最佳实践方向,遵循SOA思路,各个企业在服务化治理道路上走时间长了,踩坑多了,整个软件交付链路上各个环节基础设施逐渐成熟了,服务

    程序抖音实战-首页(上)

    你也可以用程序编写一个抖音

    程序电商实战-首页(下)

    上一篇:程序电商实战-首页(上)好了,上一期我们把首页搜索、导航栏和广告轮播给做完了,那么接下来会继续