一、 编写proto文件

   1、idea新建java项目,在maven中引入以下依赖:

 <dependencies>
        <!--grpc底层通信组件-->
        <dependency>
            <groupId>io.grpc</groupId>
            <artifactId>grpc-netty-shaded</artifactId>
            <version>1.42.0</version>
        </dependency>
        <dependency>
            <groupId>io.grpc</groupId>
            <artifactId>grpc-protobuf</artifactId>
            <version>1.42.0</version>
        </dependency>
        <!--存根-->
        <dependency>
            <groupId>io.grpc</groupId>
            <artifactId>grpc-stub</artifactId>
            <version>1.42.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.tomcat</groupId>
            <artifactId>annotations-api</artifactId>
            <version>6.0.53</version>
            <!--provided:只能作用在编译和测试时,同时没有传递性-->
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>com.google.protobuf</groupId>
            <artifactId>protobuf-java</artifactId>
            <version>3.9.1</version>
        </dependency>

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.83</version>
        </dependency>

    </dependencies>


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

  2、proto文件

syntax = "proto3";
//生成java类所在的包
option java_package = "com.cn.news.proto";

//生成多个类
option java_multiple_files = false;

//生成外层类类名
option java_outer_classname = "NewsProto";

//包名
package news;

//grpc要调用的service
service NewsService{
    //list是方法名,NewsRequest代表传入参数,NewsResponse代表返回响应
    rpc list(NewsRequest) returns (NewsResponse){}
}

//请求体
message NewsRequest{
    string date = 1;
    NewsDetail body = 2;
}

//响应体
message NewsResponse{
    //repeated说明是一个集合(数组),数组每一个元素都是News对象
    repeated News news = 1;
}

//News新闻实体对象
message News{
    //对应java的int
    int32 id = 1;
    //新闻标题
    string title = 2;
    //新闻内容
    string content = 3;
    //对应java的long
    int64 createTime = 4;
}

message NewsDetail{
    //1表示热点新闻 2表示普通新闻
    int32 msgType = 1;
    //0未读 1-已读
    int32 msgStatus = 2;
}

 3. 编译并生成java文件

二、 编写grpc服务端

    1、实现  NewsServiceGrpc.NewsServiceImplBase 接口,提供服务方法调用

package com.cn.news.service;

import com.cn.news.proto.NewsProto;
import com.cn.news.proto.NewsServiceGrpc;
import io.grpc.stub.StreamObserver;

/**
 * description: NewService <br>
 * date: 23.4.12 15:52 <br>
 * author: cn_yaojin <br>
 * version: 1.0 <br>
 */
public class NewService extends NewsServiceGrpc.NewsServiceImplBase {

    @Override
    public void list(NewsProto.NewsRequest request, StreamObserver<NewsProto.NewsResponse> responseObserver) {
        String date = request.getDate();
        System.out.println("收到客户端请求了,时间:" + date + ",参数体:" + request.getBody().getMsgType());
        NewsProto.NewsResponse newList = null;
        try {
            NewsProto.NewsResponse.Builder newListBuilder = NewsProto.NewsResponse.newBuilder();

            String title = "";
            if (request.getBody().getMsgType() == 1) {
                title = "实时热点";
            } else if (request.getBody().getMsgType() == 2) {
                title = "精准扶贫";
            } else {
                title = "为人民服务";
            }


            NewsProto.News news = NewsProto.News.newBuilder()
                    .setId(request.getBody().getMsgType())
                    .setTitle(title)
                    .setContent(request.getBody().getMsgType() + ":" + title)
                    .setCreateTime(System.currentTimeMillis())
                    .build();
            newListBuilder.addNews(news);

            newList = newListBuilder.build();
        } catch (Exception e) {
            e.printStackTrace();
            responseObserver.onError(e);
        } finally {
            responseObserver.onNext(newList);
        }

        responseObserver.onCompleted();
    }
}

    2、 grpc服务端,启动

package com.cn.news.service;

import io.grpc.Server;
import io.grpc.ServerBuilder;

/**
 * description: GRpcServer <br>
 * date: 23.4.12 16:29 <br>
 * author: cn_yaojin <br>
 * version: 1.0 <br>
 */
public class GRpcServer {

    public static void main(String[] args) {
        try {
            Server server = ServerBuilder.forPort(1031).addService(new NewService()).build().start();
            System.out.println("服务已启动,端口:" + server.getPort());
            server.awaitTermination();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}

三、 编写grpc客户端,启动

package com.cn.news.service;

import com.cn.news.proto.NewsProto;
import com.cn.news.proto.NewsServiceGrpc;
import io.grpc.Channel;
import io.grpc.ManagedChannel;
import io.grpc.ManagedChannelBuilder;

import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * description: GRpcClient <br>
 * date: 23.4.12 16:32 <br>
 * author: cn_yaojin <br>
 * version: 1.0 <br>
 */
public class GRpcClient {

    private NewsServiceGrpc.NewsServiceBlockingStub newsServiceImplBase;


    public GRpcClient(Channel channel) {
        this.newsServiceImplBase = NewsServiceGrpc.newBlockingStub(channel);
    }

    public static void main(String[] args) {
        //初始化client与服务端的连接

        ManagedChannel channel = ManagedChannelBuilder.forTarget("127.0.0.1:1031")
                .usePlaintext()
                .build();

        GRpcClient gRpcClient = new GRpcClient(channel);

        //定时任务模拟提交数据
        ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(1);
        scheduledExecutorService.scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {

                //以下是构造请求参数
                NewsProto.NewsDetail.Builder detail = NewsProto.NewsDetail.newBuilder();
                long t = System.currentTimeMillis();
                if (t % 5 == 0) {
                    detail.setMsgType(1);
                } else if (t % 5 == 1) {
                    detail.setMsgType(3);
                } else {
                    detail.setMsgType(2);
                }
                detail.setMsgStatus(0);

                NewsProto.NewsRequest request = NewsProto.NewsRequest
                        .newBuilder()
                        .setDate(t + "")
                        .setBody(detail.build())
                        .build();
                gRpcClient.list(request);
            }
        }, 10, 30, TimeUnit.SECONDS);

        try {
            Thread.sleep(Long.MAX_VALUE);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }

    /**
     * 调用grpc的提供的服务(此处调用NewService下的list方法)
     *
     * @param request
     */
    public void list(NewsProto.NewsRequest request) {
        try {
            NewsProto.NewsResponse response = newsServiceImplBase.list(request);
            List<NewsProto.News> list = response.getNewsList();
            if (list != null) {
                for (NewsProto.News t : list) {
                    System.out.println(String.format("收到服务端响应了,标题:%s,内容:%s,时间:%s", t.getTitle(), t.getContent(), t.getCreateTime()));
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}

四、启动后的运行示例 

grpc服务端
grpc服务端

 

grpc客户端
grpc客户端

 五、 编写node客户端

const grpc = require('grpc');
const protoLoader = require('@grpc/proto-loader');

//以下proto文件与当前的index.js在同一个目录下
const PROTO_PATH = 'helloworld.proto';

const packageDefinition = protoLoader.loadSync(PROTO_PATH);
const hello_proto = grpc.loadPackageDefinition(packageDefinition).news;

function main() {
  const client = new hello_proto.NewsService('127.0.0.1:1031',
    grpc.credentials.createInsecure());
    var detail={
        msgType:2,
        msgStatus:2 
    };
    var user={
        date:123123123123,
        body: detail
    };

  client.list(user, function (err, response) {
    var items = response.news

    console.log('Greeting:', items);
  });
}

main();
node客户端运行结果

 

Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐