您可以捐助,支持我们的公益事业。

1元 10元 50元





认证码:  验证码,看不清楚?请点击刷新验证码 必填



  求知 文章 文库 Lib 视频 iPerson 课程 认证 咨询 工具 讲座 Modeler   Code  
会员   
 
   
 
 
     
   
 订阅
  捐助
使用 Node.js 和 MongoDB 构建一个简单的通知服务
 
作者:Kevin Williams 来源:IBM 发布于:2015-7-6
   次浏览      
 

您是否曾试图协调一组不断增加的各种工具的行为,以便创建一些较大的系统?就我而言,我们的开发团队需要组装一个持续交付管道,并对其操作进行排序。实现此操作的一个选择是使用一个支持创建、标记和订阅事件的通知服务。

可以将这种服务应用于构建系统,宣布新版本的可用性。然后,管道的下游组件才可以接收通知,并根据新版本的出现来采取行动。行动可能包括主动配置新的测试系统和运行回归测试套件。

“通知服务并不是必须包含令人兴奋的消息才是有用的通知服务。”

我开发了一个简单的通知服务,使用 Node.js 运行时作为对使用 RESTful API 快速开发 HTTP 服务器的实现。我还选择了使用 MongoDB 作为后端。其面向文档的特性对于快速开发原型似乎是完美的,我不必提供对 ACID(原子性、一致性、隔离性和持久性)属性的严格支持。

要了解如何实际创建通知服务,请单击 Run the app 来检索由通知服务处理的最近五个事件信号的日志。您看到的大多数信号都是由我们的产品构建系统生成的,而且都是 JSON 格式的。

构建类似应用程序的要求

对 Node.js 和 Node.js 开发环境有基本的了解

拥有以下这些 Node.js 模块:Express、Underscore、Nodemailer

用于自动化测试的其他模块:Mocha、Should、Supertest

一个 MongoDB NoSQL 数据库

阅读:Node.js 超越基础

安装了 Node 和 MongoDB 之后,您就可以使用 Node 的包管理器(npm)来加载所需的依赖关系。请参见从 DevOps Services 下载的代码中的 package.json 文件,了解支持这个应用程序的模块和框架的具体版本。

让我们开始吧!

步骤 1. 创建 API

该 API 与 REST 类似,资源的访问和修改都是通过使用惟一 URL 来完成的,这些 URL 应用了以下 HTTP 动词:GET、PUT、POST 和 DELETE。使用 HTTP 消息功能的任何应用程序都可以访问该服务。这种方法为将来的基于浏览器的工具提供了一个干净的界面。

由该服务管理的主要资源是事件和订阅。一个 API 可用于每个创建、读取、更新和删除操作。

我基于 Express 框架来构建此 API,因为该框架包含一个强大的 Web 应用程序开发特性集,而且只需要遵循惯例,就能非常轻松地使用它。我们来看一看应用程序的主 server.js 模块中的以下代码,该应用程序用于设置定向到这些事件的传入请求的路由:

console.log ('registering event routes with express');
app.get('/events', event.findAll);
app.get('/events/:id', event.findById);
app.post('/events', event.addEvent);
app.put('/events/:id', event.updateEvent);
app.delete('/events/:id', event.deleteEvent);

然后,可以为订阅重复相同的基本模式:

console.log ('registering subscription routes with express');
app.get('/subscriptions', sub.findAll);
app.get('/subscriptions/:id', sub.findById);
app.post('/subscriptions', sub.addSubscription);
app.put('/subscriptions/:id', sub.updateSubscription);
app.delete('/subscriptions/:id', sub.deleteSubscription);

除了针对事件和订阅的这些基本操作之外,还有另外两个重要的 API,具体为:

一个用于标记事件的 API:

app.post('/signals', signal.processSignal);

一个用于检索最近的信号日志的 API:

app.get('/signallog', signallog.findRecent);

步骤 2. 使用后端

MongoDB 提供了服务的持久存储。我直接使用后端文档(集合),而不是使用一个对象映射器。Node.js 原生驱动程序提供了所需的全部功能。

两个主要的资源(事件和订阅)被直接映射到数据库集合。用户可以直接访问它们。例如,像前面的代码段定义的那样,对事件资源的 GET 请求会产生对 event.findAll 的调用。findAll 函数是在 events.js 模块中定义的:

exports.findAll = function(req, res) {
mongo.Db.connect(mongoUri, function (err, db) {
db.collection('events', function(er, collection) {
collection.find().toArray(function(err, items) {
res.send(items);
db.close();
});
});
});
}

findAll 函数简单地连接到数据库,获得事件集合的一个句柄,并返回所有元素,然后关闭连接。所有 API 请求都以这种类似的非常直接的方式进行处理。在下面的示例中,删除事件请求由 events.js 模块中的 deleteEvent 函数处理:

exports.deleteEvent = function(req, res) {
var id = req.params.id;
mongo.Db.connect(mongoUri, function (err, db) {
db.collection('events', function(err, collection) {
collection.remove({'_id':new BSON.ObjectID(id)}, {safe:true}, function(err,
result) {
res.send(req.body);
db.close();
});
});
});
}

和前面一样,建立一个连接,并获得某个集合的句柄。然后,根据所提供的 ID 来删除集合元素,并关闭连接。

步骤 3. 发送通知

除了对托管资源执行创建、替换、更新和删除操作之外,在标记事件时,该服务还会将消息发送给适当的订阅端点。该服务的第一个版本提供了电子邮件通知。接下来的几个代码段将跟踪端到端的整个过程。

可以通过信号路由来接收信号。您可以从 server.js 模块查看该信号,我们使用 signals 模块中的 processSignal 函数来处理此路由:

app.post('/signals', signal.processSignal);

exports.processSignal = function(req, res) {
var signal = req.body;
console.log('Processing Signal: ' + JSON.stringify(signal)); mongo.Db.connect(mongoUri, function (err, db) {
db.collection('subscriptions', function(err, collection) {
collection.find().toArray(function(err, items) {
matches = _.filter(items, function(sub){return sub.eventTitle == signal.eventTitle});
_.each(matches, function (sub) {processMatch(sub, signal)});
res.send(matches);
});
});
});

和以前一样,建立一个数据库连接,并获得相关集合的一个句柄。然后,我们通过筛选来获得与 Event 标题匹配的所有订阅。随后,通过 processMatch 函数来处理此匹配订阅子集的每个元素。

您是否注意到我使用了 _.filter 和 _.each?这些都来自一个名为 Underscore 的非常酷的库,该库提供了一些巧妙的辅助函数,使用过面向对象的语言(比如 Ruby)的??用户应该对此非常熟悉。

processMatch 函数简单地为电子邮件消息分配了适当的值,并调用了 mailer.sendMail 函数:

function processMatch(subscription, signal) {
opts = {
from: 'Simple Notification Service',
to: subscription.alertEndpoint,
subject: subscription.eventTitle + ' happened at: ' + new Date(),
body: signal.instancedata
}
// Send alert
mailer.sendMail(opts);
}

sendMail 函数也非常直观,因为我使用了名为 NodeMailer 的另一个库。您可以看到,我的 sendMail 函数只使用了一些 NodeMailer 功能来发送电子邮件通知。从根本上讲,它使用了一些身份验证值来初始化传输对象,然后指定消息内容(主题、正文、地址等),并开始发送:

exports.sendMail = function (opts) {
var mailOpts, smtpTransport;

console.log ('Creating Transport');

smtpTransport = nodemailer.createTransport('SMTP', {
service: 'Gmail',
auth: {
user: config.email,
pass: config.password
}
});

// mailing options
mailOpts = {
from: opts.from,
replyTo: opts.from,
to: opts.to,
subject: opts.subject,
html: opts.body
};

console.log('mailOpts: ', mailOpts);

console.log('Sending Mail');
// Send mail
smtpTransport.sendMail(mailOpts, function (error, response) {
if (error) {
console.log(error);
}else {
console.log('Message sent: ' + response.message);
}
console.log('Closing Transport');
smtpTransport.close();
});

}

步骤 4. 测试应用程序

我已经介绍了通知服务的主要功能。接下来,我将快速介绍自动化测试。

Node.js 生态系统中的另一个巧妙的框架是用于测试的 Mocha。结合使用 Mocha 与附加项(比如 supertest 用于 HTTP,should 用于断言),为 API 提供可读的功能测试。以下是来自 eventtests.js 模块的片段,用于验证 readbyid Event API:

it('should verify revised News flash 6 event', function(done) {
request(url)
.get('/events/'+ newsFlash6id)
.end(function(err, res) {
if (err) {
throw err;
}
res.should.have.status(200);
res.body.should.have.property('title');
res.body.title.should.equal('News flash 6 - revised');
done();
});
});

这种语法和格式具有非常好的可读性,我希望它会比较容易维护。

我的自动化功能回归测试套件包括每个 API 的测试,我已经建立了一个测试文件夹,其中包括所有测试。Mocha 承认这一惯例。要运行测试套件,可从项目的根发出命令 mocha。

如下图所示,如果没有失败,测试套件的输出应该非常简洁:

我目前要做的是在本地运行此回归测试套件,(通常)在我做了修改时会执行此操作。我总是在推送变更之前运行它,以实现源代码控制。该服务的其中一个实例在 Bluemix 平台上运行, 如果您单击了 Run the app,就已经与此实例进行了互动,而且您还会看到一个最近的事件信号的日志。

目前,我实际上有两个环境:一个是我的本地开发系统,我在上面进行修改并执行测试,另一个环境是 Bluemix 上的生产系统。这样的安排目前运作良好,但我的下一个步骤是在 BlueMix 上创建另一个托管的临时环境。新的临时环境让我可以在更接近生产的环境中运行回归套件,并在修改源代码后,在生产环境中开启自动测试和部署等选项。当我迈出这一步时,我一定会在博客上记录这一切。

考虑构建一个类似的、简单的通知服务,用大量的工具来管理事件。尝试一下,并让我们知道您的尝试结果!

   
次浏览       
相关文章

基于EA的数据库建模
数据流建模(EA指南)
“数据湖”:概念、特征、架构与案例
在线商城数据库系统设计 思路+效果
 
相关文档

Greenplum数据库基础培训
MySQL5.1性能优化方案
某电商数据中台架构实践
MySQL高扩展架构设计
相关课程

数据治理、数据架构及数据标准
MongoDB实战课程
并发、大容量、高性能数据库设计与优化
PostgreSQL数据库实战培训
最新活动计划
LLM大模型应用与项目构建 12-26[特惠]
QT应用开发 11-21[线上]
C++高级编程 11-27[北京]
业务建模&领域驱动设计 11-15[北京]
用户研究与用户建模 11-21[北京]
SysML和EA进行系统设计建模 11-28[北京]

MySQL索引背后的数据结构
MySQL性能调优与架构设计
SQL Server数据库备份与恢复
让数据库飞起来 10大DB2优化
oracle的临时表空间写满磁盘
数据库的跨平台设计
更多...   

并发、大容量、高性能数据库
高级数据库架构设计师
Hadoop原理与实践
Oracle 数据仓库
数据仓库和数据挖掘
Oracle数据库开发与管理

GE 区块链技术与实现培训
航天科工某子公司 Nodejs高级应用开发
中盛益华 卓越管理者必须具备的五项能力
某信息技术公司 Python培训
某博彩IT系统厂商 易用性测试与评估
中国邮储银行 测试成熟度模型集成(TMMI)
中物院 产品经理与产品管理
更多...