Dtrace
Restify 最酷的功能之一是无论何时添加新的路由/处理程序,它都会自动为您创建 DTrace 探针。
要使用 DTrace,您需要将 dtrace 选项传递给服务器 restify.createServer({ dtrace: true })。
理解它的最佳方式就是通过查看例:
var restify = require('restify');var server = restify.createServer({name: 'helloworld',dtrace: true});server.use(restify.plugins.acceptParser(server.acceptable));server.use(restify.plugins.authorizationParser());server.use(restify.plugins.dateParser());server.use(restify.plugins.queryParser());server.use(restify.plugins.urlEncodedBodyParser());server.use(function slowHandler(req, res, next) {setTimeout(function() {return next();}, 250);});server.get({path: '/hello/:name', name: 'GetFoo'}, function respond(req, res, next) {res.send({hello: req.params.name});return next();});server.listen(8080, function() {console.log('listening: %s', server.url);});
因此我们现在已经有了我们典型的 “hello world” 服务器,略有不同的是,我们引入了一个人为的 250ms 延迟。另外,请注意我们命名了我们的服务器,我们的路由以及我们所有的处理程序(函数)。尽管这是可选的,但它确实使 DTrace 更加可用。因此,如果您启动了该服务器,然后查找 DTrace 探针,则会看到如下所示的内容:
$ dtrace -l -P restify*ID PROVIDER MODULE FUNCTION NAME24 restify38789 mod-88f3f88 route-start route-start25 restify38789 mod-88f3f88 handler-start handler-start26 restify38789 mod-88f3f88 handler-done handler-done27 restify38789 mod-88f3f88 route-done route-done
route-start
| 字段 | 类型 | 描述 |
|---|---|---|
| server name | char * | 触发的 restify 服务器的名称 |
| route name | char * | 触发的路由名称 |
| id | int | 此请求的唯一 ID |
| method | char * | HTTP 请求方法 |
| url | char * | (完整)HTTP URL |
| headers | char * | JSON 编码的所有请求头映射表 |
handler-start
| 字段 | 类型 | 描述 |
|---|---|---|
| server name | char * | 触发的 restify 服务器的名称 |
| route name | char * | 触发的路由名称 |
| handler name | char * | 刚刚输入的函数名称 |
| id | int | 此请求的唯一 ID |
route-done
| 字段 | 类型 | 描述 |
|---|---|---|
| server name | char * | 触发的 restify 服务器的名称 |
| route name | char * | 触发的路由名称 |
| id | int | 此请求的唯一 ID |
| statusCode | int | HTTP 响应码 |
| headers | char * | JSON 编码的响应头映射表 |
handler-done
| 字段 | 类型 | 描述 |
|---|---|---|
| server name | char * | 触发的 restify 服务器的名称 |
| route name | char * | 触发的路由名称 |
| handler name | char * | 刚刚输入的函数名称 |
| id | int | 此请求的唯一 ID |
D 脚本示例
现在,如果您想要通过处理程序获得延迟细分,则可以执行如下操作:
#!/usr/sbin/dtrace -s#pragma D option quietrestify*:::route-start{track[arg2] = timestamp;}restify*:::handler-start/track[arg3]/{h[arg3, copyinstr(arg2)] = timestamp;}restify*:::handler-done/track[arg3] && h[arg3, copyinstr(arg2)]/{@[copyinstr(arg2)] = quantize((timestamp - h[arg3, copyinstr(arg2)]) / 1000000);h[arg3, copyinstr(arg2)] = 0;}restify*:::route-done/track[arg2]/{@[copyinstr(arg1)] = quantize((timestamp - track[arg2]) / 1000000);track[arg2] = 0;}
在同一个终端上运行服务器:
$ node helloworld.js
另一个 D 脚本:
$ ./helloworld.d
用 curl 连接几次服务器:
$ for i in {1..10} ; do curl -is http://127.0.0.1:8080/hello/mark ; done
然后对 D 脚本按下 Ctrl-C,您会看到堆栈底部的“slowHandler”,表明它是这个管道中的绝大数的延迟。
handler-6value ------------- Distribution ------------- count-1 | 00 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 101 | 0parseAcceptvalue ------------- Distribution ------------- count-1 | 00 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 101 | 0parseAuthorizationvalue ------------- Distribution ------------- count-1 | 00 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 101 | 0parseDatevalue ------------- Distribution ------------- count-1 | 00 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 101 | 0parseQueryStringvalue ------------- Distribution ------------- count-1 | 00 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 101 | 0parseUrlEncodedBodyvalue ------------- Distribution ------------- count-1 | 00 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 101 | 0respondvalue ------------- Distribution ------------- count1 | 02 |@@@@ 14 | 08 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 916 | 0slowHandlervalue ------------- Distribution ------------- count64 | 0128 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 9256 |@@@@ 1512 | 0getfoovalue ------------- Distribution ------------- count64 | 0128 |@@@@ 1256 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 9512 |
