1. 常用第三方库
- Consul:HashiCorp 公司推出的服务网格解决方案,它提供了服务发现、配置管理与健康检查等功能。Go 语言中有官方的
consul-api
库可用于与 Consul 进行交互。
- Etcd:一个分布式键值存储系统,常用于服务发现和共享配置。Go 语言中有
go - etcd
等库用于操作 Etcd。
- Zookeeper:一个分布式协调服务,也可用于服务发现。Go 语言有
go - zookeeper
等相关库。
2. 实现思路 - 以 Consul 为例
- 服务注册
- 在微服务启动时,使用
consul - api
库向 Consul 服务器注册自身服务信息,包括服务名称、地址、端口等。例如:
package main
import (
"fmt"
"log"
"github.com/hashicorp/consul/api"
)
func registerService() {
config := api.DefaultConfig()
client, err := api.NewClient(config)
if err != nil {
log.Fatalf("Failed to create Consul client: %v", err)
}
registration := new(api.AgentServiceRegistration)
registration.ID = "my - service - 1"
registration.Name = "my - service"
registration.Address = "127.0.0.1"
registration.Port = 8080
check := new(api.AgentServiceCheck)
check.HTTP = fmt.Sprintf("http://%s:%d/health", registration.Address, registration.Port)
check.Interval = "10s"
registration.Check = check
err = client.Agent().ServiceRegister(registration)
if err != nil {
log.Fatalf("Failed to register service: %v", err)
}
}
- 服务发现
- 客户端需要调用服务时,通过
consul - api
库从 Consul 获取服务实例列表。例如:
func discoverService() ([]*api.ServiceEntry, error) {
config := api.DefaultConfig()
client, err := api.NewClient(config)
if err != nil {
return nil, fmt.Errorf("Failed to create Consul client: %v", err)
}
services, _, err := client.Health().Service("my - service", "", true, nil)
if err != nil {
return nil, fmt.Errorf("Failed to discover service: %v", err)
}
return services, nil
}
- 负载均衡策略
- 随机策略:从获取到的服务实例列表中随机选择一个实例进行调用。
func randomLoadBalancer(services []*api.ServiceEntry) *api.ServiceEntry {
r := rand.New(rand.NewSource(time.Now().UnixNano()))
index := r.Intn(len(services))
return services[index]
}
- **轮询策略**:维护一个计数器,每次调用时按照顺序选择下一个服务实例。
var counter int
func roundRobinLoadBalancer(services []*api.ServiceEntry) *api.ServiceEntry {
service := services[counter%len(services)]
counter++
return service
}
- 服务调用
- 根据选择的负载均衡策略获取服务实例,然后进行实际的服务调用。例如,若使用 HTTP 调用:
func callService(service *api.ServiceEntry) {
url := fmt.Sprintf("http://%s:%d", service.Service.Address, service.Service.Port)
resp, err := http.Get(url)
if err != nil {
log.Fatalf("Failed to call service: %v", err)
}
defer resp.Body.Close()
// 处理响应
}
3. 健康检查
- Consul 支持对服务进行健康检查,如上述服务注册代码中设置了 HTTP 健康检查。当服务实例不健康时,Consul 会将其从可用实例列表中移除,从而保证服务调用的可靠性。同时,客户端在获取服务实例列表时,优先获取健康的实例进行调用。