微服务示例服务注册和发现
【摘要】 1 简介在 Go (Golang) 项目中使用 Gin 实现两个服务: 员工账号服务(employee-service) 商品服务(product-service) etcd 服务注册与发现。下面是完整示例代码以及etcd 配置与集成步骤。 2 项目结构示例 go-gin-etcd-demo/ │ ├── employee/ │ ├──...
1 简介
在 Go (Golang) 项目中使用 Gin 实现两个服务:
员工账号服务(employee-service)
商品服务(product-service)
etcd 服务注册与发现。

下面是完整示例代码以及etcd 配置与集成步骤。
2 项目结构示例
go-gin-etcd-demo/
│
├── employee/
│ ├── main.go # 员工服务入口
│ └── handler.go # Gin 路由与逻辑
│
├── product/
│ ├── main.go # 商品服务入口
│ └── handler.go
│
├── common/
│ ├── registry/
│ │ └── etcd.go # etcd注册与发现逻辑
│ └── utils/
│ └── config.go # 公共配置
│
└── go.mod
3 准备工作
1️⃣ 安装依赖
go get go.etcd.io/etcd/client/v3
go get github.com/gin-gonic/gin
go get github.com/google/uuid
2️⃣ 启动 etcd
本地运行:
docker run -d --name etcd -p 2379:2379 \
quay.io/coreos/etcd \
/usr/local/bin/etcd \
--advertise-client-urls http://0.0.0.0:2379 \
--listen-client-urls http://0.0.0.0:2379
测试是否可访问:
etcdctl --endpoints=http://localhost:2379 put testkey "hello etcd"
etcdctl --endpoints=http://localhost:2379 get testkey
4 公共部分:etcd 注册中心逻辑
文件:common/registry/etcd.go
package registry
import (
"context"
"fmt"
"log"
"time"
clientv3 "go.etcd.io/etcd/client/v3"
)
type EtcdRegistry struct {
client *clientv3.Client
lease clientv3.Lease
}
func NewEtcdRegistry(endpoints []string) (*EtcdRegistry, error) {
client, err := clientv3.New(clientv3.Config{
Endpoints: endpoints,
DialTimeout: 5 * time.Second,
})
if err != nil {
return nil, err
}
return &EtcdRegistry{
client: client,
lease: clientv3.NewLease(client),
}, nil
}
-
注册服务
func (r *EtcdRegistry) Register(serviceName, addr string, ttl int64) error { leaseResp, err := r.lease.Grant(context.Background(), ttl) if err != nil { return err } key := fmt.Sprintf("/services/%s/%s", serviceName, addr) _, err = r.client.Put(context.Background(), key, addr, clientv3.WithLease(leaseResp.ID)) if err != nil { return err } // 续租 keep alive ch, err := r.lease.KeepAlive(context.Background(), leaseResp.ID) if err != nil { return err } go func() { for { <-ch // 续租心跳 } }() log.Printf("✅ 服务注册成功: %s => %s", serviceName, addr) return nil } -
发现服务
func (r *EtcdRegistry) Discover(serviceName string) ([]string, error) { keyPrefix := fmt.Sprintf("/services/%s/", serviceName) resp, err := r.client.Get(context.Background(), keyPrefix, clientv3.WithPrefix()) if err != nil { return nil, err } var addrs []string for _, kv := range resp.Kvs { addrs = append(addrs, string(kv.Value)) } return addrs, nil }
5 服务的实现
- 员工账号服务
文件:employee/main.go
package main
import (
"fmt"
"log"
"github.com/gin-gonic/gin"
"go-gin-etcd-demo/common/registry"
)
func main() {
r := gin.Default()
r.GET("/employee/:id", getEmployee)
r.POST("/employee", createEmployee)
// 注册到etcd
etcd, _ := registry.NewEtcdRegistry([]string{"127.0.0.1:2379"})
addr := "127.0.0.1:8081"
err := etcd.Register("employee-service", addr, 10)
if err != nil {
log.Fatal(err)
}
r.Run(addr)
}
func getEmployee(c *gin.Context) {
id := c.Param("id")
c.JSON(200, gin.H{
"id": id,
"name": "Tom",
})
}
func createEmployee(c *gin.Context) {
c.JSON(200, gin.H{"msg": "employee created"})
}
- 商品服务
文件:product/main.go
package main
import (
"log"
"net/http"
"github.com/gin-gonic/gin"
"go-gin-etcd-demo/common/registry"
)
func main() {
r := gin.Default()
r.GET("/product/:id", getProduct)
r.GET("/employee-info/:id", getEmployeeFromDiscovery)
// 注册服务
etcd, _ := registry.NewEtcdRegistry([]string{"127.0.0.1:2379"})
addr := "127.0.0.1:8082"
err := etcd.Register("product-service", addr, 10)
if err != nil {
log.Fatal(err)
}
r.Run(addr)
}
func getProduct(c *gin.Context) {
id := c.Param("id")
c.JSON(200, gin.H{"id": id, "name": "Laptop"})
}
func getEmployeeFromDiscovery(c *gin.Context) {
id := c.Param("id")
reg, _ := registry.NewEtcdRegistry([]string{"127.0.0.1:2379"})
addrs, _ := reg.Discover("employee-service")
if len(addrs) == 0 {
c.JSON(500, gin.H{"error": "employee-service not found"})
return
}
resp, err := http.Get("http://" + addrs[0] + "/employee/" + id)
if err != nil {
c.JSON(500, gin.H{"error": err.Error()})
return
}
defer resp.Body.Close()
c.JSON(200, gin.H{"msg": "通过etcd发现的employee服务访问成功"})
}
- 运行流
1️⃣ 启动 etcd
2️⃣ 启动员工服务:
go run employee/main.go
3️⃣ 启动商品服务:
go run product/main.go
4️⃣ 测试:
curl http://127.0.0.1:8082/employee-info/123
product-service 会通过 etcd 自动发现 employee-service 并转发请求。
6 总结
功能:服务框架,示例点:Gin
功能:注册中心,示例点:etcd
功能:注册机制,示例点:TTL + KeepAlive
功能:服务发现,示例点:通过 /services/{name}/ 前缀查找
功能:交互方式,示例点:HTTP REST
【版权声明】本文为华为云社区用户原创内容,未经允许不得转载,如需转载请自行联系原作者进行授权。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)