• RPC


    一、RPC基础

    RPC是什么?

    RPC是远程过程调用(Remote Procedure Call)的缩写,简单的来说就是像调用本地方法一样调用远程方法。

    RPC简化版原理:

    RPC实现原理:

    大概由如下几部分组成:

    1. 设计

    本地应用程序与远程应用程序,需要共享什么信息?

    可以共享:POJO实体类定义、接口定义。当然还可以选择:WSDL/WADL/IDL

    • WSDL 是基于 XML 的用于描述 Web Services 以及如何访问 Web Services 的语言
    definitions>
    
    <types>
       definition of types........
    </types>
    
    <message>
       definition of a message....
    </message>
    
    <portType>
       definition of a port.......
    </portType>
    
    <binding>
       definition of a binding....
    </binding>
    
    </definitions>
    

    2. 代理

    Java下,代理可以选择使用动态代理或者AOP实现。

    3. 序列化

    • JSON
    • Hessian:不区分语言,简单紧凑,支持加密压缩,除了是序列化协议,也是一个RPC框架
    • avro :Avro的产生解决了JSON的冗长和没有IDL的问题
    • Thrift :Thrift并不仅仅是序列化协议,而是一个RPC框架。相对于JSON和XML而言,Thrift在空间开销和解析性能上有了比较大的提升
    • protobuf :序列化数据非常简洁,紧凑,与XML相比更快占用空间更小

    速度、空间对比图:

    具体数据:

    4. 网络传输

    TCP/SSL/HTTP/HTTPS

    5. 查找实现类

    通过接口去查找服务端的实现类。一般是注册方式。将实现类注册到Spring的方式

    二、常用的RPC技术

    Hessian、Thrift、gRPC

    gRPC使用示例:

    1. 引入pom文件
    <dependency>
    			<groupId>io.grpc</groupId>
    			<artifactId>grpc-all</artifactId>
    			<version>${grpc-version}</version>
    		</dependency>
    
    1. 引入plugin
    <build>
    		<plugins>
    			<plugin>
    				<groupId>org.xolstice.maven.plugins</groupId>
    				<artifactId>protobuf-maven-plugin</artifactId>
    				<version>0.5.0</version>
    				<configuration>
    					<!--
                            The version of protoc must match protobuf-java. If you don't depend on
                            protobuf-java directly, you will be transitively depending on the
                            protobuf-java version that grpc depends on.
                        -->
    					<protocArtifact>com.google.protobuf:protoc:3.5.0:exe:${os.detected.classifier}</protocArtifact>
    					<pluginId>grpc-java</pluginId>
    					<pluginArtifact>io.grpc:protoc-gen-grpc-java:${grpc-version}:exe:${os.detected.classifier}</pluginArtifact>
    				</configuration>
    				<executions>
    					<execution>
    						<goals>
    							<goal>compile</goal>
    							<goal>compile-custom</goal>
    						</goals>
    					</execution>
    				</executions>
    			</plugin>
    		</plugins>
    		<extensions>
    			<extension>
    				<groupId>kr.motd.maven</groupId>
    				<artifactId>os-maven-plugin</artifactId>
    				<version>1.4.1.Final</version>
    			</extension>
    		</extensions>
    
    	</build>
    
    1. 创建proto文件

    在src/main/proto目录下创建一个proto文件:

    内容为:

    syntax = "proto3";
    
    option java_multiple_files = true;
    option java_package = "io.grpc.examples.helloworld";
    option java_outer_classname = "HelloWorldProto";
    option objc_class_prefix = "HLW";
    
    package 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;
    }
    
    1. 运行插件,生成java文件

    2. 编写server代码

    package com.mmc.springbootstudy.grpc;
    import io.grpc.Server;
    import io.grpc.ServerBuilder;
    import io.grpc.examples.helloworld.GreeterGrpc;
    import io.grpc.examples.helloworld.HelloReply;
    import io.grpc.examples.helloworld.HelloRequest;
    import io.grpc.stub.StreamObserver;
     
    import java.io.IOException;
     
    public class HelloWorldServer {
     
     
        private int port = 50051;
        private Server server;
     
        private void start() throws IOException {
            server = ServerBuilder.forPort(port)
                    .addService(new GreeterImpl())
                    .build()
                    .start();
     
            System.out.println("service start...");
     
            Runtime.getRuntime().addShutdownHook(new Thread() {
     
                @Override
                public void run() {
     
                    System.err.println("*** shutting down gRPC server since JVM is shutting down");
                    HelloWorldServer.this.stop();
                    System.err.println("*** server shut down");
                }
            });
        }
     
        private void stop() {
            if (server != null) {
                server.shutdown();
            }
        }
     
        // block 一直到退出程序
        private void blockUntilShutdown() throws InterruptedException {
            if (server != null) {
                server.awaitTermination();
            }
        }
     
     
        public static void main(String[] args) throws IOException, InterruptedException {
     
            final HelloWorldServer server = new HelloWorldServer();
            server.start();
            server.blockUntilShutdown();
        }
     
     
        // 实现 定义一个实现服务接口的类
        private class GreeterImpl extends GreeterGrpc.GreeterImplBase {
     
     
            public void sayHello(HelloRequest req, StreamObserver<HelloReply> responseObserver) {
                System.out.println("service:"+req.getName());
                HelloReply reply = HelloReply.newBuilder().setMessage(("Hello: " + req.getName())).build();
                responseObserver.onNext(reply);
                responseObserver.onCompleted();
            }
        }
    }
    
    1. 编写client代码
    package com.mmc.springbootstudy.grpc;
    
    import io.grpc.ManagedChannel;
    import io.grpc.ManagedChannelBuilder;
    import io.grpc.examples.helloworld.GreeterGrpc;
    import io.grpc.examples.helloworld.HelloReply;
    import io.grpc.examples.helloworld.HelloRequest;
    
    import java.util.concurrent.TimeUnit;
    
    public class HelloWorldClient {
     
        private final ManagedChannel channel;
        private final GreeterGrpc.GreeterBlockingStub blockingStub;
     
     
        public HelloWorldClient(String host,int port){
            channel = ManagedChannelBuilder.forAddress(host,port)
                    .usePlaintext(true)
                    .build();
     
            blockingStub = GreeterGrpc.newBlockingStub(channel);
        }
     
     
        public void shutdown() throws InterruptedException {
            channel.shutdown().awaitTermination(5, TimeUnit.SECONDS);
        }
     
        public  void greet(String name){
            HelloRequest request = HelloRequest.newBuilder().setName(name).build();
            HelloReply response = blockingStub.sayHello(request);
            System.out.println(response.getMessage());
     
        }
     
        public static void main(String[] args) throws InterruptedException {
            HelloWorldClient client = new HelloWorldClient("127.0.0.1",50051);
            for(int i=0;i<5;i++){
                client.greet("world:"+i);
            }
     
        }
    }
    
    
    1. 启动server,再启动client发送请求,查看结果。

    三、从RPC到分布式服务化

    除了要实现远程调用方法外,还需要考虑什么?

    1. 多个相同的服务如何管理?
    2. 服务注册发现机制
    3. 负载均衡
    4. 熔断、限流
    5. 重试机制
    6. 高可用
    7. 监控

    典型的分布式架构图

    四、动手实现一个RPC框架

    动起手来吧

    书山有路勤为径,学海无涯苦作舟
  • 相关阅读:
    互联网与局域网(四)
    Socket介绍(五)
    HttpClient(七)
    TCP协议与HTTP协议区别
    TCP连接的三次握手
    context-param和init-param区别
    【HPU】[1736]老王修马路(二)
    【HPU】[1735]老王修马路(一)
    【HPU】[1734]老王修公园
    【HPU】[1733]神奇的数字9
  • 原文地址:https://www.cnblogs.com/javammc/p/15135128.html
Copyright © 2020-2023  润新知