【Java】java實現的遠端呼叫例子 rpc原理
當今分散式應用盛行,rpc框架也就隨之出現,今天用java寫一個小的demo。
首先看一下什麼事遠端呼叫
遠端呼叫涉及到了網路io,基本過程是客戶端向服務端傳送訊息,表明自己要呼叫的方法的名字以及包含的引數,然後服務端呼叫函式,再向客戶端返回結果。所以涉及了兩次網路io。
這樣的話,客戶端的程式碼寫起來比較費勁,每一個方法底層都是網路io,但是過程都是一樣的,傳遞引數,得到結果,所以這裡肯定可以優化,比如在java中可以使用動態代理機制。只需要使用一個服務端的介面類就,讓Proxy動態生成一個代理類。服務端就是一個socket的常規伺服器,可以使用執行緒池或者多路複用這樣的技術,然後通過反射來呼叫實際類。還有註冊服務的功能,所謂註冊就是讓介面和真正的實現類對接,最後就可以呼叫到實現類的方法。
所以遠端呼叫其實就是網路io,在客戶端和服務端下面都有訊息的封裝和解析,以及網路io。
下面是一個簡單的例子:
介面
public interface HelloService{
public String hello(String name);
}
實現類:
public class HelloServiceImpl implements HelloService{
@Override
public String hello(String name) {
return "Hello, " + name;
}
}
sever:
public class RPCServer { private ExecutorService threadPool; private static final int DEFAULT_THREAD_NUM = 10; public RPCServer(){ threadPool = Executors.newFixedThreadPool(DEFAULT_THREAD_NUM); } public void register(Object service, int port){ try { System.out.println("server starts..."); ServerSocket server = new ServerSocket(port); Socket socket = null; while((socket = server.accept()) != null){ System.out.println("client connected..."); threadPool.execute(new Processor(socket, service)); } } catch (IOException e) { e.printStackTrace(); } } class Processor implements Runnable{ Socket socket; Object service; public Processor(Socket socket, Object service){ this.socket = socket; this.service = service; } public void process(){ } @Override public void run() { try { ObjectInputStream in = new ObjectInputStream(socket.getInputStream()); String methodName = in.readUTF(); Class<?>[] parameterTypes = (Class<?>[]) in.readObject(); Object[] parameters = (Object[]) in.readObject(); Method method = service.getClass().getMethod(methodName, parameterTypes); try { Object result = method.invoke(service, parameters); ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream()); out.writeObject(result); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } } catch (IOException e) { e.printStackTrace(); } catch (NoSuchMethodException e) { e.printStackTrace(); } catch (SecurityException e) { e.printStackTrace(); } catch (ClassNotFoundException e1) { e1.printStackTrace(); } } } }
啟動:
public class Main {
public static void main(String args[]){
HelloService helloService = new HelloServiceImpl();
RPCServer server = new RPCServer();
server.register(helloService, 50001);
}
}
客戶端:
public class RPCClient { public static void main(String args[]){ HelloService helloService = getClient(HelloService.class, "127.0.0.1", 50001); System.out.println(helloService.hello("liyao1")); } @SuppressWarnings("unchecked") public static <T> T getClient(Class<T> clazz, String ip, int port){ return (T) Proxy.newProxyInstance(RPCClient.class.getClassLoader(), new Class<?>[]{clazz}, new InvocationHandler() { @Override public Object invoke(Object arg0, Method arg1, Object[] arg2) throws Throwable { Socket socket = new Socket(ip, port); ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream()); out.writeUTF(arg1.getName()); out.writeObject(arg1.getParameterTypes()); out.writeObject(arg2); ObjectInputStream in = new ObjectInputStream(socket.getInputStream()); return in.readObject(); } }); } }
這就是遠端呼叫的一個小例子。
可以看到,隨便實現一個僅僅是返回字串的邏輯都是如此的複雜,反射,動態代理,網路io,訊息解析等等。。。頭疼。。。。
那麼什麼是rpc呢?既然是框架,那麼必然是幫我們做了一下上面的事情的。rpc幫助我們生成了客戶端和服務端的訊息和io等公共的程式碼,這樣客戶端可以直接呼叫代理類的方法,感知不到遠端呼叫,服務端也只需要註冊服務即可,也就是上面的io,反射,代理等等複雜的程式碼rpc框架都給我們生成了。
使用了rpc框架,我們只需要定義一個介面,然後讓rpc框架為我們生成客戶端的代理類,同時生成服務端的serversocket類,我們只需要在服務端編寫真正的實現類,然後註冊在伺服器上就可以。其餘的事情都是框架做的。
再說一遍,我們只需要:
(1)定義介面;
(2)用介面生成服務端和客戶端代理的程式碼;
(3)編寫介面實現;
(4)註冊服務;
這下是不是簡單了很多,這就是rpc框架的魅力。
下一節我會給出一個thrift的小例子,就可以感受使用框架的便捷。
相關推薦
【Java】java實現的遠端呼叫例子 rpc原理
當今分散式應用盛行,rpc框架也就隨之出現,今天用java寫一個小的demo。 首先看一下什麼事遠端呼叫 遠端呼叫涉及到了網路io,基本過程是客戶端向服務端傳送訊息,表明自己要呼叫的方法的名字以及包含的引數,然後服務端呼叫函式,再向客戶端返回結果。所以涉及了兩次網路io。
【opencv】Java實現的opencv3.x版本後Highhui報錯
-a sun div fan let 版本 ava line 報錯 隨筆為博主原創,如需轉載,請註明出處。 opencv3.x以後Highgui不再使用,用Imgcodecs代替,引入import org.opencv.imgcodecs.Imgcode
【轉】Java並發編程:Synchronized及其實現原理
st2 等待 OS threads img 參考 使用 leg ble 一、Synchronized的基本使用 Synchronized是Java中解決並發問題的一種最常用的方法,也是最簡單的一種方法。Synchronized的作用主要有三個:(1)確保線程互斥的
【Thumbnailator】java 使用Thumbnailator實現等比例縮放圖片,旋轉圖片等【轉載】
strong class chm eight load angle true api ins Thumbnailator概述: Thumbnailator是與Java界面流暢的縮略圖生成庫。它簡化了通過提供一個API允許精細的縮略圖生成調整生產從現有的圖
【java】簡單實現數據庫連接池
zed cal lean jdbc stat eof LEDE import thread 一直在想java事務是怎麽實現的,在原聲jdbc的時候級別下,我們可以通過關掉autocommit 然後再手動commit。但是項目開發中基本上是看不見conection的。所以自己
【轉】Java學習---快速掌握RPC原理及實現
消費者 阿裏 局限 kryo nes 很多 cal 網絡 href 【原文】https://www.toutiao.com/i6592365493435236872/ ?RPC概述 RPC(Remote Procedure Call)即遠程過程調用,也就是說兩臺服務器A,
【License】java簡單實現license認證-DES
長度 none value ber license過期 println his 加密解密 否則 思路 在config文件中配置一個變量,license。 license中包括該license允許的截止日期,使用DES算法進行加密 在用戶登錄時,讀取該license,並對l
【Java】使用IDEA遠端除錯Java程式碼 【Java】Maven Tomcat外掛使用
概述 服務端程式執行在一臺遠端伺服器上,我們可以在本地服務端的程式碼(前提是本地的程式碼必須和遠端伺服器執行的程式碼一致)中設定斷點,每當有請求到遠端伺服器時時能夠在本地知道遠端服務端的此時的內部狀態 測試專案 建立方式參考:【Java】Maven Tomcat外掛使用 專案中新增了一個測
【雜談】Java I/O的底層實現
硬盤 字節數 lower jni 處理 裝飾器模式 eight dma 字節數組 前言 Java I/O功能封裝的很好,使用起來很方便,就是剛開始學的時候,如果不了解裝飾器模式,會被他繁多的類給嚇到。用多了也就習慣了,而且現在有很多實用的封裝良好的實用類,可直接讀寫整個
【Elasticsearch】Java Client連線池程式碼實現
用過Elasticsearch API的都知道,在Java端使用是ES服務需要建立Java Client,但是每一次連線都例項化一個client,對系統的消耗很大,而且最令人頭疼的是它的連線非常慢。所以為了解決上述問題並提高client利用率,用池化技術複用client,第一次用去建立cli
【轉】Java併發問題--樂觀鎖與悲觀鎖以及樂觀鎖的一種實現方式-CAS
首先介紹一些樂觀鎖與悲觀鎖: 悲觀鎖:總是假設最壞的情況,每次去拿資料的時候都認為別人會修改,所以每次在拿資料的時候都會上鎖,這樣別人想拿這個資料就會阻塞直到它拿到鎖。傳統的關係型資料庫裡邊就用到了很多這種鎖機制,比如行鎖,表鎖等,讀鎖,寫鎖等,都是在做操作之前先上
【十】Java設計模式GOF23之介面卡模式(類方式實現、物件方式實現)
目錄 Target.java package com.bjsxt.adapter; /** * @author liyijie * @date 2016年8月12日下午4:13:21 *
【Java】sql實現插入,插入值的主鍵自增,防止遷移資料時報主鍵衝突的錯誤;
一、問題 我們要自己造一些測試資料,並且這些SQL指令碼要遷移到其他環境,遷移過程中,如果主鍵寫死,在其他環境,可能會出現主鍵衝突;所以,我們要寫活的主鍵,實現起來也很簡單; 二、解決方法 insert into userInfo(id,name,age)val
【轉載】Java動態代理之JDK實現和CGlib實現(簡單易懂)
原文地址:http://www.cnblogs.com/ygj0930/p/6542259.html 一:代理模式(靜態代理) 代理模式是常用設計模式的一種,我們在軟體設計時常用的代理一般是指靜態代理,也就是在程式碼中顯式指定的
【MongoDB】-Java實現對mongodb的And、Or、In操作
1)And(同時滿足多個條件時用And) public void testAnd(){ DBObject queryCondition = new BasicDBObject();
【 專欄 】- Java語言下單例模式的實現
Java語言下單例模式的實現 單例模式,即整個程式中某個物件只能被例項化一次,而在多執行緒環境下,普通懶漢式單例模式將無法滿足要求,這裡主要介紹幾種方法
【Java】Java多執行緒實現的聊天客戶端和伺服器
主要涉及知識 ·Java中GUI程式的編寫,包括事件監聽機制。 ·Java的網路通訊程式設計,ServerSocket,Socket類的使用。 ·Java中多執行緒的程式設計,Thread類,Runnable介面的使用。 原始碼 客戶端 package project1
【演算法】java版紅黑樹演算法的完整實現及swing介面演示程式
【前言】 當初因為覺得資料結構及演算法是碼農的基礎(正如鋤頭對農民一樣)才決定話費時間來補習的,但是真正自行實現演算法及演算法的視覺化演示的時候才發現難度是如此之大。 演算法寫起來慢,swing介面寫起來也慢。 紅黑樹的結構最重要就是幾個規則: 1、根節點為黑色,NIL
【java】Java驗證碼功能實現
一、前言 驗證碼可以說在我們生活中已經非常普遍了,任何一個網站,任何一個App都會有這個功能,但是為啥要有這個呢?如何做才能做出來呢?下面小編會帶領大家一起用java完成一個驗證碼的功能。 二、驗證碼的作用 一般可以防止有人利用機器
【java】HttpClient實現HTTP檔案通用下載工具類
package com.imopan.cps.apart.api.util; import java.io.File; import java.io.FileOutputStream; import java.io.InputStream; import org.apa