Golang は、もともと Google によって設計および開発された、高速で静的に型指定され、コンパイルされたプログラミング言語です。 Golang は、Web アプリケーションやクラウド システムの開発、特に同時実行性の高いシナリオで広く使用されています。
現代の Web アプリケーションでは、長時間接続は非常に重要なテクノロジです。これは、通常の HTTP リクエストでは、クライアントがサーバーから応答を受信すると接続が閉じられるためです。これにより、各リクエストが接続を確立したり閉じたりすることになり、サーバーとクライアントのパフォーマンスに大きな影響を与えます。長時間接続テクノロジは、クライアントとサーバーが相互に通信し、接続を継続的に維持できるように接続を維持する方法です。この記事では、Golang の長時間接続ソリューションを紹介し、その長所と短所について説明します。
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 接続は全二重であるため、サーバーが多数のクライアントにメッセージをブロードキャストする必要がある場合、多数の長い接続を維持する必要があり、大量のメモリ リソースを占有します。
サーバー送信イベント (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 は適切ではない可能性があります。
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 サイトの他の関連記事を参照してください。