go集成nacos测试grpc负载均衡
简介
代码
proto
syntax = "proto3";
import "google/protobuf/empty.proto";
option go_package = ".;proto";
service Test{
rpc Test(google.protobuf.Empty) returns(TestResponse);
}
message TestResponse{
string msg = 1;
}
输入代码生成对应的go代码
protoc -I . proto.proto --go_out=plugins=grpc:.
server
package service
import (
"context"
"go-nacos-demo/load_balance_nacos/server/proto"
"google.golang.org/protobuf/types/known/emptypb"
"log"
)
type Service struct{}
func (s Service) Test(ctx context.Context, empty *emptypb.Empty) (*proto.TestResponse, error) {
log.Println("收到一个请求")
return &proto.TestResponse{Msg: "test"}, nil
}
package main
import (
"fmt"
"github.com/nacos-group/nacos-sdk-go/clients"
"github.com/nacos-group/nacos-sdk-go/common/constant"
"github.com/nacos-group/nacos-sdk-go/vo"
"go-nacos-demo/load_balance_nacos/server/proto"
"go-nacos-demo/load_balance_nacos/server/service"
"google.golang.org/grpc"
"log"
"net"
)
func main() {
server := grpc.NewServer()
proto.RegisterTestServer(server, &service.Service{})
port := GenFreePort()
listen, err := net.Listen("tcp", fmt.Sprintf(":%d", port))
if err != nil {
log.Fatalf("监听端口:%d失败: %s", port, err.Error())
}
// 创建serverConfig
// 支持多个;至少一个ServerConfig
serverConfig := []constant.ServerConfig{
{
IpAddr: "192.168.193.128",
Port: 8848,
},
}
// 创建clientConfig
clientConfig := constant.ClientConfig{
NamespaceId: "97b46c8b-81e6-4614-80fb-4fe5553590ca", // 如果需要支持多namespace,我们可以场景多个client,它们有不同的NamespaceId。当namespace是public时,此处填空字符串。
TimeoutMs: 5000,
NotLoadCacheAtStart: true,
LogLevel: "debug",
}
// 创建服务发现客户端的另一种方式 (推荐)
namingClient, err := clients.NewNamingClient(
vo.NacosClientParam{
ClientConfig: &clientConfig,
ServerConfigs: serverConfig,
},
)
if err != nil {
log.Fatalf("初始化nacos失败: %s", err.Error())
}
success, err := namingClient.RegisterInstance(vo.RegisterInstanceParam{
Ip: "192.168.1.103",
Port: uint64(port),
ServiceName: "test-server",
Weight: 10,
Enable: true,
Healthy: true,
Ephemeral: true,
Metadata: map[string]string{"name": "test"},
ClusterName: "DEFAULT", // 默认值DEFAULT
GroupName: "DEFAULT_GROUP", // 默认值DEFAULT_GROUP
})
if err != nil {
log.Fatalf("注册服务失败: %s", err.Error())
}
log.Println("success: ", success)
log.Printf("服务启动成功;PORT:%d\n", port)
_ = server.Serve(listen)
}
// GenFreePort 获取一个空闲的端口;端口避免写死,因为要启动多个实例,测试负载均衡
func GenFreePort() int {
addr, err := net.ResolveTCPAddr("tcp", "localhost:0")
if err != nil {
panic(err)
}
listen, err := net.ListenTCP("tcp", addr)
if err != nil {
panic(err)
}
defer listen.Close()
return listen.Addr().(*net.TCPAddr).Port
}
client
package main
import (
"context"
"fmt"
"github.com/nacos-group/nacos-sdk-go/clients"
"github.com/nacos-group/nacos-sdk-go/common/constant"
"github.com/nacos-group/nacos-sdk-go/vo"
"go-nacos-demo/load_balance_nacos/server/proto"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
"google.golang.org/protobuf/types/known/emptypb"
"log"
)
func main() {
// 创建serverConfig
// 支持多个;至少一个ServerConfig
serverConfig := []constant.ServerConfig{
{
IpAddr: "192.168.193.128",
Port: 8848,
},
}
// 创建clientConfig
clientConfig := constant.ClientConfig{
NamespaceId: "97b46c8b-81e6-4614-80fb-4fe5553590ca", // 如果需要支持多namespace,我们可以场景多个client,它们有不同的NamespaceId。当namespace是public时,此处填空字符串。
TimeoutMs: 5000,
NotLoadCacheAtStart: true,
LogLevel: "debug",
}
// 创建服务发现客户端的另一种方式 (推荐)
namingClient, err := clients.NewNamingClient(
vo.NacosClientParam{
ClientConfig: &clientConfig,
ServerConfigs: serverConfig,
},
)
if err != nil {
log.Fatalf("初始化nacos失败: %s", err.Error())
}
for i := 0; i < 10; i++ {
// SelectOneHealthyInstance将会按加权随机轮询的负载均衡策略返回一个健康的实例
// 实例必须满足的条件:health=true,enable=true and weight>0
instance, err := namingClient.SelectOneHealthyInstance(vo.SelectOneHealthInstanceParam{
ServiceName: "test-server",
GroupName: "DEFAULT_GROUP", // 默认值DEFAULT_GROUP
Clusters: []string{"DEFAULT"}, // 默认值DEFAULT
})
log.Printf("获取到的实例IP:%s;端口:%d", instance.Ip, instance.Port)
conn, err := grpc.Dial(fmt.Sprintf("%s:%d", instance.Ip, instance.Port), grpc.WithTransportCredentials(insecure.NewCredentials()))
if err != nil {
log.Fatalf("监听%s:%d失败:%s", instance.Ip, instance.Port, err.Error())
}
client := proto.NewTestClient(conn)
res, err := client.Test(context.Background(), &emptypb.Empty{})
if err != nil {
log.Fatalf("调用TestClient失败: %s", err.Error())
}
log.Println(res.Msg)
}
}
测试
- 启动两个server


- 观察nacos


- 启动client测试负载均衡(加权随机轮询)
