什么是RPC? RPC是Remote Procedure Call的缩写,像Client-Servier一样的远程过程调用,也就是调用远程服务就跟调用本地服务一样方便,一般用于将程序部署在不同的机器上,供客户端进行调用。就像一个request-response调用系统一样简单。在面向对象编程的程序中,RPC也可以用Remote method invocation(RMI)来展现。为什么用它呢,因为随着分布式结构的普遍,越来越多的应用需要解耦,将不同的独立功能部署发布成不同的服务供调用。

  它的主要流程是Client -> Client Stub -> Network -> Server Stub -> Server 执行完成之后再进行返回。

  这里边比较重要的就是Clint Stub和Server Stub,他们主要的作用就是将调用的方法和参数进行编码(Marshalling)序列化,将序列化后的数据通过网络发送给Server Stub,然后等待Server回执。Server Stub将受到的序列化字节进行解码(Unmarshaling)反序列化,然后再将参数传入到对应到的方法中执行,将得出的结果计算出来之后再进行返回,返回的过程和正向的过程类似。

  那么这个结构里边的内容这么复杂,而且还需要保证数据的完整,网络等因素,所以这块有一个通讯的标准就是IDL(Interface Description Language)接口定义语言,因为很多程序采用了不同的编程语言(Java,C, C++ etc.)和不同的操作系统(Windows, CentOs, RHEL etc.),要保证数据能够正常通讯,并且不受语言和操作系统等限制,就有了它。比如Apache的Thrift 、Avro和Google的 Protocol Buffers、阿里的Dubbo等。

  其实很多人早已经应用了它了,但是可能不知道,比如web service的WSDL。下面我就用一个小程序来创建一个简单基于的WSDL的RPC。使用JDK的JAX-WS实现

  接口类(定义了一个非常简单的方法):

package com.hqs.rpc;

import javax.jws.WebMethod;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;
import javax.jws.soap.SOAPBinding.Style; /**
* 接口
* @author hqs
*
*/
@WebService
@SOAPBinding(style = Style.RPC)
public interface IRPCService {
@WebMethod
public String RPCMethod(String str);
}

  实现类:

package com.hqs.rpc;

import javax.jws.WebService;

/**
* 实现类
* @author hqs
*
*/
@WebService (endpointInterface = "com.hqs.rpc.IRPCService")
public class RPCServiceImpl implements IRPCService { @Override
public String RPCMethod(String str) {
System.out.println("service received:" + str);
return "RPC Method invoked: " + str;
} }

  服务发布类:

package com.hqs.rpc;

import javax.xml.ws.Endpoint;

/**
* 发布类
* @author hqs
*
*/
public class RPCPublisher {
public static void main(String[] args) {
//自己定义地址
Endpoint.publish("http://localhost:9966/rpc", new RPCServiceImpl());
}
}

  这个时候启动服务类,然后就可以通过地址http://localhost:9966/rpc?wsdl访问WSDL文件了了:

<?xml version="1.0" encoding="UTF-8"?>

<!-- Published by JAX-WS RI at http://jax-ws.dev.java.net. RI's version is JAX-WS RI 2.2.4-b01. -->

<!-- Generated by JAX-WS RI at http://jax-ws.dev.java.net. RI's version is JAX-WS RI 2.2.4-b01. -->

-<definitions name="RPCServiceImplService" targetNamespace="http://rpc.hqs.com/" xmlns="http://schemas.xmlsoap.org/wsdl/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://rpc.hqs.com/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:wsam="http://www.w3.org/2007/05/addressing/metadata" xmlns:wsp1_2="http://schemas.xmlsoap.org/ws/2004/09/policy" xmlns:wsp="http://www.w3.org/ns/ws-policy" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">

<types/>

-<message name="RPCMethod">

<part type="xsd:string" name="arg0"/>

</message>

-<message name="RPCMethodResponse">

<part type="xsd:string" name="return"/>

</message>

-<portType name="IRPCService">

-<operation name="RPCMethod">

<input message="tns:RPCMethod" wsam:Action="http://rpc.hqs.com/IRPCService/RPCMethodRequest"/>

<output message="tns:RPCMethodResponse" wsam:Action="http://rpc.hqs.com/IRPCService/RPCMethodResponse"/>

</operation>

</portType>

-<binding type="tns:IRPCService" name="RPCServiceImplPortBinding">

<soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>

-<operation name="RPCMethod">

<soap:operation soapAction=""/>

-<input>

<soap:body namespace="http://rpc.hqs.com/" use="literal"/>

</input>

-<output>

<soap:body namespace="http://rpc.hqs.com/" use="literal"/>

</output>

</operation>

</binding>

-<service name="RPCServiceImplService">

-<port name="RPCServiceImplPort" binding="tns:RPCServiceImplPortBinding">

<soap:address location="http://localhost:9966/rpc"/>

</port>

</service>

</definitions>

  接下来我们就可以写客户端类:

package com.hqs.rpc;

import java.net.MalformedURLException;
import java.net.URL; import javax.xml.namespace.QName;
import javax.xml.ws.Service; /**
* 客户端类
* @author hqs
*
*/
public class RPCClient {
public static void main(String[] args) {
try {
URL url = new URL("http://localhost:9966/rpc?wsdl");
QName qname = new QName("http://rpc.hqs.com/","RPCServiceImplService");
Service service = Service.create(url, qname);
IRPCService irpc = service.getPort(IRPCService.class);
System.out.println(irpc.RPCMethod("client"));
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} }
} RPC Method invoked: client

  简单的RPC就这么实现了。其实目前实现上一些公司实现的比较复杂,分为服务分为provider和consumer,以及负责监控管理的provider,provider一般采用zookeeper单数集群,用于管理和监控provider的服务注册,因为provider可能部署在同一台机器上的不同端口或者不同机器上,consumer通过zookeeper就可以拿到provider的IP/接口/版本号/端口等信息,然后进行调用。

  好了,如果有不对的地方,请大家指正。

聊聊RPC及其原理的更多相关文章

  1. RPC实现原理(HSF、dubbo) 从头开始(一)

    前言 阔别了很久博客园,虽然看了以前写的很多东西感觉好幼稚,但是还是觉得应该把一些自己觉得有用的东西和大家分享.废话不多说,现在开始进入正题. 之前的六年工作经验,呆过了一些大公司,每个在大公司呆过的 ...

  2. 网络编程 -- RPC实现原理 -- 目录

    -- 啦啦啦 -- 网络编程 -- RPC实现原理 -- NIO单线程 网络编程 -- RPC实现原理 -- NIO多线程 -- 迭代版本V1 网络编程 -- RPC实现原理 -- NIO多线程 -- ...

  3. 网络编程 -- RPC实现原理 -- NIO单线程

    网络编程 -- RPC实现原理 -- 目录 啦啦啦 Class : Service package lime.pri.limeNio.optimize.socket; import java.io.B ...

  4. 网络编程 -- RPC实现原理 -- NIO多线程 -- 迭代版本V1

    网络编程 -- RPC实现原理 -- 目录 啦啦啦 V1——设置标识变量selectionKey.attach(true);只处理一次(会一直循环遍历selectionKeys,占用CPU资源). ( ...

  5. 网络编程 -- RPC实现原理 -- NIO多线程 -- 迭代版本V2

    网络编程 -- RPC实现原理 -- 目录 啦啦啦 V2——增加WriteQueue队列,存放selectionKey.addWriteEventToQueue()添加selectionKey并唤醒阻 ...

  6. 网络编程 -- RPC实现原理 -- Netty -- 迭代版本V1 -- 入门应用

    网络编程 -- RPC实现原理 -- 目录 啦啦啦 V1——Netty入门应用 Class : NIOServerBootStrap package lime.pri.limeNio.netty.ne ...

  7. 网络编程 -- RPC实现原理 -- Netty -- 迭代版本V2 -- 对象传输

    网络编程 -- RPC实现原理 -- 目录 啦啦啦 V2——Netty -- 使用序列化和反序列化在网络上传输对象:需要实现 java.io.Serializable 接口 只能传输( ByteBuf ...

  8. 网络编程 -- RPC实现原理 -- Netty -- 迭代版本V3 -- 编码解码

    网络编程 -- RPC实现原理 -- 目录 啦啦啦 V2——Netty -- pipeline.addLast(io.netty.handler.codec.MessageToMessageCodec ...

  9. 网络编程 -- RPC实现原理 -- Netty -- 迭代版本V4 -- 粘包拆包

    网络编程 -- RPC实现原理 -- 目录 啦啦啦 V2——Netty -- new LengthFieldPrepender(2) : 设置数据包 2 字节的特征码 new LengthFieldB ...

随机推荐

  1. Spring Boot Document Part II(下)

    Part II. Getting started 11. 开发第一个Spirng Boot Application使用Spring Boot的关键特征开发一个基于JAVA Web的“Hello Wor ...

  2. Json操作问题总结

    大家都知道,Json是一种轻量级的数据交换格式,对JS处理数据来说是很理想滴! 熟练写过xxx.json文件和操作的小伙伴来说,我说的问题都不是什么大问题啦,可以忽略本宝宝的文章,更希望各位大佬指点一 ...

  3. Python数据分析流程

    一.数据分析的步骤: 1.查看数据并提出问题 2.数据清洗 3.代码编写,提取出结果数据,并分析是否有异常数据,修改代码 4.根据数据选择合适的图表进行展示 5.根据图表小组讨论交流获得最终的结果 二 ...

  4. RuntimeError: Python is not installed as a framework 错误解决办法

    因为我是macbook,mac是自带的python 2.7,但是我开发需要使用到的是python3,所以先使用pip3 install matplotlib 然后在交互页面键入import matpl ...

  5. yii2-swiftmailer入门

    1. 安装 用yii 2.0框架,默认会有这个扩展 composer require --prefer-dist yiisoft/yii2-swiftmailer 修改composer.json,re ...

  6. Python之scrapy安装

    1.按照网上教程一步步实验,运行时报错: 'HtmlResponse' object has no attribute 'xpath' in scrapy 个人使用的是scrapy0.14.4,搜索得 ...

  7. Parallel.Invoke 并行的使用

    Parallel类  在System.Threading.Tasks 命名空间下 下面有几个方法,这里讲一下Invoke的用法 下面我们定义几个方法方便测试 先自定义Response 防止并行的时候占 ...

  8. SQL Server XML数据解析

    --5.读取XML --下面为多种方法从XML中读取EMAIL DECLARE @x XML SELECT @x = ' <People> <dongsheng> <In ...

  9. java自动化测试-http请求get

    首先我10.1过来自己玩通了讨鬼转极,看了电视剧白夜追凶,换了工作小组,这段时间确实比较少的更新博客,确实有点不勤奋,我先自我检讨 我就不赘述java的安装了,这个是比较简单的,有必要的话以后在讲 对 ...

  10. 【转载】基于VoiceOver的移动web站无障碍访问实战

    文章转载自 张鑫旭-鑫空间-鑫生活 http://www.zhangxinxu.com/wordpress/ 原文链接:http://www.zhangxinxu.com/wordpress/?p=5 ...