Go 语言 实现简单的服务注册与发现示例

Go阿木 发布于 2025-06-22 21 次阅读


Go 语言实现简单的服务注册与发现示例

在微服务架构中,服务注册与发现是至关重要的组件。它允许服务实例在启动时注册自身,并在运行时动态地发现其他服务实例。这有助于提高系统的可伸缩性、容错性和灵活性。本文将使用 Go 语言实现一个简单的服务注册与发现系统。

系统设计

我们的服务注册与发现系统将包含以下组件:

1. 服务注册中心(Registry):负责存储所有服务的注册信息。

2. 服务提供者(Provider):提供服务的实例,并在启动时向注册中心注册。

3. 服务消费者(Consumer):需要调用其他服务的实例,从注册中心发现服务提供者。

服务注册中心

服务注册中心是一个简单的键值存储,用于存储服务提供者的信息。我们可以使用内存映射文件来实现。

go

package registry

import (


"sync"


)

type Service struct {


Name string


Addr string


Timeout int


}

var (


services = make(map[string]Service)


mu sync.RWMutex


)

func Register(service Service) {


mu.Lock()


defer mu.Unlock()


services[service.Name] = service


}

func Deregister(service Service) {


mu.Lock()


defer mu.Unlock()


delete(services, service.Name)


}

func GetService(name string) (Service, bool) {


mu.RLock()


defer mu.RUnlock()


service, ok := services[name]


return service, ok


}


服务提供者

服务提供者负责启动服务,并在启动时向注册中心注册。

go

package provider

import (


"fmt"


"net/http"


"time"

"github.com/yourusername/yourproject/registry"


)

type Provider struct {


Name string


Addr string


Timeout int


}

func (p Provider) Start() {


registry.Register(&registry.Service{


Name: p.Name,


Addr: p.Addr,


Timeout: p.Timeout,


})

http.HandleFunc("/", func(w http.ResponseWriter, r http.Request) {


fmt.Fprintf(w, "Hello from %s!", p.Name)


})

http.ListenAndServe(p.Addr, nil)


}

func (p Provider) Stop() {


registry.Deregister(&registry.Service{


Name: p.Name,


Addr: p.Addr,


Timeout: p.Timeout,


})


}


服务消费者

服务消费者从注册中心发现服务提供者,并调用服务。

go

package consumer

import (


"fmt"


"net/http"


"time"

"github.com/yourusername/yourproject/registry"


)

type Consumer struct {


Name string


Addr string


Timeout int


}

func (c Consumer) Call(serviceName string) {


service, ok := registry.GetService(serviceName)


if !ok {


fmt.Printf("Service %s not found", serviceName)


return


}

fmt.Printf("Calling %s at %s", serviceName, service.Addr)


// 发送 HTTP 请求到服务提供者


resp, err := http.Get(fmt.Sprintf("http://%s/", service.Addr))


if err != nil {


fmt.Printf("Error calling %s: %v", serviceName, err)


return


}


defer resp.Body.Close()

fmt.Fprintf(os.Stdout, "Response from %s: %s", serviceName, resp.Status)


}

func (c Consumer) Start() {


for {


time.Sleep(time.Second)


c.Call("provider")


}


}


测试

为了测试我们的服务注册与发现系统,我们可以创建两个服务提供者和一个服务消费者。

go

package main

import (


"github.com/yourusername/yourproject/consumer"


"github.com/yourusername/yourproject/provider"


)

func main() {


provider1 := &provider.Provider{Name: "provider1", Addr: ":8081"}


provider2 := &provider.Provider{Name: "provider2", Addr: ":8082"}

go provider1.Start()


go provider2.Start()

consumer := &consumer.Consumer{Name: "consumer", Addr: ":8080"}


go consumer.Start()


}


运行上述代码,我们将在控制台看到服务消费者调用服务提供者并打印响应。

总结

本文使用 Go 语言实现了一个简单的服务注册与发现系统。通过这个示例,我们可以了解服务注册与发现的基本原理和实现方法。在实际项目中,我们可以使用更复杂的数据存储和通信机制,例如 Etcd、Consul 或 ZooKeeper,以及更高级的负载均衡和故障转移策略。