Files
lone-services/README-NEW.md
T
gjs f49d155373
CI / changes (push) Successful in 4s
CI / docker-bff (push) Failing after 2s
CI / docker-product (push) Failing after 2s
CI / docker-admin (push) Failing after 1s
CI / docker-user (push) Failing after 1s
add action,login log
2026-08-20 17:35:04 +08:00

7.4 KiB
Raw Blame History

常用命令

命令 goctl 生成/更新脚手架

cd lone-services/
rpc/scripts/gen-rpc.sh 服务名  如 product

什么时候跑:

  • 增删改 字段BFF gateway 编解码需要)
  • 增删 RPC
  • google.api.http 路由

如何加一个新服务

以加 order 为例(对标现有 product)。

0. 安装 goctl

go install github.com/zeromicro/go-zero/tools/goctl@latest
goctl --version
go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest

1. 创建 RPC 服务(goctl

在仓库根目录执行:

cd services
goctl rpc new order
cd order

2. 将 proto 移到 proto/ 目录

goctl rpc new 默认把 proto 放在服务根目录(如 order/order.proto)。统一挪到 ../rpc/order/order.proto

mkdir ../rpc/proto
mv order.proto proto/
修改 option go_package="./order"; 为 option go_package="lone-services/rpc/order";

3. 删除order目录

4. Zero 兼容 Nacos 等配置

编辑 order/internal/config/config.go

package config

type Config struct {
	Nacos NacosConf
}

type NacosConf struct {
	Hosts       []string
	NamespaceId string `json:",optional"`
	Group       string `json:",optional"`
	RegisterIP  string `json:",optional"`
	ConfigID    string `json:",optional"`
}

5. 配置服务名与监听端口

编辑 order/etc/order.yaml

Nacos:
  Hosts:
    - host.docker.internal:8848
  NamespaceId: test
  Group: LONE_SERVICES
  RegisterIP: order
  ConfigID: develop-order

6. 服务注册

编辑 order/order.go

增加初始化


func main() {
flag.Parse()
var c config.Config
conf.MustLoad(*configFile, &c)

// Nacos配置拉取初始化
nacosParam := utils.NacosConfig{
Hosts:       c.Nacos.Hosts,
NamespaceId: c.Nacos.NamespaceId,
Group:       c.Nacos.Group,
ConfigID:    c.Nacos.ConfigID,
}
utils.InitConfig(nacosParam)

// 日志配置
logConf := logx.LogConf{
ServiceName: utils.GetConfigString("log.serviceName"),
Mode:        utils.GetConfigString("log.mode"),
Encoding:    utils.GetConfigString("log.encoding"),
Level:       utils.GetConfigString("log.level"),
Path:        utils.GetConfigString("log.path"),
KeepDays:    utils.GetConfigInt("log.keepDays"),
MaxSize:     utils.GetConfigInt("log.maxSize"),
MaxBackups:  utils.GetConfigInt("log.maxBackups"),
Compress:    utils.GetConfigBool("log.compress"),
}
logx.SetUp(logConf)
logx.AddWriter(logx.NewWriter(os.Stdout))

listenOn := utils.GetConfigString("base.listenOn")
mode := utils.GetConfigString("base.mode")
serviceName := utils.GetConfigString("base.name")

// 初始化服务发现
if err := discovery.Init(discovery.Config{
Hosts:       c.Nacos.Hosts,
NamespaceId: c.Nacos.NamespaceId,
Group:       c.Nacos.Group,
}); err != nil {
logx.Errorf("nacos init: %v", err)
os.Exit(1)
}

port, err := listenPort(listenOn)
if err != nil {
logx.Errorf("parse ListenOn: %v", err)
os.Exit(1)
}

// 注册服务
if err := discovery.Register(discovery.Instance{
ServiceName: serviceName,
IP:          c.Nacos.RegisterIP,
Port:        port,
Group:       c.Nacos.Group,
}); err != nil {
logx.Errorf("nacos register: %v", err)
os.Exit(1)
}
logx.Infof("服务注册成功: %s:%d", c.Nacos.RegisterIP, port)

defer func() {
if err := discovery.Deregister(); err != nil {
logx.Errorf("nacos deregister: %v", err)
}
}()

// 初始化MySQL
db, err := mysql.New(mysql.Config{
Host:         utils.GetConfigString("mysql.host"),
Port:         utils.GetConfigInt("mysql.port"),
User:         utils.GetConfigString("mysql.user"),
Password:     utils.GetConfigString("mysql.password"),
Database:     utils.GetConfigString("mysql.database"),
Charset:      utils.GetConfigString("mysql.charset"),
Prefix:       utils.GetConfigString("mysql.prefix"),
ReadHost:     utils.GetConfigString("mysql_read.host"),
ReadPort:     utils.GetConfigInt("mysql_read.port"),
ReadUser:     utils.GetConfigString("mysql_read.user"),
ReadPassword: utils.GetConfigString("mysql_read.password"),
ReadDatabase: utils.GetConfigString("mysql_read.database"),
})
if err != nil {
logx.Errorf("mysql init: %v", err)
os.Exit(1)
}

// 初始化Redis
if err := redis.Init(redis.Config{
Host:     utils.GetConfigString("redis.host"),
Port:     utils.GetConfigInt("redis.port"),
Password: utils.GetConfigString("redis.password"),
DB:       utils.GetConfigInt("redis.db"),
}); err != nil {
logx.Errorf("redis init: %v", err)
os.Exit(1)
}

//日志队列初始化
if err := logRedis.Init(logRedis.LogRedisConfig{
Host:     utils.GetConfigString("log-redis.host"),
Port:     utils.GetConfigInt("log-redis.port"),
Password: utils.GetConfigString("log-redis.password"),
DB:       utils.GetConfigInt("log-redis.db"),
}); err != nil {
logx.Errorf("log redis init: %v", err)
os.Exit(1)
}

debug := utils.GetConfigBool("mysql.debug")
modelbase.Init(db, modelbase.Config{Prefix: utils.GetConfigString("mysql.prefix"), Debug: debug})

// 初始化服务信息
rpcConf := zrpc.RpcServerConf{
ListenOn: listenOn,
}
rpcConf.Mode = mode
ctx := svc.NewServiceContext(c, db)

s := zrpc.MustNewServer(rpcConf, func(grpcServer *grpc.Server) {
order.RegisterOrderServer(grpcServer, server.NewOrderServer(ctx))
if mode == service.DevMode || mode == service.TestMode {
reflection.Register(grpcServer)
}
})
defer s.Stop()

s.AddUnaryInterceptors(validate.UnaryServerInterceptor(validate.MustNew()))

logx.Infof("Starting rpc server at %s...", listenOn)
s.Start()
}

// listenPort 拆分端口
func listenPort(listenOn string) (uint64, error) {
_, portStr, err := net.SplitHostPort(listenOn)
if err != nil {
return utils.NumberZero, err
}
return strconv.ParseUint(portStr, utils.NumberTen, utils.NumberSixtyFourth)
}


执行 tidy

go mod tidy

编辑 internal/svc/servicecontext.go

package svc

import (
	"lone-services/pkg/utils"
	"lone-services/services/order/internal/config"

	"gorm.io/gorm"
)

type ServiceContext struct {
	Config config.Config
	DB     *gorm.DB
	Prefix string
}

func NewServiceContext(c config.Config, db *gorm.DB) *ServiceContext {
	return &ServiceContext{
		Config: c,
		DB:     db,
		Prefix: utils.GetConfigString("mysql.prefix"),
	}
}


7. 接入 Docker Compose

deploy/docker-compose.dev.override.yml 增加服务:

  order:
    image: golang:1.26.5
    volumes:
      - ..:/src
      - go-mod-cache:/go/pkg/mod
      - go-build-cache:/root/.cache/go-build
    working_dir: /src/services/order
    command: go run . -f etc/order.yaml
    ports:
      - "10200:10200"
    environment:
      NACOS_SERVER_ADDR: rnacos:8848
    depends_on:
      - rnacos

9. 在 BFF 配 UpstreamHTTP 路由写在 proto

编辑 bff/etc/bff.yaml,在 Upstreams 增加一段(不必写 Mappingsgateway 会从 ProtoSet 里的 http option 注册路由):

  - Name: order
    Grpc:
      Target: order-service   # 必须等于 order.yaml 的 Name
      Timeout: 5000
    ProtoSets:
      - etc/order.pb

在对应 RPC 上声明 google.api.http(需 import "google/api/annotations.proto";):

rpc Ping(Request) returns (Response) {
  option (google.api.http) = {
    post: "/admin/v3/order/ping"
    body: "*"
  };
}

编写业务须知

只改业务逻辑(internal/logic/)不必跑 goctl。 改 proto/order.proto(新增/改名 RPC、改字段、改 http option 等)后,按文末「三条命令何时用」处理;

若 HTTP 路径有变,改 proto 里的 google.api.http 后重新跑命令 ② 生成 ProtoSet。