1. 程式人生 > >模擬基本的RPC框架程式碼

模擬基本的RPC框架程式碼

最近晚上沒事,加上工作上要使用,所以開始自己學習RPC框架,目前寫了一個基本的,便於理解,後續往裡面新增內容。

**

服務提供方:

**

服務介面程式碼:

package zhm.rpc.server;

public interface IServer {
    public String testMethod(String arg);
}

介面實現類:

/**
 * rpcServerImpl.java
 * zhm.rpc.server
 * 2017年10月9日下午8:44:06
 *
 */
package zhm.rpc.server;

/**
 * @author
zhuheming * rpcServerImpl * 2017年10月9日下午8:44:06 */
public class rpcServerImpl implements IServer { /* (non-Javadoc) * @see zhm.rpc.server.IServer#testMethod(java.lang.String) */ @Override public String testMethod(String arg) { // TODO Auto-generated method stub return
"hello, "+arg; } }

反射類:
主要用於接收服務消費方發起的遠端呼叫請求,得到method和args,就是方法和引數,再利用反射方式執行該方法,返回執行結果。

這裡反射使用了commons.lang3包中的MethodUtils工具類實現。

/**
 * serverReflect.java
 * zhu.rpc.reflect
 * 2017年10月9日下午9:24:47
 *
 */
package zhu.rpc.reflect;

import java.io.IOException;
import java.io.ObjectInputStream;
import
java.io.ObjectOutputStream; import java.net.ServerSocket; import java.net.Socket; import org.apache.commons.lang3.reflect.MethodUtils; /** * @author zhuheming * serverReflect * 2017年10月9日下午9:24:47 */ public class ServerReflect implements Runnable{ private Object object; private int port; public ServerReflect(Object object,int port){ this.object=object; this.port=port; } /* (non-Javadoc) * @see java.lang.Runnable#run() */ @Override public void run() { // TODO Auto-generated method stub //新建連線 //SocketConnect sc=new SocketConnect(); //Socket socket=sc.connect("127.0.0.1", port); try { ServerSocket ss=new ServerSocket(port); while(true){ try { final Socket socket=ss.accept(); //建立輸入 ObjectInputStream ois=new ObjectInputStream(socket.getInputStream()); try{ //得到方法名和引數列表 String method=ois.readUTF(); Object[] args=(Object[])ois.readObject(); System.out.print(method+" "+args.toString()); //反射得到對應方法的執行結果 Object resultObject=MethodUtils.invokeExactMethod(object, method, args); ObjectOutputStream oos=new ObjectOutputStream(socket.getOutputStream()); try{ //返回結果 oos.writeObject(resultObject); }catch(Exception e){ oos.writeObject(e); e.printStackTrace(); }finally{ oos.close(); } } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); }finally{ ois.close(); } }catch(Exception e){ e.printStackTrace(); } } } catch (IOException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } } //private static Thread serverThread=new Thread(); //public void waittingServer(Class<T> serverClass,int port) }

測試入口:
省得麻煩,直接使用8081埠,用一個Thread來執行等待服務消費端的呼叫。

/**
 * test.java
 * zhm.rpc.test
 * 2017年10月9日下午10:18:33
 *
 */
package zhm.rpc.test;

import zhm.rpc.server.IServer;
import zhm.rpc.server.rpcServerImpl;
import zhu.rpc.reflect.ServerReflect;

/**
 * @author zhuheming
 * test
 * 2017年10月9日下午10:18:33
 */
public class testServer {
    public static void main(String args[]) throws InterruptedException{
        IServer is=new rpcServerImpl();
        Thread serverThread=new Thread(new ServerReflect(is,8081));
        serverThread.start();
        serverThread.join();
    }

}

**

服務消費方:

**

socket聯結器,這裡使用了一個連線介面IConnect,方便以後如果使用多種連線方式可以抽象

package zhm.rpc.connect;

import java.net.Socket;


/**
 * socket聯結器
 * @author zhuheming
 * socketConnet
 * 2017年9月28日下午11:29:24
 */
public class SocketConnect implements IConnect {

    @Override
    public Socket connect(String host, int port) {
        // TODO Auto-generated method stub
        //判斷輸入引數
        if(!"".equalsIgnoreCase(host)&&port!=0){
            Socket socket=null;
            try{
                socket=new Socket(host,port);

            }catch(Exception e){
                e.getStackTrace();
            }
            return socket;
        }else{
            return null;
        }

    }

    public void close(Object connectObject){
        if(connectObject!=null){
            try{
                Socket socket=(Socket)connectObject;
                socket.close();
            }catch(Exception e){
                e.getStackTrace();
            }
        }
    }


}

服務消費方的動態代理實現:
思路是將服務提供方的IServer介面生成動態代理類,使用動態代理類執行執行IServer的介面方法時,會呼叫invoke方法,在invoke方法中,遠端連線消費提供方,將方法名稱和引數傳送給服務提供方,由服務提供方返回執行結果。


/**
 * cosumeProxy.java
 * zhm.rpc.proxy
 * 2017年9月29日上午12:03:30
 *
 */
package zhm.rpc.proxy;

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.Socket;

import zhm.rpc.connect.SocketConnect;

/**
 * @author zhuheming
 * cosumeProxy
 * 2017年9月29日上午12:03:30
 */
public class ConsumeProxy {
    //匿名內部類方法實現需要呼叫,所以host和port需要為final
    @SuppressWarnings("unchecked")
    public static <T> T consume(Class<T> interfaceClass,final String host,final int port){

        //先建立一個InvocationHandler介面的物件(實現內部方法)
        //InvocationHandler invocationHandler=;

        return (T) Proxy.newProxyInstance(interfaceClass.getClassLoader(), new Class<?>[]{interfaceClass},new InvocationHandler(){

            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable{
                //建立連線
                SocketConnect sc=new SocketConnect();
                Socket socket=sc.connect(host, port);
                //傳送方法和引數
                ObjectOutputStream ops=new ObjectOutputStream(socket.getOutputStream());
                ops.writeUTF(method.getName());
                ops.writeObject(args);
                //接收返回
                ObjectInputStream ois=new ObjectInputStream(socket.getInputStream());
                Object getObject=ois.readObject();
                return getObject;
            }
    });
        //return null;

    }
}

服務提供方給的服務介面
注意,實現是在服務提供方,消費方只有介面

package zhm.rpc.server;

public interface IServer {
    public String testMethod(String arg);
}

服務消費方入口:

先生成代理類,再遠端執行方法。

package zhm.rpc.test;

import zhm.rpc.proxy.ConsumeProxy;
import zhm.rpc.server.IServer;

public class Test {

    //遠端呼叫服務端的testMethod方法,客戶端只有介面,沒有方法實現。
    public static void main(String args[]) throws InterruptedException{
        Object obj= ConsumeProxy.consume(IServer.class, "127.0.0.1", 8081);
        if(obj!=null){
            System.out.println(obj.getClass().getInterfaces().toString());
            //System.out.println(obj.toString());
            System.out.println("not null!");
        }else{
            System.out.println("null!");
        }
        IServer rpc=(IServer)obj;

        for(int i=0;i<100;i++){

            System.out.println(rpc.testMethod(""+i));
            Thread.sleep(1000);
        }
    }

}

好了,以上就是最簡單的RPC遠端執行框架,要想豐滿起來,後續還要考慮很多,如自己實現序列化反序列化,軟負載均衡,高可用NIO通訊方式,服務的解耦合IOC方式,以及服務治理,類似zk的服務釋出等。

繼續努力吧。

相關推薦

模擬基本RPC框架程式碼

最近晚上沒事,加上工作上要使用,所以開始自己學習RPC框架,目前寫了一個基本的,便於理解,後續往裡面新增內容。 ** 服務提供方: ** 服務介面程式碼: package zhm.rpc.server; public interface IS

基於ns3的LTE模擬基本架構程式碼

#include <ns3/core-module.h> #include <ns3/network-module.h> #include <ns3/mobility-module.h> #include <ns3/lte-modu

RPC框架幾行程式碼就夠了

大牛 樑飛 阿里  我僅僅只是copy了一次   反射、代理、socket package com.kinsey.woo.rpc.study; public interface HelloService { public String hello(String nam

RPC框架效能基本比較測試

Wildfly是JBossAS改名後的JBoss應用伺服器,實現了完整的JavaEE規範。我們知道JavaEE中遠端RPC呼叫是在EJB規範中定義的。我們這裡就是要測試Wildlfy中的遠端EJB呼叫能力, 選用的Wildfly8.2是目前釋出的最新穩定版本。這個版本也支援埠多路服用,也就是EJB遠端呼叫是

一起寫RPC框架(十五)RPC註冊中心二--註冊中心的基本實現

註冊中心的實現方式有很多種,實現的方式也有難有易,可以使用zookeeper,consul這些第三方已有的包去幫助實現,這樣可以減少開發註冊中心的難度,卻可能加大運維的難度,當然最最原始的方法就是使用java去實現,不借助其他任何已有的第三方包去搞定,這樣做的好處其實並不明

手寫RPC框架指北另送貼心註釋程式碼一套

Angular8正式釋出了,Java13再過幾個月也要釋出了,技術迭代這麼快,框架的複雜度越來越大,但是原理是基本不變的。所以沉下心看清程式碼本質很重要,這次給大家帶來的是手寫RPC框架。 完整程式碼以及說明文件,點我跳躍~ 1. 什麼是RPC? RPC是指遠端過程呼叫,也就是說兩臺伺服器A,B,一個應用部署

GRPC 1.3.4 發布,Google 高性能 RPC 框架(Java C++ Go)

框架 9.png 高性能 修復 git ogl arch bsp 版本 GRPC 1.3.4 發布了,GRPC 是一個高性能、開源、通用的 RPC 框架,面向移動和 HTTP/2 設計,是由谷歌發布的首款基於 Protocol Buffers 的 RPC 框架。 GRPC

RPC框架研究(二)Hadoop源代碼-1

trac 挑戰 b2c ott 技術分享 style dsm mod spa 報名了阿裏中間件性能大賽,我來說是一個全新的挑戰。一切從空白學起,比賽的過程也是學習的過程 是的。想讓自己學好。給自己報一個比賽吧~ 就像當初學圍棋,也是報了圍棋比賽,為

RPC框架與分布式服務框架的區別

rpc第一:RPC框架是點對點的通信方式,即服務消費者與服務提供者是點對點通信第二;分布式服務框架,不近具有RPC框架的特性,同時,還包括以下特性: 1、提供多臺服務器提供服務,具有負載均衡策略 2、服務自動註冊,發布 3、具有服務的治理 。。。。。。。本文出自 “XEJ分布式工作室”

穩定性 耗時 監控原因分析-- dubbo rpc 框架 的線程池,io 連接模型. 客戶端,服務端

情況 現在 src tcp協議 時間 .cn 關系 1.0 繼續 上次 提到的Nagle算法特性有可能是dubbo調用”網絡耗時高“的始作俑者,後來又仔細看了下dubbo的代碼,發現dubbo在consumer端已經將tcp設置成非延遲(即關閉Nag

Netty自娛自樂之類Dubbo RPC 框架設計構想 【上篇】

哈哈 ebe cte proc 文件 num one lex round   之前在前一篇的《Netty自娛自樂之協議棧設計》,菜鳥我已經自娛自樂了設計協議棧,gitHub地址為https://github.com/vOoT/ncustomer-protocal。先這一篇中

簡易RPC框架-私有協議棧

rem nowrap adding document list highlight fine repl alt HTTP協議 客戶機與服務端之間的數據交互需要遵守一定的約定,比如協議版本,數據類型,是否有緩存,是否有壓縮等,只有在這些約定的基礎上才能相互之間愉快的

簡易RPC框架-心跳與重連機制

依賴 tile tegra port public row edi cat ice 心跳 就是告訴其它人自己還活著。在簡易RPC框架中,采用的是TCP長連接,為了確保長連接有效,就需要客戶端與服務端之間有一種通知機制告知對方的存活狀態。 如何實現 客戶端發

簡易RPC框架-過濾器機制

sym vbo else on() alias dcb nac urb min 過濾器 字面義上理解的過濾器類似下圖,從一堆物品中篩選出符合條件的留下,不符合的丟棄。 GOF 職責鏈 GOF中有一種設計模式叫職責鏈,或者叫責任鏈,常規的UML圖如下:

一個簡單的基於BIO的RPC框架

簡單的 png 1-1 -s github 幫助 spa 兩個類 還需 github地址:https://github.com/Luyu05/BioRpcExample PART1:先來整體看下項目的構成 其中bio-rpc-core就是所謂的rpc框架 bio-rp

JAVA中幾種常用的RPC框架介紹

github 不同的 target int https love num 分布 有一個 RPC是遠程過程調用的簡稱,廣泛應用在大規模分布式應用中,作用是有助於系統的垂直拆分,使系統更易拓展。Java中的RPC框架比較多,各有特色,廣泛使用的有RMI、Hessian、Du

基於Spring開發的一個BIO-RPC框架(對小白很友好)

instance 啟動項 jar包 pan 發現 就是 遠程 map 配置 PART1:先來整體看下項目的構成 其中bio-rpc-core就是所謂的rpc框架 bio-rpc-example-client即所謂的服務調用方(你的項目中想要調用服務的地方) bio-rp

輕量級分布式 RPC 框架

rap 系統 內容 oot fio del scan ans iteye RPC,即 Remote Procedure Call(遠程過程調用),說得通俗一點就是:調用遠程計算機上的服務,就像調用本地服務一樣。 RPC 可基於 HTTP 或 TCP 協議,Web Servi

Hadoop RPC框架

階段 none order 網絡異常 mat pro resp 邏輯 實現原理 1、RPC框架概述 1.1 RPC(Remote Procedure Call

三百行代碼完成一個簡單的rpc框架

rpc dubbo demo 花了半天的時間寫了個簡單的rpc框架,是因為我最初看dubbo源碼的時候發現dubbo雖然看起來很龐大,但是隱隱約約總感覺,其實其絕大多數功能,都是基於可擴張性和服務治理的需要而編寫的。我看過dubbo和grpc的源碼,這兩個都是非常優秀的rpc框架,但是為了讓初學r