On Github 17koa / node4koa
将下一代 Web 框架 Koa 进行到底
什么是全栈?一直站在前面讲么?
Oh hey, these are some notes. They'll be hidden in your presentation, but you can see them if you open the speaker notes window (hit 's' on your keyboard).http://nodeonly.com/stack/
支持koa 1 和 Koa 2(稍后会把ava和bluebird加上)
1)Node SDK里的ES 6 语法支持
2)Koa
3)异步流程控制
1. 性能
2. 异步流程控制
3. Koa核心概念
benchmark koa-1 1 middleware 5893.92 5 middleware 5902.22 10 middleware 1935.14 15 middleware 5300.84 20 middleware 5137.80 30 middleware 5339.12 50 middleware 5049.62 100 middleware 4578.32
benchmark koa-2 1 middleware 5872.58 5 middleware 5729.20 10 middleware 4860.80 15 middleware 5767.69 20 middleware 5766.93 30 middleware 5446.56 50 middleware 5022.90 100 middleware 5250.70
benchmark koa-2-async 1 async middleware 5815.71 5 async middleware 4639.42 10 async middleware 4423.81 15 async middleware 4261.05 20 async middleware 4217.97 30 async middleware 3620.62 50 async middleware 2478.95 100 async middleware 1745.38
benchmark express 1 middleware 6374.90 5 middleware 6098.11 10 middleware 4436.94 15 middleware 4344.61 20 middleware 5904.50 30 middleware 5945.77 50 middleware 5171.96 100 middleware 4317.21
1. callback
2. Promise/A+
3. generator/yield + co
4. async/await
Generators are a way of returning an arbitrary sequence of results from a function, with the function’s execution suspended in between results.
I will not yield a step. 我寸步不让。
function* gen(x){ var y = yield x + 2; return y; } var g = gen(1); g.next() // { value: 3, done: false } g.next(2) // { value: 2, done: true }
let getTweets = function* () { let totalTweets = []; let data;
// pause. On `iterator.next()` get the 1st tweet and carry on. data = yield get('https://api.myjson.com/bins/2qjdn'); totalTweets.push(data); // pause. On `iterator.next()` get the 2nd tweet and carry on. data = yield get('https://api.myjson.com/bins/3zjqz'); totalTweets.push(data); // pause. On `iterator.next()` get the 3rd tweet and carry on. data = yield get('https://api.myjson.com/bins/29e3f'); totalTweets.push(data);
// log the tweets console.log(totalTweets); };
Generator based control flow goodness for nodejs and the browser, using promises, letting you write non-blocking code in a nice-ish way.
co(function* () { var result = yield Promise.resolve(true); return result; }).then(function (value) { console.log(value); }, function (err) { console.error(err.stack); });
app.use(async (ctx, next) => { const start = new Date(); await next(); const ms = new Date() - start; console.log(`${ctx.method} ${ctx.url} - ${ms}ms`); });
它就一个语法糖
function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else {
return Promise.resolve(value) .then(function (value) { return step("next", value); }, function (err) { return step("throw", err); }); } } return step("next"); }); }; }
app.use(async (ctx, next) => { await next(); ctx.body = body; });
翻译后
app.use((() => { var ref = _asyncToGenerator(function* (ctx, next) { yield next(); ctx.body = body; }); return function (_x3, _x4) { return ref.apply(this, arguments); }; })());
Express
function middleware(req, res, next) { ... next() }
koa 1
middleware = function *(next){ ... yield next ... this.xxx }
app.use((ctx, next) => { const start = new Date(); return next().then(() => { const ms = new Date() - start; console.log(`${ctx.method} ${ctx.url} - ${ms}ms`); }); });
app.use(async (ctx, next) => { const start = new Date(); await next(); const ms = new Date() - start; console.log(`${ctx.method} ${ctx.url} - ${ms}ms`); });
app.use(co.wrap(function *(ctx, next) { const start = new Date(); yield next(); const ms = new Date() - start; console.log(`${ctx.method} ${ctx.url} - ${ms}ms`); }));
app.js里堆叠的那些。。。
router.get('/', $middlewares.check_api_token, $.api.list);
let m = async (ctx, next) => { ... }
等于
var m = async function (ctx, next) { ... }
import test from 'ava'; test('foo', t => { t.pass(); }); test('bar', async t => { const bar = Promise.resolve('bar'); t.is(await bar, 'bar'); });
wrk -t8 -c1000 -d2 http://127.0.0.1:3333 > wrk.log
结果
Running 2s test @ http://127.0.0.1:3333 8 threads and 1000 connections Thread Stats Avg Stdev(标准偏差) Max +/- Stdev( 正负一个标准差占比) Latency 135.20ms 40.84ms 389.59ms 93.44% Req/Sec 683.58 294.98 1.24k 62.99% 10712 requests in 2.10s, 1.54MB read Socket errors: connect 0, read 202, write 14, timeout 0 Requests/sec: 5108.43 Transfer/sec: 753.29KB
然后呢?
1)提取文本
Running 2s test @ http://127.0.0.1:3333
正则js里的match
/Running\s(\d+)s\s+test\s+\@\s+http:\/\/([\w\W]+):([\d+]+)\n?/
2)wrkparser
Install
npm i -S wrkparser
Usages
var obj = require('wrkparser')('wrk.log', 'wrk.log.json')
3)合并多次测试结果你(wrk_scan)
var files = require('fs').readdirSync(path) // console.log(files) var result = {} files.forEach(function(file){ if (/\.log$/.test(file)) { console.log(file) result[file.replace('.log', '')] = require('wrkparser')(file) } })
4)可视化
5)cli支持
package.json里加入
"preferGlobal": "true", "bin": { "wrk_scan": "bin/wrk_scan.js" },
扫描当前目录下的日志,合并生产wrk.json
$ npm i -g wrk_scan $ wrk_scan
6)TODO
天津
少抱怨,多思考,未来更美好。有的时候我看的不是你一时的能力,而是你面对世界的态度。
console.log('The End, Thanks~')