Node 的 “字节码增强技术” 你了解吗?

栏目: Node.js · 发布时间: 5年前

内容简介:如果听了之后,对你有所启发和帮助,希望能帮忙转发一下。如果有问题,请关注下面公众号,发送问题给我。

Node 的 “字节码增强技术” 你了解吗? 戳蓝字「 Node全栈进阶 」关注我们哦!

Node 的 “字节码增强技术” 你了解吗?

编者注:作者是网易资深前端@金炳,当前负责网易严选自研Node框架建设工作。做过前端、后端、产品设计,是一名全栈工程师。目前致力于Node应用框架研究开发与生态建设,实践Node应用在Serverless、Faas场景下的迁移和落地,探索Service Mesh在Node应用中的价值。

Node的“字节码增强技术”你了解吗?纠正,专业名词叫monkey patch

一、介绍

1.1 什么是“字节码加强技术”?

有些人可能没有听过“字节码增强技术”是什么?

这个技术其实来源于Java,被一些牛逼的 Java 工程师掌握的核心技术之一,被用来开发一些底层的基建类 工具 或者平台使用。

“字节码增强技术”: 在Java字节码生成之后, 运行期 对其进行修改,增强其功能,这种方式相当于对应用程序的二进制文件进行修改。Java字节码增强主要用来提供一些现有代码没有的功能,赋能原有项目,或者增加性能等。

1.2 类比Node

概括的讲:相当于我们用typescript或者javascript写的代码,编译成一个js文件或者打包后,使用了“字节码增强技术”之后,可以增强原有的代码或者修改底层的代码。例如原来写了一个node程序,通过加入这个技术之后,你可以将原有的node程序对接到分布式链路跟踪平台上,看到对应的链路情况,代码并没有改,但是你让一个简单的node项目有了链路跟踪的功能。那我把它也叫做Node的“字节码增强技术”了。

二、举个简单的例子

2.1 写个程序

我们为了文章的可读性,贴太多代码不好,所以举一个特别简单的代码:首先我们创建一个工程

// 创建一个工程目录
mkdir test_code 
// 进入工程目录
cd test_code
// 初始化package.json
npm init -y
// 安装koa的依赖
npm install koa -s

然后我们创建一个index.js

var koa = require('koa')

const app = new koa();

app.use((ctx, next)=>{
    ctx.body = "hello world";
})

app.listen(8000);

然后我们运行这个工程:

node index.js

然后我们就可以访问http://127.0.0.1:8000,然后就能在浏览器上看到"hello world"了。

2.2 使用“字节码增强技术”

假设上面的代码,就是我们的业务代码。

我们做基建的人,肯定最好的情况就是不去修改上面的代码。所以我们就来利用“字节码增强技术”来开发一个工具,来增强原来的代码。

我们这个工具名字:power.js

利用“字节码增强技术”,我们需要借助shimmer这个npm包(早先知道他的时候,下载还很少,现在越来越多人用了)。如下:每周下载量有105万了,说明项目底层可能都用了,大家放心使用。

Node 的 “字节码增强技术” 你了解吗?
image.png

我们安装一下shimmer这个依赖

npm install shimmer -S

然后power.js的代码如下:

我们比如想要增强,原先代码,我们不知道有哪些path被调用了,那我们就增强一下这个功能。

var shimmer = require('shimmer');
var http = require('http');

// 此处为了简单,http.createServer(handler)
shimmer.wrap(http, "createServer", function wrapCreateServer(original){
    return function wrapFunction (handler){
        let newFunction = function(req, res){
            console.log(req.url);
            return handler(req, res);
        }
        return original.call(this, newFunction);
    }
});

上面为了简单演示,就是我们会去加强原有http模块的createServer函数,作用就是将原有的handler做一个wrap。

相当于我们不管用koa还是express,我们底层都会去调用http.createServer方法。

所以我们通过加强http.createServer的handler方法。

然后我们怎么在应用:

node -r power.js index.js

我们通过-r power.js去引入这个文件

然后我们打开浏览器http://127.0.0.1:8000/hello,然后我们能看到,命令行里面会打印了

/hello

相当于打印出了这个url。

所以我们并没有去修改原有代码,而且这个插件,我们再使用一个express的应用程序,这个我体现在这个通用性这章节

2.3 通用性特点

为了验证这个通用性,我们在写一个express程序,

var express = require('express');
var app = express();

app.get('/*', function (req, res) {
  res.send('Hello World!');
});

app.listen(3000);

然后我们也这个运行:

node -r power.js index.js

然后我们打开浏览器http://127.0.0.1:8000/hello,然后我们能看到,命令行里面会打印了

/hello

相当于打印出了这个url。

2.4 总结

当我们组的一些开发开发了一个应用,然后我们通过“字节码增强技术”开发了一个插件,然后让组内其他成员,运行应用的时候,去-r ./xxx,就能增强原来的代码了,比如有没有内存泄漏呀,链路跟踪,每次请求的返回啊,都能去做统计。

三、应用场景

3.1 基建类

上面这个我们举例了一个应用场景,比如其他成员开发了一个node业务项目,然后基建成员,可以去开发一个插件,让业务方成员启动的时候,加上这个参数。

最终实现:

  1. 内存泄漏统计

  2. 链路跟踪

  3. 每个请求的返回的耗时

  4. 错误捕获的上报

  5. mysql的调用情况的一些统计

  6. 等等

3.2 业务项目中的应用

上面我们演示的是node程序,他其实也能应用在前端代码中。

比如我们使用基建代码的时候,发现这个基建在某种情况下出问题了,这个时候我们就可以去做这个wrap操作。

否则等组件发包比较慢,这个时候,我们通过wrap原来的original函数,然后最终修复这个基建中出现的问题。

四、建议

上面的代码中演示的代码比较简陋,只是为了让大家能更好的理解。

4.1 插件包建议用typescript

因为我们wrap的时候,需要去看原有函数,而且原有函数可能有多种参数情况,所以我们typescript的时候,我们就能更好的看到这个情况。防止少覆盖了一些情况。

4.2 参考一些现有代码和官方文档

另外大家可以查看pandora.js这个项目里面这个的使用方式,以及另外github上面去搜索这个代码片段,就能看到一些基础类的代码中,都用了这个shimmer。

五、原理

像react、angular等,我们其实分析到底下,他最后就会落到那么几个最底层的原理。

那我们打开shimmer包。

打开源码地址:

https://github.com/othiym23/shimmer/blob/master/index.js

就一个文件,大家看一下就能看完了,最终这个包的最底层就是:

Object.defineProperty

如果听了之后,对你有所启发和帮助,希望能帮忙转发一下。如果有问题,请关注下面公众号,发送问题给我。

Node 的 “字节码增强技术” 你了解吗?


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

One Click

One Click

Richard L. Brandt / Portfolio Hardcover / 2011-10-27 / 25.95

An insightful look at how Amazon really works and how its founder and CEO makes it happen. Amazon's business model is deceptively simple: make online shopping so easy and convenient that customers ......一起来看看 《One Click》 这本书的介绍吧!

JS 压缩/解压工具
JS 压缩/解压工具

在线压缩/解压 JS 代码

图片转BASE64编码
图片转BASE64编码

在线图片转Base64编码工具

随机密码生成器
随机密码生成器

多种字符组合密码