使用Facebook/Ent框架快速生成gRPC服务端

使用Facebook/Ent框架快速生成gRPC服务端

ent ent 项目地址: https://gitcode.com/gh_mirrors/ent4/ent

前言

在现代微服务架构中,gRPC因其高效的二进制协议和跨语言支持而广受欢迎。而Ent作为Go语言中强大的实体框架,为数据访问层提供了优雅的解决方案。本文将介绍如何利用Ent框架快速生成一个功能完整的gRPC服务端,实现数据的CRUD操作。

准备工作

首先确保你的开发环境已经安装以下工具:

  • Go 1.16+
  • Protocol Buffers编译器(protoc)
  • protoc-gen-go插件
  • protoc-gen-go-grpc插件

项目初始化

创建一个新项目并初始化Go模块:

mkdir ent-grpc-demo
cd ent-grpc-demo
go mod init ent-grpc-demo

定义Ent Schema

  1. 首先使用Ent CLI工具初始化User实体:
go run -mod=mod entgo.io/ent/cmd/ent new User
  1. 添加entproto依赖:
go get -u entgo.io/contrib/entproto
  1. 编辑ent/schema/user.go文件,定义User实体的结构:
package schema

import (
	"entgo.io/ent"
	"entgo.io/ent/schema"
	"entgo.io/ent/schema/field"
	"entgo.io/contrib/entproto"
)

type User struct {
	ent.Schema
}

func (User) Fields() []ent.Field {
	return []ent.Field{
		field.String("name").
			Unique().
			Annotations(
				entproto.Field(2),
			),
		field.String("email_address").
			Unique().
			Annotations(
				entproto.Field(3),
			),
	}
}

func (User) Annotations() []schema.Annotation {
	return []schema.Annotation{
		entproto.Message(),
		entproto.Service(),
	}
}

关键点说明:

  • entproto.Message()注解表示要为该实体生成Protobuf消息
  • entproto.Service()注解表示要生成gRPC服务
  • 每个字段都需要通过entproto.Field()指定Protobuf字段编号

代码生成

  1. 修改ent/generate.go文件,添加生成指令:
package ent

//go:generate go run -mod=mod entgo.io/ent/cmd/ent generate ./schema
//go:generate go run -mod=mod entgo.io/contrib/entproto/cmd/entproto -path ./schema
  1. 执行代码生成:
go generate ./...

这个命令会生成:

  • Ent的基础CRUD操作代码
  • Protobuf消息定义(.proto文件)
  • gRPC服务接口
  • gRPC服务实现

实现gRPC服务端

创建服务端主程序cmd/server/main.go

package main

import (
	"context"
	"log"
	"net"

	_ "github.com/mattn/go-sqlite3"
	"ent-grpc-demo/ent"
	"ent-grpc-demo/ent/proto/entpb"
	"google.golang.org/grpc"
)

func main() {
	// 初始化Ent客户端
	client, err := ent.Open("sqlite3", "file:ent?mode=memory&cache=shared&_fk=1")
	if err != nil {
		log.Fatalf("数据库连接失败: %v", err)
	}
	defer client.Close()

	// 执行数据库迁移
	if err := client.Schema.Create(context.Background()); err != nil {
		log.Fatalf("数据库迁移失败: %v", err)
	}

	// 创建gRPC服务实例
	svc := entpb.NewUserService(client)

	// 创建gRPC服务器
	server := grpc.NewServer()
	entpb.RegisterUserServiceServer(server, svc)

	// 监听5000端口
	lis, err := net.Listen("tcp", ":5000")
	if err != nil {
		log.Fatalf("监听失败: %s", err)
	}

	// 启动服务
	log.Println("gRPC服务启动,监听端口5000...")
	if err := server.Serve(lis); err != nil {
		log.Fatalf("服务异常终止: %s", err)
	}
}

创建gRPC客户端

创建客户端程序cmd/client/main.go测试服务:

package main

import (
	"context"
	"fmt"
	"log"
	"math/rand"
	"time"

	"ent-grpc-demo/ent/proto/entpb"
	"google.golang.org/grpc"
	"google.golang.org/grpc/status"
)

func main() {
	rand.Seed(time.Now().UnixNano())

	// 连接gRPC服务端
	conn, err := grpc.Dial(":5000", grpc.WithInsecure())
	if err != nil {
		log.Fatalf("连接服务端失败: %s", err)
	}
	defer conn.Close()

	// 创建User服务客户端
	client := entpb.NewUserServiceClient(conn)
	ctx := context.Background()

	// 创建随机用户
	user := &entpb.User{
		Name:         fmt.Sprintf("用户_%d", rand.Int()),
		EmailAddress: fmt.Sprintf("user_%d@example.com", rand.Int()),
	}

	created, err := client.Create(ctx, &entpb.CreateUserRequest{User: user})
	if err != nil {
		se, _ := status.FromError(err)
		log.Fatalf("创建用户失败: 状态码=%s 消息=%s", se.Code(), se.Message())
	}
	log.Printf("用户创建成功,ID: %d", created.Id)

	// 查询刚创建的用户
	get, err := client.Get(ctx, &entpb.GetUserRequest{Id: created.Id})
	if err != nil {
		se, _ := status.FromError(err)
		log.Fatalf("查询用户失败: 状态码=%s 消息=%s", se.Code(), se.Message())
	}
	log.Printf("查询到用户: ID=%d, 名称=%s, 邮箱=%s", 
		get.Id, get.Name, get.EmailAddress)
}

运行演示

  1. 启动服务端:
go run cmd/server/main.go
  1. 在另一个终端运行客户端:
go run cmd/client/main.go

你将看到类似以下输出,表示gRPC调用成功:

用户创建成功,ID: 1
查询到用户: ID=1, 名称=用户_123456, 邮箱=user_123456@example.com

当前限制

需要注意的是,当前版本的entproto还存在一些限制:

  1. 仅支持唯一性边关系(O2O, O2M)
  2. 创建/更新操作会设置所有字段,不考虑零值
  3. 缺少列表查询等常用方法

总结

通过Ent框架的entproto扩展,我们可以快速将数据模型转换为gRPC服务,极大地提升了开发效率。这种模式特别适合需要快速构建微服务原型的场景。随着entproto功能的不断完善,它将成为构建gRPC服务的强大工具。

对于生产环境使用,建议结合Ent的隐私策略和钩子机制,实现更精细的访问控制和业务逻辑。

ent ent 项目地址: https://gitcode.com/gh_mirrors/ent4/ent

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

田慧娉

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值