RPC

1、RPC基礎

RPC是什麼?java

RPC是遠程過程調用(Remote Procedure Call)的縮寫,簡單的來講就是像調用本地方法同樣調用遠程方法。spring

RPC簡化版原理:
springboot

RPC實現原理:網絡

大概由以下幾部分組成:架構

1. 設計負載均衡

本地應用程序與遠程應用程序,須要共享什麼信息?框架

能夠共享:POJO實體類定義、接口定義。固然還能夠選擇:WSDL/WADL/IDLmaven

  • 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實現。ide

3. 序列化

  • JSON
  • Hessian:不區分語言,簡單緊湊,支持加密壓縮,除了是序列化協議,也是一個RPC框架
  • avro :Avro的產生解決了JSON的冗長和沒有IDL的問題
  • Thrift :Thrift並不單單是序列化協議,而是一個RPC框架。相對於JSON和XML而言,Thrift在空間開銷和解析性能上有了比較大的提高
  • protobuf :序列化數據很是簡潔,緊湊,與XML相比更快佔用空間更小

速度、空間對比圖:

具體數據:

4. 網絡傳輸

TCP/SSL/HTTP/HTTPS

5. 查找實現類

經過接口去查找服務端的實現類。通常是註冊方式。將實現類註冊到Spring的方式

2、經常使用的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發送請求,查看結果。

3、從RPC到分佈式服務化

除了要實現遠程調用方法外,還須要考慮什麼?

  1. 多個相同的服務如何管理?
  2. 服務註冊發現機制
  3. 負載均衡
  4. 熔斷、限流
  5. 重試機制
  6. 高可用
  7. 監控

典型的分佈式架構圖

4、動手實現一個RPC框架

動起手來吧

相關文章
相關標籤/搜索
本站公眾號
   歡迎關注本站公眾號,獲取更多信息