核心框架类

/*
* Copyright 2011 Alibaba.com All right reserved. This software is the
* confidential and proprietary information of Alibaba.com ("Confidential
* Information"). You shall not disclose such Confidential Information and shall
* use it only in accordance with the terms of the license agreement you entered
* into with Alibaba.com.
*/
package com.alibaba.study.rpc.framework;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.net.ServerSocket;
import java.net.Socket;
/**
* RpcFramework
*
* @author william.liangf
*/
public class RpcFramework {
   /**
    * 暴露服务
    *
    * @param service 服务实现
    * @param port 服务端口
    * @throws Exception
    */
   public static void export(final Object service, int port) throws Exception {
       if (service == null)
           throw new IllegalArgumentException("service instance == null");
       if (port <= 0 || port > 65535)
           throw new IllegalArgumentException("Invalid port " + port);
       System.out.println("Export service " + service.getClass().getName() + " on port " + port);
       ServerSocket server = new ServerSocket(port);
       for(;;) {
           try {
               final Socket socket = server.accept();
               new Thread(new Runnable() {
                   @Override
                   public void run() {
                       try {
                           try {
                               ObjectInputStream input = new ObjectInputStream(socket.getInputStream());
                               try {
                                   String methodName = input.readUTF();
                                   Class<?>[] parameterTypes = (Class<?>[])input.readObject();
                                   Object[] arguments = (Object[])input.readObject();
                                   ObjectOutputStream output = new ObjectOutputStream(socket.getOutputStream());
                                   try {
                                       Method method = service.getClass().getMethod(methodName, parameterTypes);
                                       Object result = method.invoke(service, arguments);
                                       output.writeObject(result);
                                   } catch (Throwable t) {
                                       output.writeObject(t);
                                   } finally {
                                       output.close();
                                   }
                               } finally {
                                   input.close();
                               }
                           } finally {
                               socket.close();
                           }
                       } catch (Exception e) {
                           e.printStackTrace();
                       }
                   }
               }).start();
           } catch (Exception e) {
               e.printStackTrace();
           }
       }
   }
   /**
    * 引用服务
    *
    * @param <T> 接口泛型
    * @param interfaceClass 接口类型
    * @param host 服务器主机名
    * @param port 服务器端口
    * @return 远程服务
    * @throws Exception
    */
   @SuppressWarnings("unchecked")
   public static <T> T refer(final Class<T> interfaceClass, final String host, final int port) throws Exception {
       if (interfaceClass == null)
           throw new IllegalArgumentException("Interface class == null");
       if (! interfaceClass.isInterface())
           throw new IllegalArgumentException("The " + interfaceClass.getName() + " must be interface class!");
       if (host == null || host.length() == 0)
           throw new IllegalArgumentException("Host == null!");
       if (port <= 0 || port > 65535)
           throw new IllegalArgumentException("Invalid port " + port);
       System.out.println("Get remote service " + interfaceClass.getName() + " from server " + host + ":" + port);
       return (T) Proxy.newProxyInstance(interfaceClass.getClassLoader(), new Class<?>[] {interfaceClass}, new InvocationHandler() {
           public Object invoke(Object proxy, Method method, Object[] arguments) throws Throwable {
               Socket socket = new Socket(host, port);
               try {
                   ObjectOutputStream output = new ObjectOutputStream(socket.getOutputStream());
                   try {
                       output.writeUTF(method.getName());
                       output.writeObject(method.getParameterTypes());
                       output.writeObject(arguments);
                       ObjectInputStream input = new ObjectInputStream(socket.getInputStream());
                       try {
                           Object result = input.readObject();
                           if (result instanceof Throwable) {
                               throw (Throwable) result;
                           }
                           return result;
                       } finally {
                           input.close();
                       }
                   } finally {
                       output.close();
                   }
               } finally {
                   socket.close();
               }
           }
       });
   }
}

定义服务接口

/*
* Copyright 2011 Alibaba.com All right reserved. This software is the
* confidential and proprietary information of Alibaba.com ("Confidential
* Information"). You shall not disclose such Confidential Information and shall
* use it only in accordance with the terms of the license agreement you entered
* into with Alibaba.com.
*/
package com.alibaba.study.rpc.test;
/**
* HelloService
*
* @author william.liangf
*/
public interface HelloService {
   String hello(String name);
}

实现服务

/*
* Copyright 2011 Alibaba.com All right reserved. This software is the
* confidential and proprietary information of Alibaba.com ("Confidential
* Information"). You shall not disclose such Confidential Information and shall
* use it only in accordance with the terms of the license agreement you entered
* into with Alibaba.com.
*/
package com.alibaba.study.rpc.test;
/**
* HelloServiceImpl
*
* @author william.liangf
*/
public class HelloServiceImpl implements HelloService {
   public String hello(String name) {
       return "Hello " + name;
   }
}

暴露服务

/*
* Copyright 2011 Alibaba.com All right reserved. This software is the
* confidential and proprietary information of Alibaba.com ("Confidential
* Information"). You shall not disclose such Confidential Information and shall
* use it only in accordance with the terms of the license agreement you entered
* into with Alibaba.com.
*/
package com.alibaba.study.rpc.test;
import com.alibaba.study.rpc.framework.RpcFramework;
/**
* RpcProvider
*
* @author william.liangf
*/
public class RpcProvider {
   public static void main(String[] args) throws Exception {
       HelloService service = new HelloServiceImpl();
       RpcFramework.export(service, 1234);
   }
}

引用服务

/*
* Copyright 2011 Alibaba.com All right reserved. This software is the
* confidential and proprietary information of Alibaba.com ("Confidential
* Information"). You shall not disclose such Confidential Information and shall
* use it only in accordance with the terms of the license agreement you entered
* into with Alibaba.com.
*/
package com.alibaba.study.rpc.test;
import com.alibaba.study.rpc.framework.RpcFramework;
/**
* RpcConsumer
*
* @author william.liangf
*/
public class RpcConsumer {
   public static void main(String[] args) throws Exception {
       HelloService service = RpcFramework.refer(HelloService.class, "127.0.0.1", 1234);
       for (int i = 0; i < Integer.MAX_VALUE; i ++) {
           String hello = service.hello("World" + i);
           System.out.println(hello);
           Thread.sleep(1000);
       }
   }
}

总结

这个简单的例子的实现思路是使用阻塞的socket IO流来进行server和client的通信,也就是rpc应用中服务提供方和服务消费方。并且是端对端的,用端口号来直接进行通信。方法的远程调用使用的是jdk的动态代理,参数的序列化也是使用的最简单的objectStream。

真实的rpc框架会对上面的实现方式进行替换,采用更快更稳定,更高可用易扩展,更适宜分布式场景的中间件,技术来替换。例如使用netty的nio特性达到非阻塞的通信,使用zookeeper统一管理服务注册与发现,解决了端对端不灵活的劣势。代理方式有cglib字节码技术。序列化方式有hession2,fastjson等等。使用原生的jdk api就展现给各位读者一个生动形象的rpc demo,实在是强。rpc框架解决的不仅仅是技术层面的实现,还考虑到了rpc调用中的诸多问题,重试机制,超时配置…这些就需要去了解成熟的rpc框架是如果考虑这些问题的了。

推荐一个轻量级的rpc框架:motan。weibo团队在github开源的一个rpc框架,有相应的文档,用起来感觉比dubbo要轻量级,易上手。

简单了解RPC实现原理-copy的更多相关文章

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

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

  2. 分布式架构的基石.简单的 RPC 框架实现(JAVA)

    前言 RPC 的全称是 Remote Procedure Call,它是一种进程间通信方式.允许像调用本地服务一样调用远程服务. 学习来源:<分布式系统架构:原理与实践> - 李林锋 1. ...

  3. Java实现简单的RPC框架(美团面试)

    一.RPC简介 RPC,全称为Remote Procedure Call,即远程过程调用,它是一个计算机通信协议.它允许像调用本地服务一样调用远程服务.它可以有不同的实现方式.如RMI(远程方法调用) ...

  4. 如何实现一个简单的RPC

    在如何给老婆解释什么是RPC中,我们讨论了RPC的实现思路. 那么这一次,就让我们通过代码来实现一个简单的RPC吧! RPC的实现原理 正如上一讲所说,RPC主要是为了解决的两个问题: 解决分布式系统 ...

  5. 动手实现一个简单的 rpc 框架到入门 grpc (上)

    rpc 全称 Remote Procedure Call 远程过程调用,即调用远程方法.我们调用当前进程中的方法时很简单,但是想要调用不同进程,甚至不同主机.不同语言中的方法时就需要借助 rpc 来实 ...

  6. 徒手撸一个简单的RPC框架

    来源:https://juejin.im/post/5c4481a4f265da613438aec3 之前在牛逼哄哄的 RPC 框架,底层到底什么原理得知了RPC(远程过程调用)简单来说就是调用远程的 ...

  7. RPC通信原理概述

    RPC通信原理概述 1.RPC概述 1.什么是RPC RPC(Remote Procedure Call Protocol)远程过程调用协议.它是一种通过网络从远程计算机程序上请求服务,而不需要了解底 ...

  8. 聊聊RPC及其原理

    什么是RPC? RPC是Remote Procedure Call的缩写,想Client-Servier一样的远程过程调用,也就是调用远程服务就跟调用本地服务一样方便,一般用于将程序部署在不同的机器上 ...

  9. 自己用 Netty 实现一个简单的 RPC

    目录: 需求 设计 实现 创建 maven 项目,导入 Netty 4.1.16. 项目目录结构 设计接口 提供者相关实现 消费者相关实现 测试结果 总结 源码地址:github 地址 前言 众所周知 ...

  10. 最简单的RPC框架实现

    通过java原生的序列化,Socket通信,动态代理和反射机制,实现一个简单的RPC框架,由三部分组成: 1.服务提供者,运行再服务端,负责提供服务接口定义和服务实现类 2.服务发布者,运行再RPC服 ...

随机推荐

  1. Reviewbot 开源 | 为什么我们要打造自己的代码审查服务?

    Reviewbot 是七牛云开源的一个项目,旨在提供一个自托管的代码审查服务, 方便做 code review/静态检查, 以及自定义工程规范的落地. 静态检查不是个新鲜事. 我记得早在几年前,我们就 ...

  2. cmu15545-索引并发控制(Concurrent Indexes)

    目录 Overview Lock和Latch辨析 设计目标 大致分类 Hash Table Latches Page Latches Slot Latches B+Tree Latches 并发问题 ...

  3. pnpm 是如何颠覆 npm 和 yarn 的?

    今天研究了一下 pnpm 的机制,发现它确实很强大,甚至可以说对 yarn 和 npm 形成了降维打击 . 我们从包管理工具的发展历史,一起看下到底好在哪里? npm2 在 npm 3.0 版本之前, ...

  4. Goland破解之无限重置(最新)

    分享一下 JetBrains 全家桶 IDEA 2021.x 的激活破解教程,相当于永久激活 破解了,亲测有效,下面是详细文档哦~ JetBrains 全家桶 IDEA 2021.x 破解激活教程,相 ...

  5. Redis集群搭建-Docker

    使用docker搭建本地集群Redis服务(参考:https://www.cnblogs.com/slowbirdoflsh/p/11633113.html) 环境配置 # 拉取redis镜像 doc ...

  6. Coqui TTS合成语音

    工具介绍 Coqui TTS是一个用于语音转文本的高性能深度学习模型库.提供1100种语言的预训练模型,提供训练新模型和微调已有模型的工具,提供数据集分析工具.XTTS-v2版本支持16种语言: En ...

  7. moectf2023的一些题

    [moectf]GUI 这是一道win32窗口程序 找到线程的回调函数 sub_740C94这个函数里有很多函数,意义不明,实际并不会对输入的字符串做出改变 回调函数里下断点,然后单步动调 sub_7 ...

  8. OS之《内存管理》

    程序装入方式 绝对装入:程序逻辑地址和物理地址是完全对应的.不现实 可重定位装入:装入的时候重新 计算内存地址.程序中的实际地址加上程序载入的起始地址:但是解决不了进程挂起 后重新唤醒的问题.唤醒的后 ...

  9. Python中构建全局字典的详细指南

    在Python编程中,全局变量是指在整个程序运行期间都可以访问的变量.全局字典作为一种特殊的全局变量,可以存储各种类型的数据,包括字符串.数字.列表.元组等,这使得它在数据管理和跨模块通信方面非常有用 ...

  10. 【C#】【ffmpeg】外部调用线程执行ffmepg读取返回的信息乱码问题

    起因 C#使用FFmpeg获取电脑音视频可以用设备,当返回内容包含中文时,出现乱码问题 解决方案 ffmpeg本身的输出都是使用的错误输出,所以设置的是StandardErrorEncoding,如果 ...