用了一段时间的分布式,今天也稍微整理一下我理解的分布式,写个文章当做是自己的一个记录吧!
一、什么是分布式?
分布式是一个很笼统的东西,一个工作方式。一个程序或系统,只要运行在不同的机器上,就可以叫分布式。
说明白点就是"一个业务分拆多个子业务,可以部署在不同的服务器上"
以下如图,我列举了一个我工作中遇见的一个分布式项目结构。可能每个公司的架构不一样,但是这个不重要,重要的还是分布式架构的思想!有了这个我们才能在接下来的微服务浪潮中更愉快的玩耍哈。
二、分布式结构
当然仅凭一张个人理解的图,估计不能让大家看明白,这里就继续一一讲解一下。
图中,可以分为三个角色:消费者,服务协调者,服务提供者。
1.消费者:用java代码说,就是controller层。用MVC架构来说,包含了视图层和控制层。职能: 校验第三方传入的参数,调用相应的服务接口,返回给用户对应的视图。其他的事,没特殊情况就别再这层处理。
2.服务协调者:就是接口提供者提供的接口并给予消费者请求的接口。
3.服务提供者:这个是重点,也最复杂。原则上来说从数据库层,表的设计开始,每个模块的表和代码都是独立存在的。
三、重点讲解服务提供者
服务提供者,概念上来说,可以分为底层公共模块,业务模块,process跨模块层。
1.模块独立
模块之间相互独立,独立到哪一步呢?例如:我有两个模块,一个是商品模块一个是订单模块。商品模块有商品表和商品收藏表,订单模块有订单表和订单评价表,我现在有个需求,我要获取订单对应的商品名称,这个咋弄?可能有人会说,这还不简单,直接一个sql不就完了么?比方说:
select p.name from product p , order
o where o.id = ?1 and p.id = o.product_id
正常来说一个简单的跨表查询就可以了,但是此时是分模块的,问题来了!模块是独立的,甚至连表我们也得当做为不同的数据库。比如商品表在A数据库,订单表在B数据库,数据库都不同你还怎么跨表查询? 所以说模块是独立的,除了一些底层的公共模块不能缺少,业务模块之间不管少了谁,也不会影响自己的业务正常进行。根据2/8原则我就能够把资源更多的放在我那个20%的业务上,加强子节点的性能,同时整个系统也能够协同工作。
2.底层共用
诸如redis,发短信,系统内部消息等等第三方功能以及调用频率极高的会员模块,此类功能模块都可以下沉到底层。被各个模块所引用,保证业务的正常运行。
3.跨模块调用
如上,刚刚说的想要获取订单对应的商品名,在不同的模块怎么办?此时process层就出现了,这个层可以组装各个service提供的接口,将不同模块的信息组装起来作为VO返回给前端。顺便提一下,这里涉及的一个概念。 比方查询一个分页数据怎么办?这里可以先查询数据源,然后遍历查询出来的列表,根据每一行对应的其他表的ID去查询组装相应的跨模块数据。意思就是我有10个订单列表,需要遍历十个订单,每次遍历都需要拿当前订单的商品ID去数据库查询对应的商品信息。可能有人会疑惑这样,我不就是查询了11次数据库么??其实不然,在大量数据下,没有外键远比有外键的设计高效。加之一般这种查询都会有索引,并且往往是在一个机房局域网内。所以即便是多次查询也远比关联查询来的高效。
4.高度服务化
写服务模块的一个重要原则就是"我就是一个提供服务的接口而已"。尽量不要在入参上代入判断分支条件的参数。我们要达到的目的就是,调用者只需要知道这个服务是干什么的,需要什么参数即可。而不需要让调用者再去判断比如一个
boolean 或枚举类型每个类型代表什么意思,给调用者带来跟多困扰。甚至有可能在第三方来当消费者的情况下,系统的可用性更一步降低。在文档缺失的情况下,更是灾难性的。所以,切记每一个接口都要明确自己提供的服务,不要混用。
5.不可信
当作为服务层开发者的时候,一定要明确一切外来的数据都是不可信的,明确自己是独立的存在!所以要适当的加上 参数的校验,以及相关逻辑的校验。确保做到即便接口被人为的错误调用,也能够保证正常流程。
四、优缺点
优点:
1.层次结构设计清晰,业务功能分明
2.面向服务化,对应消费者端很友好
3.一般遵循开闭原则,可扩展性,可维护性都比较不错
4.适合大型项目,给予不同的小组开发。并且降低人力成本。甚至服务层可以只交由少数核心人员开发,配置一些初级工程师即可完成大部分消费者端重复,简单的页面及逻辑。
5.代码可重用性强,不同的项目不需要重复的框架代码,不需要单独的部署项目。
6.分布式一般适用于大型项目,且开发质量一般比较高。架构设计和代码质量,项目规范一般都比较优良。
缺点:
1.复杂性更高,尤其是随着产品的横向扩展。表设计更复杂,很多性质一样的表,但是根据产品特性不同字段不一致。导致无论横表或者纵表设计,总会有一定的缺失。
2.部分服务治理框架不能热编译。比如我用的dubbo还未找到热编译的方式(或许存在,是我没找到),所以服务端的代码改动需要重新启动,花费时间长。连tomcat远程debug也用不了,让人更困扰。
3.编写一个好的分布式项目对设计人员要求更高,设计的差的项目从结构到代码给人的感觉都会比较差。
4.部署时间长,即便是脚本一键发布。但是代码上传服务器的网络传输,项目启动都会花费不少时间。
以上是自己理解的分布式概念,当然不同的公司方式肯定不一样,我所了解的也有限,本文仅供参考即可。而且真正的代码实现,从启动到API暴露,以及接口调用,版本迭代,业务升级,自动化发布等等都是更加的复杂,并且会有一定的改变,一个好的分布式项目远没想象中简单!