随笔-77  评论-750  文章-51  trackbacks-22

分布式系统设计原理与方案

  一直在思考分布式系统设计的问题,业务对象原封不动的情况下部署在客户端和服务器端,可以根据配置文件选择是连接服务器还是连接本地的数据库,这个问题让我绞尽脑汁,我总是设想的客户端与服务器端通信的方式是最低端的Socket。花了两个晚上研究CSLA.NET框架关于数据门户这块代码,才发现问题的关键所在:客户端与服务器端通信不能采用最低端的Socket,而要用高端的WebService、.NET Remoting或者是自己定义一种协议等,只要它们支持客户端直接根据服务器端的服务URL、类名、方法名和方法参数四个信息就可以调用服务器对应的类和方法就行。

说明:本文中所表达的思想与CSLA.NET有很大区别,不要看了本文就以为是CSLA.NET的设计思想,也不要以为本文错误的解释了CSLA.NET,这不是一篇介绍CSLA.NET的文章,但纯思想上它们是相同的。

  • 分布式系统的部署

  平常我们都说三层架构,我认为它是一个广义的模型,更多层的设计可以合并相邻几层的方式最终回归到三层这个宽泛的概念上来,我的意思是:这些都只是概念,忘记这些概念去实际分析设计会离这些概念更近一些。

  接下来我要把三层变的更简单点,两层,数据访问层合并到业务层,统称为业务层,因为我们面对的问题不是分层的问题,而是分布式系统中各层应该怎么部署的问题。在CSLA.NET书中也说到业务层和数据访问层放到同一台机器上可以提高性能和容错性。因此他们俩的合并不影响分布式系统的部署。

  不过要解释的是数据库系统(CSLA.NET中说的数据存储和管理层)并没有考虑到三层中来,也就是它不包含在数据访问层中,如果把它算进来,那么它是在数据访问层之下单独存在的。

  综上,在分布式系统部署角度考虑的分层实际是三层:界面层、业务层(包含数据访问层的业务层)、数据存储层。

  下面举例说明可能的部署情景,带阴影的框框表示一台机器,虚线框表示根据使用场合可有可无,虚横线表示从此处划开单独出服务器。在B/S应用中,Web浏览器为客户端,其他全部为服务器。在C/S应用中,处在最上层的界面层+业务层为客户端,其他为服务器

非分布式系统的部署

单机版

单机版

 

分层2

两三台机器

分布式系统的部署

分层3

分布式的Web系统

 

分层4

分布式的C/S系统

有几点要说明:
1. 客户端上的验证等业务逻辑是不可信的,因此任何一种部署都需要服务器端包含业务层;
2. 为了开发、维护和部署中的高度可伸缩性,图中的各业务层所包含的代码都是一模一样的;
3. 因为第2点,所以我遇到了业务层的同一个操作是与其他机器上的业务层通信还是访问数据库这个难题。

解决业务层的数据访问问题

  这个问题是关键问题,也就是上面几点说明中的第3个问题,为了解决这个问题我们引入数据门户的概念。

  下面以WebService为例说明:界面层访问本机的业务对象的增删改查中的“查”方法时,跳过数据库的查询操作,访问另一台机器中的同一个业务对象类的“查”方法。

请求

  以上是向另一台机器发送请求,该请求并不直接调用另一台机器上的业务对象类的“查”方法,而是将要调用的业务对象和方法参数信息转为一个“二进制包”,作为参数去调用另一台机器上通用的“查”方法,另一台机器上的“查”方法再解开这个包,然后去调用解开的包中所表示的业务对象类型,下面的静态图是另一台机器接受到请求后的工作。

响应

又有些说明:
1. 关于原理都已在图中做了描述,不另写大段文字解释了;
2. 上面两个图中,除了“实际业务对象类”以外的部分全部属于架构或者框架部分;
3. 如果用OO的思想去审查上面的两个图,你一定会为这糟糕的设计而抱怨,这里只是为了尽可能简单的表述分布式系统的工作原理,你可以采用策略模式使数据门户不改变的情况下适应各种请求响应场合,采用工厂模式实现不同的请求响应场合的切换。

 

 关于数据库的分布

  为了解决数据库服务器的负担,我们可能希望把数据分布存储在多个服务器上,我设想的数据库分布方案是,各服务器上的数据库在结构上一模一样,而表里的数据存储到不同服务器上,这样数据访问层在查数据的时候分别向所有数据库服务器发送同样的sql命令,然后数据访问层得到数据后整合,这样减轻每台服务器的工作量。亦或者根据表里的某个代表性的字段(如:省份)分布数据到不同服务器。

作者:Rick Carter
出处:http://pains.cnblogs.com/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

posted on 2011-06-06 05:25 Rick Carter 阅读(2411) 评论(17) 编辑 收藏

评论:
#1楼 2011-06-06 08:17 | kesking[未注册用户]
2. 为了开发、维护和部署中的高度可伸缩性,图中的各业务层所包含的代码都是一模一样的;


不理解,为什么这么复杂啊。业务层有一个地方有就够了吧,加一个业务接口层,客户端通过服务端暴露出来的业务层接口来调用就行了。

 回复 引用   
#2楼 2011-06-06 08:35 | 李磊(leige)      
楼主好早啊,
 回复 引用 查看   
#3楼 2011-06-06 11:23 | 检全      
这么说分布式解决方案还是没有大家一致认可的办法呗?我最近想研究研究一个大型的系统应该如何设计?楼主是否有这方面的建议?
1)单台服务器如何提高性能?
2)服务器集群部署问题?
3)数据库服务器如何部署?

 回复 引用 查看   
#4楼 2011-06-06 11:38 | 大石头      
楼主有自己的想法,支持!
只是不同意楼主所设想的做法

 回复 引用 查看   
#5楼[楼主] 2011-06-06 13:56 | Rick Carter      
@kesking
我的想法就是把这种客户端与服务器端的调用工作放到架构里去,让开发人员只需去关心软件的实际业务需求,而不用关心自己写的代码是运行在客户端还是服务器端,当然如果是简单的软件不存在分布部署的问题就不需要这样做了。

 回复 引用 查看   
#6楼[楼主] 2011-06-06 13:58 | Rick Carter      
@李磊(leige)
我这叫很晚,现在快下午两点了才起床才叫好早,哈哈。

 回复 引用 查看   
#7楼[楼主] 2011-06-06 14:19 | Rick Carter      
@检全
1.如果确定以后系统只可能是单台服务器上运行,当然这篇文章的做法是不可取的。
2.服务器集群部署,就像文章中说的一样,业务层不做任何改变部署到服务器集群中,每个服务器都具有访问数据存储层服务器的权利,就是图中与数据存储层服务器相连的业务层服务器(带虚线框的那个)去掉,这样实现负载平衡,对这个服务器集群的调用采用某个算法,比如:第一次请求是调用集群中的第一台,第二次调用第二台...
3.数据库服务器之间没有直接的关系,但数据访问层访问所有数据库服务器,这样单台数据库服务器在处理大数据量时候的执行时间分摊到每台数据库服务器上,这样来提高性能。

 回复 引用 查看   
#8楼[楼主] 2011-06-06 14:24 | Rick Carter      
@大石头
为了让开发人员只需去关心软件的实际业务需求问题,这就是我的想法,每个人想法和做法都不同吧,呵呵。

 回复 引用 查看   
#9楼 2011-06-07 11:51 | 模模      
我使用的分层
1.Client(可以是WebForm,也可以是Winform)
2.ClientProxy(实现服务端与客户端调用接口的映射)
3.IBLL
4.BLL(主要业务逻辑)
5.IServices(服务接口层,开放客户端调用接口,由ClientProxy统一调用)
6.RemotingServices(IServices的Remoting实现层,调用IBLL组织服务接口中的业务逻辑,当然可以用WebService或WCF)
7.Entities(实体,数据表的映射,贯穿各层)
8.DAL(数据访问层,用工厂模式实现各数据库统一的访问方式)
9.Hosting(业务服务层,服务承载的地方,可以是IIS,我选用Window服务)

客户端调用过程由2.ClientProxy直接代理,所以客户端不需要关心具体是WCF还是Webservice还是Remoting。同时因所有的调用都由2.ClientProxy处理,所以可以在此处直接做软负载均衡

客户端使用方法
UserInfo user = PL.RemObj.Framework.QueryUser(userId);
bool created = PL.RemObj.Framework.CreateUser(user);
bool updated = PL.RemObj.Framework.UpdateUser(user);
bool deleted = PL.RemObj.Framework.DeletedUser(user);
DataTable dt = PL.RemObj.Framework.QueryUsers(param);

 回复 引用 查看   
#10楼[楼主] 2011-06-07 12:05 | Rick Carter      
@模模
嗯,道理差不多。
我的想法的目的只有两个:
1.让业务开发人员只需要关系业务的实现;
2.让每一层都可以不修改代码的情况下部署到任何位置,只要改配置就行。

 回复 引用 查看   
#11楼 2011-06-07 15:29 | chenlulouis      
引用Rick Carter:
@检全
1.如果确定以后系统只可能是单台服务器上运行,当然这篇文章的做法是不可取的。
2.服务器集群部署,就像文章中说的一样,业务层不做任何改变部署到服务器集群中,每个服务器都具有访问数据存储层服务器的权利,就是图中与数据存储层服务器相连的业务层服务器(带虚线框的那个)去掉,这样实现负载平衡,对这个服务器集群的调用采用某个算法,比如:第一次请求是调用集群中的第一台,第二次调用第二台...
3.数据库服务器之间没有直接的关系,但数据访问层访问所有数据库服务器,这样单台数据库服务器在处理大数据量时候的执行时间分摊到每台数据库服务器上,这样来提高性能。


我觉得楼主这个分布式系统架构没有考虑到重点,每个大型分布式系统有业务缓存数据,你2中用到的服务器集群根本没考虑在不同机器上业务缓存数据的同步问题。

 回复 引用 查看   
#12楼[楼主] 2011-06-07 15:56 | Rick Carter      
@chenlulouis
依靠数据库的触发器或者在数据库上再加一层,再或者让数据访问层去通知其他机器等等吧。
不过这并不能算分布式系统的重点吧,不过本人对分布式系统数据缓存的同步没想清楚,呵呵,谢谢指导,回去研究下。

 回复 引用 查看   
#13楼 2011-06-07 16:55 | chenlulouis      
@Rick Carter
呵呵 这个是个大工程啊主要要代码层面支撑而且基本做不到实时,想好了通知下哈 哈哈

 回复 引用 查看   
#14楼[楼主] 2011-06-07 17:09 | Rick Carter      
@chenlulouis
之前实现过单机的数据缓存功能,采用not in的方式避免从数据库重复查缓存已有的数据,但还有个数据顺序的问题,另外数据库如果在本机的情况下缓存几乎没性能提升,可能取缓存那块代码还有待优化。
分布式的缓存同步问题恐怕我想不来了,缓存本来是为了性能,但弄的复杂了程序也可能会复杂,反而降低性能就不好了,呵呵。

 回复 引用 查看   
#15楼 2011-06-09 18:00 | 龚安川      
看不懂,太高深了。。。
 回复 引用 查看   
#16楼 2011-08-03 22:41 | penguin7006      
宝贝:我是你的老婆,你很棒,我爱你
 回复 引用 查看   
#17楼 2011-11-03 15:40 | 风雨者2      
@penguin7006
哦,你好厉害啊!

 回复 引用 查看   
发表评论

昵称: [登录] [注册]

主页:

邮箱:(仅博主可见)

评论内容:

  登录  注册

[使用Ctrl+Enter键快速提交评论]

0 2073482 tsChbci88wg=