ホームページ >バックエンド開発 >Golang >golang の長い接続ソリューション

golang の長い接続ソリューション

PHPz
PHPzオリジナル
2023-05-13 09:48:36923ブラウズ

Golang は、もともと Google によって設計および開発された、高速で静的に型指定され、コンパイルされたプログラミング言語です。 Golang は、Web アプリケーションやクラウド システムの開発、特に同時実行性の高いシナリオで広く使用されています。

現代の Web アプリケーションでは、長時間接続は非常に重要なテクノロジです。これは、通常の HTTP リクエストでは、クライアントがサーバーから応答を受信すると接続が閉じられるためです。これにより、各リクエストが接続を確立したり閉じたりすることになり、サーバーとクライアントのパフォーマンスに大きな影響を与えます。長時間接続テクノロジは、クライアントとサーバーが相互に通信し、接続を継続的に維持できるように接続を維持する方法です。この記事では、Golang の長時間接続ソリューションを紹介し、その長所と短所について説明します。

  1. WebSocket

WebSocket は、単一の TCP 接続を介した全二重通信用のプロトコルです。 HTTP プロトコルを使用して接続を確立し、それを WebSocket プロトコルに変換して長時間の接続を実現します。 WebSocket プロトコルを使用すると、クライアントとサーバーは接続を閉じることなく相互に通信できるため、メッセージを効率的に配信できます。

Golang の標準ライブラリは、WebSocket サーバーとクライアントの実装に使用できる組み込み WebSocket パッケージ (「net/http」) を提供します。以下は、単純な WebSocket サーバーの例です。

package main

import (
    "fmt"
    "log"
    "net/http"
    "github.com/gorilla/websocket"
)

var upgrader = websocket.Upgrader{
    ReadBufferSize:  1024,
    WriteBufferSize: 1024,
    CheckOrigin: func(r *http.Request) bool {
        return true
    },
}

func wsHandler(w http.ResponseWriter, r *http.Request) {
    conn, err := upgrader.Upgrade(w, r, nil)
    if err != nil {
        log.Println("websocket upgrade error:", err)
        return
    }

    for {
        _, msg, err := conn.ReadMessage()
        if err != nil {
            break
        }

        fmt.Printf("received message: %s
", msg)
    }
}

func main() {
    http.HandleFunc("/ws", wsHandler)
    http.ListenAndServe(":8080", nil)
}

この例では、WebSocket リクエストをより簡単に処理できる Gorilla WebSocket ライブラリを使用します。 websocket.Upgrader() 関数を使用して、HTTP 接続を WebSocket 接続にアップグレードします。 wsHandler() 関数では、クライアントからのメッセージを継続的にリッスンします。

WebSocket を使用する利点は、双方向通信を簡単に実現できることです。クライアントとサーバーはどちらも、接続を閉じることなくメッセージを送受信できます。さらに、WebSocket プロトコルはオーバーヘッドが少なく、効率的にデータを送信できます。欠点は、WebSocket がブラウザまたはクライアント アプリケーションからの特別なサポートを必要とすることです。一部の下位バージョンのブラウザまたはクライアントでは、WebSocket テクノロジに問題が発生する可能性があります。さらに、WebSocket 接続は全二重であるため、サーバーが多数のクライアントにメッセージをブロードキャストする必要がある場合、多数の長い接続を維持する必要があり、大量のメモリ リソースを占有します。

  1. サーバー送信イベント

サーバー送信イベント (SSE) は、Web アプリケーションに長時間接続を実装するためのもう 1 つのテクノロジです。 SSE は、サーバーがクライアントにデータを送信する方法を提供し、このデータはリアルタイムです。 WebSocket とは異なり、SSE は単一のストリームであり、サーバーがクライアントにデータを送信することのみを許可しますが、クライアントがサーバーにデータを送信することはサポートしません。

Golang を使用した SSE の実装は非常に簡単です。 SSE サーバーの例を次に示します。

package main

import (
    "fmt"
    "log"
    "net/http"
)

func sseHandler(w http.ResponseWriter, r *http.Request) {
    w.Header().Set("Content-Type", "text/event-stream")
    w.Header().Set("Cache-Control", "no-cache")
    w.Header().Set("Connection", "keep-alive")

    for {
        fmt.Fprintf(w, "data: %s

", "Hello, world!")
        w.(http.Flusher).Flush()

        // Artificially slow down the server so
        // that we're forced to use multiple connections.
        time.Sleep(1 * time.Second)
    }
}

func main() {
    http.HandleFunc("/sse", sseHandler)
    http.ListenAndServe(":8080", nil)
}

この例では、HTTP 応答ヘッダーを設定して、1 回限りの応答を待つのではなく、サーバー送信イベントを受信して​​いることをブラウザーに伝えます。簡単なメッセージをクライアントに送信し、http.Flusher を使用して応答をクライアントにすぐに送信します。次に、少し待って、新しいメッセージを再度送信します。

サーバー送信イベントを使用する利点は、HTTP プロトコルを使用するため、特別なプロトコルのサポートが必要ないことです。さらに、SSE データは解析が容易なため、サーバーがリアルタイムでクライアントにデータをプッシュすることをサポートするアプリケーションに最適です。欠点は、SSE は一方向通信のみをサポートし、サーバーがクライアントにデータを送信することしかできないことです。クライアントがサーバーにデータを送信する必要があるアプリケーションの場合、SSE は適切ではない可能性があります。

  1. gRPC

gRPC は、データ交換に Google のプロトコル バッファを使用する、拡張性が高くパフォーマンスが最適化されたリモート プロシージャ コール (RPC) プロトコルです。その目標は、クライアント アプリケーションがサーバー アプリケーションと線形時間で通信できるようにし、従来の HTTP REST API に代わるスケーラブルで効率的な代替手段を提供することです。

gRPC は長時間接続用に特別に設計されたものではありませんが、長時間接続の実装にも使用できます。 gRPC はトランスポートに HTTP/2 を使用するため、大量のデータを迅速かつ確実に転送でき、サーバー プッシュをサポートします。 gRPC を使用すると、クライアントはサーバーとの長い接続を確立でき、サーバーはいつでもクライアントにメッセージをプッシュできます。

以下は簡単な gRPC サーバーの例です:

package main

import (
    "context"
    "fmt"
    "log"
    "net"
    "google.golang.org/grpc"
    pb "github.com/proto/example"
)

type server struct{}

func (s *server) Push(ctx context.Context, in *pb.Message) (*pb.Response, error) {
    log.Printf("received message: %v", in)

    return &pb.Response{Code: 200}, nil
}

func main() {
    lis, err := net.Listen("tcp", ":9090")
    if err != nil {
        log.Fatalf("failed to listen: %v", err)
    }
    s := grpc.NewServer()
    pb.RegisterPushServer(s, &server{})
    if err := s.Serve(lis); err != nil {
        log.Fatalf("failed to serve: %v", err)
    }
}

この例では、メッセージの送信時に Called を受け取る Push() 関数を定義します。 。この関数では、必要に応じてクライアントからの情報を処理し、必要に応じてメッセージをクライアントにプッシュできます。

gRPC を使用する利点は、大量のデータを迅速かつ確実に転送できることと、サーバー プッシュをサポートしていることです。さらに、gRPC はトランスポートに HTTP/2 を使用するため、多重化やサーバー プッシュなどの HTTP/2 の利点を活用できます。欠点は、gRPC のセットアップと開始に多くの時間とリソースが必要になる可能性があり、クライアントとサーバーの両方が gRPC プロトコルをサポートする必要があることです。

要約

それぞれの長い接続テクノロジには、独自の長所と短所があります。 WebSocket は、双方向通信を実現できる強力な長期接続テクノロジですが、特別なサポートが必要であり、サーバー リソースの需要が大きくなります。 Server-Sent Events もシンプルな長期接続テクノロジであり、使用と実装が簡単ですが、一方向の通信のみをサポートします。 gRPC は、スケーラビリティが高く、パフォーマンスが最適化されたリモート プロシージャ コール (RPC) プロトコルで、大量のデータを迅速かつ確実に転送でき、サーバー プッシュをサポートしますが、セットアップと起動にはより多くの時間とリソースが必要となる場合があり、クライアントとサーバーは gRPC プロトコルをサポートします。

ほとんどの Web アプリケーションでは、WebSocket と Server-Sent Events がおそらく最良の選択です。これらは使用と実装が簡単で、ほとんどの場合、長時間の接続のニーズを満たすことができます。大量のデータを処理する必要がある場合、またはサーバーがリアルタイムでクライアントにデータをプッシュする必要がある場合は、gRPC の方が良い選択となる可能性があります。どのテクノロジーを選択する場合でも、アプリケーションのニーズとシナリオに基づいて選択し、最適化する必要があります。

以上がgolang の長い接続ソリューションの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

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