网络服务器架构模式

前段时间做了个简单的dtwisted项目,只有个雏形,高层点的东西就没有了。

以前用ACE做过小型游戏服务器、视频转发服务器,比较熟悉点的是reactor模式。其间也尝试过proactor,一知半解不得要领,于是放弃了。

今天工作闲暇尝试用D语言实现目前工作中用到的文件上传服务器,有了一些思考。

下面还是先为D语言做点广告。稍后回来。。。

自从用了D语言以后,我可以更加方便地尝试一些想法了,用C/C++实现很多东西都比较麻烦,而且即便实现出来也必定有许多看不过眼的东西和实现方式。使用C++开发有几年了,从我接触的同事实现的代码来看,包括我自己的代码,基本上没有能让我看过以后觉得“还行”的代码,光是Big Three就够伤脑筋的了。使用D语言以后,我自己觉得要考虑的细节少多了,更多时候我是在考虑如何架构。从开发效率上来讲,D已经足够快了,我甚至觉得已经不比一些脚本语言慢。从维护成本和运行效率上来讲,它都足以让你满意。

欢迎回来。。

通常网络服务器在并发连接比较少的时候,根本不需要考虑得太多,我们可以用单线程select+阻塞操作,也可以单线程+非阻塞,还可以多线程(每连接一线程或是线程池都不麻烦)。当并发连接数比较多的时候,几个问题就出来了:

1、单个连接传输效率下降。这个可能不光是并发数多引起的,也可能是外网带宽引起的。
2、连接数过多。每连接一线程导致线程开销过大,过多的线程同时操作可以引起IO性能急剧下滑。用线程池阻塞方式处理?可能几个慢客户就拖慢了整个服务器,实际上服务器并无负担,但线程全被占用。
3、文件上传服务器每个客户占用时间都比较多,采用每连接一线程可能导致每个客户传输效率都下降,采用线程池又只能同时处理有限的连接数。

以上几个问题在使用reactor模式后大部分可以解决掉。reactor的基本方式是使用事件方式,可以单线程处理所有连接,由于它只处理有事件的socket,所以不会长时间占用线程。如果在业务逻辑中有耗时操作,或者是IO等待,还可以实现多线程的reactor,相当于是实现了一个线程池,同时又没有上面所说的线程方式的缺点。

回到今天的试验,打算用dtwisted实现目前的文件上传服务器。文件上传服务器目前是基于短连接的,每个连接建立以后,发送一个包头。这个包头是通用格式,首先是包头长度,有了它就可以解出完整的包头,包头里面包含上传路径、文件长度和文件签名。

使用dtwisted,直观的实现方式是从Protocol上先实现一个通用的解包头的类,所有需要解包头的协议都从它上面派生。dataReceived方法里面先判断包头长度是否已经收齐,通常这要占用2-4字节。如果收齐了长度,就进入收包头状态,直到包长度收完,然后开始处理包。由于包类型可能有多种,方便以后扩充,所以从收取包到解出包头都是一个同样的模式,写成一个基类供业务逻辑类派生使用。

目前为止这个模型是合理的,我甚至把消息类都写成接口,这样不同的解包方法都可以兼容。

不过接下来一个需求打乱了这个过程。上传消息和其它几个消息不一样的地方,是包头后面直接附加了文件内容。由于前面进行了封装,所以包的处理方法的参数就是包对象,不再包含socket或transport对象,使得接收文件内容有了麻烦。当然我也可以直接调用transport来收取,但总觉得这样和基类实现依赖太高。同时这个模式还有几个缺点:
1、dataReceived要处理当前状态,这种状态的处理增加了复杂度。
2、即便可以直接调用transport来收取文件,但由于是单线程,这会导致所有其它客户都会被阻塞,违背了使用reactor的本意。
3、类层次过多,每个层实现的功能太少。

基于这几个缺点,于是想到另一种实现方式。在连接建立时,服务器发起一个读请求,指示该读取4字节(包长),并传递一个处理方法委托。当该连接收齐这4字节时,调用处理方法。这个处理方法把这4字节转成包长,接着发起一个读请求,指示该读取这么多字节的包内容。再一次收齐时,就开始解包及处理过程。如果收到的是上传消息,发起一个读取文件内容的请求,指示读取指定长度,比如是40k。在读取到文件内容以后,调用处理方法写入文件。当然一次收齐40K才处理也不合理,但收包头的过程中又希望它收齐才处理,于是在发起读请求时指定一个参数,说明是全部读取完毕才处理,还是有一点就处理一次。

上面这个过程基本上是状态方式的一种升级,发起请求就包含了这个状态,只不过现在是隐式的和看起来更合理的。

终于整个过程合理了。仔细想了一下,这不就是proactor吗?proactor本身的实现还可以优化,只有发起过读请求的连接才会加入到事件检查中,效率上可能会有优化。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值