ホームページ  >  記事  >  バックエンド開発  >  Golang を使用してメッセージ転送を実装する方法

Golang を使用してメッセージ転送を実装する方法

PHPz
PHPzオリジナル
2023-04-27 09:11:24832ブラウズ

Golang は、完璧な同時実行制御メカニズムと豊富な標準ライブラリ関数を備えた、効率的で簡潔かつ強力なプログラミング言語です。クラウドコンピューティング、ネットワークプログラミング、分散システム、マイクロサービスなどの分野で広く使用されています。これらのアプリケーション シナリオでは、メッセージ転送は非常に重要な機能です。この記事では、Golang を使用してメッセージ転送を実装する方法を紹介します。

  1. メッセージ モデル

メッセージ転送アプリケーションでは、最も重要なものはメッセージ モデルです。メッセージ モデルは、システム内でメッセージを配信するために使用されるデータ構造と対話方法を指します。通常、メッセージ モデルには次の特性が必要です。

1.1 柔軟性

メッセージ モデルは、さまざまなメッセージ タイプをサポートするために、ある程度の柔軟性を備えている必要があります。たとえば、メッセージはテキスト、バイナリ データ、画像、ビデオなどです。

1.2 信頼性

メッセージの配信を保証するには、メッセージ モデルにはある程度の信頼性が必要です。分散システムでは、メッセージが宛先ノードに到達するために複数のネットワーク ノードを通過する必要がある場合があります。したがって、ネットワークの問題やその他の異常な状況によってメッセージが失われないようにする必要があります。

1.3 効率

システムのパフォーマンスとユーザー エクスペリエンスを確保するには、メッセージ モデルにはある程度の効率が必要です。メッセージ転送アプリケーションでは、メッセージ送信によるシステムのフリーズや遅延を引き起こすことなく、メッセージをターゲット ノードに迅速に送信する必要があります。

上記の特性に基づいて、次の図に示すように、基本的なメッセージ モデルを設計できます。

Golang を使用してメッセージ転送を実装する方法

図のメッセージ モデルには、以下の部分:

  • メッセージ ヘッダー: メッセージ タイプ、送信者 ID、受信者 ID などのメッセージのメタ情報が含まれます。
  • メッセージ本文: テキスト、画像、バイナリ データなどのメッセージの実際のコンテンツが含まれます。
  • メッセージ キュー: メッセージの安定した配信を保証するためにメッセージをキャッシュするために使用されます。これは、Redis、Kafka、RocketMQ などのキュー テクノロジを使用して実現できます。
  • メッセージ ルーティング: ターゲット ノードにメッセージを送信するために使用され、RPC、HTTP、およびその他のプロトコルを使用して実装できます。
  1. メッセージ転送の実装

メッセージ モデルの設計が完了したら、メッセージ転送の具体的な実装を検討する必要があります。一般的に、メッセージ転送には次の 2 つの方法が使用できます。

2.1 ポイントツーポイント方法

ポイントツーポイント方法とは、メッセージ送信者がメッセージを直接送信することを意味します。メッセージ受信者。この方法の利点は、実装が簡単で、メッセージ送信が高速であることです。ただし、分散システムでは、ノード障害やネットワーク パケット損失などの問題が発生し、メッセージが正しく配信されなくなる可能性があります。

2.2 パブリッシュ/サブスクライブ方式

パブリッシュ/サブスクライブ方式とは、中央のメッセージ サーバーにメッセージを送信し、サブスクライバー (受信者) がサーバーからの関心のあるメッセージをサブスクライブすることを指します。この方法の利点は、メッセージの信頼性が高く、ノード障害などの問題が中央サーバーによって自動的に処理されることです。欠点は、実装が比較的複雑で、ネットワーク伝送遅延がある程度増加することです。

以下では、Golang を使用して、パブリッシュとサブスクライブに基づくメッセージ転送モジュールを実装します。メッセージ キューとして Redis を使用し、メッセージ ルーティングには RPC プロトコルを使用します。

2.3 メッセージ キューの設計

Redis は、メッセージ キューとしても使用できる、高速で安定したメモリ キャッシュ データベースです。以下は、Redis をメッセージ キューとして使用するためのコア コード フラグメントです。

type RedisBroker struct {
    client *redis.Client
    topic  string
}

func NewRedisBroker(address, password, topic string) *RedisBroker {
    client := redis.NewClient(&redis.Options{
        Addr:     address,
        Password: password,
    })

    return &RedisBroker{
        client: client,
        topic:  topic,
    }
}

func (b *RedisBroker) Publish(msg *Message) error {
    data, err := json.Marshal(msg)
    if err != nil {
        return err
    }

    _, err = b.client.LPush(b.topic, data).Result()
    if err != nil {
        return err
    }

    return nil
}

func (b *RedisBroker) Subscribe() (<p> 上記のコードでは、RedisBroker と呼ばれる構造を実装しました。これは、Redis の LPush メソッドと Subscribe メソッドをカプセル化し、メッセージを送信するために使用されます。メッセージをプッシュし、メッセージ キューにサブスクライブします。 Broker インスタンスの作成後、Publish メソッドを使用して Redis キューにメッセージをプッシュし、Subscribe メソッドを使用して Redis キュー内のメッセージをサブスクライブできます。メッセージ処理関数では、Redis メッセージ内の Message オブジェクトを解析し、RPC サービスに送信します。 </p><p>2.4 メッセージ ルーティングの設計</p><p>RPC プロトコルは、TCP/IP プロトコルに基づくリモート プロシージャ コール プロトコルで、ネットワーク経由でリモート ノードに関数呼び出しを配信し、結果を返します。 RPC プロトコルを使用してメッセージ ルーティングを実装します。以下は、gRPC 実装に基づくコア コード スニペットです: </p><pre class="brush:php;toolbar:false">type Server struct {
    brok *RedisBroker
}

func (s *Server) Send(ctx context.Context, msg *proto.Message) (*proto.Response, error) {
    log.Printf("Receive message from %v to %v: %v", msg.Sender, msg.Receiver, msg.Text)

    // Publish message to Redis
    err := s.brok.Publish(&Message{
        Sender:   msg.Sender,
        Receiver: msg.Receiver,
        Text:     msg.Text,
    })
    if err != nil {
        log.Println("failed to publish message:", err)
    }

    return &proto.Response{Ok: true}, nil
}

func StartRPCService(address string, brok *RedisBroker) {
    lis, err := net.Listen("tcp", address)
    if err != nil {
        log.Fatalf("failed to listen: %v", err)
    }

    s := grpc.NewServer()

    proto.RegisterMessageServiceServer(s, &Server{
        brok: brok,
    })

    log.Println("start rpc service at", address)

    if err := s.Serve(lis); err != nil {
        log.Fatalf("failed to serve: %v", err)
    }
}

上記のコードでは、gRPC プロトコルに基づいてサーバー構造を実装しました。受信したメッセージを Redis キューに送信するための Send メソッド。 Send メソッドでは、gRPC メッセージを解析して Message オブジェクトに変換し、RedisBroker の Publish メソッドを通じてメッセージを Redis キューに送信します。 RPC サービスを開始するときは、s.Serve メソッドを通じて RPC サービスを開始し、アドレス address で TCP 接続を待機します。

  1. 使用例

パブリッシュとサブスクライブに基づいてメッセージ転送モジュールを実装したので、それをテストできます。ターミナルで RPC サービスを開始できます:

func main() {
    // New Redis broker
    broker := NewRedisBroker("localhost:6379", "", "go-message-broker")

    // Start RPC service
    StartRPCService(":9090", broker)
}

次に、クライアント プログラムを作成し、クライアント プログラムにレシーバーを実装し、Redis キューからレシーバー ID が「receiver-01」のメッセージをサブスクライブします。

func main() {
    // New Redis broker
    broker := NewRedisBroker("localhost:6379", "", "go-message-broker")

    // Receive message
    ch, err := broker.Subscribe()
    if err != nil {
        log.Fatal("subscribe error:", err)
    }

    for {
        select {
        case message := <p>同時に、メッセージ送信の動作をシミュレートする送信者も必要です。 </p><pre class="brush:php;toolbar:false">func main() {
    // New RPC client
    conn, err := grpc.Dial(":9090", grpc.WithInsecure())
    if err != nil {
        log.Fatalf("did not connect: %v", err)
    }
    defer conn.Close()

    c := proto.NewMessageServiceClient(conn)

    // Send message
    _, err = c.Send(context.Background(), &proto.Message{
        Sender:   "sender-01",
        Receiver: "receiver-01",
        Text:     "hello go message broker",
    })
    if err != nil {
        log.Fatalf("could not send message: %v", err)
    }
}

上記の 3 つのプログラムを実行すると、送信者はメッセージを送信し、受信者はメッセージを受信します。と同時に、関連するログ出力が送信側と受信側の端末に表示されるようになります。

  1. 概要

この記事では、Golang を使用して、パブリッシュとサブスクライブに基づいたメッセージ転送モジュールを実装する方法を紹介します。 Redis キューと RPC プロトコルを使用することで、効率的で柔軟かつ信頼性の高いメッセージ転送システムを実装しました。もちろん、これは単なる実装であり、実際の運用環境では、メッセージの署名、セキュリティの保証、負荷分散など、さらに多くの問題に対処する必要があります。しかし、この記事で説明する内容を学ぶことで、メッセージ送信における Golang のコア技術と考え方を習得し、より効率的で信頼性の高い分散システムの開発をサポートすることができます。

以上がGolang を使用してメッセージ転送を実装する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。