远程过程调用失败_Java开发大型互联网RPC远程调用服务实现之问题处理方案

引言

RPC(Remote Procedure Call Protocol)——远程过程调用协议,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议。RPC协议假定某些传输协议的存在,如TCP或UDP,为通信程序之间携带信息数据。在OSI网络通信模型中,RPC跨越了传输层和应用层。RPC使得开发包括网络分布式多程序在内的应用程序更加容易。

RPC采用客户机/服务器模式。请求程序就是一个客户机,而服务提供程序就是一个服务器。首先,客户机调用进程发送一个有进程参数的调用信息到服务进程,然后等待应答信息。在服务器端,进程保持睡眠状态直到调用信息到达为止。当一个调用信息到达,服务器获得进程参数,计算结果,发送答复信息,然后等待下一个调用信息,最后,客户端调用进程接收答复信息,获得进程结果,然后调用执行继续进行。有多种 RPC模式和执行。

RPC 结构

实现 RPC 的程序包括 5 个部分:

1. User

2. User-stub

3. RPCRuntime

4. Server-stub

5. Server

RPC 调用分类

RPC 调用的分类方式有很多种。

从通信协议层面可以分为:

基于 HTTP 协议的 RPC;

基于二进制协议的 RPC;

基于 TCP 协议的 RPC。

从是否跨平台可分为:

单语言 RPC,如 RMI, Remoting;

跨平台 RPC,如 google protobuffer, restful json,http XML。

从调用过程来看,可以分为同步通信RPC和异步通信RPC:

同步 RPC:指的是客户端发起调用后,必须等待调用执行完成并返回结果;

异步 RPC:指客户方调用后不关心执行结果返回,如果客户端需要结果,可用通过提供异步 callback 回调获取返回信息。大部分 RPC 框架都同时支持这两种方式的调用。

RPC 功能目标

RPC 的主要功能目标是让构建分布式计算(应用)更容易,在提供强大的远程调用能力时不损失本地调用的语义简洁性。为实现该目标,RPC 框架需提供一种透明调用机制让使用者不必显式的区分本地调用和远程调用,在前文《浅出篇》中给出了一种实现结构,基于 stub 的结构来实现。下面我们将具体细化 stub 结构的实现。

Java RPC 实现

在进一步拆解了组件并划分了职责之后,这里以一个最简单 Java RPC 框架实现为例,对 RPC 具体逻辑进行分析。

RPC 框架服务发布代码:

e96bacff77a88f3b7a2cb9ea85333372.png
57b15fb492a8b904f3c5c193c2e877c2.png
158e492a6ffec2eecc171b15981bdc21.png
e7d2585585054a9694e51b77a67db8b7.png
18ddd4d33c8f7646a15d363b4bfa67a5.png

服务端发布服务的代码如上,首先校验传入的端口和服务是否合法,然后开启一个 socket 监听,这儿为了简便,没有采用 NIO 方式,同时直接采用 java 的序列化方式,将传入的数据通过反射取出调用的方法和参数,本地执行后将运行结果通过 socket 套接字返回给客户端。RPC 框架服务调用代码:框架中客户端调用的代码中,首先校验对应的端口和主机是否合法,然后通过动态代理生成一个代理对象,在代理对象的方法中,拦截调用,通过建立 socket 连接,将方法和参数传递到远端执行并获取远程执行返回结果。

RPC 调用测试:如上图所示,服务器端发布一个接口服务 HelloService,客户端成功通过 RPC 调用。

怎么做到远程服务调用?

怎么封装通信细节才能让用户像以本地调用方式调用远程服务呢?对java来说就是使用代理!java代理有两种方式:1) jdk 动态代理;2)字节码生成。尽管字节码生成方式实现的代理更为强大和高效,但代码不易维护,大部分公司实现RPC框架时还是选择动态代理方式。

下面简单介绍下动态代理怎么实现我们的需求。我们需要实现RPCProxyClient代理类,代理类的invoke方法中封装了与远端服务通信的细节,消费方首先从RPCProxyClient获得服务提供方的接口,当执行helloWorldService.sayHello(“test”)方法时就会调用invoke方法。

Java

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

publicclassRPCProxyClient implementsjava.lang.reflect.InvocationHandler{

privateObjectobj;

publicRPCProxyClient(Objectobj){

this.obj=obj;

}

/**

* 得到被代理对象;

*/

publicstaticObjectgetProxy(Objectobj){

returnjava.lang.reflect.Proxy.newProxyInstance(obj.getClass().getClassLoader(),

obj.getClass().getInterfaces(),newRPCProxyClient(obj));

}

/**

* 调用此方法执行

*/

publicObjectinvoke(Objectproxy,Method method,Object[]args)

throwsThrowable{

//结果参数;

Objectresult=newObject();

// ...执行通信相关逻辑

// ...

returnresult;

}

}

Java

1

2

3

4

5

6

publicclassTest{

publicstaticvoidmain(String[]args){

HelloWorldService helloWorldService=(HelloWorldService)RPCProxyClient.getProxy(HelloWorldService.class);

helloWorldService.sayHello("test");

}

}

异常处理

无论 RPC 怎样努力把远程调用伪装的像本地调用,但它们依然有很大的不同点,而且有一些异常情况是在本地调用时绝对不会碰到的。在说异常处理之前,我们先比较下本地调用和 RPC调用的一些差异:

  1. 本地调用一定会执行,而远程调用则不一定,调用消息可能因为网络原因并未发送到服务方。
  2. 本地调用只会抛出接口声明的异常,而远程调用还会抛出 RPC 框架运行时的其他异常。
  3. 本地调用和远程调用的性能可能差距很大,这取决于 RPC 固有消耗所占的比重。

正是这些区别决定了使用 RPC 时需要更多考量。

当调用远程接口抛出异常时,异常可能是一个业务异常, 也可能是 RPC 框架抛出的运行时异常(如:网络中断等)。

业务异常表明服务方已经执行了调用,可能因为某些原因导致未能正常执行, 而 RPC 运行时异常则有可能服务方根本没有执行,对调用方而言的异常处理策略自然需要区分。

由于 RPC 固有的消耗相对本地调用高出几个数量级,

本地调用的固有消耗是纳秒级,而 RPC 的固有消耗是在毫秒级。

那么对于过于轻量的计算任务就并不合适导出远程接口由独立的进程提供服务,

只有花在计算任务上时间远远高于 RPC 的固有消耗才值得导出为远程接口提供服务。

总结

以 上就是我对Java开发大型互联网RPC远程调用服务实现之问题处理方案 问题及其优化总结,分享给大家,觉得收获的话可以点个关注收藏转发一波喔,谢谢大佬们支持!

最后,每一位读到这里的网友,感谢你们能耐心地看完。希望在成为一名更优秀的Java程序员的道路上,我们可以一起学习、一起进步!都能赢取白富美,走向架构师的人生巅峰!

想了解学习Java方面的技术内容以及Java技术视频的内容可加群:722040762 验证码:头条(06 必过)欢迎大家的加入哟!

38ac8831f8f0c61083b2b484c3d28d75.png

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/533985.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

chrome 新的session 设置_为什么还是由这么多人搞不懂Cookie、Session、Token?

作者:不学无数的程序员链接:https://urlify.cn/Yfm6Vr# Cookie洛:大爷,楼上322住的是马冬梅家吧? 大爷:马都什么? 夏洛:马冬梅。 7大爷:什么都没啊? 夏洛…

mysql for update用处_for update的作用和用法

一、for update定义for update是一种行级锁,又叫排它锁,一旦用户对某个行施加了行级加锁,则该用户可以查询也可以更新被加锁的数据行,其它用户只能查询但不能更新被加锁的数据行.如果其它用户想更新该表中的数据行&…

python大数据零基础_零基础学习大数据人工智能,学习路线篇!

大数据处理技术怎么学习呢?首先我们要学习Python语言和Linux操作系统,这两个是学习大数据的基础,学习的顺序不分前后。Python:Python 的排名从去年开始就借助人工智能持续上升,现在它已经成为了语言排行第一名。从学习难易度来看…

python删除文件和linux删除文件区别_使用Python批量删除文件列表

使用Python批量删除文件列表环境:已知要删除的文件列表,即确定哪些文件要删除。代码如下:#!/usr/bin/env python#codingutf-8#目的:本程序主要为删除给定的文件列表import osimport shutil#引入模块,os为包含普遍的操作…

华为python有必要学吗_【华为云技术分享】这个 Python 库有必要好好学学

这里看一个最基本的例子,这里给到一个 User 的 Class 定义,再给到一个 data 数据,像这样:1 class User(object):2 def __init__(self, name, age):3 self.name name4 self.age age56 data [{7 name: Germey,8 age: 239 }, {10 nam…

python求平行四边形面积_python 已知平行四边形三个点,求第四个点的案例

我就废话不多说了,大家还是直接看代码吧!import numpy as np#已知平行四边形三个点,求第四个点#计算两点之间的距离def CalcEuclideanDistance(point1,point2):vec1 np.array(point1)vec2 np.array(point2)distance np.linalg.norm(vec1 -…

eview面板数据之混合回归模型_【视频教程】Eviews系列25|面板数据回归分析之Hausman检验及本章常见问题解答...

点击上方关注我们!本期我们学习Eviews统计建模最后一部分--面板数据回归分析Hausman检验及本章常见问题解答。实操:Hausman检验判断是固定效应模型还是随机效应模型上期我们讲到模型判断若选择模型2,需进一步通过Hausman检验判断固定效应还是随机效应,接…

python打出由边框包围的_python opencv 图像边框(填充)添加及图像混合的实现方法(末尾实现类似幻灯片渐变的效果)...

图像边框的实现图像边框设计的主要函数cv.copyMakeBorder()——实现边框填充主要参数如下:参数一:源图像——如:读取的img参数二——参数五分别是:上下左右边的宽度——单位:像素参数六:边框类型&#xff1…

mysql5.7.21备份脚本_Shell脚本使用汇总整理——mysql数据库5.7.8以后备份脚本

#!/bin/sh#db_backups_conf.txt文件路径db_backups_conf"/wocloud/shell/db_backups_conf.txt"#判断文件是否存在if [ -f "${db_backups_conf}" ];thenecho $(date %Y-%m-%d %H:%M:%S)" 数据库配置信息文件存在,开始进行数据备份"#获…

python嵌套列表操作_python基础(list列表的操作,公共方法,列表嵌套,元祖)...

list 列表索引,切片与str相同。列表的操作(增删改查)1,增加.append()  追加,增加到最后li [alex,wusir,egon,女神,taibai]li.append(ppp)print(li).insert()  中间插入,通过索引li [alex,wusir,egon,女神,taibai]li.insert(…

mybatis mysql selectkey_Mybatis示例之SelectKey的应用

SelectKey在Mybatis中是为了解决Insert数据时不支持主键自动生成的问题,他可以很随意的设置生成主键的方式。不管SelectKey有多好,尽量不要遇到这种情况吧,毕竟很麻烦。SelectKey需要注意order属性,像Mysql一类支持自动增长类型的…

python程序设计上机实践第三章答案_20192419 实验三《Python程序设计》实验报告

学号 2019-2020-2 《Python程序设计》实验3报告课程:《Python程序设计》班级:1924姓名: 万腾阳学号:20192419实验教师:王志强实验日期:2020年5月16日必修/选修: 公选课1.实验内容创建服务端和客…

完成数独的算法 python_python实现数独算法实例

本文实例讲述了python实现数独算法的方法。分享给大家供大家参考。具体如下:# -*- coding: utf-8 -*-Created on 2012-10-5author: Administratorfrom collections import defaultdictimport itertoolsa [[ 0, 7, 0, 0, 0, 0, 0, 0, 0], #0[ 5, 0, 3, 0, 0, 6, 0, …

python读取多个文件csv_Python:读取多个文本文件并写入相应的csv文件

我在别处找不到这个问题的答案,所以我将继续把它贴在这里:我有一个Python脚本,它将读取文本文件的内容,将其内容拆分为单词,然后输出一个CSV文件,该文件将文本缩减为单词频率列表。(最后,我将插…

java treetable_在Swing中创建TreeTable | 学步园

TreeTable是Tree和Table的一个结合-就是一个即能够展开和收起行,同时也能够显示多个列的组件。在Swing的标准包里没有一个叫做JtreeTable的组件,但是我们很容易通过把Jtree做成Jtable的渲染器来创建一个这样的组件。这篇文章就是关于如何使用…

python爬去微博十大流行语_用python重新定义【2019十大网络流行语】-后台/架构/数据库-敏捷大拇指-一个敢保留真话的IT精英社区...

↑关注 置顶 ~ 有趣的不像个技术号52568040f9313098ffa367d9d9d21437.jpg (5.73 KB, 下载次数: 0)2019-12-10 04:43 上传3f4d5fe0016d011a7a68af763314befd.jpg (1.06 KB, 下载次数: 0)2019-12-10 04:43 上传“文明互鉴真硬核,融梗柠檬谁觉得。霸凌第一九九六&…

java中怎么获取配置文件的值_java如何获取配置文件的值

转:原创 编码小王子 发布于2018-10-11 18:07:52 阅读数 2722 收藏展开java大型项目中都会很多系统常量,比如说数据库的账号和密码,以及各种token值等,都需要统一的管理,如果零落的散布到各个类等具体的代码中的话,在后期管理上将是一场灾难,所有需要对这些变量进行统…

python实现队列_用Python实现的数据结构与算法:队列

一、概述队列(Queue)是一种先进先出(FIFO)的线性数据结构,插入操作在队尾(rear)进行,删除操作在队首(front)进行。二、ADT队列ADT(抽象数据类型)一般提供以下接口:Queue() 创建队列enqueue(item) 向队尾插入项dequeue() 返回队首的项&#xf…

java 监听窗口是否改变_JAVA项目监听文件是否发生变化

一.spring容器都初始化完成之后做操作packagecom.bijian.study.listener;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.context.ApplicationListener;importorg.springframework.context.event.ContextRefreshedEvent;importorg.s…

笨办法学python3 pdf 脚本之家_解决python3输入的坑——input()

如下所示:a,b,c,d input()很简单的代码,如果输入为1 -1 -2 3结果会报错,原因在于input函数会将你的输入作为python脚本运行,那么输入就变成了1-1 -2 3,即0 -2 3结果当然是错误的了,解决办法就是将输入用引…