1. 程式人生 > >分散式服務架構學習(一):實現自己的RPC框架(採用Java Socket)

分散式服務架構學習(一):實現自己的RPC框架(採用Java Socket)

RPC實現原理圖:

1、Service API對應服務介面。

HelloService.java程式碼如下:

package com.shan.rpc.service;

public interface HelloService {
	public String sayHello(String content);
}

2、Service Impl對應服務介面的實現:

HelloServiceImpl.java程式碼如下:

package com.shan.rpc.service.impl;

import com.shan.rpc.service.HelloService;

public class HelloServiceImpl implements HelloService {
	public String sayHello(String content) {
		return "hello," + content;
	}
}

3、Consumer Proxy 角色對應服務消費者代理類。通過實現服務介面的動態代理物件獲得服務介面的動態代理例項Proxy.newProxyInstance,通過實現InvocationHandler介面中的invoke方法來完成遠端RPC的呼叫。具體通過輸出流將呼叫介面的方法及引數寫入Socket,發起遠端呼叫。之後通過Java物件輸入流從Socket獲得返回結果。

ConsumerProxy.java程式碼如下:

package com.shan.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.Socket;

public class ConsumerProxy {
	
	/**
	 * @Title: consume
	 * @Description:服務消費代理
	 * @author fuss
	 * @date 2018年7月12日
	 * @param interfaceClass
	 * @param host
	 * @param port
	 * @return
	 * @throws Exception
	 */
	public static <T> T consume(final Class<T> interfaceClass, final String host, final int port) throws Exception {
		return (T) Proxy.newProxyInstance(interfaceClass.getClassLoader(), new Class<?>[]{interfaceClass}, new InvocationHandler() {
			@Override
			public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
				Socket socket = new Socket(host, port);
				try {
					ObjectOutputStream output = new ObjectOutputStream(socket.getOutputStream());
					try {
						output.writeUTF(method.getName());
						output.writeObject(args);
						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();
				}
			}
		});
	}
	
}

4、Provider Reflect角色對應服務釋出實現。通過輸入流從Socket中按照ConsumerProxy的寫入順序注意獲取調動方法

名稱及方法引數,通過MethodUtils.invokeExactMethod對服務實現類發起反射呼叫,將呼叫結果寫入Socket返回給對方。

ProviderReflect.java程式碼如下:

package com.shan.rpc.framework;

import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import org.apache.commons.lang3.reflect.MethodUtils;

public class ProviderReflect {
	
	private static final ExecutorService EXECUTOR_SERVICE = Executors.newCachedThreadPool();
	
	/**
	 * @Title: provider
	 * @Description:服務釋出
	 * @author fuss
	 * @date 2018年7月12日
	 * @param service
	 * @param port
	 * @throws Exception
	 */
	public static void provider(final Object service, int port) throws Exception {
		ServerSocket serverSocket = new ServerSocket(port);
		while (true) {
			final Socket socket = serverSocket.accept();
			EXECUTOR_SERVICE.execute(new Runnable() {
				@Override
				public void run() {
					try {
						ObjectInputStream input = new ObjectInputStream(socket.getInputStream());
						try {
							try {
								String methodName = input.readUTF();//方法名稱
								Object[] args = (Object[]) input.readObject();//方法引數
								ObjectOutputStream output = new ObjectOutputStream(socket.getOutputStream());
								try {
									Object result = MethodUtils.invokeExactMethod(service, methodName, args);
									output.writeObject(result);
								} catch (Throwable t) {
									output.writeObject(t);
								} finally {
									output.close();
								}
							} catch (Exception e) {
								e.printStackTrace();
							} finally {
								input.close();
							}
						} finally {
							socket.close();
						}
					} catch (Exception e) {
						e.printStackTrace();
					}
					
				}
			});
		}
	}
	
}

然後寫main方法通過ProviderReflect釋出服務,程式碼如下:

package com.shan.rpc.invoke;

import com.shan.rpc.framework.ProviderReflect;
import com.shan.rpc.service.HelloService;
import com.shan.rpc.service.impl.HelloServiceImpl;

public class RpcProviderMain {

	public static void main(String[] args) throws Exception {
		HelloService service = new HelloServiceImpl();
		ProviderReflect.provider(service, 8083);
	}

}

客戶端呼叫遠端服務的main方法,程式碼如下:

package com.shan.rpc.invoke;

import com.shan.rpc.framework.ConsumerProxy;
import com.shan.rpc.service.HelloService;

public class RpcConsumerMain {

	public static void main(String[] args) throws Exception {
		HelloService service = ConsumerProxy.consume(HelloService.class, "127.0.0.1", 8083);
		for (int i = 0; i < 1000; i++) {
			String hello = service.sayHello("fuss_" + i);
			System.out.println(hello);
			Thread.sleep(1000);
		}
	}

}

執行結果如圖:

相關推薦

分散式服務架構學習實現自己RPC框架採用Java Socket

RPC實現原理圖: 1、Service API對應服務介面。 HelloService.java程式碼如下: package com.shan.rpc.service; public interface HelloService { public String

【轉】歸納一個從某課程薅來的Java架構學習計劃和知識體系-給自己記錄一下趕緊學

1.Java基礎-原始碼 1. 常用的設計模式 Proxy代理模式 Factory工廠模式 Singleton單例模式 Delegate委派模式 Strategy策略模式 Prototype原型模式 Template模版模式 Deco

服務架構學習與思考(07)企業團隊組織架構如何變革?

### 康威定律 >康威定律 (康威法則 , Conway's Law) 是[馬爾文·康威](https://zh.wikipedia.org/wiki/%E9%A9%AC%E5%B0%94%E6%96%87%C2%B7%E5%BA%B7%E5%A8%81)1967年提出的: >**設計系統的架構受制於產生這

Scala學習筆記10—— Akka 實現簡單 RPC 框架

1 Akka 介紹 目前大多數的分散式架構底層通訊都是通過RPC實現的,RPC框架非常多,比如前我們學過的Hadoop專案的RPC通訊框架,但是Hadoop在設計之初就是為了執行長達數小時的批量而設計的,在某些極端的情況下,任務提交的延遲很高,所有Hadoop的

服務架構學習筆記gRPC Spring Boot Starter 2.2.0 釋出,及使用步驟

簡介 gRPC Spring Boot Starter 專案是一個 gRPC 的 Spring Boot 模組。通過在 Spring Boot 中內嵌一個 gRPC Server 對外提供服務,並支援 Spring Cloud 的服務發現、註冊、鏈路跟蹤等等。 更新內容 在 2.

服務架構學習筆記重新認識微服務

一、什麼是微服務 微服務(Microservice)是服務化思路的一種最佳實踐方向,遵循SOA的思路,各個企業在服務化治理的道路上走的時間長了,踩的坑多了,整個軟體交付鏈路上各個環節的基礎設施逐漸成熟了,微服務自然而然就誕生了。 早些年的服務實現和實施思路是將很多功能從開發到交付都打包成一個

分散式服務架構原理 設計與實踐讀書總結

文章目錄 1. 分散式微服務架構設計原理 1.1 從傳統的單體架構到到服務化架構 1.2 從服務化到微服務 1.3 微服務架構的核心要點和實現原理 1.4 Java平臺微服務架構的專案組織形式 1.5

推薦分散式服務架構方面的好書文末彩蛋

講解高可用架構核心:可伸縮與可擴充套件,詳解分散式發號器訊息佇列框架、資料庫分庫分表、快取、El

Java學習第一章 計算機、程式和Java概述

第一章 計算機、程式和Java概述   (1)匯流排--》    儲存裝置、記憶體、CPU、通訊裝置、輸入裝置、輸出裝置; (2)語言: 機器語言: 二進位制形式

吳恩達深度學習系列課程筆記卷積神經網路

本系列文章將對吳恩達在網易公開課“深度學習工程師”微專業內容進行筆記總結,這一部分介紹的是“卷積神經網路”部分。 1、計算機視覺 計算機視覺在我們還是生活中有非常廣泛的應用,以下幾個是最常見的例子: 影象分類: 可以對影象中的物體種類進行判斷,如確定影象中

學習筆記 -- 斯坦福課程CNN for Visual Recognition

去年就想聽聽這“接地氣”的課程了,但最終也沒有堅持下來。今年既然有了線上的課程視訊,我也開個筆記系列,好好地從基礎開始學起吧。由於課程內容還是比較基礎,這裡只紀錄一些個人覺得有趣或者有用的點,更多的內容大家直接去網站上看吧,相信會有不少收穫的。 Lectu

OpenCV學習筆記04Mat類詳解

1. 前言:Mat類簡介 OpenCV 作為強大的計算機視覺開源庫,很大程度上參考了MatLab的實現細節和語法風格,比如說,在OpenCV2.x版本以後,越來越多的函式實現了MatLab所具有的功能,甚至乾脆連函式名都一模一樣(如 imre

Java for Web學習筆記一一再談Entity對映4動態表格建立

如果這個不確定表格也需要我們的war來建立,如何實現。create table的原生SQL,entityManager是無法執行的,因為這不是可以回滾的事務。這種情況,我們需要: 捕獲表格不存在的異常 從原始的Connection中實現表格建立。獲取Connection能否從

【遠端呼叫框架】如何實現一個簡單的RPC框架優化利用動態代理改變使用者服務呼叫方式

【如何實現一個簡單的RPC框架】系列文章: 這篇部落格,在(一)(二)的基礎上,對第一版本實現的服務框架進行改善,不定期更新,每次更新都會增加一個優化的地方。 1、優化一:利用動態代理改變使用者服務呼叫方式 1.1 目的 改變使用者

SpingCloud微服務架構學習之Actuator監控

pid fig 變量 -s 健康 服務架構 pan frame localhost 我們那我們之前編寫的服務提供者為例,為項目添加如下依賴: <dependency>   <groupId>org.springframework.boot&

RNN學習筆記長短時記憶網路LSTM

  一、前言        在影象處理領域,卷積神經網路(Convolution Nerual Network,CNN)憑藉其強大的效能取得了廣泛的應用。作為一種前饋網路,CNN中各輸入之間是相互獨立的,每層神經元的訊號只能向下一層傳播,同一卷積層對不同通道資

C++學習1最大子段和多種解法

多少 問題: code namespace 數據 組成 amp using () 問題:給定由n個數(可能為負數)組成的序列a1,a2,a3,...,an,求該序列子段和的最大值。 第一種解法:(最容易考慮的方法,將所有的子段一一相加,然後比較) 1 #include&

構建NetCore應用框架之實戰篇什麽是框架,如何設計一個框架

net 希望 dmi 清晰 構建 組織 評估 系統開發 概念 一、系列簡述 本篇起,將通過一系列文章,去描述如何構建一個應用開發框架,並以作者開發的框架為例,逐個點展開分析,如何從零開始,構建自己的開發框架。 本系列文章的目的,是帶領有一編程經驗的人,通過動手,初步完成

beego學習筆記4開發文檔閱讀3

new github model div email true ews mail IV 通過運行 bee new quickstart 來創建新的項目,其結構如下: quickstart |-- conf | `-- app.conf |-- controllers

RabbitMQ學習第三記發布/訂閱模式Publish/Subscribe

font image 直接 email err spl 回調方法 byte []   工作隊列模式是直接在生產者與消費者裏聲明好一個隊列,這種情況下消息只會對應同類型的消費者。   舉個用戶註冊的列子:用戶在註冊完後一般都會發送消息通知用戶註冊成功(失敗)。如果在一個系統中