Go語言開發gRpc服務,springboot2.x客戶端調用

Golang開發gRpc服務

  1. 首先本機安裝proto客戶端,並配置環境變量
  2. 創建golang項目 結構如下圖

3.新建一個helloworld.proto文件,內容如下

syntax = "proto3";

package helloworld;
option java_package = "com.example.grpc.helloworld";
option java_multiple_files = true;

// The greeting service definition.
service Greeter {
  // Sends a greeting
  rpc SayHello (HelloRequest) returns (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;
}

這個文件稍後還會用在springboot項目中

4.使用命令將proto文件生成成go文件,命令如下

# proto文件編譯爲go文件命令
// protoc --go_out=plugins=grpc:{輸出目錄}  {proto文件}   
protoc --go_out=plugins=grpc:./helloworld/ ./helloworld.proto

5.在server文件夾下 新建main.go,作爲gRpc的服務端

/*
@Time : 2020/5/25 15:01
@Author : wkang
@File : server
@Description:
*/
package main

import (
	"context"
	"fmt"
	"google.golang.org/grpc"
	"google.golang.org/grpc/reflection"
	"log"
	"net"
	pb "../helloworld"
)

const (
	port = ":50051"
)

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

// SayHello implements helloworld.GreeterServer
func (s *server) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) {
	fmt.Println("######### get client request name :"+in.Name)
	return &pb.HelloReply{Message: "GO gRpc服務的響應爲: Hello " + in.Name}, nil
}

func main() {
	lis, err := net.Listen("tcp", port)
	fmt.Println(port)
	if err != nil {
		log.Fatalf("failed to listen: %v", err)
	}
	s := grpc.NewServer()
	pb.RegisterGreeterServer(s, &server{})
	// Register reflection service on gRPC server.
	reflection.Register(s)
	if err := s.Serve(lis); err != nil {
		log.Fatalf("failed to serve: %v", err)
	}
}

6.服務端創建成功,我們在server文件夾下運行終端 輸入命令啓動服務

go run main.go

7.可以看到服務啓動成功,我打印了一下端口號

8.我們可以初始化一個客戶端,來看看服務端是否正常,在client文件夾下,添加main.go,代碼如下

/*
@Time : 2020/5/25 15:01
@Author : wkang
@File : server
@Description:
*/
package main

import (
	"context"
	"fmt"
	"google.golang.org/grpc"
	"google.golang.org/grpc/reflection"
	"log"
	"net"
	pb "../helloworld"
)

const (
	port = ":50051"
)

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

// SayHello implements helloworld.GreeterServer
func (s *server) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) {
	fmt.Println("######### get client request name :"+in.Name)
	return &pb.HelloReply{Message: "GO gRpc服務的響應爲: Hello " + in.Name}, nil
}

func main() {
	lis, err := net.Listen("tcp", port)
	fmt.Println(port)
	if err != nil {
		log.Fatalf("failed to listen: %v", err)
	}
	s := grpc.NewServer()
	pb.RegisterGreeterServer(s, &server{})
	// Register reflection service on gRPC server.
	reflection.Register(s)
	if err := s.Serve(lis); err != nil {
		log.Fatalf("failed to serve: %v", err)
	}
}

9.在client文件夾下 啓動客戶端服務,可在命令行界面看到響應

10.服務端終端顯示如下圖

當前服務正常~

Springboot創建gRpc服務端和客戶端

1.首先我們新建一個sprongboot項目,修改pom文件如下

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.example</groupId>
    <artifactId>grpc-java-demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>grpc-java-demo</name>
    <description>Demo project for Spring Boot gRpc</description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.0.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>


    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
        <grpc-spring-boot-starter.version>3.0.0</grpc-spring-boot-starter.version>
        <os-maven-plugin.version>1.6.1</os-maven-plugin.version>
        <protobuf-maven-plugin.version>0.6.1</protobuf-maven-plugin.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>io.github.lognet</groupId>
            <artifactId>grpc-spring-boot-starter</artifactId>
            <version>${grpc-spring-boot-starter.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <extensions>
            <extension>
                <groupId>kr.motd.maven</groupId>
                <artifactId>os-maven-plugin</artifactId>
                <version>${os-maven-plugin.version}</version>
            </extension>
        </extensions>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
            <plugin>
                <groupId>org.xolstice.maven.plugins</groupId>
                <artifactId>protobuf-maven-plugin</artifactId>
                <version>${protobuf-maven-plugin.version}</version>
                <configuration>
                    <protocArtifact>com.google.protobuf:protoc:3.5.1-1:exe:${os.detected.classifier}</protocArtifact>
                    <pluginId>grpc-java</pluginId>
                    <pluginArtifact>io.grpc:protoc-gen-grpc-java:1.16.1:exe:${os.detected.classifier}</pluginArtifact>
                </configuration>
                <executions>
                    <execution>
                        <goals>
                            <goal>compile</goal>
                            <goal>compile-custom</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

</project>

2.將開始創建好的proto文件複製到項目中,目錄結構如下

3.mvn compile之後 proto插件會根據當前proto文件生成對應的類,如下圖

4.接下來的四個文件 是springboot的啓動類 grpc客戶端 grpc服務端 和一個控制器,用來測試效果

5.GrpcJavaDemoApplication 啓動文件

package com.example.grpcjavademo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class GrpcJavaDemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(GrpcJavaDemoApplication.class, args);
    }

}

6.HelloWorldClient客戶端文件

package com.example.grpcjavademo.grpc;

import com.example.grpc.helloworld.GreeterGrpc;
import com.example.grpc.helloworld.HelloReply;
import com.example.grpc.helloworld.HelloRequest;
import io.grpc.ManagedChannel;
import io.grpc.ManagedChannelBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;

@Component
public class HelloWorldClient {

  private static final Logger LOGGER =
      LoggerFactory.getLogger(com.example.grpcjavademo.grpc.HelloWorldClient.class);

  private GreeterGrpc.GreeterBlockingStub helloWorldServiceBlockingStubForGo;
  private GreeterGrpc.GreeterBlockingStub helloWorldServiceBlockingStubForJava;

  @PostConstruct
  private void init() {
    //初始化一個連接Go grpc的客戶端
    ManagedChannel managedChannelForGo = ManagedChannelBuilder
        .forAddress("127.0.0.1", 50051).usePlaintext().build();

    helloWorldServiceBlockingStubForGo =
            GreeterGrpc.newBlockingStub(managedChannelForGo);

    //初始化一個連接Java grpc的客戶端
    ManagedChannel managedChannelForJava = ManagedChannelBuilder
            .forAddress("127.0.0.1", 6565).usePlaintext().build();

    helloWorldServiceBlockingStubForJava =
            GreeterGrpc.newBlockingStub(managedChannelForJava);
  }

  public String sayHello(String name,String server) {
    HelloRequest person = HelloRequest.newBuilder().setName(name).build();
    LOGGER.info("client sending {}", person);

    String res="";
    if (server=="go"){
      HelloReply greeting =
              helloWorldServiceBlockingStubForGo.sayHello(person);
      LOGGER.info("client received {}", greeting);
      res=greeting.getMessage();
    }

    if (server=="java"){
      HelloReply greeting =
              helloWorldServiceBlockingStubForJava.sayHello(person);
      LOGGER.info("client received {}", greeting);
      res=greeting.getMessage();
    }



    return res;
  }
}

在這裏我們初始化了兩個客戶端,分別連接不同的端口,一個用來連接測試上面Go創建的grpc服務,一個用來連接測試java創建的gRpc服務

7.服務端文件HelloWorldServiceImpl

package com.example.grpcjavademo.grpc;


import com.example.grpc.helloworld.GreeterGrpc;
import com.example.grpc.helloworld.HelloReply;
import com.example.grpc.helloworld.HelloRequest;
import io.grpc.stub.StreamObserver;
import org.lognet.springboot.grpc.GRpcService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@GRpcService
public class HelloWorldServiceImpl
    extends GreeterGrpc.GreeterImplBase {

  private static final Logger LOGGER =
      LoggerFactory.getLogger(com.example.grpcjavademo.grpc.HelloWorldServiceImpl.class);

  @Override
  public void sayHello(HelloRequest request,
                       StreamObserver<HelloReply> responseObserver) {
    LOGGER.info("server received {}", request);

    String message = "Java gRpc服務的響應爲: Hello " + request.getName() + "!";
    HelloReply greeting =
            HelloReply.newBuilder().setMessage(message).build();
    LOGGER.info("server responded {}", greeting);

    responseObserver.onNext(greeting);
    responseObserver.onCompleted();
  }
}

8.用來測試的控制器

package com.example.grpcjavademo.controller;

import com.example.grpcjavademo.grpc.HelloWorldClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;

@RestController
@RequestMapping("/home")
public class HomeController {
    @Resource
    private HelloWorldClient helloWorldClient;

    //連接Go的gRpc服務端
    @GetMapping("/testgo")
    public String testGo(){
        String s = helloWorldClient.sayHello("World","go");
        return s;
    }

    //連接java(當前項目)的gRpc服務端
    @GetMapping("/testjava")
    public String testJava(){
        String s = helloWorldClient.sayHello("World","java");
        return s;
    }
}

 

9.啓動項目,我們使用postman來訪問控制器提供的兩個接口

訪問testgo時,我們通過客戶端請求了Go語言開發的服務端

接下來我們訪問testjava

我們請求了當前項目下啓動的grpc。

 

至此完結,因爲不復雜,所以沒有寫的很詳細,可以查看兩個項目的源碼

go gRpc客戶端和服務端的demo https://github.com/flyingkoala/grpc-go-demo

springboot  gRpc客戶端和服務端的demo https://github.com/flyingkoala/grpc-java-demo

 

最後ps一下踩到的坑

1.go語言開發grpc用到的框架,因爲被qiang的原因,可能在下載的過程中麻煩一些,方法可以自行百度一下,無非就是gopm、代理、git下載到本地自行安裝這幾種。

2.proto文件保持一致。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章