剥析surging的架构思想
1、前言
前面第一篇阐述了采用基于.NET CORE微服务架构,应用surging服务端与客户端之间进行通信的简单示例以及对于surging服务化框架简单介绍。在这篇文章中,我们将剥析surging的架构思想
2、通信机制
2.1 简介
在单体应用中,模块之间的调用通信通过引用加载方法或者函数来实现,但是单体应用最终都会因为团队壮大,项目模块的扩展和部署等出现难以维护的问题。随着业务需求的快速发展变化,敏捷性、灵活性和可扩展性需求不断增长,迫切需要一种更加快速高效的软件交付方式。微服务可以弥补单体应用不足,是一种更加快速高效软件架构风格。单体应用被分解成多个更小的服务,每个服务有自己的独立模块,单独部署,然后共同组成一个应用程序。把范围限定到单个独立业务模块功能。分布式部署在各台服务器上。一般来说,每个微服务都是一个进程。而各服务之间的交互必须通过进程间通信(IPC)来实现
2.2 交互模式
交互模式有以下几种方式:
• 请求/响应:一个客户端向服务器端发起请求,等待响应。客户端期望此响应即时到达。在一个基于线程的应用中,等待过程可能造成线程阻塞。
• 通知(也就是常说的单向请求):一个客户端请求发送到服务端,服务端不返回请求响应。
• 请求/异步响应:客户端发送请求到服务端,服务端异步响应请求。客户端不会阻塞,而且被设计成默认响应不会立刻到达。
• 发布/ 订阅模式:客户端发布通知消息,被零个或者多个感兴趣的服务消费。
• 发布/异步响应模式:客户端发布请求消息,然后等待从感兴趣服务发回的响应。
服务之间的通信可以使用同步的请求/响应和请求/异步响应模式,在surging框架采用的基于RPC的netty 请求/异步响应和基于rabbitmq 的消息通信模式。首先来看异步消息通信模式
2.1.1 异步消息通信模式
Surging采用基于Rabbitmq发布订阅的异步交换消息的IPC进程通信,客户端通过pub发布请求,然后服务端进行Consume,之间的通信是异步,客户端不会因为等待而阻塞。
消息由头部(元数据)和消息体构成,生产者发送消息到channel,消费者则通过channel接受数据,channel 则分为点对点和发布订阅,点对点Channel 会把消息准确发送到消费者,之间采用的是一对一的交互模式。而发布/订阅则把消息PUB到所有从channel 订阅消息的消费者中,之间采用的一对多的交互模式
2.1.2 基于请求/异步响应通信模式
Surging采用基于netty的
(IPC)进程通信,是基于请求/异步响应的IPC机制,客户端向服务端发送请求,服务端处理请求,异步响应,客户端不会因为等待服务返回而阻塞其它请求。
在请求/异步响应模式中,服务器端异步响应是在多处理器系统上可以并行处理或者单处理上交错执行,这使得当某个线程阻塞请求的同时其它线程得以继续执行。但访问共享资源时,需要保证其线程安全,可以通过锁,先进先出集合或者其它机制来处理线程安全的问题。
3、部署和调用
1.单体应用架构
当网站流量很小时,只需要将所有功能部署在一起,以减少部署节点和成本
单体架构业务流程往往在同一个进程内部完成处理,不需要进行分布式协作,它的工作原理如下:
图 1-1 单体架构本地方法调用
2.垂直应用架构
当访问量逐渐增大,单体架构压力越来越大,将架构拆成互不相干的若干应用以提升效率,此时采用MVC、webAPI进行调用
3.分布式微服务架构
当垂直应用越来越多,应用之间交互不可避免,可以将各个独立的业务模块,部署成独立的微服务,逐渐形成稳定的服务中心。
而Surging 微服务采用分布式集群部署方式,服务的消费者和提供者通常运行在不同的进程中,进程之间通信采用RPC方式调用,它的工作原理如下:
图1-2 Surging分布式RPC调用
Surging微服务采用基于netty进行通信,数据之间的传递通过序列化和反序列JSON,相比于本地方法调用,会产生如下问题:
1.数据序列化问题:微服务进程的通信都需要经过序列化和反序列化,因数据结构不一致、数据类型的不支持、编码错误都会造成数据转化的失败,从而导致调用失败
2.网络问题:常见的包括网络超时、网络闪断、网络阻塞等, 都会导致微服务远程调用失败。
每个微服务都独立打包部署,让服务之间进行进程隔离,对于大型的互联网项目,会有成百上千的微服务,通常不会百分百独立部署,对于同一业务的微服务会打包部署在一起,对于时延非常敏感,会合设在同一进程之内,采用本地方法调用。
不同的微服务合设在同一进程中,会产生以下问题:
- 处理较慢的微服务会阻塞其它微服务
- 某个微服务故障,可能导致整个进程不可用
3、总体架构
Surging框架代码逻辑一共划分了8层,各个层的设计要点:
- 业务模块服务接口层(IModuleServices):该层是与实际业务逻辑相关的,根据服务提供方和服务消费方,设计业务模块接口。
- 业务模块服务层(ModuleServices):该层是通过Domain和Repository实现实际业务逻辑
- 基础通信平台(CPlatform):提供基础数据通信对应的接口和基础实现,如:基础日志,远程调用服务,Event bus,负载均衡算法,数据序列化等
- DotNetty服务层(DotNetty):实现基于DotNetty服务的信息的发送和接收
- RabbitMQ服务层(EventBusRabbitMQ):封装基于Rabbitmq的发布订阅的事件总线
- 代理服务层(ProxyGenerator):封装代理服务的生成及创建调用。
- 服务注册层(Zookeeper):封装服务地址的注册与发现,以Zookeeper为服务注册中心,实现ServiceRouteManagerBase抽象,通过心跳检测的方式更新路由
- 系统服务层(system):对于系统底层接口的封装
4、分布式的可靠性
Surging 微服务的运行质量,除了自身的可靠性因素之外,还受到其它因素的影响,包括网络,数据库访问,其它关联的微服务的运行质量,可靠性设计,需要考虑上述综合因素,总结如下:
4.1 异步I/O 操作
4.1.1 网络I/O
1.同步阻塞I/o 通信:
即典型的请求/响应模式。 该模型最大的问题就是缺乏弹性伸缩能力,当客户端并发访问量增加后,服务端的线程个数和客户端并发访问数呈1:1的正比关系,线程数量快速膨胀后,系统的性能将急剧下降,随着访问量的继续增大,系统最终崩溃。
- 异步非阻塞I/O 通信:
Surging 是基于Netty进行异步非阻塞I/O 通信,即典型的请求/异步响应模式。此模式的优点如下:
- 更好的吞吐量,低延迟,更省资源
- 不再因过快、过慢或超负载访问导致系统崩溃
4.1.2 磁盘I/O
微服务对磁盘I/O的操作主要分为同步文件操作和异步文件操作,
在Surging项目中,需要从注册中心获取路由信息缓存到本地,通过创建代理,负载均衡算法选择Router,路由信息的缓存到采用的是心跳检测的方式进行更新。
4.1.3 数据库操作
一般来说文件 I/O、网络访问乃至于进程间同步通信,以及本节所讨论的 数据库访问等都较为耗时,ado.net,Entity Framework以及其它ORM框架都提供了异步执行方法。
4.2 故障隔离
由于大部分微服务采用同步接口调用,而且多个领域相关的微服务会部署在同一个进程中,很容易发生“雪崩效应”,即某个微服务提供者故障,导致调用该微服务的消费者、或者与故障微服务合设在同一个进程中的其它微服务发生级联故障,最终导致系统崩溃。为了避免“雪崩效应”的发生,需要支持多种维度的依赖和故障隔离,
4.1.1 通信链路隔离
由于网络通信本身通常不是系统的瓶颈,因此大部分服务框架会采用多线程+单个通信链路的方式进行通信,原理如下所示:
4.1.2 调度资源隔离
4.1.2.1微服务之间隔离
当多个微服务合设运行在同一个进程内部时,可以利用线程实现不同微服务之间的隔离。
4.3 进程级隔离
对于核心的微服务,例如商品用户注册、计费、订单等,可以采用独立部署的方式,实现高可用性。
4.3.1 容器隔离
微服务将整个项目解耦成各个独立的业务模块,部署成独立的微服务,利用Docker 容器部署微服务可以升级和扩容,并且有以下优点:
高效:使用Docker部署微服务,微服务的启动 和销毁速度非常快,在高压力时,可以实现秒级弹性伸缩。
高性能:Docker 容器的性能接近逻辑,比VM高20%
隔离性:可以实现高密度的部署微服务,而且是基于细粒度的资源隔离机制,实现微服务隔离,保证微服务的可靠性
可移植性:通过将运行环境和应用程序打包到一起,来解决部署的环境依赖问题,真正做到跨平台的分发和使用。可谓是一次编写,到处运行。
4.3.2 VM隔离
除了Docker容器隔离,也可以使用VM对微服务进行故障隔离,相比于Docker容器,使用VM进行微服务隔离存在如下优势:
1.微服务的资源隔离性更好,CPU、内存、网络等可以实现完全的资源隔离。
2.对于已经完成硬件虚拟化的遗留系统,可以直接使用已有的VM,而不需要在VM中重新部署Docker容器。
4.4 集群容错
略
5、Cache和EventBus中间件
5.1 Cache 中间件设计
设计目标:
- 将缓存服务器的部署配置与应用隔离,
- 实现分布式,提高数据的均匀分布,并且能实现故障隔离
- 根据KEY前缀的不同分配到MemoryCache 或者redis 上ache
- 统计缓存的使用情况,便于分析和提高缓存合理资源的分配。
设计如下:
缓存中间件内部使用一致性哈希算法实现分布式。设置的虚拟节点能均匀分布。
缓存中间件暂时只实现Redis,MemoryCache做为缓存服务。后期应该会实现CacheBase
缓存中间件后期会提供配置服务,方便管理缓存服务配置,以及显示一些状态信息
5.2 EventBus中间件设计
设计目标:
- 基于发布/订阅的模式异步传递消息。
- 集成第三方消息中间件,如:MSMQ,Rabbitmq
- 实现基于发布/订阅的异步通知
设计如下:
1.publisher: 是发布者把消息事件Event通过Event Bus 发布到Topic
2.Event bus::是事件总线,对于publisher 和 Subscriber 之间进行解耦,找到已经注册的事件订阅者,分发消息事件Event发送到topic的消息
3.Topic: 是消息路由,对于订阅者以广播的形式,让在线的Subscriber接收消息事件。
4.Subscriber:是订阅者, 收到事件总线发下来的消息。即Handle方法被执行。注意参数类型必须和发布者发布的参数一致。
5、总结
surging 0.0.0.1版本还有很多需要完善的地方,比如路由容错,服务降级、熔断,监控平台和配置服务平台,以及后续的第三方中间件的集成,这些任务都已经规划到日程,再不久的将来会看到1.0稳定版本的发布 ,如有兴趣可以加入QQ群:615562965
剥析surging的架构思想的更多相关文章
- [转载]剥析surging的架构思想
1.前言 2.通信机制 2.1 简介 在单体应用中,模块之间的调用通信通过引用加载方法或者函数来实现,但是单体应用最终都会因为团队壮大,项目模块的扩展和部署等出现难以维护的问题.随着业务需求 ...
- ReactiveCocoa常见操作方法介绍/MVVM架构思想
1.ReactiveCocoa常见操作方法介绍. 1.1 ReactiveCocoa操作须知 所有的信号(RACSignal)都可以进行操作处理,因为所有操作方法都定义在RACStream.h中, ...
- iOS swift的xcworkspace多项目管理(架构思想)
iOS swift的xcworkspace多项目管理(架构思想) 技术说明: 今天在这里分享 swift下的 xcworkspace多项目管理(架构思想),能为我们在开发中带来哪些便捷?能为我们对整 ...
- 前端笔记之NodeJS(四)MongoDB数据库&Mongoose&自制接口&MVC架构思想|实战
一.MongoDB数据库 1.1 NoSQL简介 随着互联网web2.0网站的兴起,传统的SQL数据库(关系数据库)在应付web2.0网站,特别是超大规模和高并发的SNS(social network ...
- 『练手』005 Laura.SqlForever历史遗留 的 架构思想缺陷
005 Laura.SqlForever历史遗留 的 架构思想缺陷 我们 比较一下 Laura.WinFramework 和 Laura.XtraFramework 的差异: Laura.WinFra ...
- Restful架构思想
java作为一门后端语言,其厉害之处在于web,大家比较熟知的各种网络应用,java都能做,那么在这个移动优先的时代,如何继续发挥java的强大呢.通常是让java作为一个app的服务端,为app客户 ...
- 对SOA架构思想的一些说明(转)
出处:http://kb.cnblogs.com/page/510698/ 从纵向到横向 传统业务系统的构建更多的是竖井式的纵向思想,这个主要是从单个业务系统孤立来看都是垂直应用.那么SOA架构的视角 ...
- 架构思想之CAP原理
由于自己负责后端的设计已经有一段时间,对设计的一些思想和理论有一些理解,但最近被问到什么是CAP时,却一脸懵逼,下来后专门针对CAP架构思想进行了一些专题学习,在这里也将这个概念引入给大家,大家可以有 ...
- SpringMVC的项目架构思想
SpringMVC的项目架构思想 一.DO和Model的区别 DO是对数据库表的映射.Model是处理业务逻辑的模型(领域模型).例如:用户信息表和用户密码表分别是两个DO,但是对于实体用户来说,密码 ...
随机推荐
- .net Core1.0 邮件发送
今天一天早,公司需要将之前的.net Core项目增加一个预处理机制,就是当程序出现异常后给我们的开发人员发送邮件,因为今天写些关于.netCore上发送邮件. 根据查阅资料发现在目前的Core1.0 ...
- node使用消息队列RabbitMQ一
基础发布和订阅 消息队列RabbitMQ使用 1 安装RabbitMQ服务器 安装erlang服务 下载地址 http://www.erlang.org/downloads 安装RabbitMQ 下载 ...
- 动手写个数字输入框1:input[type=number]的遗憾
前言 最近在用Polymer封装纯数字的输入框,开发过程中发现不少坑,也有很多值得研究的地方.本系列打算分4篇来叙述这段可歌可泣的踩坑经历: <动手写个数字输入框1:input[type=nu ...
- Mac苹果系统 多系统启动:The rEFInd Boot Manager
苹果系统 多系统启动 下载安装REFIT: 首先安装一下:REFIT, 在这个页面下载: http://refit.sourceforge.net/#download 选择mac disk image ...
- Winform调用WebKitBrowser,基于chrome内核WebKit的浏览器控件
在C#中,默认的WebBrowser控件默认使用的是IE的core,而IE的种种遭人吐槽的诟病使我不敢轻易使用WebBrowser,因此,打算使用Chrome的内核替换IE.Chrome的内核使用的是 ...
- 使用HAL库函数建立STM32F2工程
一.建立一个新的文件夹,新建三个文件夹User.Driver.Project,还可以加一个Doc存放工程的相关说明等等. 1.将STM32F2xx的库函数(HAL函数库)中的Drivers文件夹中的所 ...
- [Leetcode] Binary tree Zigzag level order traversal二叉树Z形层次遍历
Given a binary tree, return the zigzag level order traversal of its nodes' values. (ie, from left to ...
- IntelliJ IDEA 2017.1.4 x64配置说明
只是为了研究下idea这款编译器怎么使用.开门见山,说下如何配置这款编译器,不配置也能用,但是强迫症表示不服.下面直入正题: 下载与安装就不说了,除了更改安装目录外,没啥注意的地方,建议下载idea去 ...
- php调用java
PHP调用JAVA方式 1. 背景 在开发招商银行信用卡分期付款功能过程中,在支付成功之后需要对银行的返回数据进行签名验证,因签名加密方式招商银行是不提供的,只提供了相应的JAVA验证类测试例 ...
- Java基本之数据类型
一.创建一个简单的Java应用程序 public class Code { public static void main(String[]args) { System.out.println(&qu ...