iT邦幫忙

2022 iThome 鐵人賽

DAY 15
1

註冊與探索

動態服務探索

試想當一個節點啟動時,遠端節點該如何知道它的存在? 在 Moleculer 框架就有一個內建模組可以用來探索及定期 Heartbeat 驗證。節點一開始啟動時不需要知道其他節點的相關服務資訊,但它會向其他節點宣告它的存在,以便每個節點都可以獲得自己的本地服務註冊清單。假如節點掛掉或是停止的時候,其它節點會偵測受影響的服務,並且將它從本地註冊清單移除,如此一來才能將請求路由到活躍的節點。

本地探索

Moleculer 預設的本地探索會使用 Transporter 模組來交換節點資訊及 Heartbeat 封包(關於封包結構請參考 Moleculer 協定[2] )。本地是內建機制中最簡單且最快的,它是個不需要任何外部依賴的解決方案。但是此方法也有缺點,尤其是超過 100 個節點的大型部署。它在傳輸 Heartbeat 封包時會產生大量流量,當通訊傳輸流量滿載時,將造成請求與響應的速度變慢,進而影響 Action 與事件的效率。

注意,因為 TCP Transporter 使用了 Gossip 協定及 UDP 封包進行探索及實施 Heartbeat 機制,因此它只能選擇使用本地探索方式。

範例:快速使用

moleculer.config.js

module.exports = {
    registry: {
        discoverer: "Local"
    }
}

範例:選項設定方式

moleculer.config.js

module.exports = {
    registry: {
        discoverer: {
            type: "Local",
            options: {
                // 每 10 秒發送一次 heartbeat 封包
                heartbeatInterval: 10,
                // Heartbeat 逾時 30 秒
                heartbeatTimeout: 30,
                // 停用 heartbeat 驗證機制
                disableHeartbeatChecks: false,
                // 停用離線節點移除機制
                disableOfflineNodeRemoving: false,
                // 10 分鐘後移除離線節點
                cleanOfflineNodesTimeout: 10 * 60
            }
        }
    }
}

Redis

Redis[3] 是透過一個專用的連線服務來交換探索資訊及 Heartbeat 封包,這種方法可以降低 Transporter 模組的負擔,使得它可以專注於處理請求、響應、事件封包的傳遞。當啟用 Redis 探索方法時,Moleculer 節點會定期向 Redis 收發遠端節點資訊,並更新本地服務註冊清單。當節點的 Heartbeat 封包於一定時間內沒有回應,也就是該節點已斷線的話,Redis 將會自動移除過期的密鑰。

注意,由於此方法必須依賴 Redis 服務做定期 Heartbeat 檢查,因此檢測新節點的速度較慢,如果你想要快一點可以調整 heartbeatInterval 選項。

使用前請安裝 ioredis 套件 npm install ioredis --save

範例:快速使用

moleculer.config.js

module.exports = {
    registry: {
        discoverer: "Redis"
    }
}

範例:連線到遠端 Redis 服務器

moleculer.config.js

module.exports = {
    registry: {
        discoverer: "redis://redis-server:6379"
    }
}

範例:選項設定方式

moleculer.config.js

module.exports = {
    registry: {
        discoverer: {
            type: "Redis",
            options: {
                redis: {
                    // Redis 連線選項
                    // 更多資訊: https://github.com/luin/ioredis#connect-to-redis
                    port: 6379,
                    host: "redis-server",
                    password: "123456",
                    db: 3
                }
                // 序列化器
                serializer: "JSON",
                // 使用完整的 heartbeat 檢測將消耗更多的流量
                // 10 表示每 10 個週期執行一次
                fullCheck: 10,
                // 一次掃描的大小
                scanLength: 100,
                // 顯示 Redis 命令
                monitor: true,
                // 以下為通用探索選項
                // 每 10 秒發送一次 heartbeat 封包
                heartbeatInterval: 10,
                // Heartbeat 逾時 30 秒
                heartbeatTimeout: 30,
                // 停用 heartbeat 驗證機制
                disableHeartbeatChecks: false,
                // 停用離線節點移除機制
                disableOfflineNodeRemoving: false,
                // 10 分鐘後移除離線節點
                cleanOfflineNodesTimeout: 10 * 60
            }
        }
    }    
}

若要進一步減少流量,請參考前一篇網路連結中的序列化工具,而非使用 JSON 序列化。

etcd3

Etcd3[4] 的探索方法與 Redis 相似,會在 Etcd3 服務器上儲存探索資訊及 Heartbeat 封包。etcd3 會透過 Lease 機制來檢測活躍度,當叢集的 Heartbeat 封包於一定時間內沒有回應,會將過期節點的密鑰都刪除[5] 。因此 Etcd3 與 Redis 的探索具有相同的優缺點,它不會使用 Transporter 模組進行探索,也因此檢測新節點的速度較慢。

使用前請安裝 etcd3 套件 npm install etcd3 --save

範例:快速使用

moleculer.config.js

module.exports = {
    registry: {
        discoverer: "Etcd3"
    }
}

範例:連線到遠端 Redis 服務器

moleculer.config.js

module.exports = {
    registry: {
        discoverer: "etcd3://etcd-server:2379"
    }
}

範例:選項設定方式

moleculer.config.js

module.exports = {
    registry: {
        discoverer: {
            type: "Etcd3",
            options: {
                etcd: {
                    // etcd3 連線選項
                    // 更多資訊: https://mixer.github.io/etcd3/interfaces/options_.ioptions.html
                    hosts: "etcd-server:2379",
                    auth: "12345678"
                }
                // 序列化器
                serializer: "JSON",
                // 使用完整的 heartbeat 檢測將消耗更多的流量
                // 10 表示每 10 個週期執行一次
                fullCheck: 10,
                // 以下為通用探索選項
                // 每 10 秒發送一次 heartbeat 封包
                heartbeatInterval: 10,
                // Heartbeat 逾時 30 秒
                heartbeatTimeout: 30,
                // 停用 heartbeat 驗證機制
                disableHeartbeatChecks: false,
                // 停用離線節點移除機制
                disableOfflineNodeRemoving: false,
                // 10 分鐘後移除離線節點
                cleanOfflineNodesTimeout: 10 * 60
            }
        }
    }    
}

客製化探索器

你可以建立客製化探索器模組,官方建議可以參考 Redis 探索器的原始碼[6] 來修改,再實作必要的方法。

內建服務註冊清單

Moleculer 有一個內建的服務註冊模組,它儲存了關於服務、 Actions 、事件監聽和節點資訊。當你呼叫 Action 或發送事件時, Broker 會由註冊表查詢可執行請求的節點。假如存在多個節點,則會根據負載平衡規則來選擇節點。

註冊清單可由服務呼叫 broker.call("$node.list"); 取得。

關於負載平衡規則將在下一個章節進行說明。

參考文獻

[1] Registry & Discovery, https://moleculer.services/docs/0.14/registry.html
[2] Protocol 4.0 (rev. 1), https://github.com/moleculer-framework/protocol/blob/master/4.0/PROTOCOL.md
[3] Redis, https://redis.io/
[4] etcd, https://etcd.io/
[5] Lease API, https://etcd.io/docs/v3.5/learning/api/#lease-api
[6] Redis discoverer, https://github.com/moleculerjs/moleculer/blob/master/src/registry/discoverers/redis.js

家家酒小劇場

  • Otter - 微服務節點會很容易斷線嗎?
  • Boxy - 這很難說,在設計服務的時候就必須先考慮微服務隨時可能出錯,在微服務之間呼叫的時候都需要做好保護機制,以及適當的設定逾時來避免服務突然失效。

上一篇
Day 14 : 網路連結
下一篇
Day 16 : 負載平衡
系列文
Moleculer 家家酒31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言