onvno / pokerface

日常技术文章阅读整理
3 stars 0 forks source link

20190613 - Node接口转发及流Stream,Pipe #41

Open onvno opened 5 years ago

onvno commented 5 years ago

流是Node中常用的概念,在查找Node接口转发寻找比较好的方案时,针对源码做了了解 目前项目使用的是:koa-better-http-proxy

koa-better-http-proxy

请求使用了Node自带的httphttps包 缺点:

  1. 多个proxy,会多次匹配 2.请求不是转发,是获取值结果后再返回Container.proxy.resData = Buffer.concat(chunks, chunkLength(chunks));
    
    # sendProxyRequest
    return new Promise(function(resolve, reject) {
    var protocol = Container.proxy.requestModule;
    var proxyReq = protocol.request(reqOpt, function(rsp) {
      var chunks = [];
      rsp.on('data', function(chunk) { chunks.push(chunk); });
      rsp.on('end', function() {
        Container.proxy.res = rsp;
        Container.proxy.resData = Buffer.concat(chunks, chunkLength(chunks));
        resolve(Container);
      });
      rsp.on('error', reject);
    });

缺点:

#### koa中使用pipe
* [Can't pipe stream to ctx.res](https://github.com/koajs/koa/issues/944)

ctx.body = ctx.req.pipe(request(https://www.google.com/?q=${ctx.query.q}));

价值:可以用来转发

#### buffer带来性能提升
Node如直接返回String,需要一个转换,这样性能比较低,可以直接使用buffer
* [Node JS Buffer使用理解](https://juejin.im/post/5b76e6a86fb9a019fe684018):一个例子,提升了177%
* [Node.js学习之路04——Buffer对象与字符串](https://segmentfault.com/a/1190000013005766)

var buf = new Buffer('BUFFER OBJECT'); console.log(buf); console.log(buf.toString()); console.log(buf.toString('utf8', 2, 5));

onvno commented 5 years ago

koa-send

也是pipe流读取文件 https://github.com/koajs/send/blob/master/index.js

  ctx.body = fs.createReadStream(path)
onvno commented 5 years ago

用 nodejs 做反向代理服务器

var http = require('http'), httpProxy = require('http-proxy');

// 新建一个代理 Proxy Server 对象
var proxy = httpProxy.createProxyServer({});

// 捕获异常
proxy.on('error', function (err, req, res) {
  res.writeHead(500, {
    'Content-Type': 'text/plain'
  });
  res.end('Something went wrong. And we are reporting a custom error message.');
});

// 另外新建一个 HTTP 80 端口的服务器,也就是常规 Node 创建 HTTP 服务器的方法。
// 在每次请求中,调用 proxy.web(req, res config) 方法进行请求分发
var server = require('http').createServer(function(req, res) {
  // 在这里可以自定义你的路由分发
  var host = req.headers.host, ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress;
  console.log("client ip:" + ip + ", host:" + host);
  
  switch(host){
    case 'aaaa.com':
    case 'bbs.aaaa.com':
        proxy.web(req, res, { target: 'http://xyd.bbbbb.com:82' });
    break;
    case 'vps.cccc.com':
        proxy.web(req, res, { target: 'http://xyd.bbbbb.com:8080' });
    break;
    case 'dddd.com':
    case 'www.dddd.com':
        proxy.web(req, res, { target: 'http://localhost:81' });
    break;
    case 'eeeeee.com.cn':
    case 'www.eeee.com.cn':
        proxy.web(req, res, { target: 'http://eeeee.com.cn:8082' });
    break;
    default:
        res.writeHead(200, {
            'Content-Type': 'text/plain'
        });
        res.end('Welcome to my server!');
  }
});

console.log("listening on port 80")
server.listen(80);
onvno commented 5 years ago

目前一些转发及请求库:

* [node-http-proxy](https://github.com/nodejitsu/node-http-proxy)

http.createServer(function(req, res) { proxy.web(req, res, { target: 'http://mytarget.com:8080' }); });

* [koa-proxy](https://github.com/edorivai/koa-proxy)

var koa = require('koa'); var proxy = require('koa-proxy'); var app = koa(); app.use(proxy({ host: 'http://alicdn.com' })); app.listen(3000);

onvno commented 5 years ago

几篇文章

onvno commented 5 years ago

流式返回结果,有一篇问答,和自己预期的结果一样 koa.js streaming response from remote url

var req = require('request');
//...
this.body = req(url);
onvno commented 5 years ago

实际测试一个接口,pipe流和cache流转发,时间上边是毫米级别的差距,300kb文件只有30ms左右的差距

onvno commented 4 years ago

基于node的stream pipe实现反向代理 node-hhtp-proxy性能讨论performance issues

onvno commented 4 years ago

https://github.com/request/request/issues/1664 express POST流式返回:

'use strict';

let express = require('express');
let request = require('request');

let app = express();

app.use('/', (req, res) => {
  req.pipe(request.post({ url: 'http://www.example.com', form: { foo: 'bar' }}), {end: false}).pipe(res);
});

app.listen(process.env.PORT || 3000);
onvno commented 4 years ago

Node实现透明转发;nodejs 实现 http proxy 透明转发

var http = require('http');

var proxy = http.createServer(function(request, response) {

    var options = {
        host: 'proxy.xxxx.com', // 这里是代理服务器       
        port: 8080,             // 这里是代理服务器端口 
        path: request.url,       
        method: request.method,
        headers: {
          // 如果代理服务器需要认证
          'Proxy-Authentication': 'Base ' + new Buffer('user:password').toString('base64')    // 替换为代理服务器用户名和密码
        }       
    };

    var req = http.request(options, function(req, res) {
        res.pipe(response);    // 这个pipe很喜欢
        console.log(req.url);
    }).end();

}).listen(8080);

测试如上代码不可用