使用 Node.js 搭建微服务网关
Node.js 是什么
Node.js 是一个基于 Chrome v8 引擎的 Javascript 运行环境,它使用了一个"事件驱动"且"异步非阻塞 I/O" 的模型使其轻量且高效, Node.js 的包管理器 NPM 是全球最大的开源库生态系统。
对其定义的补充说明:
- Node.js 是一个运行环境,而不是 Javascript 类库或者框架
- Node.js 是基于 Chrome 浏览器的 V8 引擎开发的,该引擎是业界公认的高性能 js 引擎
- Node.js 提供了事件驱动模型,可以将当前事件加入到事件队列中轮询
- Node.js 提供了异步非阻塞式 I/O 模型,它比传统的同步阻塞式 I/O 模型具有更高的吞吐率
- Node.js 的包管理器与 java 的 Maven 类似,但生态圈似乎更加庞大
安装 node.js
wget https://nodejs.org/dist/v10.15.0/node-v10.15.0-linux-x64.tar.xz
tar -xvzf node-v10.15.0-linux-x64.tar.xz -C /usr/local/ --strip-components=1
Node.js 入门
先给一段代码
var fs = require('fs')
fs.readFile('/etc/hosts', function (err, data) {
if (err) {
throw err;
}
console.log(data.toString());
});
Node.js 会创建一个读取文件的事件,并立刻将该事件加入到事件队列中,当前线程不会阻塞在这里。理论上后续不管有多少线程都会进来并产生一系列事件,这些事件都会加入到同样的事件队列中,它们会在事件队列中进行循环,一旦某个事件被触发(比如读取文件成功),就会执行后面定义的回调函数。
除了回调函数这种异步方式,它也提供了同步 API,代码如下
var fs = require('fs')
var data = fs.readFileSync('/etc/hosts')
console.log(data.toString());
Node.js 应用场景
Node.js 是针对实时 web 应用程序而开发的,非常适合为了满足实时性较强且并发量较大的应用场景。
-
I/O 密集型 web 应用
应用程序分为两大类
- CPU 密集型应用
- 对 CPU 要求较高,需要一个强大的计算过程
- 如股票交易系统,数据分析系统等
- I/O 密集型应用
- 常常有频繁的网络传输或磁盘存储现象
- 如高并发网站,实时 Web 系统等
Express 是一个非常优秀的 web 框架
- CPU 密集型应用
-
Web 聊天室 Socket.IO
-
命令行工具
可以写一段 Node.js 程序,通过 NPM 的命令将其安装到操作系统中,随时在命令行控制台输入该命令运行。
Commander.js
基于 Node.js 的前端开发工具如下 Bower, Grunt, Gulp, Webpack, Yeoman
-
HTTP 代理服务器
Node.js 可以通过异步的方式处理大量的兵法请求,它可以作为服务器端应用程序的代理,起到如 Nginx, Apache 等 HTTP代理服务器的作用。
常用的 HTTP 代理服务器模块 node-http-proxy ,在实现微服务架构的服务网关是会用到该项技术。
npm 镜像
淘宝提供了一个 NPM 镜像,速度非常快。
npm install --registry=https://registry.npm.taobao.org
在安装一个要打包到生产环境的安装包时,你应该使用 npm install --save
,
如果你在安装一个用于开发环境的安装包(例如,linter, 测试库等),你应该使用 npm install --save-dev
。可在 npm 文档 中查找更多信息。
淘宝 npm 镜像官网 http://npm.taobao.org/
使用 Node.js 搭建微服务网关
什么是微服务架构
先来整体回顾下下微服务架构
微服务网关(Node.js) 是微服务架构中的核心组件,它是客户端请求的门户,是调用具体服务端的桥梁。它类似于 Facade 模式(门面模式),将底层复杂的细节进行了屏蔽,对外提供简单且统一的调用方式,如 HTTP 方式。
微服务网关,也称为服务网关(Service Gateway),或者 API 网关(API Gateway)。它们之间的关系如下面架构图所示:
在上图中,我们使用服务网关来建立 client 与 service1 之间的联系。当从 client 发送请求时,请求首先进入 service gateway, 随后 service gateway 就会将请求路由到具体的服务器。在路由过程中,会涉及具体的路由算法,最简单的做法就是在 service gateway 中解析 client 请求中的路径和请求头,从而路由到具体的服务端。
为了确保服务具有较高的可用性,我们可部署多个相同的服务端,此时需要再 service gateway 中设置相关路由算法,将请求随机路由到具体的服务端,当然也可以对 client ip 地址进行 Hash 算法,从而实现请求路由。
服务网关的路由过程我们称为"反向代理"。和 Nginx ,Apache 类似。
反向代理的应用场景有
- 使静态资源与动态资源分离
- 实现 AJAX 跨域访问
- 搭建统一服务网关接口
使用 Node.js 实现反向代理
Node.js 搭建反向代理服务器,需要下面 3 步
-
使用如下命令安装 HTTP Proxy 模块
npm install http-proxy
-
使用 HTTP Proxy 模块启动代理服务器,新建一个名为 app_proxy.js 的文件
var http = require('http'); var httpProxy = require('http-proxy'); var PORT = 1234; // 创建代理服务器对象 var proxy = httpProxy.createProxyServer(); proxy.on('error', function (err, req, res) { res.end(); // 输出空白响应数据 }); var app = http.createServer(function (req, res) { // 执行反向代理 proxy.web(req, res, { target: 'http://localhost:8080' // 目标地址 }) }) app.listen(PORT, function() { console.log('server is running at %d', PORT) })
-
启动 app_proxy.js 应用程序
node app_proxy.js
运行后,就可以通过 "localhost:1234" 去访问 "localhost:8080"。
除了 HTTP,该模块还支持 HTTPS 与 WebSocket 的反向代理。
可以使用 apache bench 对其性能做一个简单的测试。模拟 1000 个用户,每个用户并发 100 个请求
ab -n 1000 -c 100 http://localhost:1234
Node.js 与 Nginx 相比性能不差,而且其扩展性远高于 Nginx。我们可以动态指定被代理的目标地址,而 Nginx 中配置的目标地址却是静态的。这一点对实现服务发现功能及其重要,因为我们需要从 Service Registry 中获取需要代理的微服务信息,并执行反向代理操作,调用相应的微服务 REST API。
最后需要说明的是,服务网关不仅仅提供反向代理与服务发现特性,此外它还具备安全认证,性能监控,数据缓存,请求分片,静态响应等特性,我们可以根据实际情况扩展。
参考
- 《架构探险—轻量级微服务架构》