go语言集成gin nacos 以及GRPC实现微服务跨语言调用
1.实现前提需要的基础知识
- gin基础知识
- go注册nacos的基础知识 这部分直接nacos官方有实现内容
- GRPC以及protobuf的基础知识
2.开始搭建
整体项目结构
3.开始搭建server提供服务
1.在server中创建proto文件夹存放proto文件,
文件夹中创建proto文件 greeter.proto
// 固定写法指定版本
syntax = "proto3";
// 指定目录和包名 封号前面是.proto文件所在的路径 没有该文件或自动创建
option go_package = "../Service;";
//message是一种消息类型 关键字message是定义结构体
// 并且结构中可以嵌套定义结构,
message HelloReq{
string name =1;
}
message HelloRes{
string message = 1;
}
// 创建 服务提供者和要提供的方法
service GreeterService{
rpc SayHello(HelloReq)returns(HelloRes);
}
执行
protoc --go_out=plugins=grpc:./ *.proto
会在server文件下生成一个Service文件夹和greeter.pb.go文件
greeter.pb.go生成的代码就不解释了这里主要是两段代码
服务端用的
以及客户端用的
接下来在main函数中实现该服务端的方法 等到客户端调用方法的时候会访问到实现GreeterService接口的子结构体内实现的该方法SayHello
type Hello struct{}
func (this *Hello) SayHello(c context.Context, req *Service.HelloReq) (*Service.HelloRes, error) {
fmt.Println("收到的数据", req)
return &Service.HelloRes{
Message: "你好" + req.Name + "数据已经收到",
}, nil
}
代码生成好接下来就是注册nacos和RGPC了
注册nacos服务
// 注册nacos
func RegisterNacos() naming_client.INamingClient {
// 配置nacos的连接配置
sc := []constant.ServerConfig{
constant.ServerConfig{
ContextPath: "/nacos",
IpAddr: "127.0.0.1",
Port: 8848,
},
}
// 配置客户端注册在哪里
cc := constant.ClientConfig{
NamespaceId: "", //不写默认public
TimeoutMs: 5000,
NotLoadCacheAtStart: true,
LogDir: "/emp/nacos/log",
CacheDir: "/temp/nacos/cache",
LogLevel: "debug",
}
// 创建服务发现客户端
client, err := clients.NewNamingClient(vo.NacosClientParam{
ClientConfig: &cc,
ServerConfigs: sc,
})
if err != nil {
log.Fatal("创建服务发现客户端", err)
}
client.RegisterInstance(
vo.RegisterInstanceParam{
Ip: "127.0.0.1", // 配置自己IP
Port: 8080, // server服务端口
Weight: 10,
Enable: true, // true表示可以访问 其他服务可以根据nacos访问到这个服务
Healthy: true, // true表示是否健康
Metadata: nil, // 选填
//ClusterName: "go_dialogue", //集群名称 表示要连接哪个nacos服务
ServiceName: "server",
GroupName: "", // 默认不写为default
Ephemeral: true,
})
if err != nil {
log.Fatal("创建服务发现客户端", err)
}
return client
}
注册GRPC
func RegisterGrpc() {
// 创建一个GRPC服务
server := grpc.NewServer()
// 2.注册服务
Service.RegisterGreeterServiceServer(server, new(Hello))
listen, err := net.Listen("tcp", "127.0.0.1:8080")
if err != nil {
log.Fatalf("监听端口错误", err)
return
}
// 启动服务
server.Serve(listen)
}
最后就是启动gin服务 main函数主体
func main() {
// 集成nacos
RegisterNacos()
// 注册Grpc服务
RegisterGrpc()
r := gin.Default()
// 3.监听端口
r.Run(":8080")
// 3.监听端口
r.GET("/test", func(c *gin.Context) {
// 这个gin服务的其他逻辑操作
// 可以单独向前端提供服务 也可以向java集成nacos提供服务
})
}
整个main函数具体代码
package main
import (
"context"
"fmt"
"gin-GRPC-nacos/server/Service"
"github.com/gin-gonic/gin"
"github.com/nacos-group/nacos-sdk-go/v2/clients"
"github.com/nacos-group/nacos-sdk-go/v2/clients/naming_client"
"github.com/nacos-group/nacos-sdk-go/v2/common/constant"
"github.com/nacos-group/nacos-sdk-go/v2/vo"
"google.golang.org/grpc"
"log"
"net"
)
type Hello struct{}
func (this *Hello) SayHello(c context.Context, req *Service.HelloReq) (*Service.HelloRes, error) {
fmt.Println("收到的数据", req)
return &Service.HelloRes{
Message: "你好" + req.Name + "数据已经收到",
}, nil
}
func main() {
// 集成nacos
RegisterNacos()
RegisterGrpc()
r := gin.Default()
// 3.监听端口
r.Run(":8080")
// 3.监听端口
r.GET("/test", func(c *gin.Context) {
// 这个gin服务的其他逻辑操作
// 可以单独向前端提供服务 也可以向java集成nacos提供服务
})
}
func RegisterGrpc() {
// 创建一个GRPC服务
server := grpc.NewServer()
// 2.注册服务
Service.RegisterGreeterServiceServer(server, new(Hello))
listen, err := net.Listen("tcp", "127.0.0.1:8080")
if err != nil {
log.Fatalf("监听端口错误", err)
return
}
// 启动服务
server.Serve(listen)
}
// 注册nacos
func RegisterNacos() naming_client.INamingClient {
// 配置nacos的连接配置
sc := []constant.ServerConfig{
constant.ServerConfig{
ContextPath: "/nacos",
IpAddr: "127.0.0.1",
Port: 8848,
},
}
// 配置客户端注册在哪里
cc := constant.ClientConfig{
NamespaceId: "",
TimeoutMs: 5000,
NotLoadCacheAtStart: true,
LogDir: "/emp/nacos/log",
CacheDir: "/temp/nacos/cache",
LogLevel: "debug",
}
// 创建服务发现客户端
client, err := clients.NewNamingClient(vo.NacosClientParam{
ClientConfig: &cc,
ServerConfigs: sc,
})
if err != nil {
log.Fatal("创建服务发现客户端", err)
}
client.RegisterInstance(
vo.RegisterInstanceParam{
Ip: "127.0.0.1", // 配置自己IP 表示谁都可以访问
Port: 8080,
Weight: 10,
Enable: true, // true表示可以访问 其他服务可以根据nacos访问到这个服务
Healthy: true, // true表示是否健康
Metadata: nil, // 选填
//ClusterName: "go_dialogue", //集群名称 表示要连接哪个nacos服务
ServiceName: "server",
GroupName: "", // 默认不写为default
Ephemeral: true,
})
if err != nil {
log.Fatal("创建服务发现客户端", err)
}
return client
}
接下来编写客户端
proto在server已经生成过了 这里就直接复制过来
第一步就是编写向nacos注册服务
// 注册nacos
func RegisterNacos() naming_client.INamingClient {
// 配置nacos的连接配置
sc := []constant.ServerConfig{
constant.ServerConfig{
ContextPath: "/nacos",
IpAddr: "127.0.0.1",
Port: 8848,
},
}
// 配置客户端注册在哪里
cc := constant.ClientConfig{
NamespaceId: "",
TimeoutMs: 5000,
NotLoadCacheAtStart: true,
LogDir: "/emp/nacos/log",
CacheDir: "/temp/nacos/cache",
LogLevel: "debug",
}
// 创建服务发现客户端
client, err := clients.NewNamingClient(vo.NacosClientParam{
ClientConfig: &cc,
ServerConfigs: sc,
})
if err != nil {
log.Fatal("创建服务发现客户端", err)
}
client.RegisterInstance(
vo.RegisterInstanceParam{
Ip: "127.0.0.1", // 配置自己IP
Port: 8082,
Weight: 10,
Enable: true, // true表示可以访问 其他服务可以根据nacos访问到这个服务
Healthy: true, // true表示是否健康
Metadata: nil, // 选填
//ClusterName: "go_dialogue", //集群名称 表示要连接哪个nacos服务
ServiceName: "client",
GroupName: "", // 默认不写为default
Ephemeral: true,
})
if err != nil {
log.Fatal("创建服务发现客户端", err)
}
return client
}
第二步就是连接服务端的Grpc服务
// address 是ip+端口 ip:port
// c 是gin请求的执行方法的上下文
// req 是请求参数
func RegisterClient(address string, c *gin.Context, req *Service.HelloReq) *Service.HelloRes {
// 可以集成nacos获取这个服务地址 ip和port
dial, err := grpc.Dial(address, grpc.WithTransportCredentials(insecure.NewCredentials()))
if err != nil {
log.Fatal("连接服务器错误", err)
}
client := Service.NewGreeterServiceClient(dial)
res, err2 := client.SayHello(c, req)
if err2 != nil {
log.Fatal("调用方法失败", err2)
}
fmt.Println("收到了", res)
return res
}
main方法编写 主要是编写一个gin请求来访问服务端
func main() {
// 从nacos获取服务地址
client := RegisterNacos()
r := gin.Default()
// 连接服务器
r.GET("/GetServer", func(c *gin.Context) {
instance, _ := client.SelectOneHealthyInstance(vo.SelectOneHealthInstanceParam{
Clusters: nil, // 集群名称
ServiceName: "server", //服务名称
GroupName: "", //服务分组 默认不写则为 public
})
address := instance.Ip + ":" + strconv.Itoa(int(instance.Port))
// 调用这个http地址 获取server服务的方法返回结果
res := RegisterClient(address, c, &Service.HelloReq{
Name: "张三",
})
// 序列化
marshal, _ := proto.Marshal(res)
c.Writer.Write(marshal)
})
r.Run(":8082")
}
整个main.go函数代码
package main
import (
"fmt"
"gin-GRPC-nacos/client/Service"
"github.com/gin-gonic/gin"
"github.com/nacos-group/nacos-sdk-go/v2/clients"
"github.com/nacos-group/nacos-sdk-go/v2/clients/naming_client"
"github.com/nacos-group/nacos-sdk-go/v2/common/constant"
"github.com/nacos-group/nacos-sdk-go/v2/vo"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
"google.golang.org/protobuf/proto"
"log"
"strconv"
)
/**
*
* Create_Time:下午 03:14
**/
func main() {
// 从nacos获取服务地址
client := RegisterNacos()
r := gin.Default()
// 连接服务器
r.GET("/GetServer", func(c *gin.Context) {
instance, _ := client.SelectOneHealthyInstance(vo.SelectOneHealthInstanceParam{
Clusters: nil, // 集群名称
ServiceName: "server", //服务名称
GroupName: "", //服务分组 默认不写则为 public
})
address := instance.Ip + ":" + strconv.Itoa(int(instance.Port))
// 调用这个http地址 获取server服务的方法返回结果
res := RegisterClient(address, c, &Service.HelloReq{
Name: "张三",
})
// 序列化
marshal, _ := proto.Marshal(res)
c.Writer.Write(marshal)
})
r.Run(":8082")
}
func RegisterClient(address string, c *gin.Context, req *Service.HelloReq) *Service.HelloRes {
// 可以集成nacos获取这个服务地址 ip和port
dial, err := grpc.Dial(address, grpc.WithTransportCredentials(insecure.NewCredentials()))
if err != nil {
log.Fatal("连接服务器错误", err)
}
client := Service.NewGreeterServiceClient(dial)
res, err2 := client.SayHello(c, req)
if err2 != nil {
log.Fatal("调用方法失败", err2)
}
fmt.Println("收到了", res)
return res
}
// 注册nacos
func RegisterNacos() naming_client.INamingClient {
// 配置nacos的连接配置
sc := []constant.ServerConfig{
constant.ServerConfig{
ContextPath: "/nacos",
IpAddr: "127.0.0.1",
Port: 8848,
},
}
// 配置客户端注册在哪里
cc := constant.ClientConfig{
NamespaceId: "",
TimeoutMs: 5000,
NotLoadCacheAtStart: true,
LogDir: "/emp/nacos/log",
CacheDir: "/temp/nacos/cache",
LogLevel: "debug",
}
// 创建服务发现客户端
client, err := clients.NewNamingClient(vo.NacosClientParam{
ClientConfig: &cc,
ServerConfigs: sc,
})
if err != nil {
log.Fatal("创建服务发现客户端", err)
}
client.RegisterInstance(
vo.RegisterInstanceParam{
Ip: "127.0.0.1", // 配置自己IP 表示谁都可以访问
Port: 8082,
Weight: 10,
Enable: true, // true表示可以访问 其他服务可以根据nacos访问到这个服务
Healthy: true, // true表示是否健康
Metadata: nil, // 选填
//ClusterName: "go_dialogue", //集群名称 表示要连接哪个nacos服务
ServiceName: "client",
GroupName: "", // 默认不写为default
Ephemeral: true,
})
if err != nil {
log.Fatal("创建服务发现客户端", err)
}
return client
}
接下来就是先启动服务端然后启动客户端来访问服务端
浏览器输入
http://localhost:8082/GetServer
我这里会直接下载为一个文件 不知道为什么 正常应该是直接输出 把张三换掉就好了