现在框架两字已经烂大街了,xx公司架构设计随处可见,不过大多看个热闹,这些框架如何来的,细节又是如何思考的,相互之间的隔离依据又是什么...相信不少朋友应该依然存在本身的疑惑,特别是愈来愈火热的微服务以及衍生的微服务网关产品,正好最近打算写一个小开源框架OSS.Core,过程当中有一点思考,经过这篇文章记录一下,也但愿能尽可能帮助你们去理解一下,大概围绕如下几个问题:前端
1. 微服务产生的由来git
2. 微服务的设计思路github
3. OSS.Core框架的设计和实现sql
在展开讲述以前,我但愿你们首先要明白传统架构和微服务架构之间不是相互独立/对立关系,微服务是在传统框架下为了应对并发维护等问题衍生出的逻辑概念,更多的是在项目不一样阶段的思考和解决问题方式的转变。其次,把逻辑架构和物理架构(文件) 区分开来,多数时候逻辑架构和物理架构对应的,不过有时一个物理架构中是能够包含多个逻辑架构的。数据库
一. 微服务产生的由来编程
微服务主要是将一些大型的,复杂的应用拆解为多个服务组合,每一个服务自治,以达到更加灵活,维护方便的效果。 缓存
为了更好的理解,咱们先来看下常见三种解决并发的方式:安全
1. 添加数据库主从分离,甚至多主写入或者分区等机制,在应用程序中对应修改链接串或添加访问中间件,来提升数据库的处理能力。架构
2. 因为数据库资源相对紧张而且比较耗时,为了提升访问速度,这个时候通常也会经过分布式缓存等来减小对底层的访问。并发
3. 负载均衡分流处理,在大量请求抵达应用程序以前,将其分散到不一样的机器上,来解决单机带宽和性能瓶颈问题。
固然解决并发还有不少其余的方式,如前端静态文件压缩,CDN加速,IP速率控制等,这里先略过。
以上这三种方法不少朋友应该都见过,之因此这里列一下,再结合这张图能够更加容易的对比出传统整个服务到微服务之间的变化:
在传统的总体服务框架中,模块之间存在着很大的耦合,项目内部存在互相调用,以及各类复杂聚合操做,因此在多数状况下只能总体部署,在左侧图中咱们能够看到负载均衡时咱们须要总体部署在多台机器上,相对数据库也是如此,而一个项目中每一个模块的需求是不同的。
例如:产品和下单模块的访问频率和流程的复杂度上有着很大的不一样,下单频率相对较小,复杂度高,咱们更但愿运行在预算能力高的相对少机器上,也方便更快的排查问题和维护。右图中能够看到把服务细化以后,咱们能够用更小的部署单元来根据状况进行组合。
同时,在互联网产品快速迭代的今天,一个产品须要具备快速为不一样终端上线不一样应用功能的能力,同时业务的调整可以快速的上线,传统的总体服务模式已经力不从心。微服务由于已经化整为零,反而由于各模块的独立能很快相互组合,而且每一个模块能够根据不一样的需求点采用不一样特性的编程语言。
二. 微服务的设计思路
由于每一个产品都有本身的标准和重点,因此设计服务单元时也各有不一样,可是有最基本一点: 服务自治
当你设计一个微服务模块时,须要保证当前服务的独立,特别是数据模块的独立,其余服务无权直接操做当前服务下的数据库模块,对外交互只能经过服务接口来完成。由于模块的独立,因此你能够选择适合的编程语言,以及对应的部署规模。达到局部的灵活优化。微服务相互独立带来以上便利的同时,它也带来了一些咱们须要面对的问题:
首先:如何如何界定当前服务的边界,如何肯定当前服务治理范围。
既然是要最小化服务单元,那就要肯定服务的职责边界问题,这个问题建议结合:服务生命周期流程,领域,以及预估规模 这几点综合考虑,例如用户服务,在访问量小人员少时能够把用户基础信息,余额帐户放在一个服务模块下,以减小工做量减小精力分散。规模大时再分基础服务和资产服务。
其次:跨服务数据查询问题
例如在客户端中搜索商品,还能够搜索用户或者统计数据查询等如何处理。对于这种我给两个处理方式:
1. API Gateway
这种状况适合在服务单元过多,客户端须要查询使用不一样的服务单元中的数据,这个时候咱们能够针对性的搭建一个API服务网关(请注意和APP Gateway区分开),经过这个网关聚合多个服务,客户端只须要和当前网关交互,网关聚合转发给不一样的微服务。以下图:
2. 数据冗余或者后台数据同步
好比在订单信息中我须要用户的名称等少许用户字段,这个时候彻底能够把这几个字段冗余到订单微服务数据模块下。又好比在统计模块下,其数据制造者和查询者彻底属于不一样的对象,无很高实时性,那我建议建立一个统计服务以及对应的统计数据库,其余服务经过事件消息交互,更新对应的统计数据,查询时经过统计服务本身的数据便可完成。
再次:如何解决服务间的通讯问题
由于咱们已经将服务之间相互独立,断绝直接操做不一样服务数据库的可能。那么数据的一致性如何处理,在传统的服务模型中由于都糅合在一块,咱们能够经过事务或者存储过程来保证数据的一致性。常见的有如下两个方式:
1. 异步事件消息驱动
这类解决方案适合对数据实时性要求相对不高的场景,好比上边的统计服务更新,在下单等服务的事件触发后给消息队列推送响应的消息通知,订阅此队列的服务接收更新数据。如图:
2. 直接接口请求(HTTP,RPC)
通常状况下不建议,以防止产生级联依赖。这类主要针对数据实时性要求较高的请求,好比在秒杀下单过程当中须要当即知道库存服务扣除是否成功等。(注:.net 下对task的支持已经特别好了,http请求建议使用异步,同时前端返回Task<ActionResult>,减小因IO操做形成的工做线程消耗)
最后:客户端如何访问
当咱们封装完服务以后,这个服务如何和最后的客户端如何访问,这个须要根据实际的安全规则和要求各自决定了,通常状况下,若是服务相对较少,功能不算复杂的状况下能够直接暴露服务接口给客户端进行访问,如图:
或者经过上边说的 API Gateway 的形式提供给客户端,固然也有不少已经成熟的微服务网关好比Azure云上的Service Fabric或者API Management,都是能够的。
三. OSS.Core框架的思路和实现
OSS.Core这个项目是我最近在写的一个小开源产品,了解的朋友应该知道我在前面写了一些组件像: OSS.Social,OSS.PayCenter,OSS.Common,OSS.Http 这个项目但愿能把这几个组件给串联起来,上边已经介绍了微服务的大概思考方式,我将会在这个产品的逻辑架构中尽量的体现这一点,先把项目的物理架构图展现一下:
这个项目中AdminSite,WebSite 放置在FrontEnds文件夹下,两个问站点分别是用户前端,和后台管理前端
WebApi,Service,DomainMos(图中的Models和Interface)类库在 Layers 文件夹下,构成API基础
Infrastructure(业务相关通用实体枚举辅助类) 和 Common(业务无关相关实体辅助类) 做为基础设施类库,能够在各级类库中调用
Repositories(暂时是项目中的OSS.Core.RepDapper的Mysql实现,之后可能增长其余数据库支持),主要是Rep.. Interface的具体实现。
Plugs是实现了Common插件下的日志,缓存,和配置接口具体实现,能够经过Common在各级直接调用。
回到微服务的话题上,在这个产品中我不会为每一个服务建立一套Layers下的类库实现,我将在这个项目经过文件夹隔离的形式来分开各个服务,你能够把WebApi当作一个API Gateway,内部的调用顺序我但愿是这样的:
如今代码结构图:
=============================
若是你还有其余问题,欢迎关注公众号(OSSCoder)