文章目录

Go 网络编程:HTTP/2 与 gRPC

发布于 2026-04-06 12:29:00 · 浏览 15 次 · 评论 0 条

Go 网络编程:HTTP/2 与 gRPC

Go 语言标准库对 HTTP/2 有着原生且强大的支持,而 gRPC 则是基于 HTTP/2 构建的高性能 RPC 框架。掌握这两者的开发流程,是构建现代微服务架构的关键。


第一阶段:构建 HTTP/2 服务器

HTTP/2 相比 HTTP/1.1 具有多路复用、头部压缩等优势。在 Go 中,只需少量配置即可启用。

1. 生成自签名证书

HTTP/2 标准强制要求使用 TLS(传输层安全协议)。若没有域名和正规证书,需本地生成自签名证书用于测试。

打开 终端,执行 以下 OpenSSL 命令生成私钥文件 server.key 和证书文件 server.crt

openssl req -newkey rsa:2048 -nodes -keyout server.key -x509 -days 365 -out server.crt

输入 提示所需的国家、城市等信息(测试用途可直接回车跳过)。

2. 编写 HTTP/2 服务端代码

Go 的 net/http 标准库在启用 TLS 时会自动协商使用 HTTP/2。

创建 文件 server.go写入 以下代码:

package main

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

func main() {
    // 定义处理函数
    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        // 检查是否为 HTTP/2 协议
        if r.ProtoMajor == 2 {
            fmt.Fprintf(w, "Welcome to HTTP/2 Protocol")
        } else {
            fmt.Fprintf(w, "Welcome to HTTP/1.1")
        }
    })

    // 配置服务器结构体
    server := &http.Server{
        Addr:    ":8443",
        Handler: nil, // 使用 DefaultServeMux
    }

    // 启动 TLS 服务,ListenAndServeTLS 会自动启用 HTTP/2
    log.Println("Server starting on https://localhost:8443")
    log.Fatal(server.ListenAndServeTLS("server.crt", "server.key"))
}

运行 服务端:

go run server.go

3. 验证 HTTP/2 连接

由于使用自签名证书,使用 curl 时需加 -k 参数忽略证书验证。

执行 以下命令:

curl -k --http2 https://localhost:8443/

若输出 Welcome to HTTP/2 Protocol,则表明 HTTP/2 服务搭建成功。


第二阶段:gRPC 快速实战

gRPC 默认使用 Protocol Buffers (Protobuf) 作为接口定义语言 (IDL) 和消息交换格式。

1. 环境准备

安装 Protobuf 编译器 protoc 与 Go 代码生成插件。

执行 安装插件命令:

go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest

更新 PATH 环境变量(若未自动添加):

export PATH="$PATH:$(go env GOPATH)/bin"

2. 定义 Protobuf 接口

创建 项目目录 grpc-demo,并在其中 创建 proto/service.proto 文件。

写入 以下定义:

syntax = "proto3";

package demo;

option go_package = "./pb";

// 定义服务接口
service Greeter {
  rpc SayHello (HelloRequest) returns (HelloReply) {}
}

// 定义请求消息
message HelloRequest {
  string name = 1;
}

// 定义响应消息
message HelloReply {
  string message = 1;
}

3. 生成 Go 代码

进入 项目根目录 grpc-demo执行 编译命令:

protoc --go_out=. --go_opt=paths=source_relative \
    --go-grpc_out=. --go-grpc_opt=paths=source_relative \
    proto/service.proto

确认 生成的文件:目录 proto/pb 下应出现 service.pb.goservice_grpc.pb.go 两个文件。

4. 实现 gRPC 服务端

初始化 Go 模块:

go mod init grpc-demo
go mod tidy

创建 server/main.go实现 接口逻辑:

package main

import (
    "context"
    "fmt"
    "google.golang.org/grpc"
    "grpc-demo/proto/pb"
    "log"
    "net"
)

type server struct {
    pb.UnimplementedGreeterServer
}

// 实现 SayHello 方法
func (s *server) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) {
    return &pb.HelloReply{Message: fmt.Sprintf("Hello, %s! (via gRPC)", in.Name)}, nil
}

func main() {
    // 监听 TCP 端口
    lis, err := net.Listen("tcp", ":50051")
    if err != nil {
        log.Fatalf("failed to listen: %v", err)
    }

    // 创建 gRPC 服务器实例
    s := grpc.NewServer()

    // 注册服务
    pb.RegisterGreeterServer(s, &server{})

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

5. 编写 gRPC 客户端

创建 client/main.go编写 调用逻辑:

package main

import (
    "context"
    "google.golang.org/grpc"
    "google.golang.org/grpc/credentials/insecure"
    "grpc-demo/proto/pb"
    "log"
)

func main() {
    // 建立连接 (本例不使用 TLS,使用 insecure)
    conn, err := grpc.Dial("localhost:50051", grpc.WithTransportCredentials(insecure.NewCredentials()))
    if err != nil {
        log.Fatalf("did not connect: %v", err)
    }
    defer conn.Close()

    // 创建客户端存根
    c := pb.NewGreeterClient(conn)

    // 调用远程方法
    r, err := c.SayHello(context.Background(), &pb.HelloRequest{Name: "Developer"})
    if err != nil {
        log.Fatalf("could not greet: %v", err)
    }

    log.Printf("Server Response: %s", r.GetMessage())
}

6. 运行与测试

启动 服务端:

go run server/main.go

另开 终端窗口,运行 客户端:

go run client/main.go

查看 输出结果,若显示 Server Response: Hello, Developer! (via gRPC),则表示 gRPC 通信成功。


第三阶段:通信流程解析

gRPC 的调用过程封装了复杂的网络交互。以下是客户端调用服务端方法的完整流程示意。

sequenceDiagram participant Client as "gRPC Client" participant Stub as "Client Stub" participant Net as "Network (HTTP/2)" participant Server as "gRPC Server" Client->>Stub: "1. Call Method(Name)" Stub->>Stub: "2. Serialize (Protobuf)" Stub->>Net: "3. Send HTTP/2 Stream" Net->>Server: "4. Transmit Data" Server->>Server: "5. Deserialize & Execute" Server-->>Net: "6. Send Response" Net-->>Stub: "7. Receive Data" Stub-->>Client: "8. Return Result"

核心差异对比

原生 HTTP/2 与 gRPC 在开发模式与性能特征上存在显著区别。

特性 原生 HTTP/2 (net/http) gRPC
数据格式 文本 (Header) + 二进制 (Body) Protocol Buffers (二进制)
代码生成 通常需手写 Handler 自动生成 Client/Server 代码
连接类型 支持 HTTP/2 多路复用 强制 HTTP/2,长连接流式传输
适用场景 浏览器与服务端通信 微服务间高性能通信

评论 (0)

暂无评论,快来抢沙发吧!

扫一扫,手机查看

扫描上方二维码,在手机上查看本文