本節將介紹 Broker 的生命週期中,啟動 Broker 與停止 Broker 到底各自發生了什麼事情。
當一個 Broker 被啟動時,它將會嘗試與 Transporter 建立連線。建立完成後,它不會將本地服務清單發佈到遠端節點,而是先啟動所有的服務,然後呼叫每個服務中的 started 處理程序。待所有的服務都啟動成功後, Broker 才會將本地服務清單發佈到遠端節點。因此只有在所有本地服務都成功初始化並啟動後,遠端節點才能夠發送請求。

Fig. 1. 啟動 Broker 流程
當兩個服務互相依賴的時候,可能會陷入死結。例如:
users服務設定了dependencies: ["posts"],posts也設定了dependencies: ["users"]。為避免此狀況,請移除dependencies設定,改使用this.waitForServices來等待多個服務後再啟動。
補充,官方文件是寫在started執行,但筆者測試仍然會死結,建議可以檢查是否有架構設計上的缺陷,或可將微服務再做細分來避免此狀況,例如另外建立一個整合服務來等待兩個服務。
當呼叫 broker.stop 或停止處理程序時,首先 Broker 會透過 Transporter 發送空的服務列表,這時已停止的服務就不會繼續收到請求,而是將請求改送到其它的實例。接著 Broker 會開始停止所有的本地服務,最後中斷 Transporter 的連線並結束處理程序。

Fig. 2. 停止 Broker 流程
在介紹完 Broker 的生命週期後,本節將介紹服務的創建、啟動、停止與合併事件,以及該如何使用生命週期事件來做處理。
created 事件會在服務實例被創建時觸發。例如: broker.createService 、 broker.loadService 。
範例:在服務創建時建立 http 模組實例並存放於 this 中。
const http = require("http");
module.exports = {
name: "www",
created() {
// 建立 HTTP 服務
this.server = http.createServer(this.httpHandler);
}
};
注意,這是個同步事件處理函數,不可以返回
Promise,也不可以使用async/await語法糖。
started 事件會在呼叫 broker.start 並啟動所有本地服務時被觸發。
範例:用於連線到資料庫。
module.exports = {
name: "users",
async started() {
try {
await this.db.connect();
} catch(e) {
throw new MoleculerServerError("Unable to connect to database.", e.message);
}
}
};
注意,這是個非同步事件處理函數,可以返回
Promise,也可以使用async/await語法糖。
stopped 事件會在呼叫 broker.stop 並停止所有本地服務時被觸發。
範例:用於中斷資料庫連線。
module.exports = {
name: "users",
async stopped() {
try {
await this.db.disconnect();
} catch(e) {
this.logger.warn("Unable to stop database connection gracefully.", e);
}
}
};
注意,這是個非同步事件處理函數,可以返回
Promise,也可以使用async/await語法糖。
merged 事件會在綱目 (包含 mixin ) 合併後被呼叫,呼叫完成後才會將服務註冊,因此你可以在這之前就先對其操作。
module.exports = {
name: "posts",
settings: {},
actions: {
find: {
params: {
limit: "number"
},
handler(ctx) {
// ...
}
}
},
merged(schema) {
// 修改服務設定
schema.settings.myProp = "myValue";
// 修改 Actions 的驗證參數
schema.actions.find.params.offset = "number";
}
};
[1] Lifecycle, https://moleculer.services/docs/0.14/lifecycle.html