添加用户微服务

This commit is contained in:
JACKYMYPERSON
2025-09-08 10:11:44 +08:00
parent 863e985028
commit 2811948f2e
4 changed files with 358 additions and 126 deletions

View File

@@ -1,144 +1,76 @@
// server.go
package main
import (
"context"
"go-micro.dev/v4/errors"
"log"
"net"
"os"
"os/signal"
"syscall"
"time"
"go-micro.dev/v4"
"go-micro.dev/v4/registry"
"go.etcd.io/etcd/client/v3"
"go.etcd.io/etcd/client/v3/naming/endpoints"
)
// UserServer 用户服务结构体
type UserServer struct{}
// Login 登录方法示例
func (u *UserServer) Login(username string, password string) string {
if username == "admin" && password == "123456" {
return "登录成功token: abc123"
}
return "登录失败,用户名或密码错误"
// 定义请求和响应结构体
type LoginRequest struct {
Username string
Password string
}
// 服务注册到etcd
func registerService(etcdAddr []string, serviceName, serviceAddr string) (*clientv3.Client, error) {
// 1. 创建etcd客户端返回客户端方便后续注销
client, err := clientv3.New(clientv3.Config{
Endpoints: etcdAddr,
DialTimeout: 5 * time.Second,
})
if err != nil {
return nil, err
}
// 2. 创建租约10秒有效期
leaseResp, err := client.Grant(context.Background(), 10)
if err != nil {
client.Close()
return nil, err
}
leaseID := leaseResp.ID
// 3. 启动租约续约
keepAliveChan, err := client.KeepAlive(context.Background(), leaseID)
if err != nil {
client.Revoke(context.Background(), leaseID) // 清理租约
client.Close()
return nil, err
}
// 后台处理续约结果
go func() {
for {
select {
case keepAliveResp, ok := <-keepAliveChan:
if !ok {
// 续约通道关闭,尝试重新连接
log.Println("租约续约通道关闭,尝试重新连接...")
return
}
log.Printf("服务续约成功租约ID: %v", keepAliveResp.ID)
}
}
}()
// 4. 注册服务到etcd
em, err := endpoints.NewManager(client, "/services/"+serviceName)
if err != nil {
client.Revoke(context.Background(), leaseID)
client.Close()
return nil, err
}
// 注册服务并绑定租约
err = em.AddEndpoint(
context.Background(),
"/services/"+serviceName+"/"+serviceAddr,
endpoints.Endpoint{Addr: serviceAddr},
clientv3.WithLease(leaseID),
)
if err != nil {
client.Revoke(context.Background(), leaseID)
client.Close()
return nil, err
}
return client, nil
type LoginResponse struct {
Token string
}
// 从etcd注销服务
func unregisterService(client *clientv3.Client, serviceName, serviceAddr string) {
if client == nil {
return
}
defer client.Close()
// UserService 实现
type UserService struct{}
em, err := endpoints.NewManager(client, "/services/"+serviceName)
if err != nil {
log.Printf("注销服务失败: %v", err)
return
}
// 主动删除服务节点
err = em.DeleteEndpoint(context.Background(), "/services/"+serviceName+"/"+serviceAddr)
if err != nil {
log.Printf("删除服务节点失败: %v", err)
} else {
log.Println("服务已从etcd注销")
func (u *UserService) Login(ctx context.Context, req *LoginRequest, rsp *LoginResponse) error {
if req.Username == "admin" && req.Password == "123456" {
rsp.Token = "abc123"
return nil // 返回 nil 表示成功
}
return errors.New("登录失败", "失败", 500) // 返回 error 表示失败
}
func main() {
// 服务配置
etcdAddr := []string{"http://127.0.0.1:2379"}
serviceName := "user-service"
serviceAddr := "127.0.0.1:8080" // 服务监听地址
// 注册服务到etcd
etcdClient, err := registerService(etcdAddr, serviceName, serviceAddr)
// 1. 创建原生 etcd 客户端
etcdClient, err := clientv3.New(clientv3.Config{
Endpoints: []string{"127.0.0.1:2379"},
DialTimeout: 5 * time.Second,
})
if err != nil {
log.Fatalf("服务注册失败: %v", err)
log.Fatal("创建 etcd 客户端失败:", err)
}
log.Printf("服务 %s 已注册到etcd地址: %s", serviceName, serviceAddr)
defer etcdClient.Close()
// 启动一个实际的服务监听例如TCP服务避免程序立即退出
listener, err := net.Listen("tcp", serviceAddr)
if err != nil {
log.Fatalf("服务监听失败: %v", err)
// 2. 创建自定义的 etcd 注册中心
reg := registry.NewRegistry(
registry.Addrs("127.0.0.1:2379"),
registry.Timeout(5*time.Second),
// 这里可以添加更多自定义配置
)
// 3. 创建微服务实例
service := micro.NewService(
micro.Name("user.service"),
micro.Registry(reg),
// 注入 etcd 客户端
micro.BeforeStart(func() error {
return etcdClient.Sync(context.Background())
}),
)
// 4. 初始化服务
service.Init()
// 5. 注册服务处理器
if err := micro.RegisterHandler(service.Server(), new(UserService)); err != nil {
log.Fatal("注册服务处理器失败:", err)
}
defer listener.Close()
log.Printf("服务已启动,监听地址: %s", serviceAddr)
// 优雅退出处理(捕获中断信号,注销服务
sigChan := make(chan os.Signal, 1)
signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM)
<-sigChan // 等待中断信号
// 程序退出前注销服务
unregisterService(etcdClient, serviceName, serviceAddr)
log.Println("服务已停止")
// 6. 启动服务
if err := service.Run(); err != nil {
log.Fatal("服务启动失败:", err)
}
}