轻量级微服务架构【读书笔记3】

  在之前,已经了解了Spring Boot,也了解了跨域的问题,但是,如果每个微服务可能部署在不同的 IP 与端口上,前端必须知道后端部署的位置,这时候 API 网关可以帮助前端同一调用后端的服务,这里我们使用 Node.js 来进行搭建一个统一的 API 网关。

1. 什么是Node.js (What)

  Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境,使用了一个 “事件驱动” 且 “异步非阻塞 I/O” 的模型十七轻量且高效。

  需要注意的是:

  • Node.js 是一个运行环境,并非 JavaScript 类库或框架
  • Node.js 是基于 Chrome 浏览器的 V8 引擎开发的,是业界公认的高性能 JavaScript 引擎
  • Node.js 提供了“事件驱动” 模型,可以将当前事件加入事件队列中去轮询
  • Node.js 提供了 “异步非阻塞 I/O ”模型,比传统的“同步阻塞式 I/O”模型具备更高的吞吐率
  • Node.js 的包管理 NPM 与 Java 的 Maven 异曲同工

  对于高并发问题一般采用 多线程 技术来解决,创建大量线程来处理更多并发的请求。但创建并管理线程是一件非常消耗内存的事情,且在CPU核数不多的情况下,会出现大量的上下文切换现象,因为CPU需要不断地从一堆线程中选择一个线程来处理在它内部的指令。因此在内存较大且CPU强的环境是相当不错的选择。

  Node.js 则采用 单线程 技术来解决高并发问题,在内部提供了一个 “事件驱动” 与 “异步非阻塞 I/O” 模型,让我们在硬件资源相对普通的条件下也能扛住高并发下的压力。

  解决高并发问题,实际就是解决 I/O 问题。一般包含两个方面,即网络和磁盘。Java 的 I/O 模型是同步的,知道后来 NIO 技术出现,Java编程模型才有了异步的特性,而 Node.js 与生俱来就有 NIO 特性,而且利用 JavaScript 的回调函数是异步编程更简单。

  1.1 快速入门

  阅读下面这段代码:

var fs = require('fs');

fs.readFile('/etc/hosts', function (err, data) {
        if (err) throw err;
        console.log(data.toString());
});

  通过 Node.js 内置的 require() 函数引进 FS模块,创建一个fs 变量,调用其 readFile() 函数来读取 /etc/hosts 文件。实际上,Node.js 会创建一个读取文件的事件,并like将该事假加入到事件队列中,当前线程并不会阻塞在这里。

  1.2 应用场景

  • I/O 密集型 Web 应用(Express)
  • Web聊天室(Socket.IO)
  • 命令行工具(Commander.js)
  • HTTP代理服务器(node-http-proxy)

2. 如何使用 Node.js (How)

  只要我们会写 JavaScript,并了解一些基本的编程思想就可以快速使用 Node.js。

  2.1 安装 Node.js

  

  2.2 使用 Node.js 开发 Web 应用

var http = require('http');

var PORT = 1234;

var app = http.createServer(function (req , res) {
    res.writeHead(200, {'Content-Type': 'text/html'});
    res.write('<h1>Hello</h1>');
    res.end();
});

app.listen(PORT, function (){
    console.log('server is running at %d', PORT);
});

  然后执行 node app.js

  去浏览器访问 http://localhost:1234/ 。

  2.3 使用 Express 框架开发 Web 应用

  首先安装 npm install express,然后新建app_express.js 文件

var express = require('express');

var PORT = 1234;

var app = express();

app.use(express.static('.'));

app.listen(PORT, function () {
    console.log('server is running at %d', PORT);
});

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

  通过 app.get 来配置一个请求,访问 http://localhost:1234/hello 。

  2.4 搭建 Node.js 集群环境

  Node.js 采用了单线程模型,且拥有基于事件驱动的异步非阻塞 I/O 特性,可高效利用 CPU 资源,但并不能说明 Node.js 只能在单核 CPU下。原生 Node.js 已支持集群特性。让我们试一下。

var http = require('http');
var cluster = require('cluster');
var os = require('os');

var PORT = 1234;
var CPUS = os.cpus().length; // get cpu sizes

console.log('Current CPUS %d', CPUS);

if (cluster.isMaster) {
    for (var i = 0; i < CPUS; i++) {
        cluster.fork();
    }
} else {
    var app = http.createServer(function (req, res) {
        res.writeHead(200, {'Content-Type': 'text/html'});
        res.write('<h1>Hello</h1>');
        res.end();
    });
    
    app.listen(PORT, function(){
        console.log('Server is running at %d', PORT);
    });
}

  首先加载了内置的Cluster模块和OS模块,通过 OS 模块获取 CPU 内核数量,若当前进程为主进程,根据 CPU内核数去创建子进程,只有在子进程中执行相关的代码。可见,CPU 核心数越多,单台服务器上可创建的子进程就越多,支持的并发量就越大,从而整个应用程序的吞吐率就越高。

 

3. 使用 Node.js搭建微服务网关

  微服务网关是微服务架构中的核心组件。

  3.1 什么是微服务网关

  类似经典设计模式中的 Facade 模式(门面模式),它将底层的复杂细节进行屏蔽,对外提供简单且统一的调用方式,如HTTP方式。对客户端而言,可以是PC端也可以是移动端。

  实际上,服务网关的路由过程我们也称为“反向代理”。那反向代理的应用场景有:

  • 使静态资源与动态资源分离
  • 实现 AJAX 跨域访问
  • 搭建统一服务网关接口

  3.2 使用 Node.js 实现反向代理

  首先安装 HTTP Proxy 模块 npm install http-proxy

  实现代码如下:

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

var PORT = 1230;

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:1234'
    });
});

app.listen(PORT, function (){
    console.log('server is running at %d', PORT);
});

  启动应用程序,通过访问 http://localhost:1230 去访问 http://localhost:1234,除了 HTTP,该模块还支持 HTTPS 与 WebSocket 的反向代理。

posted @ 2018-04-26 16:00  zacky31  阅读(580)  评论(0编辑  收藏  举报