This article is the third day of BrainPad Advent Calendar 2018.
Hello [@ nissy0409240] is (https://twitter.com/nissy0409240). I'm an engineer at BrainPad. It's been less than a month in 2018, How is everyone doing.
Although it is a private matter This year I was allowed to take the stage at PyCon 2018 Watching C. Ronaldo's hat-trick locally at the World Cup I had a valuable experience both publicly and privately.
At the end of 2018, when using gRPC that has nothing to do with the above written content in Spring Boot, I added something out of the ordinary and gRPC (because the amount of sentences is too small) in the first place. We will send you this entry.
First, let's talk about what gRPC is. gRPC is an RPC framework created by Google. This alone is a "what a mess" state, so I will also explain the RPC framework.
The official name of RPC for the RPC framework is "Remote Procedure Call". When translated, it becomes "remote procedure call". It allows you to call the methods described in an application running on a different server as if they were running on your server.
It's hard to get an image with just the letters, so let's take a look with the figure in the document of the gPRC head family.
The figure above shows a situation where a Ruby client and a Java client are calling a service written in C ++.
In gRPC, by describing the implementation content that the service wants to provide in a definition file called a .proto file, a linkage module named stub that calls the service implementation from the client side is automatically generated. As a result, the interface specification definition file found in API linkage is always reflected in the implementation, so you can enjoy the following advantages.
--It is possible to share what type of data is exchanged between both the caller and the callee. --Since http2 + protocol buffers are used, it is possible to improve performance by API linkage. ――It is possible to proceed with microservices regardless of the language used by the caller / callee. --GRPC supports various languages, and most of the major languages used in Web development are already supported.
I would like to introduce how to use gRPC. However, it is difficult to convey with just the letters, and it is different for each language, so This time, I will use Java 8 + Spring Boot and proceed while actually moving my hands.
First, create a template product using Spring Initializer. Here is the composition of the template before it was created.
demo_protobuf
├── pom.xml
├── main
│ ├── java
│ │ └── com
│ │ └── example
│ │ └── demo_protobuf
│ │ └── DemoProtobufApplication.java
│ └── resources
│ └── application.properties
└── test
└── java
└── com
└── example
└── demo_protobuf
└── DemoProtobufApplicationTests.java
Next, I added a module to pom.xml, but this was a ridiculous part. We will discuss adding modules later, but first we will move on to the definition file.
Create a definition file when execution is complete.
This time, I will write the definition in the src / main / proto / demo.proto
file.
The composition of the product at this point is as follows.
demo_protobuf
.
├── mvnw
├── mvnw.cmd
├── pom.xml
└── src
├── main
│ ├── java
│ │ └── com
│ │ └── example
│ │ └── demo_protobuf
│ │ └── DemoProtobufApplication.java
│ │
│ ├── proto
│ │ └── demo.proto
│ └── resources
│ └── application.properties
└── test
└── java
└── com
└── example
└── demo_protobuf
└── DemoProtobufApplicationTests.java
In the created demo.proto, write as follows.
demo.proto
syntax = "proto3";
option java_multiple_files = true;
option java_package = "com.example.fizzbuzz";
option java_outer_classname = "FizzBuzzProto";
package calc;
//Defines a combination of return values and arguments for a service called Math
service Math {
rpc Math (MathRequest) returns (IntResponse);
}
//Defines the type and number of return values when IntResponse is selected
message IntResponse {
int32 value = 1;
}
//Defines the type and number of arguments when defining MathRequest
message MathRequest {
int32 x = 1;
int32 y = 2;
}
I'm sure some of you have pinned it, but in the .proto file "Which service receives what kind of request and what kind of return value is returned" is written. It just describes what type of data the .proto file exchanges with.
After writing, execute mvn clean install
.
After execution, the source code will be generated as follows.
(Actually, more code will be generated, but I will omit it here)
.
├── mvnw
├── mvnw.cmd
├── pom.xml
├── src
│ ├── main
│ │ ├── java
│ │ │ └── com
│ │ │ └── example
│ │ │ └── demo_protobuf
│ │ │ └── DemoProtobufApplication.java
│ │ ├── proto
│ │ │ └── demo.proto
│ │ └── resources
│ │ └── application.properties
│ └── test
│ └── java
│ └── com
│ └── example
│ └── demo_protobuf
│ └── DemoProtobufApplicationTests.java
└── target
└── generated-sources
├── annotations
└── protobuf
├── grpc-java
│ └── com
│ └── example
│ └── fizzbuzz
│ └── MathGrpc.java
└── java
└── com
└── example
└── fizzbuzz
├── FizzBuzzProto.java
├── IntResponse.java
├── IntResponseOrBuilder.java
├── MathRequest.java
└── MathRequestOrBuilder.java
But here I realized I made a mistake. Even though I stopped trying to use FizzBuzz at first and changed to Math I have generated some code with FizzBuzz. Would you like to discard the repository and recreate it? That's not true.
Rewrite the created demo.proto as follows
demo.proto
syntax = "proto3";
option java_multiple_files = true;
option java_package = "com.example.math";
option java_outer_classname = "MathProto";
package calc;
//Defines a combination of return values and arguments for a service called Math
service Math {
rpc Math (MathRequest) returns (IntResponse);
}
//Defines the type and number of return values when IntResponse is selected
message IntResponse {
int32 value = 1;
}
//Defines the type and number of arguments when defining MathRequest
message MathRequest {
int32 x = 1;
int32 y = 2;
}
Run mvn clean install
.
.
├── mvnw
├── mvnw.cmd
├── pom.xml
├── src
│ ├── main
│ │ ├── java
│ │ │ └── com
│ │ │ └── example
│ │ │ └── demo_protobuf
│ │ │ └── DemoProtobufApplication.java
│ │ ├── proto
│ │ │ └── demo.proto
│ │ └── resources
│ │ └── application.properties
│ └── test
│ └── java
│ └── com
│ └── example
│ └── demo_protobuf
│ └── DemoProtobufApplicationTests.java
└── target
└── generated-sources
├── annotations
└── protobuf
├── grpc-java
│ └── com
│ └── example
│ └── math
│ └── MathGrpc.java
└── java
└── com
└── example
└── math
├── MathProto.java
├── IntResponse.java
├── IntResponseOrBuilder.java
├── MathRequest.java
└── MathRequestOrBuilder.java
The code under target has been reworked. You can also see that this method is good when you want to update demo.proto.
All you have to do is inherit the generated code and create the service and client.
Since I touched on a series of flows, I would like to introduce what I got stuck in here. To put it simply, "Be careful because the groupId of the module is different from the content that appears in the Maven Repository."
What is Maven Repository in the first place? As many of you may know, this is a site that must tell you what to write when importing middleware. In the case of other languages, Python's PyPi is similar.
And there are many so-called starters that are all-in-one tools that support the framework called Spring Boot. For example, use Spring Boot Security Starter when creating an authentication module.
Until now, when using gRPC with Spring Boot, it was written as follows.
pom.xml
<!-- https://mvnrepository.com/artifact/org.lognet/grpc-spring-boot-starter -->
<dependency>
<groupId>org.lognet</groupId>
<artifactId>grpc-spring-boot-starter</artifactId>
<version>2.3.2</version>
</dependency>
However, when the latest version of this module was updated to 3 series, the groupId changed from "org.lognet" to "org.github.lognet", so not only the version but also the groupId had to be changed. I did.
The same information as above can be found in the grpc-spring-boot-starter repository.
Therefore, it is necessary to describe as follows from now on.
pomxml
<dependency>
<groupId>io.github.lognet</groupId>
<artifactId>grpc-spring-boot-starter</artifactId>
<version>3.0.0</version>
</dependency>
Please note that if you leave the groupId uncorrected, the following error will occur at the time of mvn install
.
[ERROR] Failed to execute goal on project demo_protobuf: Could not resolve dependencies for project com.example:demo_protobuf:jar:1.16.1: Failure to find org.lognet:grpc-spring-boot-starter:jar:3.0.0 in https://repo.maven.apache.org/maven2 was cached in the local repository, resolution will not be reattempted until the update interval of central has elapsed or updates are forced -> [Help 1]
[ERROR]
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR]
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/DependencyResolutionException
Although the structure is a little strange, I would like to replace this entry with the hope that it will help those who are addicted to posting information with few Japanese entries along with an error message. I'm sorry that the text was disorganized, but thank you for staying with us until the end.
https://qiita.com/nozaq/items/9cd9bf7ee6118779bda9 http://redj.hatenablog.com/entry/2017/10/13/084423 https://github.com/LogNet/grpc-spring-boot-starter https://kengotoda.gitbooks.io/what-is-maven/primer/maven-repository.html
Recommended Posts