不做大哥好多年 不做大哥好多年
首页
  • MySQL
  • Redis
  • Elasticsearch
  • Kafka
  • Etcd
  • MongoDB
  • TiDB
  • RabbitMQ
  • 01.GO基础
  • 02.面向对象
  • 03.并发编程
  • 04.常用库
  • 05.数据库操作
  • 06.Beego框架
  • 07.Beego商城
  • 08.GIN框架
  • 09.GIN论坛
  • 10.微服务
  • 01.Python基础
  • 02.Python模块
  • 03.Django
  • 04.Flask
  • 05.SYL
  • 06.Celery
  • 10.微服务
  • 01.Java基础
  • 02.面向对象
  • 03.Java进阶
  • 04.Web基础
  • 05.Spring框架
  • 100.微服务
  • Docker
  • K8S
  • 容器原理
  • Istio
  • 数据结构
  • 算法基础
  • 算法题分类
  • 前置知识
  • PyTorch
  • 01.Python
  • 02.GO
  • 03.Java
  • 04.业务问题
  • 05.关键技术
  • 06.项目常识
  • 10.计算机基础
  • Linux基础
  • Linux高级
  • Nginx
  • KeepAlive
  • ansible
  • zabbix
  • Shell
  • Linux内核

逍遥子

不做大哥好多年
首页
  • MySQL
  • Redis
  • Elasticsearch
  • Kafka
  • Etcd
  • MongoDB
  • TiDB
  • RabbitMQ
  • 01.GO基础
  • 02.面向对象
  • 03.并发编程
  • 04.常用库
  • 05.数据库操作
  • 06.Beego框架
  • 07.Beego商城
  • 08.GIN框架
  • 09.GIN论坛
  • 10.微服务
  • 01.Python基础
  • 02.Python模块
  • 03.Django
  • 04.Flask
  • 05.SYL
  • 06.Celery
  • 10.微服务
  • 01.Java基础
  • 02.面向对象
  • 03.Java进阶
  • 04.Web基础
  • 05.Spring框架
  • 100.微服务
  • Docker
  • K8S
  • 容器原理
  • Istio
  • 数据结构
  • 算法基础
  • 算法题分类
  • 前置知识
  • PyTorch
  • 01.Python
  • 02.GO
  • 03.Java
  • 04.业务问题
  • 05.关键技术
  • 06.项目常识
  • 10.计算机基础
  • Linux基础
  • Linux高级
  • Nginx
  • KeepAlive
  • ansible
  • zabbix
  • Shell
  • Linux内核
  • GO基础

  • 面向对象

  • 并发编程

  • 常用库

  • 数据库操作

  • Beego框架

  • Beego商城

  • GIN框架

  • GIN论坛

  • 微服务

    • 01.RPC
    • 02.protobuf
    • 03.gRPC
    • 04.micro简介
    • 05.consul
    • 06.go-micro
    • 07.nacos安装
    • 08.grpc注册nacos
    • 09.gin_grpc_nacos
      • 00.测试效果
      • 01.proto文件夹
        • 1.1 proto/common/common.proto
        • 1.2 proto/hello/helloTest.proto
      • 02.gRPC服务端
        • 2.1 helloService/main.go
        • 2.2 viper配置文件
        • 2.2.1helloService/Configs/configs.yml
        • 2.2.2 helloService/Configs/configLoad.go
        • 2.3 将服务注册到 nacos
        • 2.3.1 helloService/Initial/nacosregister.go
        • 2.4 gRPC服务
        • 2.4.1 helloService/Provider/helloProvider.go
      • 03.gRPC客户端
        • 3.1 allClient/main.go
        • 3.2 allClient/Utils/common.go
        • 3.3 gRPC客户端
        • 3.3.1 allClient/helloClient/Route/helloRoute.go
        • 3.3.2 allClient/helloClient/Model/helloModel.go
        • 3.3.3 allClient/helloClient/Controller/helloGin.go
        • 3.3.4 allClient/helloClient/Controller/grpcInitial.go
    • 10.限流
  • 设计模式

  • Go
  • 微服务
xiaonaiqiang
2021-12-09
目录

09.gingrpcnacos

# 00.测试效果

  • 项目地址 (opens new window)
  • 1)拉取模块到本地
go mod tidy
1
  • 2)生成protobuf文件
cd proto
protoc -I=. common/common.proto --go_out=plugins=grpc:. ./hello/helloTest.proto
1
2
  • 3)运行server
    • 修改 helloService/Configs/configs.yml 端口号为 5502
cd helloService
go run main.go
1
2
  • 4)运行client
cd allClient
go run main.go
1
2
  • 5)postman测试负载均衡
http://127.0.0.1:9009/api/v1/helloTest
1
  • 6)负载均衡效果截图

# 01.proto文件夹

cd proto
protoc -I=. common/common.proto --go_out=plugins=grpc:. ./hello/helloTest.proto
1
2

# 1.1 proto/common/common.proto

  • 公共 .proto文件
syntax = "proto3"; // 指定proto版本
package common;     // 指定包名

// 指定生成位置
option go_package = "./protoGo";

// 通用参数
message CommonRequest {
  string CommonRequest_Id = 1;
  string CommonRequest_Name = 2;
  string CommonRequest_Ip = 3;
  string CommonRequest_CreateTime = 4;
}
1
2
3
4
5
6
7
8
9
10
11
12
13

# 1.2 proto/hello/helloTest.proto

  • hello服务的 .proto文件
syntax = "proto3"; // 指定proto版本
package hello;     // 指定默认包名

// 指定生成位置
option go_package = "./protoGo";

import "common/common.proto";

// 定义Hello服务
service Hello {
  // 定义SayHello方法
  rpc SayHello(HelloRequest) returns (HelloResponse) {}
}

// HelloRequest 请求结构
message HelloRequest {
  string name = 1;
  string allParmas = 2;
  common.CommonRequest commonRequest = 3;
}

// HelloResponse 响应结构
message HelloResponse {
  string message = 1;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

# 02.gRPC服务端

# 2.1 helloService/main.go

package main

import (
	"fmt"
	"google.golang.org/grpc"
	"google.golang.org/grpc/grpclog"
	"log"
	setting "nacos-grpc-gin/helloService/Configs"
	ClientInitial "nacos-grpc-gin/helloService/Initial"
	"nacos-grpc-gin/helloService/Provider"
	pb "nacos-grpc-gin/proto/protoGo"
	"net"
)

func main() {
	// 加载配置
	setting.Init()
	// 将服务注册到 nacos
	ClientInitial.RegisterNacos()
	// 获取配置信息中 ip:port
	Address := setting.Conf.Address + ":" + setting.Conf.Port

	log.Println("启动grpc")
	listen, err := net.Listen("tcp", Address)
	if err != nil {
		grpclog.Fatalf("Failed to listen: %v", err)
	}

	// 实例化grpc Server
	s := grpc.NewServer()

	// 注册HelloService
	pb.RegisterHelloServer(s, HelloProvider.HelloService)

	fmt.Println(setting.Conf.Address)

	log.Print("监听 " + Address)
	s.Serve(listen)
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39

# 2.2 viper配置文件

# 2.2.1helloService/Configs/configs.yml

address: "127.0.0.1"
port: 5501
mysql:
  host: "127.0.0.1"
  port: 3306
  user: "root"
  password: "1"
  dbname: "grpctest"
  max_open_conns: 200
  max_idle_conns: 50
1
2
3
4
5
6
7
8
9
10

# 2.2.2 helloService/Configs/configLoad.go

package setting

import (
	"fmt"
	"github.com/fsnotify/fsnotify"
	"github.com/spf13/viper"
)

var Conf = new(AppConfig)

type AppConfig struct {
	Address      string `mapstructure:"address"`
	Port         string `mapstructure:"port"`
	*MySQLConfig `mapstructure:"mysql"`
}

type MySQLConfig struct {
	Host         string `mapstructure:"host"`
	User         string `mapstructure:"user"`
	Password     string `mapstructure:"password"`
	DB           string `mapstructure:"dbname"`
	Port         int    `mapstructure:"port"`
	MaxOpenConns int    `mapstructure:"max_open_conns"`
	MaxIdleConns int    `mapstructure:"max_idle_conns"`
}

func Init() (err error) {
	viper.SetConfigFile("./Configs/configs.yml")
	err = viper.ReadInConfig() // 读取配置信息
	if err != nil {
		// 读取配置信息失败
		fmt.Printf("viper.ReadInConfig failed, err:%v\n", err)
		return
	}

	// 把读取到的配置信息反序列化到 Conf 变量中
	if err := viper.Unmarshal(Conf); err != nil {
		fmt.Printf("viper.Unmarshal failed, err:%v\n", err)
	}

	viper.WatchConfig()
	viper.OnConfigChange(func(in fsnotify.Event) {
		fmt.Println("配置文件修改了...")
		if err := viper.Unmarshal(Conf); err != nil {
			fmt.Printf("viper.Unmarshal failed, err:%v\n", err)
		}
	})
	return
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49

# 2.3 将服务注册到 nacos

# 2.3.1 helloService/Initial/nacosregister.go

package ClientInitial

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"
	setting "nacos-grpc-gin/helloService/Configs"
	"strconv"
)

func RegisterNacos() {
	// 创建clientConfig
	clientConfig := constant.ClientConfig{
		//NamespaceId:         "e525eafa-f7d7-4029-83d9-008937f9d468", // 如果需要支持多namespace,我们可以场景多个client,它们有不同的NamespaceId。当namespace是public时,此处填空字符串。
		TimeoutMs:           5000,
		NotLoadCacheAtStart: true,
		LogDir:              "/tmp/nacos/log",
		CacheDir:            "/tmp/nacos/cache",
		RotateTime:          "1h",
		MaxAge:              3,
		LogLevel:            "debug",
	}

	// 至少一个ServerConfig
	serverConfigs := []constant.ServerConfig{
		{
			IpAddr:      "127.0.0.1",
			ContextPath: "/nacos",
			Port:        8848,
			Scheme:      "http",
		},
	}

	// 创建服务发现客户端 (推荐)
	namingClient, err := clients.NewNamingClient(
		vo.NacosClientParam{
			ClientConfig:  &clientConfig,
			ServerConfigs: serverConfigs,
		},
	)
	if err != nil {
		fmt.Println("clients.NewNamingClient err,", err)
	}

	intPort, _ := strconv.Atoi(setting.Conf.Port)
	port := uint64(intPort)

	fmt.Println(55, setting.Conf.Address, setting.Conf.Port)
	success, err := namingClient.RegisterInstance(vo.RegisterInstanceParam{
		Ip:          setting.Conf.Address,
		Port:        port,
		ServiceName: "demo.go",
		Weight:      10,
		Enable:      true,
		Healthy:     true,
		Ephemeral:   true,
		Metadata:    map[string]string{"idc": "shanghai"},
		ClusterName: "cluster-a", // 默认值DEFAULT
		GroupName:   "group-a",   // 默认值DEFAULT_GROUP
	})
	if !success {
		return
	} else {
		fmt.Println("namingClient.RegisterInstance Success")
	}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67

# 2.4 gRPC服务

# 2.4.1 helloService/Provider/helloProvider.go

package HelloProvider

import (
	"encoding/json"
	"fmt"
	"golang.org/x/net/context"
	"log"
	pb "nacos-grpc-gin/proto/protoGo" // 引入编译生成的包
)

// 定义helloService并实现约定的接口
type helloService struct{}

// HelloService Hello服务
var HelloService = helloService{}

// SayHello 实现Hello服务接口
func (h helloService) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloResponse, error) {
	//log.Printf("服务端接受数据: %v \n", in)
	//log.Printf("ctx: %v \n", ctx)
	//log.Printf("allParams: %v \n", in.AllParmas)

	// 将字节切片映射到指定map上
	// key:string类型,value:interface{}  类型能存任何数据类型
	var jsonInput map[string]interface{}
	err := json.Unmarshal([]byte(in.AllParmas), &jsonInput)
	if err != nil {
		log.Printf("json转义失败: %v \n", err)
	}
	// 打印对象结构
	log.Printf("jsonInput: %v \n", jsonInput)
	log.Printf("es: %v, \n", jsonInput["es"])

	resp := new(pb.HelloResponse)
	resp.Message = fmt.Sprintf("Hello %s.", in.Name)
	return resp, nil
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37

# 03.gRPC客户端

# 3.1 allClient/main.go

package main

import (
	"github.com/gin-gonic/gin"
	HelloRoute "nacos-grpc-gin/allClient/helloClient/Route"
)

func main() {
	r := gin.New()
	// 创建路由组
	r = HelloRoute.InitRouter(r)
	_ = r.Run(":9009")
}
1
2
3
4
5
6
7
8
9
10
11
12
13

# 3.2 allClient/Utils/common.go

  • 公共模块
package ClientUtils

import (
	"github.com/gin-gonic/gin"
)

// 统一返回体格式
type Res struct {
	Code int         `json:"code"`
	Data interface{} `json:"data"`
	Note string      `json:"note"`
}

// 对所有分会进行统一封装
func ReturnMsg(ctx *gin.Context, code int, data interface{}, note string) {
	ctx.JSON(200, Res{
		Code: code,
		Data: data,
		Note: note,
	})
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

# 3.3 gRPC客户端

# 3.3.1 allClient/helloClient/Route/helloRoute.go

  • 路由
package HelloRoute

import (
	"github.com/gin-gonic/gin"
	. "nacos-grpc-gin/allClient/helloClient/Controller"
)

func InitRouter(r *gin.Engine) *gin.Engine {
	v1 := r.Group("/api/v1")
	{
		v1.POST("/helloTest", TestClient)
	}
	return r
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14

# 3.3.2 allClient/helloClient/Model/helloModel.go

  • gRPC请求参数的结构体
package HelloModel

type Hello struct {
	Name  string   `json:"name"`
	Game  int      `json:"game"`
	Kafka string   `json:"kafka"`
	Redis string   `json:"redis"`
	Es    struct{} `json:"es"`
	Sql   struct{} `json:"sql"`
}
1
2
3
4
5
6
7
8
9
10

# 3.3.3 allClient/helloClient/Controller/helloGin.go

  • gin服务的视图函数
package helloClientController

import (
	"encoding/json"
	"github.com/gin-gonic/gin"
	"log"
	ClientUtils "nacos-grpc-gin/allClient/Utils"
	"nacos-grpc-gin/allClient/helloClient/Model"
	pb "nacos-grpc-gin/proto/protoGo"
	"net/http"
)

// @Router /api/v1/helloTest [post]
func TestClient(c *gin.Context) {
	// Set up a connection to the server.
	log.Printf("Test方法 \n")

	conn, err := InitGrpc()
	if err != nil {
		log.Fatalf("服务端链接失败: %v", err)
	}
	log.Printf("hello服务端链接成功 \n")
	client := pb.NewHelloClient(conn)
	var input HelloModel.Hello
	if err := c.ShouldBindJSON(&input); err != nil {
		ClientUtils.ReturnMsg(c, 402, nil, err.Error())
		return
	}
	log.Printf("接口入参: %v \n", input)  // 接口入参: {zhangsan 0   {} {}}
	name := input.Name

	// 联系服务器并打印它的响应
	data, _ := json.Marshal(input)
	// 接口入参json: {"name":"zhangsan","game":0,"kafka":"","redis":"","es":{},"sql":{}}
	log.Printf("接口入参json: %v \n", string(data))
	req := &pb.HelloRequest{Name: name, AllParmas: string(data)}
	res, err := client.SayHello(c, req)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{
			"error": err.Error(),
		})
		ClientUtils.ReturnMsg(c, 400, nil, err.Error())
		return
	} else {
		ClientUtils.ReturnMsg(c, 200, res.Message, res.Message)
	}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47

# 3.3.4 allClient/helloClient/Controller/grpcInitial.go

  • gRPC服务的负载均衡地址
package helloClientController

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"
	"google.golang.org/grpc"
	"log"
	"strconv"
)

func InitGrpc() (*grpc.ClientConn, error) {
	addr := getNacosServerIp()
	//conn, err := grpc.Dial("localhost:50051", grpc.WithInsecure())
	fmt.Println("addr ---->", addr)
	conn, err := grpc.Dial(addr, grpc.WithInsecure())
	if err != nil {
		log.Fatalf("服务端链接失败: %v", err)
	}
	//ServiceConnection = conn
	log.Printf("hello服务端链接成功 \n")
	return conn, err
}

func getNacosServerIp() (string) {
	// 创建clientConfig
	clientConfig := constant.ClientConfig{
		//NamespaceId:         "e525eafa-f7d7-4029-83d9-008937f9d468", // 如果需要支持多namespace,我们可以场景多个client,它们有不同的NamespaceId。当namespace是public时,此处填空字符串。
		TimeoutMs:           5000,
		NotLoadCacheAtStart: true,
		LogDir:              "/tmp/nacos/log",
		CacheDir:            "/tmp/nacos/cache",
		RotateTime:          "1h",
		MaxAge:              3,
		LogLevel:            "debug",
	}

	// 至少一个ServerConfig
	serverConfigs := []constant.ServerConfig{
		{
			IpAddr:      "127.0.0.1",
			ContextPath: "/nacos",
			Port:        8848,
			Scheme:      "http",
		},
	}

	// 创建服务发现客户端的另一种方式 (推荐)
	namingClient, err := clients.NewNamingClient(
		vo.NacosClientParam{
			ClientConfig:  &clientConfig,
			ServerConfigs: serverConfigs,
		},
	)
	if err != nil {
		fmt.Println("clients.NewNamingClient error")
	}

	//// SelectAllInstance可以返回全部实例列表,包括healthy=false,enable=false,weight<=0
	//instances, err := namingClient.SelectAllInstances(vo.SelectAllInstancesParam{
	//	ServiceName: "demo.go",
	//	GroupName:   "group-a",             // 默认值DEFAULT_GROUP
	//	Clusters:    []string{"cluster-a"}, // 默认值DEFAULT
	//})

	// SelectOneHealthyInstance将会按加权随机轮询的负载均衡策略返回一个健康的实例
	// 实例必须满足的条件:health=true,enable=true and weight>0
	instance, err := namingClient.SelectOneHealthyInstance(vo.SelectOneHealthInstanceParam{
		ServiceName: "demo.go",
		GroupName:   "group-a",             // 默认值DEFAULT_GROUP
		Clusters:    []string{"cluster-a"}, // 默认值DEFAULT
	})

	addr := instance.Ip + ":" + strconv.Itoa(int(instance.Port))
	fmt.Println(addr)
	return addr
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
上次更新: 2024/3/13 15:35:10
08.grpc注册nacos
10.限流

← 08.grpc注册nacos 10.限流→

最近更新
01
04.数组双指针排序_子数组
03-25
02
08.动态规划
03-25
03
06.回溯算法
03-25
更多文章>
Theme by Vdoing | Copyright © 2019-2025 逍遥子 技术博客 京ICP备2021005373号
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式