Directorio de artículos
- 1 Problema: la documentación oficial de gRPC no es lo suficientemente detallada
- 2 Construye un proyecto java a través de maven
- 3 Defina el archivo proto
- 4 Genere código java basado en proto a través del complemento maven
- 5 gRPC-java, ejemplo de código del lado del servidor
- 6 gRPC-java, ejemplo de código del lado del cliente
- 7 resultados de ejecución de código de muestra gRPC-java
- 8 Referencia
1 Problema: la documentación oficial de gRPC no es lo suficientemente detallada
Encontré un problema al investigar gRPC java. Según la documentación oficial, no hay forma de ejecutar el ejemplo correctamente de una vez.
En cambio, tomó dos días completos revisar varios documentos para descubrir la relación entre el compilador proto, maven y gRPC-java.
Ahora proporcione un programa de muestra gRPC-java de un extremo a otro que pueda garantizar su ejecución al mismo tiempo.
2 Construye un proyecto java a través de maven
versión de java: 1.8
versión de gRPC: 1.29.0
parte de configuración del núcleo pom.xml
2.1 dependencias del núcleo de Pom
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-netty-shaded</artifactId>
<version>1.29.0</version>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-protobuf</artifactId>
<version>1.29.0</version>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-stub</artifactId>
<version>1.29.0</version>
</dependency>
<!-- necessary for Java 9+ -->
<!--java 低于 1.8 的版本不需要此依赖-->
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>annotations-api</artifactId>
<version>6.0.53</version>
<scope>provided</scope>
</dependency>
2.2 plugin proto de configuración pom
os-maven-plugin: este complemento puede detectar la información actual del sistema
$ {os.detected.classifier}: esta variable obtiene la versión del sistema operativo, por ejemplo, osx-x86_64
<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.11.0:exe:${
os.detected.classifier}</protocArtifact>
<pluginId>grpc-java</pluginId>
<pluginArtifact>io.grpc:protoc-gen-grpc-java:1.29.0:exe:${
os.detected.classifier}</pluginArtifact>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>compile-custom</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
3 Defina el archivo proto
Coloque el archivo helloworld.proto en el directorio src / main / proto
syntax = "proto3";
option java_generic_services = true;
option java_multiple_files = true;
option java_package = "io.grpc.examples.helloworld";
// 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;
}
4 Genere código java basado en proto a través del complemento maven
El mvn compile
código del comando de ejecución se genera automáticamente.
El código generado por defecto está en el directorio target / generate-sources / protobuf.
El directorio grpc-java contiene la clase correspondiente al Servicio generado, y el directorio java contiene el objeto java correspondiente al mensaje generado.
5 gRPC-java, ejemplo de código del lado del servidor
Ejecute la función principal directamente y el servidor comenzará a funcionar.
package io.grpc.examples.helloworld;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
import io.grpc.Server;
import io.grpc.ServerBuilder;
import io.grpc.stub.StreamObserver;
/**
* @ClassName HelloWorldServer
* @Description
* @Author hugo_lei
* @Date 13/5/20 上午11:09
*/
public class HelloWorldServer {
private Server server;
private void start() throws IOException {
/* The port on which the server should run */
int port = 50051;
server = ServerBuilder.forPort(port)
.addService(new GreeterImpl())
.build()
.start();
Runtime.getRuntime().addShutdownHook(new Thread() {
@Override
public void run() {
// Use stderr here since the logger may have been reset by its JVM shutdown hook.
System.err.println("*** shutting down gRPC server since JVM is shutting down");
try {
HelloWorldServer.this.stop();
} catch (InterruptedException e) {
e.printStackTrace(System.err);
}
System.err.println("*** server shut down");
}
});
}
private void stop() throws InterruptedException {
if (server != null) {
server.shutdown().awaitTermination(30, TimeUnit.SECONDS);
}
}
/**
* Await termination on the main thread since the grpc library uses daemon threads.
*/
private void blockUntilShutdown() throws InterruptedException {
if (server != null) {
server.awaitTermination();
}
}
/**
* Main launches the server from the command line.
*/
public static void main(String[] args) throws IOException, InterruptedException {
final HelloWorldServer server = new HelloWorldServer();
server.start();
server.blockUntilShutdown();
}
static class GreeterImpl extends GreeterGrpc.GreeterImplBase {
@Override
public void sayHello(HelloRequest req, StreamObserver<HelloReply> responseObserver) {
HelloReply reply = HelloReply.newBuilder().setMessage("Hello " + req.getName()).build();
System.out.println("=====server=====");
System.out.println("server: Hello " + req.getName());
responseObserver.onNext(reply);
responseObserver.onCompleted();
}
}
}
6 gRPC-java, ejemplo de código del lado del cliente
Cada vez que se ejecuta la función principal, el cliente equivale a enviar una solicitud al servidor.
package io.grpc.examples.helloworld;
import java.util.concurrent.TimeUnit;
import io.grpc.Channel;
import io.grpc.ManagedChannel;
import io.grpc.ManagedChannelBuilder;
import io.grpc.StatusRuntimeException;
/**
* @ClassName HelloWorldClient
* @Description
* @Author hugo_lei
* @Date 13/5/20 上午11:13
*/
public class HelloWorldClient {
private final GreeterGrpc.GreeterBlockingStub blockingStub;
/** Construct client for accessing HelloWorld server using the existing channel. */
public HelloWorldClient(Channel channel) {
// 'channel' here is a Channel, not a ManagedChannel, so it is not this code's responsibility to
// shut it down.
// Passing Channels to code makes code easier to test and makes it easier to reuse Channels.
blockingStub = GreeterGrpc.newBlockingStub(channel);
}
/** Say hello to server. */
public void greet(String name) {
HelloRequest request = HelloRequest.newBuilder().setName(name).build();
HelloReply response;
try {
response = blockingStub.sayHello(request);
} catch (StatusRuntimeException e) {
return;
}
System.out.println("Greeting: " + response.getMessage());
}
/**
* Greet server. If provided, the first element of {@code args} is the name to use in the
* greeting. The second argument is the target server.
*/
public static void main(String[] args) throws Exception {
String user = "hahahahah";
// Access a service running on the local machine on port 50051
String target = "localhost:50051";
// Allow passing in the user and target strings as command line arguments
if (args.length > 0) {
if ("--help".equals(args[0])) {
System.err.println("Usage: [name [target]]");
System.err.println("");
System.err.println(" name The name you wish to be greeted by. Defaults to " + user);
System.err.println(" target The server to connect to. Defaults to " + target);
System.exit(1);
}
user = args[0];
}
if (args.length > 1) {
target = args[1];
}
// Create a communication channel to the server, known as a Channel. Channels are thread-safe
// and reusable. It is common to create channels at the beginning of your application and reuse
// them until the application shuts down.
ManagedChannel channel = ManagedChannelBuilder.forTarget(target)
// Channels are secure by default (via SSL/TLS). For the example we disable TLS to avoid
// needing certificates.
.usePlaintext()
.build();
try {
HelloWorldClient client = new HelloWorldClient(channel);
client.greet(user);
} finally {
// ManagedChannels use resources like threads and TCP connections. To prevent leaking these
// resources the channel should be shut down when it will no longer be used. If it may be used
// again leave it running.
channel.shutdownNow().awaitTermination(5, TimeUnit.SECONDS);
}
}
}