RabbitMQを介したNode.js上のマイクロサービス間の通信の学習

これは、「 RabbitMQを介した通信を行うNode.jsで最初のマイクロサービスを作成しています」という記事の続きであり、Habrのユーザーに好評でした。


この記事では、マイクロサービスが分離されたままになるように、マイクロサービス間で適切に通信する方法について説明します。


やってはいけない方法


マイクロサービス間で通信する必要があるのはなぜですか? 1つのデータベースを使用し、そこからあなたが望むものを読んでください-ビジネス何か!


いいえ、できません。 マイクロサービスの概念は、それらが互いに分離されていることであり、誰も(実際には)何も知らないということです。 おそらく、将来、システムが成長し始めたら、機能を拡張する必要があり、マイクロサービス間で通信する必要があります。たとえば、ユーザーが製品を購入したため、販売についての通知を販売者に送信する必要があります。


断熱効果


信頼性


いくつかのコントローラーがあるモノリシックアプリケーションがあるとします。


  1. 製品
  2. 割引き
  3. ブログ
  4. ユーザー

ある晴れた日、私たちのデータベースは落ちています。現在、製品、割引、ブログ投稿、ユーザーを入手できません。 サイトは完全に利用できず、顧客はログインできず、ビジネスは利益を失っています。


マイクロサービスアーキテクチャで何が起こりますか?


別のユニバースでは、ユーザーのマイクロサービスデータベースが同じ日に落ち、アクセスできなくなります。ユーザーはログアウト、登録、ログインできません。 すべてが悪く、ビジネスも利益を失っているように見えますが、そうではありません。潜在的な購入者は入手可能な商品を見て、会社のブログを読んで、割引を見つけることができます。


各マイクロサービスには独自のデータベースがあるため、副作用ははるかに少なくなります。


これは段階的劣化と呼ばれます。


抽象化


大規模なアプリケーションでは、いくつかの小さなミドルウェアを変更するとある種のコントローラーが破損する可能性があるため、1つのタスクに集中することは非常に困難です。 新しいクライアントをredisに使用したい-いいえ、できません。3年前に作成したコントローラーはバージョン0.1.0を使用しています。 Node.js 10の新機能を最終的に活用したいですか? それとも12? 申し訳ありませんが、モノリスはバージョン6を使用しています。


コミュニケーション方法


「ユーザーが製品を購入し、販売者に販売通知を送信する」という例について話し始めたので、それを実装します。


スキームは次のとおりです。


  1. ユーザーは、リンクでサービスを購入するリクエストをマイクロサービス市場に送信します/ market / buy /:id
  2. フラグは、製品が販売されているデータベースに書き込まれます
  3. マイクロサービス市場から、マイクロサービス通知にリクエストが送信され、クライアントはWebSocketを介して接続されます
  4. マイクロサービス通知は、物の販売に関するメッセージを売り手に送信します

MicroMQをインストールする


$ npm i micromq@1 -S 

ゲートウェイを書く


 const Gateway = require('micromq/gateway'); //   const gateway = new Gateway({ microservices: ['market'], rabbit: { url: process.env.RABBIT_URL, }, }); //        market gateway.post('/market/buy/:id', (req, res) => res.delegate('market')); //      gateway.listen(process.env.PORT); 

ゲートウェイは1つのエンドポイントのみで構成されていますが、これはたとえばトレーニングやトレーニングには十分です。


マイクロサービス通知の作成


 const MicroMQ = require('micromq'); const WebSocket = require('ws'); //   const app = new MicroMQ({ name: 'notifications', rabbit: { url: process.env.RABBIT_URL, }, }); //        const ws = new WebSocket.Server({ port: process.env.PORT, }); //     const clients = new Map(); //    ws.on('connection', (connection) => { //     connection.on('message', (message) => { //  ,       . //      try/catch,    json! const { event, data } = JSON.parse(message); //   'authorize'         if (event === 'authorize' && data.userId) { //         clients.set(data.userId, connection); } }); }); //       , //    ! ws.on('close', ...); //   notify,      app.action('notify', (meta) => { //      ,    400 if (!meta.userId || !meta.text) { return [400, { error: 'Bad data' }]; } //     const connection = clients.get(meta.userId); //     ,    404 if (!connection) { return [404, { error: 'User not found' }]; } //    connection.send(meta.text); //  200   return { ok: true }; }); //   app.start(); 

ここでは、Webソケットサーバーとマイクロサービスを同時に上げて、WebソケットとRabbitMQの両方の要求を受信します。


スキームは次のとおりです。


  1. ユーザーがWebソケットサーバーに接続します
  2. ユーザーは、内部に自分のuserIdでauthorizeイベントを送信してログインします
  3. 通知を送信できるように、ユーザーの接続を維持します
  4. ユーザーに通知を送信する必要があるイベントがRabbitMQに到着します
  5. 受信データの有効性を確認する
  6. ユーザー接続を取得する
  7. 通知を送信

マイクロサービス市場の作成


 const MicroMQ = require('micromq'); const { Items } = require('./api/mongodb'); //   const app = new MicroMQ({ name: 'market', rabbit: { url: process.env.RABBIT_URL, }, }); //      app.post('/market/buy/:id', async (req, res) => { const { id } = req.params; //      const item = await Items.findOne({ id, isSold: false }); //   ,  404 if (!item) { res.status(404).json({ error: 'Item not found', }); return; } //  ,    ,    await Items.updateOne({ id, }, { $set: { isSold: true, }, }); //     ,    req.app.ask('notifications', { server: { action: 'notify', meta: { userId: item.sellerId, text: JSON.stringify({ event: 'notification', data: { text: `Item #${id} was sold!`, }, }), }, }, }) //  ,      .catch(err => console.log('Cannot send message via notifications microservice', err)); //    ,     res.json({ ok: true, }); }); //   app.start(); 

スキームは次のとおりです。


  1. アイテムの購入に関するユーザーリクエストを受け取りました
  2. 適切なIDのアイテムを探しており、まだ販売されていないことを確認します
  3. アイテムを販売済みとしてマークする
  4. バックグラウンドでの販売に関する通知を販売者に送信します
  5. クライアントに対応します

確認する


  1. 3つのプロセスを開始します
  2. POST / market / buy / 1を送信します
  3. 応答{ ok: true }を取得し{ ok: true }
  4. 売り手は通知を受け取ります

 $ PORT=9000 node ./src/gateway.js $ PORT=9001 node ./src/notifications.js $ MONGODB_URL=mongodb://localhost:27017/my-super-microservice node ./src/market.js 




Source: https://habr.com/ru/post/J447250/


All Articles