Golang開發gRpc服務
- 首先本機安裝proto客戶端,並配置環境變量
- 創建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文件保持一致。