[关闭]
@stkevintan 2015-05-15T17:42:04.000000Z 字数 2560 阅读 750

LBS匿名代理服务器原理简述


为什么选用Node.js

因为匿名代理服务器为了混淆用户的真是地理信息,往往会产生很多没有实际作用虚假信息。因此,代理服务器需要接收和发出的http IO会比一般情况的要多。而Node.js正好有着出色的异步IO性能。非常适合本项目。

项目分析

  1. 接收来自客户端的查询信息,传递给匿名器进行处理:
  1. router.post('/', function (req, res, next) {
  2. psEncrypt(req.body, function (err, sres) {
  3. ...
  4. res.send(result);
  5. }

2.匿名器查询历史数据库

  1. var searchHis = function (psmodel, callback) {
  2. psDB.findOne(psmodel.toEntity({
  3. result: {$exists: true}
  4. }), function (err, doc) {
  5. callback(err, psmodel, doc);
  6. });
  7. }

3.如果没有相同的历史记录,则将该数据存入数据库,等待分解重构算法处理。

  1. var storeRec = function (psmodel, doc, callback) {
  2. if (doc) {
  3. debug.log('not through storeRec');
  4. callback(null, doc);
  5. } else if (psmodel.mark.on) {
  6. psDB.findOne(psmodel.toEntity({
  7. result: {$exists: false}
  8. }),function(err,doc){
  9. err && callback(err);
  10. if(doc)delaycb(null,doc);
  11. else{
  12. psDB.create(psmodel.toEntity(),delaycb);
  13. }
  14. });
  15. } else {
  16. debug.log('Not to Encrypt,Get Data from Server');
  17. psmodel.handle(psDB, function (err, res) {
  18. callback(err, {result: res});
  19. });
  20. }
  21. function delaycb(err,doc){
  22. setTimeout(function () {
  23. callback(err, doc);
  24. }, config.ResponseTimeOut);
  25. }
  26. }

4.经过ResponseTimeOut的时间之后,查看该条数据是否被处理,否则,直接发出请求

  1. var doWork = function (doc, callback) {
  2. if (doc && doc.result) {
  3. debug.log('Not Via doWork');
  4. callback(null, doc.result);
  5. } else psDB.findById(doc._id, {
  6. _id: 0,
  7. timestamp: 0,
  8. __v: 0
  9. }, function (err, _doc) {
  10. //debug.log(_doc.toJSON());
  11. if (err) callback(err);
  12. else if (_doc.result) {
  13. debug.log('Not via Superagent');
  14. callback(null, _doc.result);
  15. } else {
  16. //Get Data from Server
  17. debug.log('_doc',_doc);
  18. new psModel(_doc).handle(callback);
  19. }
  20. });
  21. }

5.分解重构算法
1)设定一个数据库守护进程,每隔特定时间处理数据库中未被处理的请求。

  1. setInterval(function () {
  2. //debug.log('start to check database');
  3. tot=db.search({result:{$exists:false}});
  4. if(tot>k){
  5. //refactor and group
  6. ...
  7. }
  8. }, config.DaemonInterval);

2)将得到请求数组重构,通过dfs将参数分解。

  1. colArray=[arg1,arg2,arg3,arg4];
  2. async.eachLimit(tasks, limit, function (item, callback) {
  3. item.forEach(function (item) {
  4. colArray.forEach(function ($) {
  5. ref[$].push(item[$]);
  6. });
  7. });
  8. // unique Array
  9. colArray.forEach(function ($) {
  10. ref[$] = utils.unique(ref[$]);
  11. });
  12. //refactor
  13. dfs(0, {});
  14. }, function (err) {
  15. err && debug.log('refactor error!', err);
  16. });

3)将分解后的数组按照K等级进行重组

  1. var group = function (k, total, contain) {
  2. var c = total / k;
  3. var r = total % k;
  4. if (c < r) return;
  5. //r:(k+1) c-r:k
  6. var ret = [];
  7. var index = 0;
  8. var alloc = [{unit: r, num: k + 1}, {unit: c - r, num: k}];
  9. alloc.forEach(function ($) {
  10. for (var i = 0; i < $.unit; i++) {
  11. var buk = [];
  12. for (var j = 0; j < $.num; j++) {
  13. buk.push(contain[index++]);
  14. }
  15. ret.push(buk);
  16. }
  17. });
  18. return ret;
  19. }

4.将重组后的新的请求数组使用异步并行的方式向百度地图服务器发出请求,得到结果:

  1. superagent.get(serviceUrl)
  2. .query(querys)
  3. .end(function (err, res) {
  4. callback(err, res.text);
  5. //update database
  6. if (db) {
  7. db.update(
  8. entitys,//update criteria
  9. {$set: {result: res.text}},//update action
  10. {upsert: true, multi: true},//update option
  11. function (err) {
  12. err && debug.log('database update error!');
  13. });
  14. }
  15. });
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注