gRPCã®Javaçã®チュートリアルã«ã¯ãGradleã使ã£ããã«ãæ¹æ³ã ãã説æããã¦ãããJavaçéã§ã¯MavenãGradleããã«ããã¼ã«ã¨ãã¦ãã使ããã¦ããã®ã¯ç¥ã£ã¦ããããç§ã¯makeã使ãããããã£ã¦ãã¾ãã¯ãã«ããã¼ã«ã使ããã«åã ã®æé ãé²ããæ¹æ³ãæããã«ããä¸ã§ããããMakefileã«ã¾ã¨ããã
ã¾ãã¯ä¾åããã±ã¼ã¸ãã¤ã³ã¹ãã¼ã«ãã¦ãããgRPCã®ãã¥ã¼ããªã¢ã«ã«ããããã«GitHubãããªãã¸ããªãæ®ã£ã¦ãã¦cmakeã§ãã«ããã¦ããããã使ã£ã¦ããOSã«ãã¤ããªããã±ã¼ã¸ããããªãã°ãããã使ãã®ã楽ã ãUbuntuï¼21.10ï¼ã®å ´åãaptã§ä»¥ä¸ã®ããã±ã¼ã¸ãå ¥ããã
- libprotobuf-java
- libgrpc-java
- protobuf-compiler-grpc-java-plugin
- libgoogle-common-protos-java
- libguava-java
- libnetty-java
- libperfmark-java
ãã¹ãç¨ã«ãRPCã®ã¤ã³ã¿ã¼ãã§ã¤ã¹ãprotoãã¡ã¤ã«ã¨ãã¦å®ç¾©ãã¦ãããä»»æã®æååãéãã¨ããããã®ã¾ã¾ã¨ã³ã¼ããã¯ãããµã¼ãã¹ã ãlucky_star.protoã¨ãããååã§ä¿åãã¦ãããã
syntax = "proto3"; package lucky_star; message EchoRequest { string message = 1; } message EchoResponse { string echo = 1; } service HappyService { rpc Echo(EchoRequest) returns (EchoResponse); }
ãã®protoãã¡ã¤ã«ãããGRPCã®Javaã³ã¼ããçæãããProtocol Buffersã®ã³ã³ãã¤ã©ãã©ã¤ãã§ããprotocã³ãã³ãã¨ããã®GRPC-Javaç¨ãã©ã°ã¤ã³ã§ããgrpc_java_pluginãç¨ããããã©ã°ã¤ã³ã®æ¹ã¯ãªãã絶対ãã¹ã§æå®ããªããã°ãããªããããã
$ protoc --plugin=protoc-gen-grpc_java=/usr/bin/grpc_java_plugin \ --proto_path=. --java_out=. --grpc_java_out=. lucky_star.proto
ããã±ã¼ã¸åã¨ååã®lucky_starã¨ãããã£ã¬ã¯ããªãä½ããããã®ä¸ã«ããã±ã¼ã¸åããã£ã¡ã«ã±ã¼ã¹ã«ããLuckyStar.javaãã¡ã¤ã«ã¨ããµã¼ãã¹åã«Grpcãã¤ããHappyServiceGrpc.javaãã¡ã¤ã«ãä½ãããããããã«ã¬ã³ããã£ã¬ã¯ããªã«ç§»åãããã
$ mv lucky_star/*.java .
ç§ããã¤ããªããã±ã¼ã¸ã¨ãã¦å ¥ãããã¼ã¸ã§ã³ã®grpc_java_pluginã¯ãJava8以åã®ããã±ã¼ã¸ãæ³å®ããã³ã¼ããçæããããææ°ã®JDKã使ã£ã¦ããã¨äºææ§ã®åé¡ãããããã®ã¾ã¾ãã«ããããã¨ããã¨ã以ä¸ã®ã¨ã©ã¼ãåºã¦ãã¾ãã®ã ã
HappyServiceGrpc.java:23: error: cannot find symbol @javax.annotation.Generated( ^ symbol: class Generated location: package javax.annotation
この報告ã«ããããã«ãJava8ã¾ã§ã¯javax.annotation.Generatedã§ãã£ãã¯ã©ã¹ãJava9ããã¯javax.annotation.processing.Generatedã«å¤ãã£ã¦ããã®ãåå ã ããããgrpc_java_pluginå´ã§æ°ããæ§é ãããã©ã«ãã«ãã¦ãããã¨æå¾ ãã¤ã¤ãä»ã¯çæãããã³ã¼ããæ¸ãæããã¨ããåé¿çãåãã
$ sed -e 's/javax\.annotation\.Generated/javax.annotation.processing.Generated/g' \ HappyServiceGrpc.java > ~HappyServiceGrpc.java $ mv -f ~HappyServiceGrpc.java HappyServiceGrpc.java
å®éã®ã¢ããªã±ã¼ã·ã§ã³ã®ã³ã¼ããæ¸ãæºåãæ´ã£ãã®ã§ããµã¼ãããå®è£ ãã¦ãããã以ä¸ã®ãããªã³ã¼ãã«ãªããSampleServer.javaãªã©ã¨ãã¦ä¿åããããã
package lucky_star; import io.grpc.Server; import io.grpc.ServerBuilder; import io.grpc.stub.StreamObserver; public class SampleServer { public static void main(String[] args) throws Exception { // ãµã¼ããä½ã£ã¦ããµã¼ãã¹ãç»é²ãã Server server = ServerBuilder.forPort(1978) .addService(new HappyServiceImpl()).build(); // ãµã¼ããéå§ãã server.start(); System.out.println("The server is running."); System.out.flush(); // ãµã¼ããçµäºããã¾ã§å¾ 㤠server.awaitTermination(); } // ãµã¼ãã¹ã®å®è£ ã¯ã©ã¹ static class HappyServiceImpl extends HappyServiceGrpc.HappyServiceImplBase { // Echoã®å®è£ @Override public void echo(LuckyStar.EchoRequest request, StreamObserver<LuckyStar.EchoResponse> observer) { System.out.println("Server Echo: " + request.getMessage()); System.out.flush(); // ã¬ã¹ãã³ã¹ãçæãã LuckyStar.EchoResponse.Builder response = LuckyStar.EchoResponse.newBuilder(); response.setEcho(request.getMessage()); // ã¬ã¹ãã³ã¹ãåºåãã observer.onNext(response.build()); // åºåå¦çãå®äºããã¾ã§å¾ 㤠observer.onCompleted(); } } }
ã¯ã©ã¤ã¢ã³ãã¯ä»¥ä¸ã®ãããªã³ã¼ãã«ãªããSampleClient.javaãªã©ã¨ãã¦ä¿åããããã
package lucky_star; import io.grpc.Channel; import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; import io.grpc.StatusRuntimeException; import java.util.concurrent.TimeUnit; public class SampleClient { public static void main(String[] args) throws Exception { ManagedChannel channel = null; try { // gRPCã®ãã£ã³ãã«ãä½ã channel = ManagedChannelBuilder.forTarget("localhost:1978") .usePlaintext().build(); // ãµã¼ãã¹ã®ã¹ã¿ããä½ã HappyServiceGrpc.HappyServiceBlockingStub stub = HappyServiceGrpc.newBlockingStub(channel); // Echoã¡ã½ããã®ãªã¯ã¨ã¹ããä½ã LuckyStar.EchoRequest.Builder request = LuckyStar.EchoRequest.newBuilder(); request.setMessage("Hello World"); // Echoã¡ã½ãããå®è¡ãã¦çµæã表示ãã LuckyStar.EchoResponse response; try { response = stub.echo(request.build()); } catch (StatusRuntimeException e) { System.err.println("RPC failed: " + e.getStatus()); return; } System.out.println("Client: Echo: " + response.getEcho()); } finally { if (channel != null) { // ãã£ã³ãã«ã®æ¥ç¶ãåã channel.shutdownNow().awaitTermination(5, TimeUnit.SECONDS); } } } }
ã¢ããªã±ã¼ã·ã§ã³ããã«ããããå®è¡ãããããéã«ã¯ãgRPCã®ã©ã¤ãã©ãªãã¯ã©ã¹ãã¹ã«å«ããå¿ è¦ããããgRPC-Javaããã¤ããªããã±ã¼ã¸ã§å ¥ããå ´åã/usr/share/javaã®ä¸ã«å¤æ°ã®jarãã¡ã¤ã«ãããã¯ãã ããããã¯ã¤ã«ãã«ã¼ãã§å ¨é¨æå®ããã
$ javac -d . -cp .:/usr/share/java/* HappyServiceGrpc.java LuckyStar.java SampleServer.java SampleClient.java
ãªãã·ã§ã³ã§ "-d ." ãæå®ããã®ã§ãããã±ã¼ã¸ã¨åãååã®ãã£ã¬ã¯ããªlucky_starãä½ããã¦ããã®ä¸ã«å¤§éã®ã¯ã©ã¹ãã¡ã¤ã«ãä½ããã¦ããã¯ãã ããã¨ã¯æ®éã«ãjavaã³ãã³ãã§ãµã¼ããã¯ã©ã¤ã¢ã³ãã®mainã®ããã¯ã©ã¹ãæå®ããã°å®è¡ã§ããããµã¼ãå´ã¯ä»¥ä¸ã®ããã«ããã
$ java -cp .:/usr/share/java/* lucky_star.SampleServer The server is running.
å¥ã®ç«¯æ«ã§ã¯ã©ã¤ã¢ã³ããèµ·åããã¨ãç¡äºã«ã¨ã³ã¼ããã¯ã®åºåãå¾ãããã¯ãã ã
$ java -cp .:/usr/share/java/* lucky_star.SampleClient Client: Echo: Hello World
JARãã¡ã¤ã«ã«ã¾ã¨ãã¦æ±ãããããããã¾ããJARãã¡ã¤ã«ã ãã§åãã確èªããã
$ jar cvf lucky_star/*.class ... $ rm -rf lucky_star
$ java -cp lucky_star.jar:/usr/share/java/* lucky_star.SampleServer The server is running.
$ java -cp lucky_star.jar:/usr/share/java/* lucky_star.SampleClient Client: Echo: Hello World
以ä¸ã§ãä¸éãã®ãã«ãæé ãç¶²ç¾ ã§ãã¦ãããMavenãGradleããªãã¦ãçãã¦ãããï¼ãã£ãæ¹ã便å©ãªã®ã¯è¨ãã¾ã§ããªããï¼ããã¦ãç§ã¯å¤ãè¯ãmakeæ´¾ãªã®ã§ãMakefileãæ¸ãããæ¬å½ã¯configureããæ¸ãã®ã ãã説æã®ããã«Makefileããããªãæ¸ããã³ããããã¨ãã¯å é ã®ã¤ã³ãã³ãã¯ã¿ãã«ç½®æããå¿ è¦ãããã
SHELL = /bin/bash JARFILES = lucky_star.jar JAVAFILES = HappyServiceGrpc.java LuckyStar.java SampleServer.java SampleClient.java JAVAC = /usr/java/bin/javac GRPCJARDIR = /usr/share/java JAVACFLAGS = -d . -cp .:$(GRPCJARDIR)/* JAR = /usr/java/bin/jar JAVARUN = /usr/java/bin/java JAVARUNFLAGS = -cp lucky_star.jar:$(GRPCJARDIR)/* PROTOC = /usr/bin/protoc GRPCJAVAPLUGIN = /usr/bin/grpc_java_plugin all : $(JARFILES) clean : rm -rf $(JARFILES) lucky_star *~ check : $(JAVARUN) $(JAVARUNFLAGS) lucky_star.SampleServer & SERVER_PID="$$!" ; sleep 2 ;\ $(JAVARUN) $(JAVARUNFLAGS) lucky_star.SampleClient ;\ kill $$SERVER_PID proto2java : lucky_star.proto rm -rf lucky_star $(PROTOC) --plugin=protoc-gen-grpc_java=$(GRPCJAVAPLUGIN) \ --proto_path=. --java_out=. --grpc_java_out=. lucky_star.proto mv lucky_star/*.java . rm -rf lucky_star sed -e 's/javax\.annotation\.Generated/javax.annotation.processing.Generated/g' \ HappyServiceGrpc.java > ~HappyServiceGrpc.java mv -f ~HappyServiceGrpc.java HappyServiceGrpc.java lucky_star.jar : $(JAVAFILES) $(JAVAC) $(JAVACFLAGS) $(JAVAFILES) $(JAR) cvf $@ lucky_star/*.class rm -rf lucky_star
protoãã¡ã¤ã«ããçæããjavaãã¡ã¤ã«ã¯ãäºãããã±ã¼ã¸ããªãã¸ããªã«å ¥ãã¦ããæ¹éã«ãããããããã°ãå©ç¨è ã¯protocãprotoc-gen-grpc_javaãã¤ã³ã¹ãã¼ã«ããå¿ è¦ããªããªãããã ããªã®ã§ãéçºæã«protoãã¡ã¤ã«ãæ´æ°ããå ´åã«ã¯ãæ示çã« make prot2java ãå®è¡ãããå©ç¨è å´ã§ã¯ãmake && make check ãå®è¡ããã ãã§ãã«ãã¨åä½ç¢ºèªãã§ãããmake checkã®çµæã¯ãããªæãã«ãªãã
$ make check /usr/java/bin/java -cp lucky_star.jar:/usr/share/java/* lucky_star.SampleServer & SERVER_PID="$!" ; sleep 2 ;\ /usr/java/bin/java -cp lucky_star.jar:/usr/share/java/* lucky_star.SampleClient ;\ kill $SERVER_PID The server is running. Server Echo: Hello World Client: Echo: Hello World
ã¾ã¨ããgRPCã®Javaçã®ã¢ããªã±ã¼ã·ã§ã³ãæåã§ãã«ãããæé ãç´¹ä»ãããã¾ãããããMakefileã«ã¾ã¨ããããã«ãæé ã«èºãã¦gRPCãåé¿ãã¦ãã人ãå°ãªãããããã¨æãã®ã§ããã®è¨äºãè¦ã¦æ»ã£ã¦ãã¦ããã人ããããªãå¬ããã
Tkrzw-RPCã®Javaçã¯ã©ã¤ã¢ã³ãã®éçºãå¾åãã«ãªã£ã¦ããã®ã¯ããã®æé ã調ã¹ãã®ããããé¢åã ã£ãããã ãã¨ããããGradleããã«ãããããã«protobufã®ãã¼ã¸ã§ã³ãä¸ããªãããªããªãã£ãã®ã ããããããã¨ç¾ç¶ã®ã·ã¹ãã ã¨éäºæãçºçããã®ã§ä½æ¥ã§ããªãã£ãã®ã ãä¸æ¨æ¥ãã·ã¹ãã ãUbuntu 21.10ã«ã¢ããã°ã¬ã¼ãããã®ã§ãããããæãããã«ãªã£ããgRPCå¨ãã¯ä¾åã³ã³ãã¼ãã³ãã®ãã¼ã¸ã§ã³ã®éãã«ææãªã®ã§ããã¤ããªããã±ã¼ã¸ã§å ¥ããªãã¨ãã¤ããGradle使ããã¨è¨ããããã ããC++ã¨Pythonã¨Rubyã¨Goãã¡ã³ããã«ããªããããã§ã