feat(config): 添加 gRPC 服务器配置支持

- 在配置结构中新增 GRPCServer 类型,包含 Host 和 Port 字段
- 更新 Load 函数以支持从环境变量读取 gRPC 服务器的配置
- 引入 gRPC 和 protobuf 依赖以支持 gRPC 功能
This commit is contained in:
zhouyonggao 2025-12-20 14:08:30 +08:00
parent 858200051e
commit c02f051cb8
3 changed files with 122 additions and 7 deletions

View File

@ -6,6 +6,8 @@ require (
github.com/go-sql-driver/mysql v1.7.1
github.com/tjfoc/gmsm v1.4.1
github.com/xuri/excelize/v2 v2.8.1
google.golang.org/grpc v1.60.1
google.golang.org/protobuf v1.32.0
gopkg.in/yaml.v3 v3.0.1
)

View File

@ -17,14 +17,27 @@ type DB struct {
Name string `yaml:"name"`
}
type GRPCServer struct {
Host string `yaml:"host"`
Port string `yaml:"port"`
}
func (g GRPCServer) Address() string {
if g.Host == "" || g.Port == "" {
return ""
}
return g.Host + ":" + g.Port
}
type App struct {
Port string `yaml:"port"`
MarketingDB DB `yaml:"marketing_db"`
MarketingAuthorizationDB DB `yaml:"marketing_authorization_db"`
MarketingResellerDB DB `yaml:"marketing_reseller_db"`
YMTDB DB `yaml:"ymt_db"`
YMTTestDB DB `yaml:"ymt_test_db"`
YMTKeyDecryptKeyB64 string `yaml:"ymt_key_decrypt_key_b64"`
Port string `yaml:"port"`
MarketingDB DB `yaml:"marketing_db"`
MarketingAuthorizationDB DB `yaml:"marketing_authorization_db"`
MarketingResellerDB DB `yaml:"marketing_reseller_db"`
YMTDB DB `yaml:"ymt_db"`
YMTTestDB DB `yaml:"ymt_test_db"`
YMTKeyDecryptKeyB64 string `yaml:"ymt_key_decrypt_key_b64"`
GRPCServer GRPCServer `yaml:"grpc_server"`
}
type root struct {
@ -84,6 +97,13 @@ func Load() App {
if v := os.Getenv("YMT_TEST_DB_NAME"); v != "" {
cfg.YMTTestDB.Name = v
}
// gRPC server env overrides
if v := os.Getenv("GRPC_SERVER_HOST"); v != "" {
cfg.GRPCServer.Host = v
}
if v := os.Getenv("GRPC_SERVER_PORT"); v != "" {
cfg.GRPCServer.Port = v
}
return cfg
}

View File

@ -0,0 +1,93 @@
package grpc
import (
"context"
"fmt"
"log"
"sync"
"time"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
"google.golang.org/grpc/keepalive"
// 使用生成的 proto 代码
// 注意:需要先运行 cd grpc && make generate 生成代码
userv1 "server/grpc/user/userv1"
)
var (
userClientOnce sync.Once
userClient *UserClient
)
type UserClient struct {
conn *grpc.ClientConn
addr string
client userv1.UserClient
}
// NewUserClient 创建用户服务 gRPC 客户端
func NewUserClient(addr string) (*UserClient, error) {
if addr == "" {
return nil, fmt.Errorf("gRPC server address is empty")
}
var err error
userClientOnce.Do(func() {
opts := []grpc.DialOption{
grpc.WithTransportCredentials(insecure.NewCredentials()),
grpc.WithKeepaliveParams(keepalive.ClientParameters{
Time: 10 * time.Second,
Timeout: 3 * time.Second,
PermitWithoutStream: true,
}),
}
conn, dialErr := grpc.Dial(addr, opts...)
if dialErr != nil {
err = fmt.Errorf("failed to connect to gRPC server %s: %w", addr, dialErr)
return
}
client := userv1.NewUserClient(conn)
userClient = &UserClient{
conn: conn,
addr: addr,
client: client,
}
log.Printf("gRPC user client connected to %s", addr)
})
if err != nil {
return nil, err
}
return userClient, nil
}
// SimpleListAllUser 调用 SimpleListAllUser gRPC 方法
func (c *UserClient) SimpleListAllUser(ctx context.Context, keyword string) (*userv1.SimpleListAllUserResp, error) {
req := &userv1.SimpleListAllUserReq{
Keyword: keyword,
}
resp, err := c.client.SimpleListAllUser(ctx, req)
if err != nil {
return nil, fmt.Errorf("gRPC SimpleListAllUser failed: %w", err)
}
return resp, nil
}
// Close 关闭连接
func (c *UserClient) Close() error {
if c.conn != nil {
return c.conn.Close()
}
return nil
}
// GetConn 获取 gRPC 连接(用于直接调用生成的客户端)
func (c *UserClient) GetConn() *grpc.ClientConn {
return c.conn
}