0 Comments

使用Node.js作为完整的云环境开发堆栈(2)

发布于:2013-09-13  |   作者:广州网站建设  |   已聚集:人围观

稍微高级一点的主题:聊天服务器的负载平衡

通常,负载按比例增长也是部署到云环境的理由之一。这种部署需要实现一些负载平衡机制。

大多数轻量级 Web 服务器,比如 nginx 和 lighttpd,都能够针对多台 HTTP 服务器进行负载平衡,但如果您想要在非 HTTP 服务器之间实现平衡,nginx 可能无法满足要求。而且尽管存在通用的 TCP 负载平衡器,您可能不会喜欢它们使用的负载平衡算法。或者它们没有提供您想要使用的一些功能。或者,您只是想享受构造自己的负载平衡器的乐趣。

下面是最简单的负载平衡器。它没有实现任何故障恢复,希望所有的目的地都是可用的,而且没有进行任何错误处理。它十分简约。基本的理念是,它接收一个来自客户端的套接字连接,随机挑选一个目标服务器进行连接,然后将来自客户端的所有数据转发给该服务器,并将来自该服务器的所有数据都发回到客户端。
广州网站建设,网站建设,广州网页设计,广州网站设计


  1. net = require(‘net’);    
  2. var destinations = [   
  3. ['localhost', 8001],   
  4. ['localhost', 8002],   
  5. ['localhost', 8003],   
  6. ]   
  7.  
  8. var s = net.Server(function(client_socket) {   
  9. var i = Math.floor(Math.random() * destinations.length);   
  10. console.log(“connecting to ” + destinations[i].toString() + “\n”);   
  11. var dest_socket = net.Socket();   
  12. dest_socket.connect(destinations[i][1], destinations[i][0]);   
  13. dest_socket.on(‘data’, function(d) {   
  14. client_socket.write(d);   
  15. });   
  16. client_socket.on(‘data’, function(d) {   
  17. dest_socket.write(d);   
  18. });   
  19. });   
  20. s.listen(9001); 

destinations 的定义是我们要进行平衡的后端服务器的配置。这是一个简单的多维数组,主机名是第一个元素,端口号是第二个元素。

Server() 的定义类似于聊天服务器的例子。您创建一个套接字服务器,并让它监听一个端口。这次它将监听 9001 端口。

针对 Server() 定义的回调首先随机选择一个要连接到的目的地:


  1. var i = Math.floor(Math.random() *   
  2. destinations.length);  

您可能已经使用过轮询算法或使用“最少连接数“算法完成一些额外的工作然后离去,但我们想尽可能地保持简单。

这个例子中有两个指定的套接字对象: client_socket 和 dest_socket。

◆ client_socket 是负载平衡器与客户端之间的连接。

◆ dest_socket 是负载平衡器与被平衡服务器之间的连接。

这两个套接字分别处理一个事件:接收到的数据。当它们其中一个收到数据时,就会将数据写到另一个套接字。

让我们完整地了解当一个客户端通过负载平衡器连接到通用网络服务器上,发送数据,然后接收数据时发生的事情。

当一个客户的连接到负载平衡器时,Node.js 在客户端与自己本身之间创建一个套接字,我们称之为 client_socket。

当连接建立之后,负载平衡器挑选一个目的地并创建一个指向该目的地的套接字连接,我们称之为 dest_socket。

当客户端发送数据时,负载平衡器将相同的数据推送到目的地服务器。
广州网站建设,网站建设,广州网页设计,广州网站设计

当目的地服务器做出响应并将一些数据写到 dest_socket 时,负载平衡器通过client_socket 将这些数据推送回客户端。

可以对这个负载平衡器进行一些改进,包括错误处理,在同一个进程中嵌入另一个进程以动态增加和移除目的地,增加不同的平衡算法,以及增加一些容错处理。

超越原生解决方案:Express Web 框架

Node.js 配备有 HTTP 服务器功能,但较为低级。如果要在 Node.js 中构建一个 Web 应用程序,您可能会考虑 Express——一个为 Node.js 打造的 Web 应用程序开发框架。它弥补了 Node.js 的一些不足。

在下一个例子中,让我们重点关注使用 Express 胜过简单的 Node.js 的一些明显优势。请求路由就是其中之一,还有一个是为 HTTP “verb” 类型注册一个事件,比如“get”或“post”。

下面给出了一个十分简单的 Web 应用程序,它只是演示了 Express 的一些基本功能。


  1. ar app = require(‘express’).createServer();   
  2. app.get(‘/’, function(req, res){   
  3. res.send(‘This is the root.’);   
  4. });   
  5.  
  6. app.get(‘/root/:id’, function(req, res){   
  7. res.send(‘You sent ‘ + req.params.id + ‘ as an id’);   
  8. });   
  9. app.listen(7000); 

这两行以 app.get() 开始的代码是事件处理器,当 GET 请求进入时就会触发。这两次方法调用的第一个参数是一个正则表达式,用于指定用户可能传入的 URL。第二个参数是真正处理请求的一个函数。

正则表达式参数是路由机制。如果请求类型(GET、POST等)与资源(/, /root/123)匹配,就会调用处理器函数。在第一次app.get() 调用中,/ 被简单地指定为资源。而在第二次调用中,在指定/root 时后面还加了一个 ID。映射 regex 的 URL 中资源前面的冒号(:) 字符表明,这部分稍后可作为一个参数使用。

当请求类型与正规表达式匹配时,就会调用处理器函数。此函数带有两个参数,一个请求(req)和一个响应(res)。前面提到的参数被附加给请求对象。而 Web 服务器传回给用户的消息被传入到响应对象。

这是一个非常简单的例子,但已经清楚地说明“真正的应用程序“如何利用这个框架来构建更加丰富和完整的功能。如果插入一个模板系统和一些数据引擎(传统的或 NoSQL 均可),您可以轻松构建出一组功能来满足真正应用程序的需求。

Express 的特点之一是高性能。这与其他快速 Web 应用程序框架的常见特性一起,让Express 在注重高性能和海量可伸缩性的云部署领域中占据了重要的位置。

应了解的知识

有两个概念/趋势需要了解:

◆ 键/值数据库的突然流行。

◆ 其他异步的 Web 范型。

键/值数据库… 为什么突然流行?

因为 JavaScript 是 Web 的通用语言,对于 JavaScript Object Notation (JSON) 的讨论通常远远落后于 JavaScript 相关的研究。 JSON 是在 JavaScript 与一些其他语言之间交换数据的最常用途径。JSON 本质上是一种键/值存储,因此天生适用于对键/值数据库感兴趣的JavaScript 和 Node.js 开发人员。毕竟,如果能够以 JSON 格式存储数据,JavaScript 开发人员的工作就将变得轻松很多。

有一个不太相关的趋势,在 NoSQL 数据库环境中也会涉及键/值数据库。CAP 定理(也叫做 Brewer 定理)指出,一个分布式系统有 3 个核心属性:一致性、可用性和分区容忍性(formal proof of CAP)。这条定理是 NoSQL 发展背后的推动力量,它为牺牲传统关系数据库的某些特性以换取(通常是高可用性)提供了理论基础。一些流行的键/值数据库包括Riak、Cassandra、CouchDB 和 MongoDB。

异步 Web 范型

事件驱动的异步 Web 框架已经存在了相当长一段时间。其中最流行和最新的异步 Web 框架是 Tornado,它使用 Python 语言编写,在 Facebook 内部使用。下面这个例子说明了hello_world 在 Tornado 中(在下载示例文件中叫做 hello_tornado.py )是什么样子。


  1. import tornado.ioloop   
  2. import tornado.web   
  3. class MainHandler(tornado.web.RequestHandler):   
  4. def get(self):   
  5. self.write(“Hello, world”)   
  6. application = tornado.web.Application([   
  7. (r"/", MainHandler),   
  8. ])   
  9.  
  10. if __name__ == “__main__”:   
  11. application.listen(8888)   
  12. tornado.ioloop.IOLoop.instance().start() 

Twisted.web 也是用 Python 语言写的,工作方式也十分类似。

最后谈到真正的 Web 服务器本身,与 Apache 不同,nginx 不使用线程,而是使用一种事件驱动的(异步)架构来处理请求。异步 Web 框架使用 nginx 作为其 Web 服务器是十分常见的情况。

结束语

Node.js 在 Web 开发人员中非常引人关注。它允许开发团队同时在客户端和服务器端上编写 JavaScript。它们还可以结合与 JavaScript 相关的强大技术:JQuery、V8、JSON 和事件驱动的编程。另外还有基于 Node.js 开发的生态系统,比如 Express Web 框架。

Node.js 的优点引人关注,它也存在一些缺点。如果是 CPU 密集型编程,就无法体现Node.js 提供的非阻塞 I/O 方面的优点。有些架构可以解决这类问题,比如将一个池中的进程分流到每个 Node.js 实例上运行,但需要由开发人员去实现它。

原文:http://www.cssor.com/use-node-js-for-cloud-stack.html

飞机