2019.07.05
Developing with Java gRPC, Docker and IntelliJ
こんにちは、次世代システム研究室のN.M.です。
If you haven’t already heard, the nice folks at Google have open sourced their framework for creating internal APIs, it’s called gRPC. gRPC is based on RPC and uses Google’s protobuf data exchange format by default. You define your API in a .proto file, which the gRPC framework uses to generate code and stubs in your target programming language. In this I will talk about setting up a development environment for Java gRPC. To test our setup we will use one of the three supplied example applications, routeguide. IntelliJ will be used as the IDE. We will use Docker to run the gRPC server. I used a MacBook Pro for this, but most of the steps should be transferable to Windows.
Install protoc
$ brew install protobuf
Or use the binaries found at https://github.com/protocolbuffers/protobuf/releases, click on assets for the desired version and download the zip distribution file for your platform. See the README for details on how to install, but it should be as easy as unziping and copying the enclosed protoc binary into a location on your path.
Install Java gRPC
From git:
$ git clone [email protected]:grpc/grpc-java.git
Build Docker for Java gRPC
This Dockerfile sets up a gRPC capable linux container.
FROM openjdk:10 ENV PROTOBUF_VERSION=3.8.0 RUN curl -LO https://github.com/protocolbuffers/protobuf/releases/download/v${PROTOBUF_VERSION}/protoc-${PROTOBUF_VERSION}-linux-x86_64.zip && \ unzip protoc-${PROTOBUF_VERSION}-linux-x86_64.zip -d /usr ENV JAVA_OPTS=-agentlib:jdwp=transport=dt_socket,server=y,address=*:8000,suspend=n # runs application CMD ["tail", "-f", "/dev/null"]
You can see that first we will use the OpenJDK version 10 as our base machine. We then install Google Protocol Buffers version 3.8.0. We then define JAVA_OPTS that will later allow us to remote debug the gRPC server running on this docker machine. Save the above as Dockerfile, in a convenient location, I suggest under grpc-java/examples, since we will be doing most of our work around here. cd to the same folder as your Dockerfile and build your Docker image.
$ docker build -t grpc-java:latest . Sending build context to Docker daemon 18.24MB Step 1/5 : FROM openjdk:10 ---> b11e88dd885d Step 2/5 : ENV PROTOBUF_VERSION=3.8.0 ---> Using cache ---> 138ec8eb8c08 Step 3/5 : RUN curl -LO https://github.com/protocolbuffers/protobuf/releases/download/v${PROTOBUF_VERSION}/protoc-${PROTOBUF_VERSION}-linux-x86_64.zip && unzip protoc-${PROTOBUF_VERSION}-linux-x86_64.zip -d /usr ---> Using cache ---> 4aa5913d2e91 Step 4/5 : ENV JAVA_OPTS=-agentlib:jdwp=transport=dt_socket,server=y,address=*:8000,suspend=n ---> Using cache ---> db03b5daf8f9 Step 5/5 : CMD ["tail", "-f", "/dev/null"] ---> Using cache ---> 1cd3468bed45 Successfully built 1cd3468bed45 Successfully tagged grpc-java:latest
Run the gRPC Docker Container
$ docker run -d --name grpc -v /<FULL PATH>/grpc-java/examples:/var/grpc-java -p 8980:8980 -p 8000:8000 grpc-java:latest 98823ee7dc062a0dcef3ef453c4302dc9270014bc71262613a0bf419092bdaa2
The above command maps our host directory /<FULL PATH>/grpc-java/examples to a directory in the docker machine, /var/grpc-java.
It also maps the host port 8980 to the docker port 8980 and the host port 8000 to the docker port 8000. So the client can run on the host and access to 8980 and our debugger can run on the host and access 8000.
Login to the docker machine
$ docker exec -it 98823ee7dc062a /bin/bash root@98823ee7dc06:/#
start the server
root@98823ee7dc06:/# cd /var/grpc-java/build/install/examples/bin root@98823ee7dc06:/var/grpc-java/build/install/examples/bin# ./route-guide-server Listening for transport dt_socket at address: 8000 Jul 02, 2019 11:20:35 AM io.grpc.examples.routeguide.RouteGuideServer start INFO: Server started, listening on 8980
From the output above we can see that the server is started and listening on port 8980 for connections from the client, and also that the JVM is listening to port 8000 for remote debugging.
Developing
If you look at the the build.gradle file you will see that this project uses the idea plugin, so we can get the project ready to open for IntelliJ using the command below:
$ ./gradlew idea Starting a Gradle Daemon (subsequent builds will be faster) > Task :idea Generated IDEA project at file:///<FULL PATH>/grpc-java/examples/examples.ipr BUILD SUCCESSFUL in 55s 4 actionable tasks: 4 executed
This command allows us to simply open the IntelliJ project at /<FULL PATH>/grpc-java/examples/.
Running the Client
$ ./build/install/examples/bin/route-guide-client Jul 03, 2019 2:26:49 PM io.grpc.examples.routeguide.RouteGuideClient info INFO: *** GetFeature: lat=409,146,138 lon=-746,188,906 Jul 03, 2019 2:26:49 PM io.grpc.examples.routeguide.RouteGuideClient info INFO: Found feature called "Berkshire Valley Management Area Trail, Jefferson, NJ, USA" at 40.915, -74.619 Jul 03, 2019 2:26:49 PM io.grpc.examples.routeguide.RouteGuideClient info INFO: *** GetFeature: lat=0 lon=0 Jul 03, 2019 2:26:49 PM io.grpc.examples.routeguide.RouteGuideClient info INFO: Found no feature at 0, 0 Jul 03, 2019 2:26:49 PM io.grpc.examples.routeguide.RouteGuideClient info INFO: *** ListFeatures: lowLat=400,000,000 lowLon=-750,000,000 hiLat=420,000,000 hiLon=-730,000,000 Jul 03, 2019 2:26:49 PM io.grpc.examples.routeguide.RouteGuideClient info INFO: Result #1: name: "Patriots Path, Mendham, NJ 07945, USA" location { latitude: 407838351 longitude: -746143763 } Jul 03, 2019 2:26:49 PM io.grpc.examples.routeguide.RouteGuideClient info INFO: Result #2: name: "101 New Jersey 10, Whippany, NJ 07981, USA" location { latitude: 408122808 longitude: -743999179 } ...
The client makes queries to the gRPC server
Debugging
Go to Run/Edit Configurations in Intellij to set-up a remote debugger to connect to our gRCP server. Input name, leave the default value of Host as localhost, and set Port to 8000, which is the debug port specified in our Dockerfile above. Click OK and you can now select the debugger by the name you chose. Go to Run/Debug to see a list of configured debuggers and select the debugger. Now you may set breakpoints in the server in a class such as RouteGuideServer and step through the server code using the debugger. This is educational for the example code and invaluable for when you actually develop your own gRPC API.
Note that you may also debug the client in the same way, by creating an environment variable similar to the one defined in the Dockerfile above. Be sure to use a different port for debugging your client and then configure a client debugger to access that port in the manner described above.
Summary
We have seen how to set up a development environment for the routeguide example from the grpc-java git repo code. There are two other examples in this framework, helloworld and hello streaming, both of these should be able to be run and debugged in the same way described here. Of course, if you’ve managed to read this far, you should be able to set up a development environment for your own Java gRPC project! Hopefully you have seen how easy it is to get a development environment for Java gRPC using Docker for the server and IntelliJ for our IDE. 次世代システム研究室では、グループ全体のインテグレーションを支援してくれるアーキテクトを募集しています。インフラ設計、構築経験者の方、次世代システム研究室にご興味を持って頂ける方がいらっしゃいましたら、ぜひ募集職種一覧からご応募をお願いします。
皆さんのご応募をお待ちしています。
グループ研究開発本部の最新情報をTwitterで配信中です。ぜひフォローください。
Follow @GMO_RD