示例CloudWeGo的商品服务
1 简介
本文展示了如何使用 Gin 和 CloudWeGo(Hertz + Kitex)框架实现一个电商平台中的商品查询服务。

该示例假设有两个服务:ProductService(商品服务)和 InventoryService(库存服务)。
ProductService 通过 RPC 调用 InventoryService 来获取商品的库存信息,然后返回给客户端。
2 应用设计
Gin 和 CloudWeGo(Hertz + Kitex) 框架的应用示例 假设我们有一个微服务架构,前端客户端请求通过 Gin 和 Hertz 提供的 HTTP 服务进入,后端的微服务通过 Kitex 进行高效的 RPC 调用。
场景:电商平台的商品服务和订单服务
HTTP 层: 客户端向电商平台发送一个请求,查询商品信息,首先会到达 Gin 路由层,进入 Hertz 服务框架进行处理。
Gin 路由器可以将请求转发到后端的商品服务(ProductService)。此时,Hertz 负责优化该请求的高并发处理,确保高效响应。
商品服务(ProductService): 商品服务接收到请求后,可能需要从库存服务查询库存信息,或者从价格服务查询商品价格。 商品服务通过 Kitex 向其他服务(例如:库存服务 InventoryService)发起 RPC 调用,请求库存数据。
RPC 层: Kitex 优化了 RPC 请求的性能,确保商品服务能快速从库存服务获取信息。Kitex 通过高效的序列化和传输机制,减少了延迟。
如果库存服务的响应时间较长,Kitex 会通过智能重试、超时控制等手段来提高系统的容错能力。
响应层: 商品服务处理完库存数据后,会将最终结果通过 Hertz 返回给前端客户端,完成查询请求。
项目结构
    ├── product-service/
    │   ├── main.go           // 商品服务的主程序
    │   ├── handler.go        // 商品服务的 HTTP 处理逻辑
    │   └── product.proto     // 商品服务的 gRPC 服务定义
    ├── inventory-service/
    │   ├── main.go           // 库存服务的主程序
    │   ├── handler.go        // 库存服务的 RPC 处理逻辑
    │   └── inventory.proto   // 库存服务的 gRPC 服务定义
    └── go.mod                // Go模块文件
3 示例代码
- 
- inventory-service/main.go - 库存服务
 
首先定义库存服务,提供一个 RPC 方法获取商品的库存量。
  package main
  import (
      "context"
      "log"
      "net"
      "github.com/cloudwego/kitex/server"
      "github.com/cloudwego/kitex/pkg/rpcinfo"
      "github.com/cloudwego/kitex/client"
      "github.com/cloudwego/kitex/gen/kitex_gen"
      "github.com/cloudwego/kitex/gen/kitex_gen/inventory"
  )
  type InventoryServiceImpl struct{}
  func (s *InventoryServiceImpl) GetInventory(ctx context.Context, req *inventory.GetInventoryRequest) (*inventory.GetInventoryResponse, error) {
      // 模拟库存查询逻辑
      return &inventory.GetInventoryResponse{
          Inventory: 100, // 假设库存为 100
      }, nil
  }
  func main() {
      // 初始化并启动库存服务
      addr := "localhost:8081"
      server := kitex.NewServer(&InventoryServiceImpl{})
      if err := server.Run(); err != nil {
          log.Fatalf("server run failed: %v", err)
      }
  }
- 
- product-service/main.go - 商品服务
 
商品服务通过 HTTP 请求接收查询商品的请求,然后通过 RPC 调用 InventoryService 获取库存信息。
  package main
  import (
      "fmt"
      "github.com/cloudwego/hertz/pkg/app"
      "github.com/cloudwego/hertz/pkg/route"
      "github.com/cloudwego/kitex/client"
      "log"
      "net/http"
      "context"
      "github.com/cloudwego/kitex/gen/kitex_gen"
      "github.com/cloudwego/kitex/gen/kitex_gen/inventory"
  )
  var inventoryClient inventory.InventoryService
  func initInventoryClient() {
      // 初始化 Kitex 客户端,连接到库存服务
      client, err := inventory.NewClient("InventoryService", client.WithHostPorts("localhost:8081"))
      if err != nil {
          log.Fatalf("failed to create inventory client: %v", err)
      }
      inventoryClient = client
  }
  func GetProduct(c context.Context, ctx *app.RequestContext) {
      // 假设商品信息来自数据库
      productID := ctx.DefaultQuery("product_id", "123")
      // RPC 调用获取库存信息
      inventoryResp, err := inventoryClient.GetInventory(c, &inventory.GetInventoryRequest{ProductId: productID})
      if err != nil {
          ctx.JSON(http.StatusInternalServerError, fmt.Sprintf("Failed to get inventory: %v", err))
          return
      }
      // 构造商品的完整信息
      product := map[string]interface{}{
          "product_id": productID,
          "product_name": "Sample Product",
          "inventory": inventoryResp.Inventory,
      }
      // 返回商品信息
      ctx.JSON(http.StatusOK, product)
  }
  func main() {
      // 初始化 Kitex 客户端
      initInventoryClient()
      // 初始化 Hertz 服务
      h := route.New()
      // 定义商品查询接口
      h.GET("/product", GetProduct)
      // 启动服务
      log.Println("Starting ProductService on :8080")
      h.Serve(":8080")
  }
- 
- go.mod - Go模块文件
 
在 go.mod 文件中,声明依赖关系:
module product-service
go 1.18
require (
    github.com/cloudwego/hertz v1.0.0
    github.com/cloudwego/kitex v0.10.3
    github.com/cloudwego/kitex-gen v0.1.5
)
- 
- inventory.proto - 库存服务定义
 
定义一个简单的 gRPC 服务接口,用于获取商品库存信息。
syntax = "proto3";
package inventory;
service InventoryService {
  rpc GetInventory(GetInventoryRequest) returns (GetInventoryResponse);
}
message GetInventoryRequest {
  string product_id = 1;
}
message GetInventoryResponse {
  int32 inventory = 1;
}
- 
- product.proto - 商品服务定义(可选)
 
在商品服务中,定义类似的 gRPC 接口来与其他服务进行交互,尽管这里暂时不涉及具体的 product.proto 文件。
- 
- 运行步骤
 
启动库存服务:
在 inventory-service 目录下,运行库存服务:
		go run main.go
启动商品服务:
在 product-service 目录下,运行商品服务:
		go run main.go
访问商品查询接口:
打开浏览器或 Postman,访问  localhost 8080 product?product_id=123,查看返回的商品信息及库存。
inventory-service 提供了一个简单的 RPC 接口 GetInventory,用于返回商品的库存量。
product-service 是前端接入的 HTTP 服务,用户通过 HTTP 请求查询商品信息,商品服务则通过 Kitex 客户端发起 RPC 请求,查询库存服务,获取库存数据。
Gin 在此例中主要作为 HTTP 框架,Hertz 在后端处理高并发的 HTTP 请求,Kitex 则在服务间进行高效的 RPC 调用。
4 小结:
通过将 Gin 与 Hertz 用于 HTTP 请求处理,并结合 Kitex 进行高效的服务间 RPC 调用,这个例子展示了如何在微服务架构中高效地处理请求与服务间通信。
Hertz 和 Kitex 提供了出色的性能优化,特别适合于高吞吐量、低延迟的场景。
- 点赞
- 收藏
- 关注作者
 
             
           
评论(0)