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
      
      














All Articles