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

开平 做一网站北京最新新闻报道

开平 做一网站,北京最新新闻报道,百度创建网站吗,wordpress同步空间目录 RPC通信的基本原理 RPC结构 手撸简陋版RPC 知识点梳理 1.Socket套接字通信机制 2.通信过程的序列化与反序列化 3.动态代理 4.反射 思维流程梳理 码起来 服务端时序图 服务端—Api与Provider模块 客户端时序图 RPC通信的基本原理 RPC#xff08;Remote Proc…目录 RPC通信的基本原理 RPC结构 手撸简陋版RPC 知识点梳理 1.Socket套接字通信机制 2.通信过程的序列化与反序列化 3.动态代理 4.反射 思维流程梳理 码起来 服务端时序图 服务端—Api与Provider模块 客户端时序图 RPC通信的基本原理 RPCRemote Procedure Call是一种远程过程调用协议用于在分布式系统中进行远程通信允许一个计算机程序调用另一个地址空间通常是在不同的机器上的函数或过程就像调用本地函数一样。下面是RPC通信的基本原理 客户端调用远程客户端调用方希望调用远程服务器提供方上的一个或多个远程过程函数。客户端在本地创建一个请求并指定要调用的远程过程的名称以及传递给该过程的参数。 参数序列化在将请求发送到远程服务器之前客户端需要将参数序列化为字节流或其他适合传输的格式。序列化是将数据转换为可以在网络上传输的形式的过程。 网络传输客户端通过网络将请求发送到远程服务器。通常这涉及到将请求数据打包成网络消息然后通过网络协议如HTTP、TCP/IP将消息发送到服务器的地址。 服务器接收远程服务器接收到客户端的请求消息通常通过网络协议如HTTP服务器、Socket服务器监听特定的端口。 参数反序列化服务器从请求消息中提取参数数据并将其反序列化为本地数据结构以便将其传递给远程过程。 远程过程调用服务器调用相应的远程过程将参数传递给该过程并执行相应的操作。远程过程可以位于服务器的本地代码中或远程服务器上的远程服务中。 结果序列化远程过程执行完毕后服务器将结果序列化为字节流或其他适合传输的格式。 结果传输服务器通过网络将结果数据打包成响应消息并将其发送回客户端。 客户端接收客户端接收到服务器的响应消息。 结果反序列化客户端从响应消息中提取结果数据并将其反序列化为本地数据结构。 客户端处理客户端可以根据远程过程的执行结果采取相应的行动可能是继续执行本地代码或返回结果给调用方。 通信完成一次RPC调用完成后客户端和服务器之间的通信过程结束。 RPC结构 客户端模块代理所有远程方法的调用 将目标服务、目标方法、调用目标方法的参数等必要信息序列化 序列化之后的数据包进一步压缩压缩后的数据包通过网络通信传输到目标服务节点 服务节点将接受到的数据包进行解压 解压后的数据包反序列化成目标服务、目标方法、目标方法的调用参数 通过服务端代理调用目标方法获取结果结果同样需要序列化、压缩然后回传给客户端 手撸简陋版RPC 总觉得文字描述太干了有点咽不下去还是手撸下试试吧。毕竟艾瑞莉娅的奶奶总说 纸上得来终觉浅绝知此事要躬行。 知识点梳理 1.Socket套接字通信机制 在Java中Socket是用于网络通信的基础类之一它提供了一种机制通过该机制计算机程序可以在网络上建立连接、发送数据、接收数据和关闭连接。 服务器套接字ServerSocket 服务器套接字用于在服务器端监听并接受客户端的连接请求。 使用以下步骤创建和使用服务器套接字 创建ServerSocket对象并绑定到一个特定的端口号。 使用ServerSocket对象的accept()方法来等待客户端的连接请求并接受连接。 一旦接受连接可以创建新的Socket对象来处理客户端的通信。 完成通信后关闭Socket和ServerSocket连接。 ServerSocket serverSocket new ServerSocket(port_number); Socket clientSocket serverSocket.accept(); // 等待连接 InputStream inputStream clientSocket.getInputStream(); OutputStream outputStream clientSocket.getOutputStream(); // 使用输入流和输出流进行数据读写 clientSocket.close(); serverSocket.close(); ​ 客户端套接字Socket 客户端套接字用于连接到远程服务器发送请求并接收响应。 使用以下步骤创建和使用客户端套接字 创建Socket对象指定远程服务器的主机名或IP地址以及端口号。 使用Socket对象的输入流和输出流来进行数据的读取和写入。 完成通信后关闭Socket连接。 Socket socket new Socket(server_hostname, port_number); InputStream inputStream socket.getInputStream(); OutputStream outputStream socket.getOutputStream(); // 使用输入流和输出流进行数据读写 socket.close(); 2.通信过程的序列化与反序列化 在Java中通过 JDK 提供了 Java 对象的序列化方式实现对象序列化传输主要通过输出流java.io.ObjectOutputStream和输入流java.io.ObjectInputStream来实现 java.io.ObjectOutputStream表示对象输出流 , 它的 writeObject(Object obj)方法可以对参数指定的 obj 对象进行序列化把得到的字节序列写到一个目标输出流中 java.io.ObjectInputStream表示对象输入流 ,它的 readObject()方法源输入流中读取字节序列再把它们反序列化成为一个对象并将其返回 3.动态代理 动态代理是在运行时动态生成代理类的方式。Java提供了java.lang.reflect.Proxy类和java.lang.reflect.InvocationHandler接口来实现动态代理。JDK中提供了基于接口动态代理的方法 // 创建代理对象MyInterface proxyObject (MyInterface) Proxy.newProxyInstance(MyInterface.class.getClassLoader(),new Class[]{MyInterface.class},new MyInvocationHandler(realObject)); 使用动态代理的目的 透明远程调用 动态代理可以隐藏底层的远程调用细节使得远程过程调用看起来像本地方法调用一样简单。客户端无需关心网络通信、数据序列化和反序列化等细节因为这些都由代理对象处理。 减少重复性代码 使用动态代理可以减少编写和维护远程调用代码的工作量。代理类负责处理通用的远程调用逻辑开发者只需关注具体的业务逻辑。 集中管理远程调用逻辑 动态代理将远程调用逻辑集中在一个地方这样可以更容易地管理和维护例如添加统一的错误处理、日志记录或性能监控等功能。 4.反射 在RPCRemote Procedure Call远程过程调用中使用反射的主要目的是实现透明的远程调用即使在客户端和服务器之间存在远程分离也可以像调用本地方法一样调用远程服务。反射在RPC中的具体目的和用途如下 动态代理生成代理对象 反射机制允许在运行时生成代理对象这些代理对象可以代替实际的远程服务对象执行方法调用。这样客户端代码不需要提前知道要调用的具体远程方法和对象而可以动态生成代理并执行方法。 动态识别方法和参数 反射允许在运行时识别远程方法和方法参数的名称、类型和数量。这对于将方法调用信息打包成请求并传递给远程服务器非常有用服务器可以根据这些信息正确地解析请求并调用相应的方法。 动态序列化和反序列化 反射可以用于动态地序列化请求和响应数据。在RPC中请求和响应数据通常需要以某种格式进行序列化和反序列化以便在网络上进行传输。反射可以帮助动态识别数据类型将数据转换为适当的格式并在服务器端进行反序列化。 思维流程梳理 码起来 假设需求是客户端想要访问服务端(ip:prot/helloService/sayHello)上的helloService调用sayHello()。先定义服务端的实现。 服务端时序图 服务端—Api与Provider模块 服务端作为服务提供者自然需要具备常规的业务模块Api与Provider模块 Api模块定义简单的HelloService接口包含两个方法sayHello(String content)和saveUSer(User user) public interface IHelloService {String sayHello(String content);String saveUSer(User user); } 定义一个简单对象User类 public class User {private String name;private int age; ​// getter和setterpublic String getName() {return name;} ​public void setName(String name) {this.name name;} ​public int getAge() {return age;} ​public void setAge(int age) {this.age age;} ​Overridepublic String toString() {return User{ name name \ , age age };} } Provider模块定义HelloService接口的实现类HelloServiceImplrpc-server-provider模块的pom中需要添加rpc-server-api模块的依赖 public class HelloServiceImpl implements IHelloService {Overridepublic String sayHello(String content) {System.out.println(request in sayHello: content);return Say hello: content;} ​Overridepublic String saveUSer(User user) {System.out.println(request in saveUser: user);return Save user success;} } 定义RpcServerProxy通过代理的方式使用Socket对外暴露服务接口 public class RpcServerProxy {private ExecutorService executorService Executors.newCachedThreadPool(); ​public void publisher(Object service, int port) {ServerSocket serverSocket null;try {serverSocket new ServerSocket(port);while (true) {Socket socket serverSocket.accept(); // 使用accept()等待客户端连接接收请求executorService.execute(new ProcessorHandler(socket, service)); // 每一个socket交给一个processorHandler处理}} catch (IOException e) {e.printStackTrace();} finally {// 关闭资源,jdk1.7后提供了try-with可以自动关闭if (serverSocket ! null) {try {serverSocket.close();} catch (IOException e) {e.printStackTrace();}}}} } 需要定义一个线程ProcessorHandler对每次的socket请求进行处理 public class ProcessorHandler implements Runnable{ ​private Socket socket;private Object service; ​public ProcessorHandler(Socket socket, Object service) {this.socket socket;this.service service;} ​ ​Overridepublic void run() {// 使用ObjectOutputStream和ObjectInputStream配合socket的输入流输出流进行序列化和反序列化ObjectOutputStream objectOutputStream null;ObjectInputStream objectInputStream null;try {objectInputStream new ObjectInputStream(socket.getInputStream()); ​// 客户端传过来的信息请求哪个类哪个方法方法的参数 —— 封装为RpcRequest类RpcRequest rpcRequest (RpcRequest) objectInputStream.readObject(); // 拿到客户端通信传递的请求类Object result invoke(rpcRequest); // 反射调用本地服务 ​objectOutputStream new ObjectOutputStream(socket.getOutputStream());objectOutputStream.writeObject(result);objectOutputStream.flush(); // 手动将缓冲区中的数据强制刷新到输出流中以确保数据被立即写入底层的输出流。 ​} catch (IOException e) {e.printStackTrace();} catch (ClassNotFoundException e) {e.printStackTrace();} catch (InvocationTargetException e) {e.printStackTrace();} catch (NoSuchMethodException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();} finally {// 关闭关联资源,jdk1.7后提供了try-with可以自动关闭if (objectInputStream ! null) {try {objectInputStream.close();} catch (IOException e) {throw new RuntimeException(e);}}if (objectOutputStream ! null) {try {objectOutputStream.close();} catch (IOException e) {throw new RuntimeException(e);}}}} ​private Object invoke(RpcRequest rpcRequest) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {// 反射调用Object[] args rpcRequest.getParameters(); // 获取客户端传递的RpcRequest中的参数Class?[] types new Class[args.length]; // 获得每个参数的类型for (int i 0; i args.length; i) {types[i] args.getClass();}Class clazz Class.forName(rpcRequest.getClassName()); // 根据请求的类名反射加载类Method method clazz.getMethod(rpcRequest.getMethodName(), types); // 获取类中的方法Object result method.invoke(service, args); // 进行反射调用方法return result;} } 定义一个通用的RpcRequest类参与通信过程中的请求处理这里是需要序列化的 public class RpcRequest implements Serializable {private String className;private String methodName;private Object[] parameters;// getter and setterpublic String getClassName() {return className;} ​public void setClassName(String className) {this.className className;} ​public String getMethodName() {return methodName;} ​public void setMethodName(String methodName) {this.methodName methodName;} ​public Object[] getParameters() {return parameters;} ​public void setParameters(Object[] parameters) {this.parameters parameters;} } Provider的app中发布下服务运行没有报错服务端OK public class App {public static void main( String[] args ){IHelloService helloService new HelloServiceImpl();RpcServerProxy rpcServerProxy new RpcServerProxy();rpcServerProxy.publisher(helloService, 8080); // 把服务发布出去} } 客户端时序图 定义动态代理RpcClientProxyJDK的接口代理方式就是一句话 public class RpcClientProxy {public T T clientProxy(final ClassT interfaceCls, final String host, final int port) {return (T) Proxy.newProxyInstance(interfaceCls.getClassLoader(), new Class?[]{interfaceCls}, new RemoteInvocationHandler(host, port));} } 定义被代理接口RemoteInvocationHandler public class RemoteInvocationHandler implements InvocationHandler {private String host;private int port; ​public RemoteInvocationHandler(String host, int port) {this.host host;this.port port;} ​Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {// 客户端请求会进入这里进行包装RpcRequest rpcRequest new RpcRequest();rpcRequest.setClassName(method.getDeclaringClass().getName());rpcRequest.setMethodName(method.getName());rpcRequest.setParameters(args);// 远程通信交给RpcNetTransportRpcNetTransport rpcNetTransport new RpcNetTransport(host, port);Object result rpcNetTransport.send(rpcRequest);return result;} } 定义通信传输类RpcNetTransport public class RpcNetTransport {private String host;private int port; ​public RpcNetTransport(String host, int port) {this.host host;this.port port;} ​public Object send(RpcRequest rpcRequest) {Socket socket null;Object result null;ObjectInputStream objectInputStream null;ObjectOutputStream objectOutputStream null;try {socket new Socket(host, port); // 建立连接 ​objectOutputStream new ObjectOutputStream(socket.getOutputStream()); // 客户端通信写入objectOutputStream.writeObject(rpcRequest);objectOutputStream.flush(); ​objectInputStream new ObjectInputStream(socket.getInputStream()); // 客户端通信输出result objectInputStream.readObject();return result;} catch (UnknownHostException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();} catch (ClassNotFoundException e) {e.printStackTrace();} finally {// 关闭关联资源if (objectInputStream ! null) {try {objectInputStream.close();} catch (IOException e) {throw new RuntimeException(e);}}if (objectOutputStream ! null) {try {objectOutputStream.close();} catch (IOException e) {throw new RuntimeException(e);}}}return result;} } 客户端请求远程服务 public class App {public static void main( String[] args ){RpcClientProxy rpcClientProxy new RpcClientProxy();IHelloService helloService rpcClientProxy.clientProxy(IHelloService.class, localhost, 8080);String result helloService.sayHello(Elaine);System.out.println(result);} } 请求成功客户端获得返回结果 服务端打印了请求日志 到这里一个简陋且粗糙的RPC通信版本就好了。 别灰心要记住艾瑞莉娅的奶奶总说 路漫漫其修选兮吾将上下而求索。
http://www.huolong8.cn/news/20033/

相关文章:

  • 小说网站建设方案书ppt网页界面制作步骤
  • dw 做的网站能用吗html网页框架
  • 书城网站开发的参考文献科技布沙发清洗
  • 成都网站建制作三亚做网站
  • 用淘宝域名做网站什么效果兰州营销型网站建设
  • 网站突然被降权怎么办机器人网站建设
  • wordpress源码书籍seo优化技术是什么
  • 网站任务界面中国核工业集团2024校园招聘
  • 百度推广网站备案画画在线
  • 网站swf怎么做做微信活动是做网站还是做小程序好
  • python做网站源码个人网站可以做商业吗
  • 网站备案资质商城网站后台模板
  • 深圳网站设计公司让您放心省心宁波招聘网站开发
  • wordpress 全站404制作网页最简单的软件
  • 嘉兴秀洲区建设局网站wordpress 菜单 锚点
  • 企业网站建设方案价格德国 网站 后缀
  • 网站推广上首页四川省安全社区建设网站
  • 菏泽市城乡和建设局网站网页设计公司排名前十
  • 龙拓网站建设小说网站开发的目的
  • 网站开发前端后端书籍自动更新wordpress失败
  • 建筑智库免费网站企业营销网站模板免费下载
  • 做一个网站要注意什么东西兰州做门户网站
  • 优秀网站设计案例分析拼多多跨境电商平台
  • 重庆网站制作团队网站上线过程
  • 小说网站建设之前需求分析做网站平台公司哪家好
  • 怎么选择优秀的网站建设公司网站开发做什么的
  • dede 网站内页标题修改网站建设外包发展情况
  • 长沙网站建设建无锡市建设安全监督网站
  • 深圳网站seo设计浦口网站建设
  • 科技网站实例wordpress themememe wpex