当前位置: 首页 > news >正文

使用Java Socket实现简单版本的Rpc服务

通过如下demo,希望大家可以快速理解RPC的简单案例。如果对socket不熟悉的话可以先看下我的上篇文章 Java Scoket实现简单的时间服务器-CSDN博客 对socket现有基础了解。

RPC简介

RPC(Remote Procedure Call,远程过程调用)是一种计算机通信协议,它允许一个程序(客户端)通过网络向另一个程序(服务器)请求服务,而无需了解底层网络技术的细节。RPC 使得开发分布式应用程序更加容易,因为它隐藏了网络通信的复杂性,让开发者能够像调用本地函数一样调用远程函数。

RPC 的主要特点:

  1. 透明性:调用远程过程就像调用本地过程一样,无需关心远程调用的细节。
  2. 跨平台:可以在不同的操作系统和编程语言之间进行通信。
  3. 网络中立:RPC 协议可以运行在各种网络协议之上,如 TCP/IP、HTTP 等。
  4. 语言中立:支持多种编程语言,如 C、C++、Java、Python 等。

RPC 的工作流程:

  1. 客户端调用:客户端调用本地的 RPC 库,传递需要远程执行的函数名和参数。
  2. 序列化:RPC 库将参数序列化成网络传输的格式(如 JSON、XML 或二进制格式)。
  3. 发送请求:客户端通过网络发送序列化后的请求到服务器。
  4. 服务器接收:服务器接收到请求后,反序列化参数。
  5. 执行函数:服务器调用相应的函数执行操作。
  6. 返回结果:服务器将执行结果序列化后发送回客户端。
  7. 客户端接收:客户端接收到结果,反序列化并处理。

RPC 的应用场景:

  • 分布式系统:在分布式系统中,不同的服务可能部署在不同的服务器上,RPC 可以方便地进行服务间的通信。
  • 微服务架构:在微服务架构中,各个微服务之间通常通过 RPC 进行通信。
  • 云服务:云服务提供商可能使用 RPC 来允许用户远程调用云服务。

常见的 RPC 框架:

  • gRPC:由 Google 开发的高性能、开源和通用的 RPC 框架,支持多种语言。
  • Apache Thrift:由 Facebook 开发,后来捐赠给 Apache 基金会,支持多种编程语言。
  • Dubbo:阿里巴巴开源的一个高性能的 Java RPC 框架。
  • XML-RPC 和 JSON-RPC:基于 XML 和 JSON 数据格式的简单 RPC 协议。

RPC 是构建现代分布式系统和微服务架构的关键技术之一。如下是个人对RPC服务的理解示图。

代码实现

1.创建Service以及实现类,由于演示使用的是jdk的动态代理,所以必须得通过接口方式声明资源。代码如下:

HelloService.java

public interface HelloService {String sayHello();}

HelloServiceImpl.java 远程访问的接口实现

public class HelloServiceImpl implements HelloService {@Overridepublic String sayHello() {return "hello world !!!";}
}

参数传输DTO定义,为了简化get、set,请引入lombok工具包:

import lombok.Data;
import lombok.ToString;
import lombok.experimental.Accessors;import java.io.Serializable;@Data
@Accessors(chain = true)
@ToString
public class RequestDTO implements Serializable {/*** 请求函数名称*/private String methodName;/*** 请求参数类型*/private Class<?>[] argsType;/*** 请求的接口*/private String clazz;/*** 请求参数*/private Object[] params;/*** 响应结果*/private Object response;}

服务提供者设计:

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Method;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;public class Provide {/*** 多线程处理请求*/private static final ExecutorService POOL = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());private static final Map<String,Object> CACHE_MAP = new HashMap<>();public static void main(String[] args) throws Exception {//注册对象registerObject();//启动服务startServer();}/*** 启动服务端*/private static void startServer() throws Exception {ServerSocket serverSocket = new ServerSocket();serverSocket.bind(new InetSocketAddress(9999));System.out.println("服务器启动成功!!!");while (true){Socket socket = serverSocket.accept();POOL.execute(()->{try {ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());RequestDTO request = (RequestDTO)ois.readObject();System.out.println("获取到客户端的请求数据是:"+request);//目标对象Object target = CACHE_MAP.get(request.getClazz());if(null!=target){//反射执行并返回响应结果Method method = target.getClass().getMethod(request.getMethodName(),request.getArgsType());method.setAccessible(true);request.setResponse(method.invoke(target,request.getParams()));}ByteArrayOutputStream bos = new ByteArrayOutputStream();ObjectOutputStream oos = new ObjectOutputStream(bos);oos.writeObject(request);socket.getOutputStream().write(bos.toByteArray());socket.getOutputStream().flush();} catch (Exception e) {throw new RuntimeException(e);}finally {try {socket.close();} catch (IOException e) {throw new RuntimeException(e);}}});}}/*** 注册对象,因为演示,简化自动化扫描注册过程*/private static void registerObject() {CACHE_MAP.put(HelloService.class.getSimpleName(),new HelloServiceImpl());}}

服务调用方实现:

1.动态代理

import java.io.*;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;public class DynamicProxy<T> {private final String host = "127.0.0.1";private final int port = 9999;/*** 被代理的对象*/private Class<T> clazz;public DynamicProxy(Class<T> clazz){this.clazz = clazz;}/*** 获取代理对象*** @return T*/public T getService(){return (T) Proxy.newProxyInstance(DynamicProxy.class.getClassLoader(), new Class[]{clazz}, new InvocationHandler() {@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {RequestDTO requestDTO = new RequestDTO().setMethodName(method.getName()).setParams(args).setClazz(clazz.getSimpleName()).setArgsType(method.getParameterTypes());try (Socket socket = new Socket()){//连接客户端socket.connect(new InetSocketAddress(host,port));//进行参数传输ByteArrayOutputStream baos = new ByteArrayOutputStream();ObjectOutputStream oos = new ObjectOutputStream(baos);oos.writeObject(requestDTO);oos.flush();socket.getOutputStream().write(baos.toByteArray());socket.getOutputStream().flush();ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());Object o = ois.readObject();if(null==o){return null;}return ((RequestDTO)o).getResponse();} catch (Exception e) {throw new RuntimeException(e);}}});}}

调用过程:


public class Consumer {public static void main(String[] args) {DynamicProxy<HelloService> helloServiceDynamicProxy = new DynamicProxy<>(HelloService.class);HelloService service = helloServiceDynamicProxy.getService();System.out.println(service.sayHello());}}

总结

RPC(远程过程调用)是一种允许一个程序(客户端)通过网络向另一个程序(服务器)请求服务的协议。在RPC框架中,客户端可以像调用本地方法一样调用服务器端的方法,而无需关心底层的网络通信细节。

以下是一段基于Java Socket实现的RPC原理的demo总结:

  1. 服务器端(Server)

    • 创建一个服务器端Socket,监听一个端口等待客户端的连接。
    • 接受客户端的连接请求,创建一个新的线程或者使用线程池来处理客户端请求。
    • 接收客户端发送的请求信息,这通常包括方法名、参数类型和参数值等。
    • 根据请求信息,动态调用对应的本地方法,并获取执行结果。
    • 将方法执行结果返回给客户端。
  2. 客户端(Client)

    • 创建一个客户端Socket,连接到服务器端的IP地址和端口。
    • 封装需要远程调用的方法信息,包括方法名、参数等,并将这些信息发送给服务器。
    • 等待服务器处理请求并返回结果。
    • 接收并解析服务器返回的结果,这可能涉及到对象的反序列化。
  3. 序列化与反序列化

    • 为了通过网络传输方法的参数和返回值,需要将对象序列化成字节流。
    • Java提供了Serializable接口来支持对象的序列化。
    • 客户端发送序列化后的对象,服务器端接收后需要反序列化以恢复对象。
  4. 通信协议

    • 定义了客户端和服务器之间的通信协议,包括请求格式和响应格式。
    • 协议需要规定如何表示方法名、参数列表、返回值等信息。
  5. 异常处理

    • 在网络通信中,可能会遇到各种异常情况,如连接失败、数据传输错误等。
    • 需要在客户端和服务器端都实现异常处理机制,确保系统的健壮性。
  6. 多线程处理

    • 服务器端通常需要处理多个客户端的并发请求。
    • 使用线程池可以有效地管理线程资源,提高系统性能。
  7. 安全性

    • 在实际应用中,需要考虑数据的安全性,比如使用SSL/TLS加密Socket通信。

通过这个Demo,我们可以了解到RPC的核心原理和实现方式,虽然这是一个简化的示例,但它展示了RPC框架的基本工作流程。在实际应用中,RPC框架会提供更复杂的功能,如服务注册与发现、负载均衡、超时重试等。

相关文章:

使用Java Socket实现简单版本的Rpc服务

通过如下demo&#xff0c;希望大家可以快速理解RPC的简单案例。如果对socket不熟悉的话可以先看下我的上篇文章 Java Scoket实现简单的时间服务器-CSDN博客 对socket现有基础了解。 RPC简介 RPC&#xff08;Remote Procedure Call&#xff0c;远程过程调用&#xff09;是一种…...

P2P 网络 简单研究 1

起因&#xff0c; 目的: P2P 网络&#xff0c; 一道题。题目描述&#xff0c; 在下面。 P2P 网络&#xff0c;我以前只是听说过&#xff0c;并不深入。如果我有5台电脑的话&#xff0c;我也想深入研究一下。 P2P 简介: P2P&#xff08;Peer-to-Peer&#xff09;网络是一种分…...

RAG(检索增强生成)面经(1)

1、RAG有哪几个步骤&#xff1f; 1.1、文本分块 第一个步骤是文本分块&#xff08;chunking&#xff09;&#xff0c;这是一个重要的步骤&#xff0c;尤其在构建与处理文档的大型文本的时候。分块作为一种预处理技术&#xff0c;将长文档拆分成较小的文本块&#xff0c;这些文…...

卫爱守护|守护青春,送出温暖

2024年10月10日&#xff0c;艾多美爱心志愿者来到校园。艾多美“卫艾守护”项目于吉林省白山市政务大厅会议室举办了捐赠仪式&#xff0c;东北区外事部经理黄山出席了捐赠仪式仪式&#xff0c;为全校女同学捐赠了青春关爱包。 此次捐赠&#xff0c;面向吉林省自山市第十八中学、…...

ubuntu-24.04.1 系统安装

使用VMware虚拟机上进行实现 官网下载地址&#xff1a; https://cn.ubuntu.com/download https://releases.ubuntu.com 操作系统手册&#xff1a; https://ubuntu.com/server/docs/ &#xff08;里面包含安装文档&#xff09; 安装指南&#xff08;详细&#xff09;&#xff1a…...

华为OD机试真题---生成哈夫曼树

华为OD机试中关于生成哈夫曼树的题目通常要求根据给定的叶子节点权值数组&#xff0c;构建一棵哈夫曼树&#xff0c;并按照某种遍历方式&#xff08;如中序遍历&#xff09;输出树中节点的权值序列。以下是对这道题目的详细解析和解答思路&#xff1a; 一、题目要求 给定一个…...

小红书新ID保持项目StoryMaker,面部特征、服装、发型和身体特征都能保持一致!(已开源)

继之前和大家介绍的小红书在ID保持以及风格转换方面相关的优秀工作&#xff0c;感兴趣的小伙伴可以点击以下链接阅读~ 近期&#xff0c;小红书又新开源了一款文生图身份保持项目&#xff1a;StoryMaker&#xff0c;是一种个性化解决方案&#xff0c;它不仅保留了面部的一致性&…...

Docker 环境下 GPU 监控实战:使用 Prometheus 实现 DCGM Exporter 部署与 GPU 性能监控

Docker 环境下 GPU 监控实战&#xff1a;使用 Prometheus 实现 DCGM Exporter 部署与 GPU 性能监控 文章目录 Docker 环境下 GPU 监控实战&#xff1a;使用 Prometheus 实现 DCGM Exporter 部署与 GPU 性能监控一 查看当前 GPU 信息二 dcgm-exporter 部署1&#xff09;Docker r…...

联想小新打印机M7328w如何解决卡纸,卡了一个小角在里面,然后再次打印的时候,直接卡住,不能动了。灯显示红色。

1、今天打印一张纸&#xff0c;应该是不小心放歪了&#xff0c;打出来的也是有些斜&#xff0c;然后打出来缺少了个角。 图中的小纸就是从打印机的左边的角&#xff0c;用镊子取出来的&#xff0c;手不太好拿&#xff0c;所以拿个工具比较合适。 2、那么碰到这种卡纸应该如何处…...

软件可靠性之MTTR、MTBF、MTTF、MTTD区别

一.概念解释 1.MTBF&#xff08;Mean Time Between Failures&#xff09;&#xff1a;指两次故障之间的平均时间&#xff0c;通常用于衡量设备或系统的可靠性。 2.MTTF&#xff08;Mean Time to Failure&#xff09;&#xff1a;指设备或系统的平均无故障运行时间。 3.MTTR&am…...

Qt-QDockWidget浮动窗口相关操作(49)

目录 描述 使用 描述 在 Qt 中&#xff0c;浮动窗⼝也称之为铆接部件。浮动窗⼝是通过 QDockWidget类 来实现浮动的功能。浮动窗口⼀般是位于核心部件的周围&#xff0c;可以有多个。 使用 创建我们可以参考下面的语法格式 使用起来也很简单&#xff0c;不过只能创建一个 Q…...

图形用户界面-GUI的基本概念和组件之一

前言 GUI&#xff08;Graphical User Interface&#xff0c;图形用户界面&#xff0c;简称图形界面&#xff09;编程实际是引用java.awt或javax.swing类包中的窗口类、控制组件类、布局类、事件类等&#xff0c;通过将控制组件类&#xff0c;如菜单、按钮、文本框等&#xff0c…...

【MATLAB代码】基于RSSI原理的蓝牙定位程序(N个锚点、三维空间),源代码可直接复制

文章目录 介绍主要功能技术细节适用场景程序结构运行截图源代码详细教程:基于RSSI的蓝牙定位程序1. 准备工作2. 代码结构2.1 清理工作环境2.2 定义参数2.3 生成锚点坐标2.4 定义信号强度与距离的关系2.5 模拟未知点的位置2.6 定位函数2.7 绘图2.8 输出结果2.9 定义定位函数3. …...

Pyenv 介绍和安装指南 - Ubuntu 24

原文&#xff1a; https://www.qiulin-dev.top/articles/81aab753-0d0e-470c-b08f-2643c876841b 1. Pyenv 介绍 Pyenv 是一个非常流行的 Python 版本管理工具&#xff0c;它可以让你在同一台机器上安装并管理多个不同的 Python 版本&#xff0c;解决了不同项目需要不同 Python…...

zookeeper实现RMI服务,高可用,HA

这可不是目录 1.RMI原理与说明1.1含义1.2流程1.3rmi的简单实现1.4RMI的局限性 2.zookeeper实现RMI服务&#xff08;高可用、HA&#xff09;2.1实现原理2.2高可用分析2.3zookeeper实现2.3.1代码分析2.3.2公共部分2.3.3服务端2.3.4客户端2.3.5运行与部署2.3.6效果展示与说明 1.RM…...

通过Express + Vue3从零构建一个用户认证与授权系统(一)项目结构设计

项目背景 本文基于 TypeScript Express Vue3 &#xff0c;从零构建一个用户认证与授权管理系统。这个系统的核心部分包括前端、后端和数据库。我们需要确保各部分合理分层、易于维护和扩展&#xff0c;让我们一步步去实现我们的系统。 一、项目结构设计 1. 前端 (Vue 3 E…...

JavaScript 第13章:Ajax 与异步请求

在Web开发中&#xff0c;异步请求是一种非常重要的技术&#xff0c;它可以让网页在不重新加载的情况下与服务器交互。本章将介绍两种常用的异步请求技术&#xff1a;XMLHttpRequest 和 Fetch API&#xff0c;以及它们如何用于处理JSON数据交换&#xff0c;并通过一个实战案例—…...

速卖通商品详情接口技术解析及Python代码示例

速卖通商品详情接口技术解析及Python代码示例 速卖通&#xff08;AliExpress&#xff09;作为全球知名的跨境电商平台&#xff0c;其开放平台提供了丰富的API接口&#xff0c;允许开发者集成速卖通的各项功能&#xff0c;实现商品搜索、详情查询、订单管理等一系列操作。本文将…...

邻接表的有向网(C语言代码)

#include <stdio.h> #include <stdlib.h> #define MVNum 100 //最大顶点数 //边表结构体 typedef struct ArcNode { //表结点 int adjvex; //邻接点的位置 struct ArcNode* nextarc; //指向下一个…...

大模型生成PPT大纲优化方案:基于 nVidia NIM 平台的递归结构化生成

大模型生成PPT大纲优化方案&#xff1a;基于 nVidia NIM 平台的递归结构化生成 待解决的问题 生成PPT大纲是一种大模型在办公场景下应用的常见需求。 然而&#xff1a; 目前直接让大模型生成大纲往往是非结构化的&#xff0c;输出格式多样&#xff0c;难以统一和规范&#…...

循环冗余码校验CRC码 算法步骤+详细实例计算

通信过程&#xff1a;&#xff08;白话解释&#xff09; 我们将原始待发送的消息称为 M M M&#xff0c;依据发送接收消息双方约定的生成多项式 G ( x ) G(x) G(x)&#xff08;意思就是 G &#xff08; x ) G&#xff08;x) G&#xff08;x) 是已知的&#xff09;&#xff0…...

STM32+rt-thread判断是否联网

一、根据NETDEV_FLAG_INTERNET_UP位判断 static bool is_conncected(void) {struct netdev *dev RT_NULL;dev netdev_get_first_by_flags(NETDEV_FLAG_INTERNET_UP);if (dev RT_NULL){printf("wait netdev internet up...");return false;}else{printf("loc…...

渗透实战PortSwigger靶场-XSS Lab 14:大多数标签和属性被阻止

<script>标签被拦截 我们需要把全部可用的 tag 和 event 进行暴力破解 XSS cheat sheet&#xff1a; https://portswigger.net/web-security/cross-site-scripting/cheat-sheet 通过爆破发现body可以用 再把全部 events 放进去爆破 这些 event 全部可用 <body onres…...

服务器硬防的应用场景都有哪些?

服务器硬防是指一种通过硬件设备层面的安全措施来防御服务器系统受到网络攻击的方式&#xff0c;避免服务器受到各种恶意攻击和网络威胁&#xff0c;那么&#xff0c;服务器硬防通常都会应用在哪些场景当中呢&#xff1f; 硬防服务器中一般会配备入侵检测系统和预防系统&#x…...

《用户共鸣指数(E)驱动品牌大模型种草:如何抢占大模型搜索结果情感高地》

在注意力分散、内容高度同质化的时代&#xff0c;情感连接已成为品牌破圈的关键通道。我们在服务大量品牌客户的过程中发现&#xff0c;消费者对内容的“有感”程度&#xff0c;正日益成为影响品牌传播效率与转化率的核心变量。在生成式AI驱动的内容生成与推荐环境中&#xff0…...

智能仓储的未来:自动化、AI与数据分析如何重塑物流中心

当仓库学会“思考”&#xff0c;物流的终极形态正在诞生 想象这样的场景&#xff1a; 凌晨3点&#xff0c;某物流中心灯火通明却空无一人。AGV机器人集群根据实时订单动态规划路径&#xff1b;AI视觉系统在0.1秒内扫描包裹信息&#xff1b;数字孪生平台正模拟次日峰值流量压力…...

【C++从零实现Json-Rpc框架】第六弹 —— 服务端模块划分

一、项目背景回顾 前五弹完成了Json-Rpc协议解析、请求处理、客户端调用等基础模块搭建。 本弹重点聚焦于服务端的模块划分与架构设计&#xff0c;提升代码结构的可维护性与扩展性。 二、服务端模块设计目标 高内聚低耦合&#xff1a;各模块职责清晰&#xff0c;便于独立开发…...

学习STC51单片机32(芯片为STC89C52RCRC)OLED显示屏2

每日一言 今天的每一份坚持&#xff0c;都是在为未来积攒底气。 案例&#xff1a;OLED显示一个A 这边观察到一个点&#xff0c;怎么雪花了就是都是乱七八糟的占满了屏幕。。 解释 &#xff1a; 如果代码里信号切换太快&#xff08;比如 SDA 刚变&#xff0c;SCL 立刻变&#…...

企业如何增强终端安全?

在数字化转型加速的今天&#xff0c;企业的业务运行越来越依赖于终端设备。从员工的笔记本电脑、智能手机&#xff0c;到工厂里的物联网设备、智能传感器&#xff0c;这些终端构成了企业与外部世界连接的 “神经末梢”。然而&#xff0c;随着远程办公的常态化和设备接入的爆炸式…...

【Veristand】Veristand环境安装教程-Linux RT / Windows

首先声明&#xff0c;此教程是针对Simulink编译模型并导入Veristand中编写的&#xff0c;同时需要注意的是老用户编译可能用的是Veristand Model Framework&#xff0c;那个是历史版本&#xff0c;且NI不会再维护&#xff0c;新版本编译支持为VeriStand Model Generation Suppo…...