Usage Create your first microservice demo.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 const { ServiceBroker } = require ("moleculer" );const broker = new ServiceBroker ();broker.createService ({ name : "math" , actions : { add (ctx ) { return Number (ctx.params .a ) + Number (ctx.params .b ); } } }); broker.start () .then (() => broker.call ("math.add" , { a : 5 , b : 3 })) .then (res => console .log ("5 + 3 =" , res)) .catch (err => console .error (`Error occured! ${err.message} ` ));
1 2 3 4 5 6 7 8 9 10 11 [2019-06-03T07:54:26.366Z] INFO ********/BROKER: Moleculer v0.13.9 is starting.. . [2019-06-03T07:54:26.369Z] INFO ********/BROKER: Node ID: ******** [2019-06-03T07:54:26.370Z] INFO ********/BROKER: Namespace: <not defined> [2019-06-03T07:54:26.370Z] INFO ********/REGISTRY: Strategy: RoundRobinStrategy [2019-06-03T07:54:26.372Z] INFO ********/BROKER: Serializer: JSONSerializer [2019-06-03T07:54:26.373Z] INFO ********/BROKER: Registered 10 internal middleware(s). [2019-06-03T07:54:26.390Z] INFO ********/REGISTRY: '$node' service is registered. [2019-06-03T07:54:26.392Z] INFO ********/REGISTRY: 'math' service is registered. [2019-06-03T07:54:26.394Z] INFO ********/BROKER: ServiceBroker with 2 service(s) is started successfully. 5 + 3 = 8 [2019-06-03T07:54:26.400Z] INFO ********/BROKER: ServiceBroker is stopped. Good bye.
看到上方範例會啟用一個 microservice
計算出 5 + 3 = 8
之後結束這個程式
Create a Moleculer project Install Nats 需要先安裝 Nats
如果您是選擇其他的 transporters
也需要安裝其他的套件
目前有提供的
Nats - 推薦使用
MQTT
Redis
NATS streaming (試驗)
Kafka (試驗)
Mac
Go Initial Project 有提供一個 Cli tool
install moleculer-cli
1 $ npm i moleculer-cli -g
create a new project
1 $ moleculer init project moleculer-demo
client 會提供幾個選項讓你選擇
1 2 3 4 5 6 7 8 9 10 ? Add API Gateway (moleculer-web) service? ? Would you like to communicate with other nodes? ? Select a transporter NATS (recommended) ? Would you like to use cache? 是否要使用 cache ? Select a cacher solution ? Add Docker files? 是否要使用 Docker ? Use ESLint to lint your code? 是否使用 ESLint ? Setup unit tests with Jest? Unitest framework Create 'moleculerdemo' folder...? Would you like to run 'npm install' ?
可以依據個人的需求選擇
然後就可以得到一個專案
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 . ├── README.md ├── moleculer.config .js ├── package-lock.json ├── package.json ├── public │ ├── banner.png │ ├── favicon.ico │ └── index.html ├── services │ ├── api.service .js │ └── greeter.service .js └── test └── unit └── greeter.spec .js
Broker ServiceBroker
是 Moleculer
中主要的 component
他會處理幾件 nodes
之間溝通的事情
actions
emits
events
communicates
Ping 對遠端的 nodes 使用 broker.ping
來確認遠端 nodes 的狀態
回傳值是一個 Promise
Example ping 一個 node 並設定 1S 的 timeout
1 broker.ping("node-123" , 1000 ).then(res => broker.logger.info(res));
output
1 2 3 4 5 { nodeID: 'node -123 ', elapsedTime: 16 , timeDiff: -3 }
1 timeDiff 是兩個節點之間系統時間的誤差值
也可以同時 ping 多個 nodes
1 broker.ping(["node-100" , "node-102" ]).then(res => broker.logger.info(res));
output
1 2 3 4 5 6 7 8 9 10 11 12 { "node-100" : { nodeID: 'node -100 ', elapsedTime: 10 , timeDiff: -2 }, "node-102" : { nodeID: 'node -102 ', elapsedTime: 250 , timeDiff: 850 } }
ping 所有的 nodes
1 broker.ping().then(res = > broker.logger.info(res))
output
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 { "node-100" : { nodeID: 'node -100 ', elapsedTime: 10 , timeDiff: -2 } , "node-101" : { nodeID: 'node -101 ', elapsedTime: 18 , timeDiff: 32 }, "node-102" : { nodeID: 'node -102 ', elapsedTime: 250 , timeDiff: 850 } }
broker properties
broker methods
Services Services
代表 Moleculer
中的微服務
可以定義多個 action
並且訂閱 ‘event’
建立新的 service 必須先定義好 schema
這些 schema 類似 component of Vuejs
name
version
settings
methods
events
Actions 基本的 schema
1 2 3 4 { name: "posts" , version: 1 }
定義多個 actions
1 2 3 4 5 6 7 8 9 10 11 12 { name: "math" , actions: { add (ctx) { return Number (ctx.params.a) + Number (ctx.params.b); }, sub (ctx) { return Number (ctx.params.a) - Number (ctx.params.b); } } }
name
是必須要定義的參數
當你呼叫這個 api
時,是第一部分的 route 組成元素
1 2 3 4 5 { $noServiceNamePrefix : true }
version 不是必要的參數
可以讓同樣的 service
跑不同的 version 做 api 版本控制
可以是 Number
和 String
1 2 3 4 5 6 7 { name : "posts" , version : 2 , actions : { find ( ) {...} } }
在上方的範例中若是要呼叫這隻 API route 為 GET /v2/posts/find
Settings settings 是一個 store
你可以在裡面做各種設定
使用 this.settings
取得你的 setting object
setting options
Mixins Mixins 是一個可以在 Moleculer
中可以重複使用的 function
Service 的 constructor 會自動合併這些 mixins
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 const ApiGwService = require("moleculer-web" ); module.exports = { name: "api" , mixins: [ApiGwService] settings: { port: 8080 } , actions: { myAction() { } } }
合併的規則
Lifecycle events 當 service 生命週期各自會 trigger 的 function
Dependencies 當你的 service 有依賴到其他 service 的時候
可以利用 Dependencies 來做處理(待捕)
Hot reloading services 在開發過程中需要使用 hot reloading 的機制有兩種方式
1 2 3 4 5 const broker = new ServiceBroker ({ hotReload : true }); broker.loadService ("./services/test.service.js" );
或是 command
1 $ moleculer-runner --hot ./services/test.service .js
Local variables 如果你需要一些 Local variables
可以在 created
中宣告
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 const http = require ("http" );module .exports = { name : "www" , settings : { port : 3000 }, created ( ) { this .server = http.createServer (this .httpHandler ); }, started ( ) { this .server .listen (this .settings .port ); }, stopped ( ) { this .server .close (); }, methods ( ) { httpHandler (req, res ) { res.end ("Hello Moleculer!" ); } } }
ES6 classses 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 const Service = require ("moleculer" ).Service ;class GreeterService extends Service { constructor (broker ) { super (broker); this .parseServiceSchema ({ name : "greeter" , version : "v2" , meta : { scalable : true }, dependencies : [ "auth" , "users" ], settings : { upperCase : true }, actions : { hello : this .hello , welcome : { cache : { keys : ["name" ] }, params : { name : "string" }, handler : this .welcome } }, events : { "user.created" : this .userCreated }, created : this .serviceCreated , started : this .serviceStarted , stopped : this .serviceStopped , }); } hello ( ) { return "Hello Moleculer" ; } welcome (ctx ) { return this .sayWelcome (ctx.params .name ); } sayWelcome (name ) { this .logger .info ("Say hello to" , name); return `Welcome, ${this .settings.upperCase ? name.toUpperCase() : name} ` ; } userCreated (user ) { this .broker .call ("mail.send" , { user }); } serviceCreated ( ) { this .logger .info ("ES6 Service created." ); } serviceStarted ( ) { this .logger .info ("ES6 Service started." ); } serviceStopped ( ) { this .logger .info ("ES6 Service stopped." ); } } module .exports = GreeterService ;