GRPC 链接 NODE 和 GOLANG

GRPC 链接 NODE 和 GOLANG

GRPC 了解

什么是GRPC

  • gRPC 采用了 Protocol Buffers 作为数据序列化和反序列化的协议,可以更快速地传输数据,并支持多种编程语言的跨平台使用
  • gRPC 提供"统一水平层"来对此类问题进行抽象化。 开发人员在本机平台中编写专注于业务功能的代码,而 gRPC 会处理通信管道。

优势

RPC 使用 HTTP/2 作为传输协议。 虽然与 HTTP 1.1 也能兼容,但 HTTP/2 具有许多高级功能:

用于数据传输的二进制组帧协议 - 与 HTTP 1.1 不同,HTTP 1.1 是基于文本的。

  • 对通过同一连接发送多个并行请求的多路复用支持 - HTTP 1.1 将处理限制为一次处理一个请- 求/响应消息。
  • 双向全双工通信,用于同时发送客户端请求和服务器响应。
  • 内置流式处理,支持对大型数据集进行异步流式处理的请求和响应。
  • 减少网络使用率的标头压缩。
  • 其处理速度可以比 JSON 序列化快 8 倍,消息小 60% 到 80%

解决什么问题

  • 高效处理 不同语言端的通信。 约定协议多端 对自定义的IDL 各自单独实现

Proto 文件生成Go 代码

  • 在propto 文件夹下创建 helloworld.proto 文件
javascript 复制代码
syntax = "proto3";
// option go_package = "./yp-tpl/proto";
option go_package = "./";
 
option java_multiple_files = true;
option java_package = "io.grpc.examples.helloworld";
option java_outer_classname = "HelloWorldProto";
option objc_class_prefix = "HLW";

package helloworld;

// The greeting service definition.
service Greeter {
  // Sends a greeting
  rpc SayHello (HelloRequest) returns (HelloReply) {}

  rpc SayHelloStreamReply (HelloRequest) returns (stream HelloReply) {}
}

// The request message containing the user's name.
message HelloRequest {
  string name = 1;
}

// The response message containing the greetings
message HelloReply {
  string message = 1;
}


 
  • 使用脚本命令 生成 go文件

    protoc --go_out=. --go_opt=paths=source_relative \
      --go-grpc_out=. --go-grpc_opt=paths=source_relative \
     ./proto/*.proto
    

会生成 这两个文件

server (golang)

go 复制代码
package main

import (
	"context"
	"flag"
	"fmt"
	"log"
	"net"

	pb "yp-tpl/proto" // 相对路径引用proto文件

	"google.golang.org/grpc"
)

var (
	port = flag.Int("port", 50051, "The server port")
)

// server is used to implement helloworld.GreeterServer.
type server struct {
	pb.UnimplementedGreeterServer
}

// SayHello implements helloworld.GreeterServer
func (s *server) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) {
	log.Printf("Received: %v", in.GetName())
	return &pb.HelloReply{Message: "Hello 123" + in.GetName()}, nil
}

func start() {
	flag.Parse()
	lis, err := net.Listen("tcp", fmt.Sprintf(":%d", *port))
	if err != nil {
		log.Fatalf("failed to listen: %v", err)
	}
	s := grpc.NewServer()
	pb.RegisterGreeterServer(s, &server{})
	log.Printf("server listening at %v", lis.Addr())
	if err := s.Serve(lis); err != nil {
		log.Fatalf("failed to serve: %v", err)
	}
}

client (golang)

go 复制代码
package main

import (
	"context"
	"flag"
	"log"
	"time"
	pb "yp-tpl/proto" // 相对路径引用proto文件

	"google.golang.org/grpc"
	"google.golang.org/grpc/credentials/insecure"
)

const (
	defaultName = "world"
)

var (
	addr = flag.String("addr", "localhost:50051", "the address to connect to")
	name = flag.String("name", defaultName, "Name to greet")
)

func main() {
	flag.Parse()
	// Set up a connection to the server.
	conn, err := grpc.Dial(*addr, grpc.WithTransportCredentials(insecure.NewCredentials()))
	if err != nil {
		log.Fatalf("did not connect: %v", err)
	}
	defer conn.Close()
	c := pb.NewGreeterClient(conn)

	// Contact the server and print out its response.
	ctx, cancel := context.WithTimeout(context.Background(), time.Second)
	defer cancel()
	r, err := c.SayHello(ctx, &pb.HelloRequest{Name: *name})
	if err != nil {
		log.Fatalf("could not greet: %v", err)
	}
	log.Printf("Greeting: %s", r.GetMessage())
}

client (Node)

javascript 复制代码
import grpc from '@grpc/grpc-js';
import protoLoader from '@grpc/proto-loader';
import path from 'node:path';


const currentPath = new URL(import.meta.url).pathname;
//路径
const PROTO_PATH = path.join(currentPath, '../../../yp-tpl/proto/helloworld.proto');
console.log(PROTO_PATH);

const client = () => {
    var packageDefinition = protoLoader.loadSync(
        PROTO_PATH,
        {
            keepCase: true,
            longs: String,
            enums: String,
            defaults: true,
            oneofs: true
        });
    var help_proto = grpc.loadPackageDefinition(packageDefinition).helloworld;
    var client = new help_proto.Greeter('localhost:50051', grpc.credentials.createInsecure());
    return client;
};


export default client

//== 调用时

  const client = await grpc();
  client.sayHello({ name: "asd" }, function (err, response) {
    console.log('==>>Greeting:', response.message);
  }); 

参考资料

相关推荐
Chrikk3 小时前
Go-性能调优实战案例
开发语言·后端·golang
幼儿园老大*3 小时前
Go的环境搭建以及GoLand安装教程
开发语言·经验分享·后端·golang·go
canyuemanyue3 小时前
go语言连续监控事件并回调处理
开发语言·后端·golang
杜杜的man3 小时前
【go从零单排】go语言中的指针
开发语言·后端·golang
有梦想的咸鱼_7 小时前
go实现并发安全hashtable 拉链法
开发语言·golang·哈希算法
杜杜的man12 小时前
【go从零单排】go中的结构体struct和method
开发语言·后端·golang
幼儿园老大*12 小时前
走进 Go 语言基础语法
开发语言·后端·学习·golang·go
半桶水专家12 小时前
go语言中package详解
开发语言·golang·xcode
llllinuuu12 小时前
Go语言结构体、方法与接口
开发语言·后端·golang
cookies_s_s12 小时前
Golang--协程和管道
开发语言·后端·golang