如何用Node.js开发memcache协议的反向代理服务器
沉沙 2018-06-27 来源 : 阅读 1031 评论 0

摘要:memcache是常用的key-value缓存解决方案,它的协议也被用于nosql数据库tokyo tyrant。希望阅读本篇文章以后大家有所收获,帮助大家对Node.js的理解更加深入。

memcache是常用的key-value缓存解决方案,它的协议也被用于nosql数据库tokyo tyrant。

在实际项目中,出于负载均衡等考虑,php、java等客户端需要访问多个memcache,将一个对特定key的请求map到特定的memcache上。但这样就需要在每个客户端配置多个ip地址并实现map的算法,不便于管理和维护。最近正好在学习node.js,于是决定用node.js搭一个node.js的反向代理。对php、java等客户端,实现与memcache相同的协议。将客户端的请求,根据请求的key值分别转发到后端的数个memcache上。

node基于v8和libevent开发,主要思想是用单线程+事件循环(event loop),来实现异步io服务器。这种模式类似于nginx,比起传统的多进程(例如apache的prefork模式)或者线程(例如tomcat等app server),速度更快。

纯异步io的服务器实现有很多复杂的因素要考虑,有了错误也难以调试。使用node可以让你从繁琐的内存处理等底层工作中解放出来,把精力都花在关注你的核心的模型和应用逻辑。

用node实现一个socket server是非常容易的,如下代码即可实现简单的echo server:

1. server=net.createServer(  
2.     function(socket) {  
3.         socket.on('data',function(data){  
4.             //这个this就是socket  
5.             this.write(data);  
6.         });  
7.     }  
8. ).listen(port_number);

由于要根据请求的key值接收和分发memcache请求,需要对收到的data做解析请求的操作。接着根据请求的key决定采用哪一个memcache,然后将请求写入memcache连接。当memcache连接收到数据时,将数据写回客户端socket,代理的基本流程就结束了。

1. socket.on('data',function(data){  
2.         var request=mk_request(data);  
3.         var mc=create_memcache_conn(request.key);  
4.         mc.write(request);  
5.         mc.on('data',function(data){  
6.                 socket.write(data);  
7.             });  
8.     });

值得注意的是,由于node异步的特性,收到的data可能比一个请求数据少,或者比一个请求数据多,或者包含好几个请求,都是有可能的,剩下的数据需要加入到下次收到的data之前,才能保证接收请求没有问题。于是程序修改为如下结构:

1. function process_request(socket,request){  
2.     var mc=create_memcache_conn(request.key);  
3.     mc.write(request);  
4.     mc.on('data',function(data){  
5.             socket.write(data);  
6.         });  
7.    
8. }  
9.    
10. socket.on('data',function(data){  
11.         do{  
12.             //将之前剩下的数据与新收到的数据合并  
13.             data=new Buffer(this.remain_data,data);  
14.             //如果mk_request没解析出一个完整的请求,就返回false  
15.             var request=mk_request(data);  
16.             this.remain_data=data.slice(request===false?0:request.length);  
17.             process_request(this,request);  
18.         }while(request);  
19.    
20.         });

但改成这样之后,测试结果还是有问题。这是因为客户端有可能一次发多个请求到服务器端,服务器端使用多个memcache连接处理这些请求,在memcache连接的ondata中写回客户端的时候,无法保证写回的顺序与请求的顺序一致,导致出错。所以需要有一个队列来保证写回数据的顺序。

1. function process_request(socket,request){  
2.     var mc=create_memcache_conn(request.key);  
3.     mc.write(request);  
4.     mc.queue.push({req:request,res:false});  
5.     mc.on('data',function(data){  
6.             //收memcache响应也有和收客户端请求一样的问题,可能一次收到一半的请求  
7.             data=new Buffer(this.remain_data,data);  
8.             //如果mk_response没解析出一个完整的响应,就返回false  
9.             var response=mk_response(data);  
10.             if(response){  
11.                 //接收完一个响应,先将响应加入队列  
12.                 for(var i=0;i0){  
13.                     if(socket.queue[0].res){  
14.                         socket.write(socket.queue.shift().res.buffer);  
15.                     }else{  
16.                         break;  
17.                     }  
18.                 }  
19.                 this.removeListener('data',arguments.callee);  
20.             }  
21.         });  
22. }

另外需要实现mk_request和mk_response这两个函数,实现是基于memcache的协议,memcache的协议还是比较简单的。

在最终实现中,还加入了memcache连接池的功能,因为建立memcache连接需要花费的时间是很长的,memcache的文档中也建议与服务器保持长连接,以加快效率。


本文由职坐标整理并发布,了解更多内容,请关注职坐标WEB前端Node.js频道!

本文由 @沉沙 发布于职坐标。未经许可,禁止转载。
喜欢 | 0 不喜欢 | 0
看完这篇文章有何感觉?已经有0人表态,0%的人喜欢 快给朋友分享吧~
评论(0)
后参与评论

您输入的评论内容中包含违禁敏感词

我知道了

助您圆梦职场 匹配合适岗位
验证码手机号,获得海同独家IT培训资料
选择就业方向:
人工智能物联网
大数据开发/分析
人工智能Python
Java全栈开发
WEB前端+H5

请输入正确的手机号码

请输入正确的验证码

获取验证码

您今天的短信下发次数太多了,明天再试试吧!

提交

我们会在第一时间安排职业规划师联系您!

您也可以联系我们的职业规划师咨询:

小职老师的微信号:z_zhizuobiao
小职老师的微信号:z_zhizuobiao

版权所有 职坐标-一站式IT培训就业服务领导者 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
 沪公网安备 31011502005948号    

©2015 www.zhizuobiao.com All Rights Reserved

208小时内训课程