nodejs项目小总结(转)
1.url的处理
querystring.parse(urlObj.query)可以把url内的query参数转为字符串
JSON.parse可以把字符串转为json
2.异步与同步
我的项目大约是这样的
接受url请求并处理-解析-去拿到环境变量与参数。
等待上面的请求ok后,并发请求,使用上面的环境变量与参数去调用php与webredis
同步异步交织在一起,很蛋疼。
不过接下来使用了eventproxy进行处理,非常好用~
https://github.com/JacksonTian/eventproxy
一个非常典型的代码
1 ep.all('tpl', 'data', function (tpl, data) { 2 // 在所有指定的事件触发后,将会被调用执行 3 // 参数对应各自的事件名 4 }); 5 fs.readFile('template.tpl', 'utf-8', function (err, content) { 6 ep.emit('tpl', content); 7 }); 8 db.get('some sql', function (err, result) { 9 ep.emit('data', result); 10 });
那么注意下面两个函数,一定要保证callback执行,emit才会触发。
当all内事件都触发后,返回值作为参数,触发ep.all内的callback
更多的使用方法可以参考api。
3.nodejs发送post
1 var http = require('http'); 2 var querystring = require('querystring'); 3 4 var post_data = querystring.stringify({ 5 sys_text : '构造字符串”欢迎回来,道客'+cellphone.slice(cellphone.length-4,cellphone.length)+',您的语镜已经连接系统,请安全驾驶', 6 interval : '1440', 7 agent: '超级管理员', 8 userid :userid, 9 }); 10 11 var options = { 12 host:'192.168.1.3', 13 port:8080, 14 path:'/idts-1.0/httpservice/addweibo/php/add_sys_weibo.php', 15 method:'post', 16 headers: { 17 'Content-Type': 'application/x-www-form-urlencoded', 18 'Content-Length': post_data.length 19 } 20 }; 21 22 var req = http.request(options, function (res) { 23 console.log("Got response: " + res.statusCode); 24 res.setEncoding('utf8'); 25 res.on('error',function (e) { 26 console.log("Got error: " + e.message); 27 }).on('data', function (chunk) { 28 console.log('BODY: ' + chunk); 29 }); 30 }); 31 req.write(post_data + "\n"); 32 req.end(); 33 }
上面是整个发送post的流程。那么注意一点一定要指定content-length头。否则会报错。ngix会报类似411 length required 这样的错误。
之后只需要利用req.write向接收端写消息体即可。
至于nodejs发送get,可以直接使用http.get方法
相关的api http://docs.cnodejs.net/cman/http.html
3月13日更新
经过大牛snoopy的对代码的斧正,发现了几个问题
1.异常处理,JSON.parse可能会抛异常,因此需要处理
1 try { 2 var cellphone = JSON.parse(result).MGET[0] 3 } catch (e) { 4 // console.log(e.name); // "MyError" 5 // console.log(e.message); // "MyError" 6 console.log('数据格式不正确') 7 }
2. 拼接chunk
在接收服务端的数据时,若数据较长,直接在data监听可能会收到多次chunk。
利用字符串拼接chunk时,因为编码等问题,可能出现错误,因此建议用数组拼接
见这篇文章 http://cnodejs.org/topic/4faf65852e8fb5bc65113403
1 var chunks = []; 2 var size = 0; 3 res.on('data', function (chunk) { 4 chunks.push(chunk); 5 size += chunk.length; 6 }); 7 res.on('end', function () { 8 var data = null; 9 switch(chunks.length) { 10 case 0: data = new Buffer(0); 11 break; 12 case 1: data = chunks[0]; 13 break; 14 default: 15 data = new Buffer(size); 16 for (var i = 0, pos = 0, l = chunks.length; i < l; i++) { 17 var chunk = chunks[i]; 18 chunk.copy(data, pos); 19 pos += chunk.length; 20 } 21 break; 22 } 23 });
思路就是上面的代码,我也使用了文中提到的bufferHelper。
另外snoopy说可以使用0.10的stream2,等下次尝试。
3.多核
nodejs里内置了cluster模块,可以大大提高机器资源的使用
利用cluster做的多核
1 function start(handle) { 2 var http = require("http"); 3 var cluster = require('cluster'); 4 var http = require('http'); 5 var numCPUs = require('os').cpus().length; 6 if (cluster.isMaster) { 7 for (var i = 0; i < numCPUs; i++) { 8 cluster.fork(); 9 } 10 cluster.on('death', function (worker) { 11 console.log('worker ' + worker.pid + ' died'); 12 cluster.fork(); 13 }); 14 } else { 15 function onRequest(request, response) { 16 var options = { 17 host:'192.168.1.6', 18 port:7379, 19 path:'/SADD/' + 'niaAOVU2lg' + ':config/' + '2013-03-09' + Math.random(), 20 method:'get' 21 }; 22 var req = http.get(options, function (res) { 23 // console.log("Got response: " + res.statusCode); 24 res.on('error',function (e) { 25 // console.log("Got error: " + e.message); 26 }).on('data', function (chunk) { 27 // console.log('BODY: ' + chunk); 28 }); 29 }); 30 req.on('error', function (e) { 31 // console.log("Got error: " + e.message) 32 }) 33 req.end() 34 response.writeHead(200, {'Content-Type':'text/html'}); 35 response.end() 36 } 37 38 var server = http.createServer(onRequest).listen(8888); 39 } 40 } 41 42 exports.start = start;//定义模块给外面的函数
经过性能测试,8核的机器跑满了能达到以前的八倍。。。(8个同时跑嘛。。)
还有个问题
1 var req = http.request(o, function (res) { 2 var rec_leng = 0; 3 var rec_ary = []; 4 // res.setEncoding('utf8'); 5 res.on('error',function (e) { 6 console.log("Got res error: " + e.message); 7 }).on('data', function (chunk) { 8 rec_leng += chunk.length; 9 rec_ary.push(chunk); 10 /* 11 * if(rec_leng > postLimit){ 12 rec_ary = null; 13 req.connection.destroy() 14 } 15 * */ 16 }).on('end', function () { 17 var buf = Buffer.concat(rec_ary, rec_leng); 18 var result = buf.toString(); 19 callback.call(this, result); 20 }); 21 })
注意setEncoding转换的时候,会把2进制转成string buffer的concat会出错,所以两个不要一起用。