构建一个基于微服务的电子商务软件
使用流行的JS框架创建一个集合所有其他微服务的微服务,并为单页面应用提供API。
谈论4个微服务:
商品管理服务:功能
字段:名字、分类、描述以及价格。构建REST API
var plugin = function(options) {
var seneca = this;
/**
* Fetch the list of all the products.
*/
seneca.add({area: "product", action: "fetch"}, function(args, done) {
var products = this.make("products");
products.list$({}, done);
});
/**
* Fetch the list of products by category.
*/
seneca.add({area: "product", action: "fetch", criteria: "byCategory"}, function(args, done) {
var products = this.make("products");
products.list$({category: args.category}, done);
});
/**
* Fetch a product by id.
*/
seneca.add({area: "product", action: "fetch", criteria: "byId"}, function(args, done) {
var product = this.make("products");
product.load$(args.id, done);
});
/**
* Adds a product.
*/
seneca.add({area: "product", action: "add"}, function(args, done) {
var products = this.make("products");
products.category = args.category;
products.name = args.name;
products.description = args.description;
products.category = args.category;
products.price = args.price
products.save$(function(err, product) {
done(err, products.data$(false));
});
});
/**
* Removes a product by id.
*/
seneca.add({area: "product", action: "remove"}, function(args, done) {
var product = this.make("products");
product.remove$(args.id, function(err) {
done(err, null);
});
});
/**
* Edits a product fetching it by id first.
*/
seneca.add({area: "product", action: "edit"}, function(args, done) {
seneca.act({area: "product", action: "fetch", criteria: "byId", id: args.id}, function(err, result) {
result.data$(
{
name: args.name,
category: args.category,
description: args.description,
price: args.price
}
);
result.save$(function(err, product){
done(err, product.data$(false));
});
});
});
}
module.exports = plugin;
var seneca = require("seneca")();
seneca.use(plugin);
seneca.use("mongo-store", {
name: "seneca",
host: "127.0.0.1",
port: "27017"
});
seneca.ready(function(err){
seneca.act('role:web',{use:{
prefix: '/products',
pin: {area:'product',action:'*'},
map:{
fetch: {GET:true},
edit: {GET:false,POST:true},
delete: {GET: false, DELETE: true}
}
}});
var express = require('express');
var app = express();
app.use(require("body-parser").json());
// This is how you integrate Seneca with Express
app.use( seneca.export('web') );
app.listen(3000);
});
每个公司都需要邮件服务,通过邮件给客户发送通知、账单以及注册邮件。常见问题:邮件投递失败、邮件重复发送、邮件投递错误等。简单但复杂。
特点:只处理一个功能点、处理得很好、持有自己的专有数据。
如何发送:
接口定义:使用了Mandrill,它支持企业级邮件发送、追溯已发送邮件和创建可在线编辑的邮件模板。
集成Mandrill:调用Mandrill服务接口。
主要负责处理用户通过UI填写的订单。
var senecaEmailer = require("seneca")().client({host: "182.168.0.2", port: 8080});
var plugin = function(options) {
var seneca = this;
seneca.add({area: "orders", action: "fetch"}, function(args, done) {
var orders = this.make("orders");
orders.list$({id: args.id}, done);
});
seneca.add({area: "orders", action: "delete"}, function(args, done) {
var orders = this.make("orders");
orders.remove$({id: args.id}, function(err) {
done(err, null);
});
});
seneca.add({area: "orders", action: "create"}, function(args, done) {
var products = args.products;
var total = 0.0;
products.forEach(function(product){
total += product.price;
});
var orders = this.make("orders");
orders.total = total;
orders.customer_email = args.email;
orders.customer_name = args.name;
orders.save$(function(err, order) {
var pattern = {
area: "email",
action: "send",
template: "new_order",
to: args.email,
toName: args.name,
vars: {
// ... vars for rendering the template ...
}
}
senecaEmailer.act(pattern, done);
});
});
}
module.exports = plugin;
邮件服务发送部分邮件失败,甚至客户根本收不到邮件,这都不影响订单处理流程。我们将这种情况称为,性能降级或服务降级。系统的响应速度可能降低,但是部分功能仍然可以使用。
断路器:可以防止请求发送到不稳定的服务器上,避免应用失常的情况发生。
追求简洁性,插件化
还有一个优点就是可配置:使用RabbitMQ进行消息传递的插件
https://github.com/senecajs/seneca-rabbitmq-transport
Promise:保证某个特定事件会发生。
调试: node-inspector