网上书店网站前端搜索条怎么做,如何制作简易网站,专业网站制作地址,网站地图 怎么做基础知识 RPC的语义是远程过程调用#xff08;Remote Procedure Call#xff0c;RPC#xff09;就是将一个服务调用封装在一个本地方法中#xff0c;让调用者像使用本地方法一样调用服务#xff0c;对其屏蔽实现细节。 RPC 会给对应的服务接口名生成一个代理类#xff0c…基础知识 RPC的语义是远程过程调用Remote Procedure CallRPC就是将一个服务调用封装在一个本地方法中让调用者像使用本地方法一样调用服务对其屏蔽实现细节。 RPC 会给对应的服务接口名生成一个代理类即客户端 Stub。使用代理类可以屏蔽掉 RPC 调用的具体底层细节使得用户无感知的调用远程服务。客户端 Stub 会将当前调用的方法的方法名、参数类型、实参数等根据协议组装成网络传输的消息体将其序列化成二进制流后通过 Sockect 发送给 RPC 服务端。服务端收到二进制数据流后根据约定的协议解析出请求数据然后反序列化得到参数通过内部路由找到具体调用的方法调用该方法拿到执行结果将其序列化二进制流后通过 Socket 返回给 RPC 客户端。
GRPC
调用
Unary 模式即请求响应模式Client Streaming 模式Client 发送 多次Server 回复一次Server Streaming 模式Client 发送一次Server 发送多次双向 Streaming 模式Client/Server 都发送多次
核心类 ● ServerBuilder这是gRPC暴露给业务层的启动入口通过设置端口号和对外提供服务的实现类可以构造一个gRPC Server实例并启动。 ● ServergRPC 服务端中最顶层的服务抽象有start启动和shutdown关闭两个核心动作。实现类为ServerImpl实现了服务、方法与方法处理器的绑定、端口监听、不同类型的 Server 实现的调用、Server 生命周期管理等。 ● ServerCall服务调用抽象在收到Body请求以后真正被触发发起本地服务调用。 ● InternalServergRPC真正完成通信动作的内部服务抽象实现类为NettyServer。 ● ServerTransportInternalServer 内部依赖的通信窗口。 ● NettyServerHandler向Netty注册的处理器是真正的核心消息接收逻辑的处理者。 ● TransportState通信状态标识用来标识信道流的处理情况承担实际的请求接收解码分发工作。
服务端创建 gRPC 服务端创建采用 Build 模式对底层服务绑定、NettyServer和gRPC Server 的创建和实例化做了封装和屏蔽让服务调用者不用关心 RPC 调用细节。
int port 50052;
Server server ServerBuilder.forPort(port) // 1.绑定端口.addService(new MyGrpcServiceImpl()) // 2.添加服务实现类.build() // 3.创建NettyServer、Sever实例.start(); // 4.启动NettyServer实例开始监听将需要调用的服务端接口实现类注册到内部的注册表中RPC 调用时可以根据 RPC 请求消息中的服务定义信息ServerServiceDefinition查询到服务接口实现类。 gRPC与其它一些RPC框架的差异点是服务接口实现类的调用并不是通过动态代理和反射机制而是通过proto工具生成代码在服务端启动时将服务接口实现类实例注册到gRPC内部的服务注册中心上。请求消息接入之后可以根据服务名和方法名直接调用启动时注册的服务实例而不需要通过反射的方式进行调用性能更优。 示例
定义 PB 文件
hellworld.proto
//第一行指定了正在使用 proto3 语法若未指定编译器会使用 proto2。这个指定语法行必须是文件的非空非注释的第一个行。
syntax proto3;// 为每个 message 单独生成一个类文件
option java_multiple_files true;
option java_package com.kuaishou.helloworld;
option java_outer_classname HelloWorldProto;
option objc_class_prefix HLW;//指定 .proto 文件包名防止不同项目之间的命名冲突。在java中包名称用作Java包。
package helloworld;// The greeting service definition.
service Greeter {// Sends a greetingrpc SayHello (HelloRequest) returns (HelloReply) {}
}// The request message containing the users name.
message HelloRequest {string name 1;
}// The response message containing the greetings
message HelloReply {string message 1;
}在 .pb文件 中定义好 service 后通过借助 gRPC 的 protocol buffers 插件生成 gRPC 服务端代码。在 Java 中可使用自动构建工具 maven 的 mvn compile 命令即可生成服务端基类代码以及客户端桩代码。 重点关注生成的类 xxxxGrpc如MyGrpcServiceGrpc是 .proto 文件编译后生成的 service 类。xxxxGrpc 中有一个以 ImplBase 结尾的静态抽象内部类如MyGrpcServiceImplBase服务端需要重写该类中的 rpc 方法编写自己的业务逻辑。客户端通过 xxxxGrpc 中的静态内部类 xxxxStub 实例如MyGrpcServiceBlockingStub可以调用相应的 rpc 方法。
服务端代码
MyServer.java
package com.kuaishou.helloworld;import java.io.IOException;
import java.util.concurrent.TimeUnit;
import java.util.logging.Logger;import io.grpc.Server;
import io.grpc.ServerBuilder;
import io.grpc.stub.StreamObserver;/*** Server that manages startup/shutdown of a {code Greeter} server.*/
public class MyServer {private static final Logger logger Logger.getLogger(MyServer.class.getName());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();logger.info(Server started, listening on port);Runtime.getRuntime().addShutdownHook(new Thread() {Overridepublic 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 {MyServer.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 MyServer server new MyServer();server.start();server.blockUntilShutdown();}/*** 该类实现proto文件中对应的service类中的方法实现service中指定的rpc*/static class GreeterImpl extends GreeterGrpc.GreeterImplBase {Overridepublic void sayHello(HelloRequest req, StreamObserverHelloReply responseObserver) {HelloReply reply HelloReply.newBuilder().setMessage(Hello req.getName()).build();responseObserver.onNext(reply);responseObserver.onCompleted();}}}客户端代码
package com.kuaishou.helloworld;import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;import io.grpc.Channel;
import io.grpc.ManagedChannel;
import io.grpc.ManagedChannelBuilder;
import io.grpc.StatusRuntimeException;/*** A simple client that requests a greeting from the {link MyServer}.*/
public class MyClient {private static final Logger logger Logger.getLogger(MyClient.class.getName());private final GreeterGrpc.GreeterBlockingStub blockingStub;private final GreeterGrpc.GreeterFutureStub futureStub;/** Construct client for accessing HelloWorld server using the existing channel. */public MyClient(Channel channel) {// channel here is a Channel, not a ManagedChannel, so it is not this codes 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);futureStub GreeterGrpc.newFutureStub(channel);}/** Say hello to server. */public void greet(String name) {logger.info(Will try to greet name ...);HelloRequest request HelloRequest.newBuilder().setName(name).build();HelloReply response;ListenableFutureHelloReply futureResponse;try {response blockingStub.sayHello(request);futureResponse futureStub.sayHello(request);} catch (StatusRuntimeException e) {logger.log(Level.WARNING, RPC failed: {0}, e.getStatus());return;}logger.info(Greeting: response.getMessage());try {logger.info(Future Greeting: futureResponse.get().getMessage());} catch (Exception e) {e.printStackTrace();}}/*** 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 Tom;// Access a service running on the local machine on port 50051String target localhost:50051;// 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 {MyClient client new MyClient(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);}}
}其它
并发相关知识
ListenableFutureNetty
参考
Protocol Buffers DocumentPB 使用Protocol Buffers 编码原理grpc-java demogrpc 代码示例RPC框架原理简述从实现一个简易RPCFramework说起5 个 Java 类1 个接口类 1 个实现类 1 个 RPC 框架类 1 个服务注册类 1 个服务应用类讲清楚 RPC 本质gRPC 官方文档中文版