go使用GRPC

GRPC

  • grpc是由google主导开发的一个基于HTTP/2,并应用Protobuf进行通信的RPC通信框架。
  • grpc支持不同语言之间的通信,使用简单方便。
  • 本次介绍go语言使用grpc与Java进行通信。

go安装grpc和protobuf

  • 对于go语言的安装这里不进行说明,安装方法很简单。
  • go安装之后,要在环境变量中设置GOROOT和GOPATH。其中GOPATH是你go项目的工作目录。

安装grpc和protobuf

git clone https://github.com/grpc/grpc-go.git $GOPATH/src/google.golang.org/grpc
git clone https://github.com/golang/net.git $GOPATH/src/golang.org/x/net
git clone https://github.com/golang/text.git $GOPATH/src/golang.org/x/text
go get -u github.com/golang/protobuf/{proto,protoc-gen-go}
git clone https://github.com/google/go-genproto.git $GOPATH/src/google.golang.org/genproto

经过以上步骤,已经将go需要的grpc和protobuf等支持下载到了GOPATH的src目录下边,接下来就是进入GOPATH目录的src目录下边,进行install

cd $GOPATH/src/
go install google.golang.org/grpc

在install之后会在GOPATH目录下边生成bin和pkg两个包,里边放的就是grpc和protobuf install之后的内容。

对proto文件进行编译

  • 在bin目录中有 protoc-gen-go.exe 文件,这个文件提供go环境中对protobuf编译的支持。
  • 在文末的链接中下载 protoc.exe 文件。这个文件是用来编译proto文件的。把这个文件和 protoc-gen-go.exe 放在同目录下。
  • 通过命令行对.proto文件进行编译
$ protoc --go_out=. ./helloworld.proto
$ protoc --go_out=plugins=grpc:.  ./helloworld.proto

边两个命令是不一样的。第一个只是生成了proto序列化,反序列化代码的文件。 第二个则还增加服务器和客户端通讯、实现的公共库代码。因此如果是写客户端和服务端通信,要用第二个编译方式,如果只是作为序列化和反序列化的工具,用第一个就可以了。

tips
  • –go_out= :后边跟的是编译之后文件的存放路径
  • 如果在通信过程中收到的中文消息不是正常的中文,而是十六进制的格式,说明使用可能是proto2,改成 proto3 就可以正常的收消息了。
  • 关于Go语言:在golang中如果函数名的首字母大写,表示该函数是公有的,可以被其他程序调用,如果首字母小写,该函数就是是私有的

Java对grpc的支持

Java在编译grpc的时候可以有两种方法
- 通过maven配置grpc,protobuf相关设置,
- 直接通过protoc.exe进行编译(文末链接)

使用maven进行配置

使用maven配置的话,就可以通过maven编译proto文件,生成对应的代码,

<dependency>
    <groupId>io.grpcgroupId>
    <artifactId>grpc-nettyartifactId>
    <version>1.6.1version>
dependency>
<dependency>
    <groupId>io.grpcgroupId>
    <artifactId>grpc-protobufartifactId>
    <version>1.0.0version>
dependency>
<dependency>
    <groupId>io.grpcgroupId>
    <artifactId>grpc-stubartifactId>
    <version>1.0.0version>
dependency>


<plugin>
    <groupId>org.xolstice.maven.pluginsgroupId>
    <artifactId>protobuf-maven-pluginartifactId>
    
    <configuration>
        <protocArtifact>com.google.protobuf:protoc:3.0.0:exe:${os.detected.classifier}protocArtifact>
        <pluginId>grpc-javapluginId>
        <pluginArtifact>io.grpc:protoc-gen-grpc-java:1.0.0:exe:${os.detected.classifier}pluginArtifact>
    configuration>
    <executions>
        <execution>
            <goals>
                <goal>compilegoal>
                <goal>compile-customgoal>
            goals>
        execution>
    executions>
plugin>

代码

本文中介绍的是GO和Java进行通信,其中Go是服务器端,Java是客户端。

.proto文件

.proto文件时不同端之间商定的交互协议,因此两端都要知晓协议内容。(关于protobuf应用,可以看官网,或网上看例子。)

syntax="proto3";

package msg;

message RouterInfo{
  string ip=1;
  string domain=2;
  string applicationName=3;
  string description=4;
}

message ResultToApp{
  string userName=1;
  string password=2;
}

service MessageChannel{
  rpc registerServer(RouterInfo)returns(ResultToApp){}
}

GO端(作为服务器端)

package msg

import (
    "net"
    "log"
    "fmt"
    "google.golang.org/grpc"
    "golang.org/x/net/context"
)

const (
    port = "15000"
)

type server struct {
}
// 实现服务端的方法
func (s *server) RegisterServer(ctx context.Context, in *RouterInfo) (*ResultToApp, error) {
    fmt.Print(*in)
    name := "test"
    pas := "123"
    return &ResultToApp{UserName: name, Password: pas}, nil
}

func ListenFromJava() {
    fmt.Println("接收到消息")
    //监听接口
    serverLis, err := net.Listen("tcp", "127.0.0.1:"+port)

    if err != nil {
        log.Fatal("failed to listen: %v", err)
    }
    s := grpc.NewServer()
    //注册服务
    RegisterMessageChannelServer(s, &server{})
    if err := s.Serve(serverLis); err != nil {
        log.Fatalf("failed to serve: %v", err)
    }
}

Java端

package com.photo.spider;

import io.grpc.ManagedChannel;
import io.grpc.ManagedChannelBuilder;
import java.util.concurrent.TimeUnit;
import msg.MessageChannelGrpc;
import msg.RegisterToServer;

/**
 * Created by SunGuiyong on 2018/7/25.
 */
public class SendMsgToGo {

  private final ManagedChannel channel;
  private final MessageChannelGrpc.MessageChannelBlockingStub localStub;

  public SendMsgToGo(String host, int port) {
    channel = ManagedChannelBuilder.forAddress(host, port)
        .usePlaintext(true)
        .build();

    //初始化
    localStub = MessageChannelGrpc.newBlockingStub(channel);
  }

  public void shutdown() throws InterruptedException {
    channel.shutdown().awaitTermination(5, TimeUnit.SECONDS);
  }

  public void greet(RegisterToServer.RouterInfo routerInfo) {
    RegisterToServer.ResultToApp result = localStub.registerServer(routerInfo);
    System.out.println("name :" + result.getUserName());
  }

  public static void main(String[] args) throws InterruptedException {
    SendMsgToGo client = new SendMsgToGo("127.0.0.1", 15000);
    RegisterToServer.RouterInfo p = RegisterToServer.RouterInfo.newBuilder()
        .setIp("127.0.0.1")
        .setDomain("www.test.cn")
        .setApplicationName("这是一个测试")
        .setDescription("这是一个Go与Java通过protobuf通信的测试").build();
    client.greet(p);
    client.shutdown();
  }
}

protoc.exe工具链接:
https://download.csdn.net/download/believe__dream/10577322

你可能感兴趣的:(go使用GRPC)