65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 Proxy 和服务发现进行水平扩展应用程序。

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.33/5 (2投票s)

2016年1月6日

CPOL

6分钟阅读

viewsIcon

16841

downloadIcon

62

使用 Proxy 和服务发现进行水平扩展应用程序。

引言

在我之前的文章中,我们讨论了应用程序的水平扩展。但主要侧重点是根据我们不断增长的需求来扩展应用程序处理(中间层)和数据库层。在本文中,我们将尝试探讨如何扩展应用程序的交互/UI层。我将使用 JavaScript 编写代码,并使用 Node.js 模块来演示实现。我假设您对 Node.js 和 JavaScript 有一些基本了解。

我很想听取您对本文的反馈。请随时分享您的评论,或者您也可以发邮件给我:shettyashwin@outlook.com。如果您喜欢这篇文章,请不要忘记给它评分。

背景

当我们开始开发应用程序时,我们通常会看到应用程序处理用户交互的典型方式。浏览器或应用程序向应用程序 UI / API 发出调用。托管的应用程序在遍历其层后,按客户端的请求返回数据。这是一个典型的单体设计。现在,让我们开始增加复杂性,看看应用程序会如何表现。由于计划中的促销活动,现在我们预计会有大量用户访问我们的应用程序,同时还需要开发一些紧急补丁,而不能影响客户交互。现在更大的挑战是部署新更改而不影响用户交互,同时还要平衡我们网站上的负载。

我们的方法

为了克服这些问题,我们需要考虑两件重要的事情。

  1. 我们如何扩展应用程序以处理临时负载
  2. 我们如何进行部署而不影响客户交互

现在,让我们一个一个地解决这个问题,首先关注可扩展性。与其让应用程序直接可供最终用户访问,不如先路由请求。我所说的路由是指某种类型的代理服务,它将您的应用程序请求路由到可用的应用程序节点。让我们看看如何使用 Node.js 实现这一点。

创建一个空文件夹并命名为 ProxyServer。打开命令提示符,导航到 proxyserver 文件夹。一旦您位于 proxyserver 文件夹的根目录下,请执行以下命令来获取我们需要的依赖项。

npm install http

npm install http-proxy

成功执行上述命令后,您应该能在 ProxyServer 文件夹中看到 node_modules 文件夹。这两个模块都将在此文件夹中可用。http-proxy 是我们将用于将请求路由到可用节点的模块。现在是时候写一些代码了。在 ProxyServer 的根目录下添加一个新文件 app.js。在文本编辑器或您熟悉的任何编辑器中打开 app.js,然后添加以下代码行。

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

//load both the module which we will require

var proxy = httpProxy.createProxyServer();
// Create an instance of proxy server which will route your request.

http.createServer(function (req, res) {
    proxy.proxyRequest(req, res, { target : 'https://:8080' });
    //This will route your request to another instance of application which is running on localhost 8080
}).listen(3000);

回到命令提示符并执行

node app.js

一旦上述行成功执行,所有到达端口 3000 的请求都将被路由到 localhost :8080,我们的实际应用程序正在那里运行。现在,您可以创建一个可用实例的集合,然后通过轮询将其路由到其中一个,而不是将您的应用程序路由到端口 8080 上的单个实例(我们已经硬编码了)。

现在我们的第一个问题得到了部分解决。我之所以说“部分解决”,是因为我们硬编码了请求被路由到的 URL。当用户发出请求时,此 URL 实例可能正在运行,也可能没有运行。此外,如果我们添加了额外的节点,在不停止 ProxyServer 实例的情况下更新列表将会很困难。为了解决这个问题,我们需要添加一个额外的模块,它将充当代理和应用程序节点之间的中介。返回命令窗口并停止 ProxyServer 的运行实例。是时候安装我们的新模块了,请执行以下命令获取 seaport 模块。

npm install seaport -g

请确保您是全局安装 seaport。这是 seaport 对其模块的评价:

引用

Seaport 会为您存储 (host,port) 组合(和其他元数据),这样当您的架构扩展到跨越多台机器上的多个进程时,您就不需要花费太多精力来维护配置文件。只需向 seaport 注册您的服务,然后查询 seaport 以查看您的服务在哪里运行。 

参考: https://github.com/substack/seaport

好的,现在让我们回到代码更改。

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

//load both the module which we will require
var proxy = httpProxy.createProxyServer();

// Create an instance of proxy server which will route your request.
var ports = seaport.connect('localhost', 9090);
// Connecting to seaport instance which is available at port 9090 

var i = -1;

http.createServer(function (req, res) {
    var addresses = ports.query('application-server');
    
    // if there are not workers, give an error
    if (!addresses.length) {
        console.log("Returned service unavailable, since no service was available");
        res.writeHead(503, {'Content-Type' : 'application/json'});
        res.end('Service unavailable');
        return;
    }
    
    console.log("Address detail");
    //console.log(addresses);
  
    i = (i + 1) % addresses.length;
    console.log("Route to Instance : " + addresses[i].port); 
    // Displays which instance the request was routed 

    proxy.proxyRequest(req, res, { target : addresses[i] });

}).listen(3000);

我们在这里所做的是,我们不再硬编码 URL,而是依赖 seaport 为我们提供可用节点列表,然后将请求路由到可用的节点。我们还将获取已在 "Application-Server" 池下向 seaport 注册的服务列表。当有多种服务类型时,这一点很重要。Seaport 模块还将监视连接到它的实例。如果一个节点崩溃,它将从 Seaport 注册表中删除该节点信息。

应用程序节点必须向 seaport 注册才能参与处理请求。是的,这解决了我们第二个问题,即在不影响的情况下部署修复。一旦我们部署了新更改,新部署的节点将向 seaport 注册自己,并开始处理新的传入请求。慢慢地,我们将通过从 seaport 注销来移除所有旧实例。在本文中,我没有涵盖注销逻辑,但它相当简单。相关详情也可在此处找到:https://github.com/substack/seaport

好的,让我们回来完成一些必要的更改。现在在应用程序节点中,我们将不得不向 seaport 注册自己。以下是实现此目的的逻辑。在 ProxyServer 并行的位置创建一个新文件夹,并将其命名为 Server。像之前一样,在此文件夹中安装 http、mongoose 和 seaport 模块。

var http = require('http');

var seaport = require('seaport');
var ports = seaport.connect('localhost', 9090);
//connect to seaport instance available at port localhost port 9090
console.log("Starting basic");

var mongoose = require('mongoose');
mongoose.connect('mongodb:///pathDB'); 
//mongodb Server and Database information. pathDB is the name of the database

//Your schema defination. PaymentModes is the table / collection name inside PathDb database
var paymentModeSchema = mongoose.model('PaymentModes', {name: String, description: String});

// Create a basic server that responds to any request with the pi estimation
var server = http.createServer(function (req, res) {
     paymentModeSchema.find({},function(err, docs){
        res.writeHead(200, {'Content-Type' : 'application/json'});
        res.end(docs.toString());
    });
});

console.log("Starting hosting");
var hostingDetail = ports.register('application-server');
//register with Seaport instanse available at port 9090

// Listen to a specified port, or default to 8000
server.listen(hostingDetail);
console.log("hosting port : " + hostingDetail);

console.log("hosting completed");

在运行此模块之前,请确保您已安装 http、mongoose 和 seaport 模块。在代码示例中,Mongoose 模块仅用于从 mongoDb 数据库中获取数据。您可以更改返回逻辑,删除对 mongoose 的依赖。此外,seaport 实例需要运行。以下命令将帮助您安装 http、mongoose 和 seaport 模块,并启动 seaport 实例。

npm install npm 
npm install mongoose
npm install seaport
seaport listen 9090

现在是运行 proxyserver 和应用程序服务器的时候了。打开两个不同的命令提示符,导航到 Proxyserver 和 server 文件夹的根路径。在命令提示符中运行 node app.js。请确保您有三个命令提示符窗口运行以下每个应用程序。

  1. Seaport
  2. ProxyServer
  3. 服务器

如果您现在在浏览器中访问 https://:3000/,您应该能在 proxyserver 窗口中看到哪个应用程序节点收到了请求。

我在本文中附带了我的代码集,下载后请不要忘记在 proxyserver 中安装 http、http-proxy 和 seaport 模块,在 server 文件夹中安装 http、mongoose 和 seaport 模块。此外,代码还需要运行 mongodb 实例。

参考

https://github.com/substack/seaport

https://npmjs.net.cn/package/http-proxy

使用代理和服务发现进行应用程序水平扩展 - CodeProject - 代码之家
© . All rights reserved.