RPC 原理与实现

article/2025/9/26 19:05:34

文章目录

  • 1. RPC 简介
      • 1.1 什么是RPC
        • Reference: LPC & IPC (本地过程调用)
      • 1.2 为什么要用RPC
        • 1.2.1 系统架构的演进
        • 1.2.2 Web 服务的技术结构
          • 1.2.2 SOAP ( Simple Object Access Protocol)
          • 1.2.2 REST(Representational State Transfort)
          • SOAP & REST
          • 1.2.3 RPC 实现方式
  • 2. RPC 框架实现
      • 2.1 RMI 框架
          • 2.1.1 RMI 框架结构
          • 2.1.2 RMI 使用示例
      • 2.2 通用RPC框架
          • 2.2.1 通用RPC框架结构
          • 2.2.2 通用RPC框架简单实现
            • 1. Common 包
            • 2. Server 包
            • 3. Client 包
      • 2.3 总结
          • 2.3.1. 建立通信
          • 2.3.2. 服务寻址
            • 1. 从服务提供者的角度看:
            • 2.从调用者的角度看:
          • 2.3.3. 网络传输
            • 1. 序列化
            • 2. 反序列化
          • 2.3.4. 服务调用

1. RPC 简介

1.1 什么是RPC

远程过程调用(RPC),就是客户端基于某种传输协议通过网络向服务提供端请求服务处理,然后获取返回的数据。这种调用对于客户端而言和调用本地服务一样方便,开发人员不需要了解具体底层网络传输协议。简单讲,就是本地调用的逻辑处理过程放在的远程的机器上,而不是本地服务代理来处理。
在这里插入图片描述

其基本流程如上图所示, 如果有过Android 系统的开发经验,很容易就能想到该架构和 Android 系统中的 ServiceManager 结构极其相似。 不同点在于 Android 系统中的 ServiceManager 其实是基于 IPC机制,也就是 Linux 系统中的本地过程调用。

Reference: LPC & IPC (本地过程调用)

本地过程调用在不同的操作系统中叫法不同,使用方式也不太一样。在Windows编程中,称为LPC;在linux编程中,更习惯称之为IPC,即进程间通信。进程间通信通常有以下几种方式:

  • 管道:一种半双工的通信方式,数据只能单向流动,而且只能在父子进程间使用。
  • 命名管道:半双工的通信方式,允许无亲缘关系进程间的通信。
  • 信号量:信号量是一个计数器,可用来控制多个进程对共享资源的访问。
  • Socket 套接字:可用于网络中不同机器之间的进程间通信,应用广泛。
  • 消息队列:消息队列是消息的链接表,具有写权限的进程可以按照一定的规则向消息队列中添加新信息;对消息队列有读权限的进程则可以从消息队列中读取信息。
  • 共享内存:映射一段能被其他进程所访问的内存,这段共享内存由一个进程创建,但多个进程都可以访问。共享内存是最快的 IPC 方式。

1.2 为什么要用RPC

1.2.1 系统架构的演进

随着互联网的发展,网站应用的规模不断扩大,常规的垂直应用架构已无法应对,分布式服务架构势在必行,这样各个服务的治理以及服务之间的如何调用就需要额外的手段进行控制。

  1. 单一应用架构
    当网站流量很小时,只需一个应用将所有功能都部署在一起,以减少部署节点和成本。
    此时,用于简化增删改查工作量的数据访问框架(ORM) 是关键。

  2. 垂直应用架构
    当访问量逐渐增大,单一应用多服务器部署带来的收益越来越小,将应用拆成互不相干的几个应用,以提升效率。
    此时,用于加速前端页面开发的 Web框架(MVC) 是关键。

  3. 分布式服务架构
    当垂直应用越来越多,应用之间交互不可避免,将核心业务抽取出来,作为独立的服务,逐渐形成稳定的服务中心,使前端应用能更快速的响应多变的市场需求。
    此时,用于提高业务复用及整合的分布式服务框架提供的统一服务是关键。

分布式服务架构下调用服务的方式也有不同。SOA一般使用SOAP或者REST方式来提供服务,这样外部业务系统可以使用通用网络协议来处理请求和响应,而微服务还可以有一些私有的协议方式来提供服务,例如基于自定义协议的RPC框架。RPC使得调用服务简单,但是需要一些其他耗时间的交流协调工作,不一定适合SOA场景


1.2.2 Web 服务的技术结构

系统架构的改变必然需要相应的服务调用方案来实现,以下为Web 服务技术结构。

在这里插入图片描述

web service被W3C设立规范之初,SOAP方案已经提出。但随着服务化技术和架构的发展,SOAP多少显得过于复杂,因此出现了简化版的REST方案。此后由于分布式服务应用越来越大,对性能和易用性的要求越来越大,就出现了RPC框架。


1.2.2 SOAP ( Simple Object Access Protocol)

SOAP简单对象访问协议,是基于XML数据格式来交换数据;其内部定义了一套复杂完善的XML标签,标签中包含了调用的远程过程、参数、返回值和出错信息等等,通信双方根据这套标签来解析数据或者请求服务。与SOAP相关的配套协议是WSDL (Web Service Description Language),用来描述哪个服务器提供什么服务,怎样找到它,以及该服务使用怎样的接口规范。

因此,SOAP服务整体流程是:首先获得该服务的WSDL描述,根据WSDL构造一条格式化的SOAP请求发送给服务器,然后接收一条同样SOAP格式的应答,最后根据先前的WSDL解码数据。请求和应答通常使用HTTP协议传输,发送请求就使用HTTP的POST方法。


1.2.2 REST(Representational State Transfort)

REST表示性状态转移,由于SOAP方案过于庞大复杂,在很多简单的web服务应用场景中,轻量级的REST就替代SOAP方案了。

和SOAP相比,REST只是对URI做了一些规范,数据通常采用JSON格式底层传输使用HTTP/HTTPS,因此,所有web服务器都可以快速支持该方案;开发人员也可以快速学习和使用。

SOAP & REST

从命名来看,SOAP是一种协议,而REST只是一种方案。协议的实现通常需要设计开发专门的工具支持,而方案相对基于目前的工具来做一些设计和约束,因此可用性更高。

  • REST特点
  1. 由于数据返回格式是自定义的,绝大部分使用JSON,这种数据结构节省带宽,并且前端JavaScript能天生支持。
  2. 无状态,基于HTTP协议,所以只能适应无状态场景。
  • SOAP特点
  1. 协议有安全性的一些规范。
  2. 基于xml的标签约束不要求一定是HTTP传输,所以可支持有状态的场景。

1.2.3 RPC 实现方式

RPC 方案具有几下几种实现:

  • RMI
    RMI是Java制定的远程通信协议,是Java的标准RPC组件,其他编程语言无法使用。
  • Thrift
    Thrift 是基于IDL来跨语言的RPC组件,Thrift的使用者只需要按照Thrift官方规定的方式来写API结构,然后生成对应语言的API接口,继而就可以跨语言完成远程过程调用。
  • Dubbo
    作为服务化的组件,如果没有服务治理来完成大规模应用集群中服务调用管理工作,则运维工作非常繁重的,因此类似dubbo这种包含服务治理的RPC组件出现了。

2. RPC 框架实现

2.1 RMI 框架

2.1.1 RMI 框架结构

RMI全称是Remote Method Invocation,也就是远程方法调用。当应用比较小性能要求不高的情况下使用RMI方便快捷。

RMI 结构如下图所示:
在这里插入图片描述
其中概念需要说明:

1.Stub():
stub实际上就是远程过程在客户端上面的一个代理proxy。当客户端代码调用API接口提供的方法的时候,RMI生成
的stub代码块会将请求数据序列化,交给远程服务端处理,然后将结果反序列化之后返回给客户端。这些处理过程
对于客户端来说,基本是透明无感知的。2.Remote(远程交互):
底层网络处理,RMI对用户屏蔽了这层细节。stub通过remote来和远程服务端进行通信。3.Skeleton(骨架):
和stub相似,skeleton是服务端生成的一个代理proxy。当客户端通过stub发送请求到服务端,交给skeleton来处
理,它根据指定的服务方法来反序列化请求,然后调用具体方法执行,最后将结果返回给客户端。4.Registry(服务注册)RMI服务注册中心,在服务端实现之后需要注册到rmi server上,然后客户端从指定的rmi地址上lookup服务,调用
该服务对应的方法完成远程方法调用。registry是个很重要的功能,当服务端开发完服务之后,要对外暴露,如果
没有服务注册,则客户端是无从调用的。
2.1.2 RMI 使用示例
  1. 首先声明服务接口

    /*
    接口须继承RMI的Remote**/
    public interface RmiService extends Remote {// 必须有RemoteException,才是RMI方法String hello(String name) throws RemoteException;
    }
    
  2. 服务接口的实现类

    /* UnicastRemoteObject生成一个代理proxy**/
    public class RmiServiceImpl extends UnicastRemoteObject implements RmiService {public RmiServiceImpl() throws RemoteException {}public String hello(String name) throws RemoteException {System.out.println("RmiService invoke hello");return "Hello " + name;}
    }
    
  3. 服务端启动并发布服务

    /* 服务端server启动**/
    public class RmiServer {public static void main(String[] args) {try {RmiService service = new RmiServiceImpl();//在本地创建注册中心实例,端口为10086LocateRegistry.createRegistry(10086);//注册service服务到创建的注册中心Naming.rebind("rmi://127.0.0.1:10086/service1", service);} catch (Exception e) {e.printStackTrace();}System.out.println("------------server start-----------------");}
    }
    
  4. 客户端调用服务

    /* 客户端调用rmi服务**/
    public class RmiClient {public static void main(String[] args) {try {// 根据服务地址查找服务,然后调用API对应方法RmiService service = (RmiService) Naming.lookup("rmi://localhost:10086/service1");System.out.println(service.hello("RMI"));} catch (Exception e) {e.printStackTrace();}}
    }
    

2.2 通用RPC框架

2.2.1 通用RPC框架结构

一个通用的RPC框架组成如下图所示:

在这里插入图片描述

通用的RPC组件一般包括以下一些模块:

1. ClientService:
这个模块主要是封装服务端对外提供的API,让客户端像使用本地API接口一样调用远程服务。一般使用动态代理机
制,当客户端调用api的方法时,serviceClient会走代理逻辑,去远程服务器请求真正的执行方法,然后将响应结
果作为本地的api方法执行结果返回给客户端应用。2.Processor:
在服务端存在很多方法,当客户端请求过来,服务端需要定位到具体对象的具体方法,然后执行该方法,这个功能就
由processor模块来完成。一般这个操作需要使用反射机制来获取用来执行真实处理逻辑的方法,有的RPC直
接在server初始化的时候,将一定规则写进Map映射中,这样直接获取对象即可。3.Protocol:
一般协议层包括编码/解码,或者说序列化和反序列化工作;当然,有时候编解码不仅仅是对象序列化的工作,还有
一些通信相关的字节流的额外解析部分。4.Transport:
主要是服务端和客户端网络通信相关的功能。这里和下面的IO层区分开,主要是因为传输层处理
server/client的网络通信交互,而不涉及具体底层处理连接请求和响应相关的逻辑。5.I/O:
这个模块主要是为了提高性能可能采用不同的IO模型和线程模型,当然,一般我们可能和上面的transport层联系
的比较紧密,统一称为remote模块。
2.2.2 通用RPC框架简单实现

实现代码大致可分为 三个部分:

  • Common
    服务接口和数据序列化部分
  • Server
    服务实现,请求处理,以及服务发布
  • Client
    客户端调用的远程端,代理客户端服务的实现
1. Common 包

这个包中存放一些公共的资源,比如服务接口文件和参数传输的模型。

/* 服务接口**/
public interface RpcService {String sayHi(String name);
}
/*协议层 对传输通信的远程调用请求接口和方法参数等数据按照规定的格式进行处理
*此处使用 jdk 自带的方式进行序列化**/
public class ServiceProtocol {private static volatile ServiceProtocol instance;private ServiceProtocol() { }public static ServiceProtocol getInstance() {if (null == instance) {synchronized (ServiceProtocol.class) {if (null == instance) {instance = new ServiceProtocol();}}}return instance;}/*** 参数传递的模型*/public static class ProtocolModel implements Serializable {private static final long serialVersionUID = 1L; //jdk 序列化private String clazz; // 接口名private String method; // 方法名private String[] argTypes; // 参数类型数组private Object[] args; // 参数数组public String getClazz() {return clazz;}public void setClazz(String clazz) {this.clazz = clazz;}public String getMethod() {return method;}public void setMethod(String method) {this.method = method;}public String[] getArgTypes() {return argTypes;}public void setArgTypes(String[] argTypes) {this.argTypes = argTypes;}public Object[] getArgs() {return args;}public void setArgs(Object[] args) {this.args = args;}}
2. Server 包

这个包中存放服务端实现服务的相关类。

/* 服务实现**/
public class RpcServiceImpl implements RpcService {@Overridepublic String sayHi(String name) {return "Hello," + name;}
}
/** 服务端处理层,负责发布管理服务,并定位处理客户端的调用**/
public class ServiceProcessor {private static volatile ServiceProcessor instance;private ServiceProcessor() { }public static ServiceProcessor getInstance() {if (null == instance) {synchronized (ServiceProcessor.class) {if (null == instance) {instance = new ServiceProcessor();}}}return instance;}private static final ConcurrentMap<String, Object> PROCESSOR_INSTANCE_MAP = new ConcurrentHashMap<String, Object>(); // 存储服务实例的 Map,实际起到注册中心的作用// 发布服务则将其加入Map,以接口名为key,实例为value,生产环境下使用第三方工具注册服务public boolean publish(Class clazz, Object obj) {return PROCESSOR_INSTANCE_MAP.putIfAbsent(clazz.getName(), obj) != null;}// 定位远程调用服务方法,并返回执行结果public Object process(ServiceProtocol.ProtocolModel model) {try {// 定位调用的接口Class clazz = Class.forName(model.getClazz());Class[] types = new Class[model.getArgTypes().length];for (int i = 0; i < types.length; i++) {types[i] = Class.forName(model.getArgTypes()[i]);}// 根据参数类型定位远程调用的方法Method method = clazz.getMethod(model.getMethod(), types);Object obj = PROCESSOR_INSTANCE_MAP.get(model.getClazz());if (obj == null) {return null;}// 返回执行结果return method.invoke(obj, model.getArgs());} catch (Exception e) {e.printStackTrace();return null;}}
}
/*服务端 remote 层,负责监听Socket,接收客户端远程调用**/
public class ServerRemoter {private static final ExecutorService executor =Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());public void startServer(int port) throws Exception {final ServerSocket server = new ServerSocket();// 绑定服务地址server.bind(new InetSocketAddress(port));System.out.println("-----------start server----------------");try {while (true) {final Socket socket = server.accept();// 线程池处理请求executor.execute(new MyRunnable(socket));}} finally {server.close();}}class MyRunnable implements Runnable {private Socket socket;public MyRunnable(Socket socket) {this.socket = socket;}public void run() {try {//1.接收参数ObjectInputStream inputStream = new ObjectInputStream(socket.getInputStream());ServiceProtocol.ProtocolModel model = (ServiceProtocol.ProtocolModel) inputStream.readObject();//服务端通过processor执行实现类方法Object object = ServiceProcessor.getInstance().process(model);//返回结果给客户端ObjectOutputStream outputStream = new ObjectOutputStream(socket.getOutputStream());outputStream.writeObject(object);outputStream.flush();//5.关闭连接outputStream.close();inputStream.close();} catch (IOException | ClassNotFoundException e) {e.printStackTrace();} finally {try {socket.close();} catch (IOException e) {e.printStackTrace();}}}}
}
/* 服务端发布接口,启动服务**/
public class Server {public static void main(String[] args) throws Exception {// 注册服务ServiceProcessor.getInstance().publish(RpcService.class, new RpcServiceImpl());// 启动server,开始监听 socketServerRemoter remoter = new ServerRemoter();remoter.startServer(10086);}
}
3. Client 包

该包中自上而下实现调用的各个步骤。

/* 客户端测试调用, 用户调用远程方法**/
public class Client {public static void main(String[] args) {System.out.println("----------start invoke----------------");// 使用代理客户端创建服务接口实例RpcService service = ServiceProxyClient.getInstance(RpcService.class);// 调用远程方法System.out.println(service.sayHi("RPC World"));System.out.println("----------end invoke----------------");}
}
/* 客户端服务代理,实际是将服务调用通过动态代理的方式返回远程服务执行结果.**/
public class ServiceProxyClient {// 创建代理对象public static <T> T getInstance(Class<T> clazz) {return (T) Proxy.newProxyInstance(clazz.getClassLoader(), new Class[]{clazz}, new ServiceProxy(clazz));}// 动态代理类public static class ServiceProxy implements InvocationHandler {private Class clazz;public ServiceProxy(Class clazz) {this.clazz = clazz;}@Overridepublic Object invoke(Object o, Method method, Object[] objects) throws Throwable {//执行服务接口方法时将远程调用的参数组装为modelServiceProtocol.ProtocolModel model = new ServiceProtocol.ProtocolModel();model.setClazz(clazz.getName());model.setMethod(method.getName());model.setArgs(objects);String[] argType = new String[method.getParameterTypes().length];for (int i = 0; i < argType.length; i++) {argType[i] = method.getParameterTypes()[i].getName();}model.setArgTypes(argType);//通过ClientRemoter发起远程调用, 返回远程服务执行结果Object object = ClientRemoter.getInstance().getDataRemote(model);return object;}}
}
/* 客户端 remote 层,与服务端通过 Socket 远程交互,生产环境需从第三方工具注册中心获*取远程服务地址,之后才能发起调用**/
public class ClientRemoter {private static volatile ClientRemoter instance;private ClientRemoter() {}public static ClientRemoter getInstance() {if (null == instance) {synchronized (ClientRemoter.class) {if (null == instance) {instance = new ClientRemoter();}}}return instance;}public Object getDataRemote(ServiceProtocol.ProtocolModel model) {try (Socket socket = new Socket()) {// socket远程连接socket.connect(new InetSocketAddress("127.0.0.1", 10086));ObjectOutputStream outputStream = new ObjectOutputStream(socket.getOutputStream());// 传输参数,请求远程执行outputStream.writeObject(model);outputStream.flush();//接收返回结果ObjectInputStream inputStream = new ObjectInputStream(socket.getInputStream());Object object = inputStream.readObject();return object;} catch (Exception e) {e.printStackTrace();return null;}}
}

2.3 总结

RPC 的主要流程可分为以下几个步骤,通常经过这些步骤之后,一次完整的RPC调用算是完成了,另外可能因为网络波动等原因需要重试

2.3.1. 建立通信

首先要解决通讯的问题:即A机器想要调用B机器,首先得建立起通信连接。

2.3.2. 服务寻址

要实现服务寻址,A 服务器上的应用怎么告诉底层的RPC框架,如何连接到B服务器(如主机或IP地址)以及特定的端口,方法的名称是什么。

1. 从服务提供者的角度看:
  • 当服务提供者启动的时候,需要将自己提供的服务注册到指定的注册中心,以便服务消费者能够通过服务注册中心进行查找;
  • 当服务提供者由于各种原因致使提供的服务停止时,需要向注册中心注销停止的服务;
  • 服务的提供者需要定期向服务注册中心发送心跳检测,服务注册中心如果一段时间未收到来自服务提供者的心跳后,认为该服务提供者已经停止服务,则将该服务从注册中心上去掉。
2.从调用者的角度看:
  • 服务的调用者启动的时候根据自己订阅的服务向服务注册中心查找服务提供者的地址等信息.
  • 当服务调用者消费的服务上线或者下线的时候,注册中心会告知该服务的调用者.
  • 服务调用者下线的时候,则取消订阅.
2.3.3. 网络传输
1. 序列化

当 A 机器上的应用发起一个RPC调用时,调用方法和其入参等信息需要通过底层的网络协议如TCP传输到B机器,由于网络协议是基于二进制的,所有传输的参数数据都需要先进行序列化(Serialize)或者编组(marshal)成二进制的形式才能在网络中进行传输,然后通过寻址操作和网络传输将序列化或者编组之后的二进制数据发送给B机器。

2. 反序列化

当 B 机器接收到 A 机器的应用发来的请求之后,又需要对接收到的参数等信息进行反序列化操作(序列化的逆操作),即将二进制信息恢复为内存中的表达方式,然后再找到对应的方法(寻址的一部分)进行本地调用(一般是通过生成代理Proxy去调用,
通常会有JDK动态代理、CGLIB动态代理、Javassist生成字节码技术等),之后得到调用的返回值。

2.3.4. 服务调用

B 机器进行本地调用(通过代理Proxy和反射调用)之后得到了返回值,此时还需要再把返回值发送回A机器,同样也需要经过序列化操作,然后再经过网络传输将二进制数据发送回A机器,而当A机器接收到这些返回值之后,则再次进行反序列化操作,恢复为内存中的表达方式,最后再交给A机器上的应用进行相关处理(一般是业务逻辑处理操作)。


http://chatgpt.dhexx.cn/article/6X6kU0ow.shtml

相关文章

RPC核心原理

了解RPC RPC全称Remote Procedure Call,即远程过程调用.其中远程需要跨机器,跨机器需要可靠的网络编程技术实现,无论是Java原生的网络编程模型还是Netty都会让代码中出现大量与业务无关的网络编程代码,RPC技术则是为了解决这个问题的.它帮助我们屏蔽网络编程的细节,实现调用远…

RPC原理(1)之深入RPC原理简介

一、RPC调用原理图 下面这张图是我们微服务一次Http调用请求图&#xff1a; 首先在请求的过程中我们知道是有三次握手&#xff0c;四次挥手的流程&#xff0c;具体流程如下&#xff1a; 1.浏览器请求服务器(订单服务)&#xff0c;请求建立连接&#xff0c;首先客户端向服务器…

RPC原理简述

RPC&#xff08;Remote Procedure Call&#xff09;&#xff1a;远程过程调用&#xff0c;它是一种通过网络从远程计算机程序上请求服务&#xff0c;而不需要了解底层网络技术的思想。 RPC 是一种技术思想而非一种规范或协议&#xff0c;常见 RPC 技术和框架有&#xff1a; 应…

RPC核心原理详解

什么是RPC&#xff1f; RPC的全称是Remote Procedure Call&#xff0c;即远程过程调用。简单解读字面上的意思&#xff0c;远程肯定是指要跨机器而非本机&#xff0c;所以需要用到网络编程才能实现&#xff0c;但是不是只要通过网络通信访问到另一台机器的应用程序&#xff0c…

RPC原理

RPC就是远程过程调用&#xff0c;它是一种通过网络从远程计算机程序上请求服务&#xff0c;而不需要了解底层网络技术的思想。 原理 一个完整的RPC主要包括三部分: 服务注册中心&#xff08;Registry&#xff09;&#xff0c;负责将本地服务发布成远程服务&#xff0c;管理远…

从零开始实现RPC框架 - RPC原理及实现

RPC概述 RPC(Remote Procedure Call)即远程过程调用&#xff0c;允许一台计算机调用另一台计算机上的程序得到结果&#xff0c;而代码中不需要做额外的编程&#xff0c;就像在本地调用一样。 现在互联网应用的量级越来越大&#xff0c;单台计算机的能力有限&#xff0c;需要借…

RPC介绍与原理

RPC介绍与原理 RPC介绍 RPC是什么 RPC&#xff08;Remote Procedure Call&#xff09;是一种进程间通信方式。简单地说就是能使应用像调用本地方法一样的调用远程的过程或服务&#xff0c;可以应用在分布式服务、分布式计算、远程服务调用等许多场景。说起 RPC 大家并不陌生…

RPC理论原理

目录 集群和分布式RPC通信原理 集群和分布式 集群&#xff1a;每一台服务器独立运行一个工程的所有模块。 分布式&#xff1a;一个工程拆分了很多模块&#xff0c;每一个模块独立部署运行在一个服务器主机上&#xff0c;所有服务器协同工作共同提供服务&#xff0c;每一台服务…

一文搞懂RPC原理

了解RPC&#xff1a; RPC&#xff08;Remote Procedure Call Protocol&#xff09;——远程过程调用协议&#xff1a; 一般用于实现部署在不同机器上的系统之间的方法调用&#xff0c;使得程序能够像访问本地资源一样&#xff0c;通过网络传输去访问远端系统资源。 描述&…

rpc简介及原理

1.RPC简介及原理介绍 RPC技术内部原理是通过两种技术的组合来实现的&#xff1a;本地方法调用 和 网络通信技术。 1.1 RPC简介 在上述本地过程调用的例子中&#xff0c;我们是在一台计算机上执行了计算机上的程序&#xff0c;完成调用。随着计算机技术的发展和需求场景的变化…

RPC原理解析

1.RPC原理解析 1.1 什么是RPC RPC(Remote Procedure Call Protocol)——远程过程调用协议&#xff0c;它是一种通过网络从远程计算机程序上请求服务&#xff0c;而不需要了解底层网络技术的协议。RPC协议假定某些传输协议的存在&#xff0c;如TCP/IP或UDP&#xff0c;为通信程序…

RPC实现原理

一、什么是RPC框架&#xff1f; RPC&#xff0c;全称为Remote Procedure Call&#xff0c;即远程过程调用&#xff0c;是一种计算机通信协议。 比如现在有两台机器&#xff1a;A机器和B机器&#xff0c;并且分别部署了应用A和应用B。假设此时位于A机器上的A应用想要调用位于B机…

什么是 RPC?RPC原理是什么?

什么是 RPC?RPC原理是什么? 什么是 RPC&#xff1f; RPC&#xff08;Remote Procedure Call&#xff09;—远程过程调用&#xff0c;它是一种通过网络从远程计算机程序上请求服务&#xff0c;而不需要了解底层网络技术的协议。比如两个不同的服务 A、B 部署在两台不同的机器…

【RK3399Pro学习笔记】三、Debian 9 安装 ROS (Thinker Edge R)

目录 配置源设置 Key安装初始化rosdep环境配置测试安装rosinstall卸载 平台&#xff1a;华硕 Thinker Edge R 瑞芯微 RK3399Pro 固件版本&#xff1a;Tinker_Edge_R-Debian-Stretch-V1.0.4-20200615 参考资料&#xff1a; RK3399(Debian9 - stretch) 安装 ROS Lunar —— WB8…

VMware安装Debian9及开发环境配置

序 需要用到一个搭载armv7架构A7内核的Linux设备&#xff0c;装的是Debian系统&#xff0c;为便于兼容该设备故用VMware安装一个Debian9虚拟机&#xff0c;整理总结了网上一些信息以供参考。 目录 一、安装Debian91、WMware中的配置2、安装镜像 二、开发环境配置1、设置快捷键打…

debian 升级linux内核,Debian 9更新到最新的Linux内核

喜欢折腾的同学,会豪气如何升级 Debian Stretch 的内核到新版。遗憾的是现在能搜到的升级 Debian Linux 内核的文章多数是使用Ubuntu的deb安装包,其实这样装上去是有问题,常见的问题是,总会提示需要 apt --fix-broken install 。 这里简单记录一下,如何使用Debian官方源更…

debian 9 ssh root权限登录

debian 9默认的一样不能用root用户登录&#xff0c;还是需要设置&#xff0c;方法如下&#xff1a; 一&#xff0c;打开终端&#xff0c;用普通用户登录 输入&#xff1a;su - 输入密码&#xff0c;切换到root用户 二&#xff0c;设置root用户登录 nano /etc/ssh/sshd_conf…

Debian9到Debian11的超详细升级教程

在云服务器商镜像页面中&#xff0c;可能无法选择一些系统最新的镜像版本。 就会造成一些软件不能顺利下载。 这时就需要自己手动下载并安装最新版的Debian系统了。 1、把当前版本的包更新到最新的版本 apt-get update apt-get upgrade apt-get dist-upgrade按q 直接回车 …

【linux实战】debian9安装python3.7

之前有写了一篇ubuntu18.04使用apt安装python各个版本的&#xff0c;但是最近上debian9上&#xff0c;发现那种apt安装方式不可行&#xff0c;因为ppa不支持debian系列。 Debian 9 默认安装有 Python 2.7 和 3.5。但是我们现在没法使用apt直接安装是没法安装自己想要的版本。 …

debian 系统启动服务器,Debian9添加开机自启动服务

升级到Debian9后&#xff0c;我们发现系统默认不带/etc/rc.local文件&#xff0c;但rc.local服务仍然保留 补齐缺失文件&#xff0c;让Debian9通过编辑/etc/rc.loacl文件为我们的服务添加开机自启动 1、添加rc-local.service #以下为一整条命令&#xff0c;一起复制运行cat >…