# Go项目如何使用Nacos

# 项目介绍

设计三个服务:

  • go-service-a
  • go-service-b
  • go-service-c

其中:

  • go-service-a要调用go-service-b
  • go-service-b要调用go-service-c

微服务架构中,所有服务的IP和端口都是变化的,无法事先确定,因此需要Nacos实现服务发现(服务注册)。

# 服务注册和获取

这里以go-service-a为例,进行代码说明。

我们的项目包含一个nacos包和main包,其中nacos包负责服务的注册和获取逻辑的封装。

package nacos

import (
	"fmt"
	"log"
	"net"
	"os"
	"strconv"
	"strings"

	"github.com/nacos-group/nacos-sdk-go/clients"
	"github.com/nacos-group/nacos-sdk-go/clients/naming_client"
	"github.com/nacos-group/nacos-sdk-go/common/constant"
	"github.com/nacos-group/nacos-sdk-go/model"
	"github.com/nacos-group/nacos-sdk-go/vo"
)

// 1. 创建 Nacos 客户端
func getServiceClient() naming_client.INamingClient {

	nacos_server_addr := os.Getenv("NACOS_SERVER_ADDR")
	nacos_server_addr_list := strings.Split(nacos_server_addr, ":")
	nacosIp := nacos_server_addr_list[0]
	nacosPort, err := strconv.ParseUint(nacos_server_addr_list[1], 10, 64)
	serverConfigs := []constant.ServerConfig{
		{
			IpAddr: nacosIp,
			Port:   nacosPort,
		},
	}
	clientConfig := constant.ClientConfig{
		NamespaceId:         "public", // Nacos 命名空间 ID
		TimeoutMs:           5000,
		NotLoadCacheAtStart: true,
		LogDir:              "/tmp/nacos/log",
		CacheDir:            "/tmp/nacos/cache",
	}
	serviceClient, err := clients.CreateNamingClient(map[string]interface{}{
		"serverConfigs": serverConfigs,
		"clientConfig":  clientConfig,
	})
	if err != nil {
		panic(err)
	}

	return serviceClient
}

// 2. 服务注册
func RegisterNacos(serviceName string, port int) {

	serviceClient := getServiceClient()
	ip, err := getLocalIP()
	if err != nil {
		panic(err)
	}
	instance := vo.RegisterInstanceParam{
		Ip:          ip,
		Port:        uint64(port),
		ServiceName: serviceName,
		Weight:      10,
		Enable:      true,
		Healthy:     true,
		Ephemeral:   true,
		Metadata: map[string]string{
			"version": "1.0.0",
		},
	}
	_, err = serviceClient.RegisterInstance(instance)
	if err != nil {
		panic(err)
	}
	log.Println("service registered successfully.")
}

// 3. 服务获取
func GetInstance(serviceName string) *model.Instance {

	serviceClient := getServiceClient()
	groupName := "DEFAULT_GROUP"
	instance, err := serviceClient.SelectOneHealthyInstance(vo.SelectOneHealthInstanceParam{
		ServiceName: serviceName,
		GroupName:   groupName,
	})

	if err != nil {
		panic(err)
	}
	return instance
}

// 工具函数:获取本地 IP 地址
func getLocalIP() (string, error) {
	addrs, err := net.InterfaceAddrs()
	if err != nil {
		return "", err
	}
	for _, addr := range addrs {
		if ipNet, ok := addr.(*net.IPNet); ok && !ipNet.IP.IsLoopback() {
			if ipNet.IP.To4() != nil {
				return ipNet.IP.String(), nil
			}
		}
	}
	return "", fmt.Errorf("no local IP address found")
}

# 使用nacos包

package main

import (
	"demo/nacos"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
)

func main() {
	port := 8001
	serviceName := "go-service-a"
  // 注册服务,传入服务名称和端口
	nacos.RegisterNacos(serviceName, port)
	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
    // 获取服务,传入要获取的服务名称
		instance := nacos.GetInstance("go-service-b")
		resp, err := http.Get(fmt.Sprintf("http://%s:%d/", instance.Ip, instance.Port))
		if err != nil {
			fmt.Fprint(w, err)
			return
		}
		defer resp.Body.Close()

		body, err := ioutil.ReadAll(resp.Body)
		if err != nil {
			fmt.Fprint(w, err)
			return
		}

		fmt.Fprint(w, "go service A response succeed!\n"+string(body))
	})
	go func() {
		if err := http.ListenAndServe(fmt.Sprintf(":%d", port), nil); err != nil {
			log.Fatalf("failed to start server: %v", err)
		}
	}()
	log.Printf("server started at http://localhost:%d", port)
	select {}
}
上次更新: 2/13/2025, 3:29:47 AM