Cajo,用Java完成分布式计算的最简单方法
分布式計(jì)算在企業(yè)應(yīng)用程序開發(fā)世界中變得越來越重要。 如今,開發(fā)人員不斷需要解決以下問題:如何通過將應(yīng)用程序擴(kuò)展到單個(gè)節(jié)點(diǎn)之外來增強(qiáng)可伸縮性? 如何保證高可用性,消除單點(diǎn)故障并確保滿足客戶的SLA?
對(duì)于許多開發(fā)人員而言,解決該問題的最自然的方法是將體系結(jié)構(gòu)分為在不同服務(wù)器之間分布的組件或服務(wù)組。 盡管這并不奇怪,但考慮到大多數(shù)開發(fā)人員所擁有的CORBA,EJB,COM和RMI的傳統(tǒng),如果您決定走這條路,那么您會(huì)遇到很多麻煩。 在大多數(shù)情況下,這樣做是不值得的,它會(huì)給您帶來更多無法解決的問題。 ”
另一方面,分布式計(jì)算和Java自然地結(jié)合在一起。 作為自下而上設(shè)計(jì)的第一種語言,考慮了網(wǎng)絡(luò),Java使計(jì)算機(jī)之間的協(xié)作變得非常容易。 如果考慮一下,即使在瀏覽器中運(yùn)行的最簡(jiǎn)單的applet也是分布式應(yīng)用程序。 運(yùn)行瀏覽器的客戶端下載并執(zhí)行其他系統(tǒng)提供的代碼。 但是,如果沒有Java的可移植性和安全性保證,即使是這個(gè)簡(jiǎn)單的applet也將無法實(shí)現(xiàn):applet可以在任何平臺(tái)上運(yùn)行,并且不能破壞其主機(jī)。
cajo項(xiàng)目是一個(gè)小型圖書館,可實(shí)現(xiàn)強(qiáng)大的動(dòng)態(tài)多計(jì)算機(jī)協(xié)作。 它非常易于使用,但性能無與倫比。 它是一個(gè)獨(dú)特的“嵌入式”分布式計(jì)算框架:這意味著它對(duì)您的應(yīng)用程序沒有任何結(jié)構(gòu)上的要求,也沒有對(duì)源代碼進(jìn)行更改。 它允許多個(gè)遠(yuǎn)程JVM作為一個(gè)無縫地協(xié)同工作。
項(xiàng)目所有者約翰·凱瑟琳諾聲稱“山上之王! ;-)”并挑戰(zhàn)所有愿意證明Java中存在與cajo同樣靈活和一樣快的分布式計(jì)算框架的人 。
說實(shí)話,我個(gè)人對(duì)約翰的話深信不疑。 我堅(jiān)信如果您讓我逐步介紹此客戶端-服務(wù)器示例,您也將如此。 您會(huì)驚訝cajo框架多么簡(jiǎn)單和靈活:
Server.java
import gnu.cajo.Cajo; // The cajo implementation of the Grailpublic class Server {public static class Test { // remotely callable classes must be public// though not necessarily declared in the same classprivate final String greeting;// no silly requirement to have no-arg constructorspublic Test(String greeting) { this.greeting = greeting; }// all public methods, instance or static, will be remotely callablepublic String foo(Object bar, int count) {System.out.println("foo called w/ " + bar + ' ' + count + " count");return greeting;}public Boolean bar(int count) {System.out.println("bar called w/ " + count + " count");return Boolean.TRUE;}public boolean baz() {System.out.println("baz called");return true;}public String other() { // functionality not needed by the test clientreturn "This is extra stuff";}} // arguments and return objects can be custom or common to server and clientpublic static void main(String args[]) throws Exception { // unit testCajo cajo = new Cajo(0);System.out.println("Server running");cajo.export(new Test("Thanks"));} }通過以下方式進(jìn)行編譯:
javac -cp cajo.jar;. Server.java通過以下方式執(zhí)行:
java -cp cajo.jar;. Server如您所見,只有2個(gè)命令:
Cajo cajo = new Cajo(0); cajo.export(new Test("Thanks"));我們可以將任何POJO(普通的Java舊對(duì)象)公開為分布式服務(wù)!
現(xiàn)在是Client.java
import gnu.cajo.Cajo;import java.rmi.RemoteException; // caused by network related errorsinterface SuperSet { // client method sets need not be publicvoid baz() throws RemoteException; } // declaring RemoteException is optional, but a nice reminderinterface ClientSet extends SuperSet {boolean bar(Integer quantum) throws RemoteException;Object foo(String barbaz, int foobar) throws RemoteException; } // the order of the client method set does not matterpublic class Client {public static void main(String args[]) throws Exception { // unit testCajo cajo = new Cajo(0);if (args.length > 0) { // either approach must work...int port = args.length > 1 ? Integer.parseInt(args[1]) : 1198;cajo.register(args[0], port);// find server by registry address & port, or...} else Thread.currentThread().sleep(100); // allow some discovery timeObject refs[] = cajo.lookup(ClientSet.class);if (refs.length > 0) { // compatible server objects foundSystem.out.println("Found " + refs.length);ClientSet cs = (ClientSet)cajo.proxy(refs[0], ClientSet.class);cs.baz();System.out.println(cs.bar(new Integer(77)));System.out.println(cs.foo(null, 99));} else System.out.println("No server objects found");System.exit(0); // nothing else left to do, so we can shut down} }通過以下方式進(jìn)行編譯:
javac -cp cajo.jar;. Client.java通過以下方式執(zhí)行:
java -cp cajo.jar;. Client客戶端可以通過提供服務(wù)器地址和端口(如果有)或使用多播來查找服務(wù)器對(duì)象。 為了找到合適的服務(wù)器對(duì)象,使用“ 動(dòng)態(tài)客戶端子類型 ”。 對(duì)于所有不知道“ 動(dòng)態(tài)客戶端子類型化 ”代表什么的人,John Catherino在其相關(guān)博客文章中解釋道:
“服務(wù)對(duì)象通常會(huì)實(shí)現(xiàn)大型的,豐富的接口。 有時(shí),服務(wù)對(duì)象實(shí)現(xiàn)多個(gè)接口,將其功能分組為不同的邏輯問題。 通常,客戶端只需要使用接口的一小部分即可。 或一些邏輯分組接口中的某些方法來滿足其自身的需求。
客戶端從服務(wù)對(duì)象定義的接口定義其自己的接口的能力在Java中稱為子類型化。 (與子類形成對(duì)比)但是,與常規(guī)Java子類型不同; 動(dòng)態(tài)客戶端子類型化意味著創(chuàng)建一個(gè)完全不同的界面。 使此子類型成為動(dòng)態(tài)的原因在于,它可以與原始的未經(jīng)修改的服務(wù)對(duì)象一起使用。
對(duì)于客戶端的復(fù)雜性管理,這可能是一種非常有效的技術(shù)。”
真的不是很酷嗎??? 我們只需要定義客戶端“需要”使用的接口并找到符合客戶端規(guī)范的適當(dāng)服務(wù)器對(duì)象。 從我們的示例中派生出以下命令即可完成此任務(wù):
Object refs[] = cajo.lookup(ClientSet.class);最后但并非最不重要的一點(diǎn)是,我們可以通過發(fā)出以下命令來創(chuàng)建服務(wù)器對(duì)象的客戶端“代理”,并像普通的本地對(duì)象引用一樣遠(yuǎn)程調(diào)用其方法:
ClientSet cs = (ClientSet)cajo.proxy(refs[0], ClientSet.class);而已。 這些允許在分布式JVM之間實(shí)現(xiàn)完全的互操作性。 沒有比這更容易的了。
就性能而言,我對(duì)提供的示例進(jìn)行了一些初步測(cè)試,并在以下系統(tǒng)上獲得了12000 TPS的平均分?jǐn)?shù):
Sony Vaio具有以下特征:
- 系統(tǒng):openSUSE 11.1(x86_64)
- 處理器(CPU):Intel(R)Core(TM)2 Duo CPU T6670 @ 2.20GHz
- 處理器速度:1,200.00 MHz
- 總內(nèi)存(RAM):2.8 GB
- Java:OpenJDK 1.6.0_0 64位
為了方便起見,我提供了用于執(zhí)行壓力測(cè)試的代碼段:
int repeats = 1000000; long start = System.currentTimeMillis(); for(int i = 0; i < repeats;i ++)cs.baz(); System.out.println("TPS : " + repeats/((System.currentTimeMillis() - start)/1000d));編碼愉快! 并且不要忘記分享!
賈斯汀
相關(guān)文章 :- Java最佳實(shí)踐–高性能序列化
- Java最佳實(shí)踐– Vector vs ArrayList vs HashSet
- Java最佳實(shí)踐–字符串性能和精確字符串匹配
- Java最佳實(shí)踐–隊(duì)列之戰(zhàn)和鏈接的ConcurrentHashMap
- Java最佳實(shí)踐– Char到Byte和Byte到Char的轉(zhuǎn)換
- 如何在不到1ms的延遲內(nèi)完成100K TPS
- 提升您的休眠引擎
翻譯自: https://www.javacodegeeks.com/2011/01/cajo-easiest-way-to-accomplish.html
總結(jié)
以上是生活随笔為你收集整理的Cajo,用Java完成分布式计算的最简单方法的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 新华三 ddns(新华三 DDOS)
- 下一篇: Java相当好的隐私(PGP)