SAAS电商产品“小羊云商”使用spring boot + dubbo + nacos来实现的,这套体系架构也经历了几个大的版本迭代。很多人会有疑问,为什么要采用dubbo而不采用spring cloud? 原因是原来的Spring MVC结构更合适dubbo,dubbo并没有破坏原有的系统结构,而且能继续用原来的开发模式进行微服务的开发工作。如果是新的系统,那还是建议采用spring cloud + vue。另外采用了最新版本的dubbo之后,可以采用spring cloud alibaba的组件,这个可以spring cloud和dubbo共用, 比之前的spring cloud组件更好用,这些就是我们选择用dubbo的原因。
小羊云商的特点是
1. 按功能模块分表分库;
2. 并且每个数据库都有最少一个对应的微服务;
3. 手机端完全前后端分离;
4. 跟本地开发的开发体验保持一致,这个是spring cloud版本暂时所不具备的。
其追求的目标是用本地的开发体验来开发微服务项目,对其他系统开发也具有参考意义。
总结以上的分析,以下是朗尊软件的架构师何文强所带来的技术分享。以LegendShop的SAAS电商系统为例, 先看一下整体的SAAS电商系统的整体解决方案:
结合图中所示,下面是这套电商系统所采用的技术的主要的技术栈。
Dubbo版本跟spring cloud版本比起来,最大的区别是dubbo不需要gateway,因为dubbo默认提供的是RPC协议,不能直接对调用方来公开,所以在外面再套用一层spring mvc作为他的gateway的入口即可。 spring mvc作为controller层,它通过dubbo协议远程调用各个微服务的功能,而且这个调用对调用方即消费者来说跟本地调用的体验是完全一模一样的。调用者可以比较方便的指明这个调用是那台服务器的微服务还是本地的微服务。剩下来的开发体验跟spring cloud基本一致, 也是采用Nacos作为注册中心和配置中心,以下是详细的说明。
1、通过 API 的设计解耦,把整个系统根据业务拆分成若干个子系统或微服务
客户端通过API gateway来访问内部的应用, 通过gateway来实现黑白名单,路由控制,权限控制等。一个后台可以同时支持多个客户端。
2、每个子系统可以部署多个应用,多个应用之间使用负载均衡
每个服务会占用一个端口,同一个服务可以启动多个实例。
3、服务注册中心和配置中心都采用Nacos,所有的服务都在注册中心注册,负载均衡也是通过在注册中心注册的服务来使用一定策略来实现
4、使用 OAuth2 认证完善外部交互的安全机制
客户端在调用gateway或者内部API的时候需要系统授权才行,要不就无法保证系统安全了。LegendShop的为服务版本采用Oauth2进行权限验证, 每个调用方都会分配一个appId和secretKey, 用户调用API之前需要用appId和secretKey来换取合法的token,然后通过token来访问系统的功能。OAuth 是为用户资源的授权提供的一个安全、开放、简易的标准协议。OAuth 的授权不会使第三方触及到用户的帐号信息,非常安全。而且任何第三方都可以使用 OAuth 认证服务,在这套架构里,每一次来自外部的对微服务的请求,都要通过 OAuth2 服务器验证。OAuth2 在此统一了众多微服务的安全机制,并且将安全做到了微服务级别而不是网关级别。
作为一个电商系统,主要涉及的对象是人(商家,用户,管理员) 场(商城) 货(商品,订单)。 设计数据库的时候根据模型来划分为以下数据库:
设计微服务的颗粒度是一个有争议的议题,到底是越细越好,还是大而全比较好? 微服务分的越细,那意味着微服务就越多,部署和维护的成本就越高。 微服务的颗粒度越大那微服务的意义就不大了。
那我们初步定下来的原则是把微服务分为两种类型, 一种是业务相关的微服务,有很多的业务逻辑,例如订单,商品等。 一种是功能相关的微服务,完成之后基本就不再变化的,例如发送短信,邮件,文件上传等。 原则上一个数据库对应一个主要的微服务,例如订单,商品,搜索也是一个独立的跟商品相关的微服务。 功能微服务就按功能功能区分。
整个系统还是按照MVC的结构来编写, 但是service层早已经不是之前的Service层了,对Controller来说它只是关心Service的接口,并调用即可。Controller不需要知道这个Service到底部署在哪里。
每个服务首先分为2个项目, 一个是api项目, 一个是实现类的项目。在api项目中要实现以下类。
例如商品服务
需要声明自己的版本号, 版本号是以微服务为基础的。REGISTER标记用于表示该服务是否注册到注册中心去, 为了方便测试可以把REGISTER修改为false, 那默认就是采用本地方式运行,消费者就会自动的找到本地所有的微服务来调用,方便开发者来调试。
那在标准的dobbo的用法当中标明一个微服务的消费者和服务提供方式用@Reference和@Service注解。
用标准的注解的话那样无法统一系统的行为, 因此为每个微服务定义一个个性化的注解能解决这个问题,例如定义一个商品服务提供者的注解。
商品服务消费者注解参考
参数说明:
VERSION: 统一定义每个微服务的版本号
URL: 用于控制每个微服务的调用地址
DEFAULT_RETRIES: 默认的重试次数
如果一个Serive的注解是使用@Autowired或者@Resosurce这些标准的Spring的注解的话表示调用的是本地的接口,无需远程调用。如果注解用的是@ShopRefenence的话,表示这个是调用shop商家微服务的。@ProductMicroService表示把自身标识为一个提供远程商品服务的接口。
服务注册中心和配置中心都采用同一个化简了部署的步骤,采用Nacos之后,配置文件集中存放,既保证了配置的安全,也为部署提供了方便。比如在测试环境测试完毕之后这个war或者jar包就可以直接上生产环境, 而无需重新打包,可能引起新的问题。Nacos启动时可以指定不同的namespace命名空间,支持多套环境共存。
本文是为了化简dubbo的用法,一方面的开发体验保持跟本地的开发体验一致,另外一个方面也向spring cloud的组件靠拢。 两者除了远程调用的协议不一样,一个RPC一个Restful之外, 在spring boot的加持下,所采用的组件基本一致,更多组件将会陆续加入系统中进行验证。