摘自Jonas Boner在2006年5月1日发布在TheServerSide.com上的文章“ Distributed Computing Easy”中的介绍部分:

分布式计算在企业应用程序开发世界中变得越来越重要。 如今,开发人员不断需要解决以下问题:如何通过将应用程序扩展到单个节点之外来增强可伸缩性? 如何保证高可用性,消除单点故障并确保满足客户的SLA?

对于许多开发人员而言,解决该问题的最自然的方法是将体系结构分为在不同服务器之间分布的组件或服务组。 尽管这并不奇怪,但考虑到大多数开发人员所拥有的CORBA,EJB,COM和RMI的传统,如果您决定走这条路,那么您会遇到很多麻烦。 在大多数情况下,这样做是不值得的,它会给您带来更多无法解决的问题。

另一方面,分布式计算和Java自然地结合在一起。 作为自下而上设计的第一种语言,考虑了网络,Java使计算机之间的协作变得非常容易。 如果考虑一下,即使在浏览器中运行的最简单的applet也是分布式应用程序。 运行浏览器的客户端下载并执行其他系统提供的代码。 但是,如果没有Java的可移植性和安全性保证,即使是这个简单的applet也将无法实现:applet可以在任何平台上运行,并且不能破坏其主机。

cajo项目是一个小型图书馆,可实现强大的动态多计算机协作。 它非常易于使用,但性能无与伦比。 它是一个独特的“嵌入式”分布式计算框架:这意味着它对您的应用程序没有任何结构上的要求,也没有对源代码进行更改。 它允许多个远程JVM作为一个无缝地协同工作。

项目所有者约翰·凯瑟琳诺声称“山上之王! ;-)”并挑战所有愿意证明Java中存在与cajo同样灵活和一样快的分布式计算框架的人 。

说实话,我个人对约翰的话深信不疑。 我坚信如果您让我逐步介绍此客户端-服务器示例,您也将如此。 您会惊讶cajo框架多么简单和灵活:

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"));}
}

通过以下方式进行编译:

javac -cp cajo.jar;. Server.java

通过以下方式执行:

java -cp cajo.jar;. Server

如您所见,只有2个命令:

Cajo cajo = new Cajo(0);
cajo.export(new Test("Thanks"));

我们可以将任何POJO(普通的Java旧对象)公开为分布式服务!

现在是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}
}

通过以下方式进行编译:

javac -cp cajo.jar;. Client.java

通过以下方式执行:

java -cp cajo.jar;. Client

客户端可以通过提供服务器地址和端口(如果有)或使用多播来查找服务器对象。 为了找到合适的服务器对象,使用“ 动态客户端子类型 ”。 对于所有不知道“ 动态客户端子类型化 ”代表什么的人,John Catherino在其相关博客文章中解释道:

“服务对象通常会实现大型的,丰富的接口。 有时,服务对象实现多个接口,将其功能分组为不同的逻辑问题。 通常,客户端只需要使用接口的一小部分即可。 或一些逻辑分组接口中的某些方法来满足其自身的需求。

客户端从服务对象定义的接口定义其自己的接口的能力在Java中称为子类型化。 (与子类形成对比)但是,与常规Java子类型不同; 动态客户端子类型化意味着创建一个完全不同的界面。 使此子类型成为动态的原因在于,它可以与原始的未经修改的服务对象一起使用。

对于客户端的复杂性管理,这可能是一种非常有效的技术。”

真的不是很酷吗??? 我们只需要定义客户端“需要”使用的接口并找到符合客户端规范的适当服务器对象。 从我们的示例中派生出以下命令即可完成此任务:

Object refs[] = cajo.lookup(ClientSet.class);

最后但并非最不重要的一点是,我们可以通过发出以下命令来创建服务器对象的客户端“代理”,并像普通的本地对象引用一样远程调用其方法:

ClientSet cs = (ClientSet)cajo.proxy(refs[0], ClientSet.class);

而已。 这些允许在分布式JVM之间实现完全的互操作性。 没有比这更容易的了。

就性能而言,我对提供的示例进行了一些初步测试,并在以下系统上获得了12000 TPS的平均分数:

Sony Vaio具有以下特征:

  • 系统:openSUSE 11.1(x86_64)
  • 处理器(CPU):Intel(R)Core(TM)2 Duo CPU T6670 @ 2.20GHz
  • 处理器速度:1,200.00 MHz
  • 总内存(RAM):2.8 GB
  • Java:OpenJDK 1.6.0_0 64位

为了方便起见,我提供了用于执行压力测试的代码段:

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));

编码愉快! 并且不要忘记分享!

贾斯汀

相关文章 :
  • Java最佳实践–高性能序列化
  • Java最佳实践– Vector vs ArrayList vs HashSet
  • Java最佳实践–字符串性能和精确字符串匹配
  • Java最佳实践–队列之战和链接的ConcurrentHashMap
  • Java最佳实践– Char到Byte和Byte到Char的转换
  • 如何在不到1ms的延迟内完成100K TPS
  • 提升您的休眠引擎

翻译自: https://www.javacodegeeks.com/2011/01/cajo-easiest-way-to-accomplish.html

Cajo,用Java完成分布式计算的最简单方法相关推荐

  1. 将Java程序变成可执行文件的简单方法

    launcher下载 运行Java程序(SWING或SWT的桌面程序)可以直接执行.class文件或将所有的.class文件及相关的其他文件压缩成.jar文件,然后使用javaw -jar my.ja ...

  2. Java获取键盘屏幕输入简单方法

    在程序开发过程中,我们经常需要从键盘获取输入值,c语言给我们提供了scanf(),C++给我们提供了cin(),但是在java中,并没有给我们提供这样的平台,那我们应该如何实现呢?  以下将列出几种方 ...

  3. Java - 文件输入和输出 简单方法

    使用 PrintWriter 写数据 java.io.PrintWriter 类可用来创建一个文件并向文本文件写入数据. 首先创建一个 PrintWriter 对象,如下所示: PrintWriter ...

  4. java写入文件不覆盖写入_Java写入文件–用Java写入文件的4种方法

    java写入文件不覆盖写入 Java provides several ways to write to file. We can use FileWriter, BufferedWriter, ja ...

  5. java文件写入不覆盖_java写入文件不覆盖写入_Java写入文件–用Java写入文件的4种方法...

    java写入文件不覆盖写入 Java provides several ways to write to file. We can use FileWriter, BufferedWriter, ja ...

  6. 帮我用Java写一个生成流水号的方法

    我可以给你提供一个使用Java来生成流水号的简单方法: 使用java.util.UUID类来生成一个唯一的字符串: 使用java.time.LocalDateTime类来获取当前的日期和时间: 将上述 ...

  7. c# typescript_在任何IDE中从C#,Java或Python代码获取TypeScript接口的简单方法

    c# typescript by Leonardo Carreiro 莱昂纳多·卡雷罗(Leonardo Carreiro) 在任何IDE中从C#,Java或Python代码获取TypeScript接 ...

  8. 《JAVA与模式》之简单工厂模式

    在阎宏博士的<JAVA与模式>一书中开头是这样描述简单工厂模式的:简单工厂模式是类的创建模式,又叫做静态工厂方法(Static Factory Method)模式.简单工厂模式是由一个工厂 ...

  9. 将Java程序变成可执行文件的一个简单方法

    将Java程序变成可执行文件的一个简单方法 运行Java程序(SWING或SWT的桌面程序)可以直接执行.class文件或将所有的.class文件及相关的其他文件压缩成.jar文件,然后使用javaw ...

最新文章

  1. 全球第五大社交网站,二号员工离职创业,自爆心酸历程!想做10亿美元规模?先活着!...
  2. [BZOJ 2002][Hnoi2010]Bounce 弹飞绵羊(分块)
  3. 【Linux 内核 内存管理】内存管理架构 ④ ( 内存分配系统调用过程 | 用户层 malloc free | 系统调用层 brk mmap | 内核层 kmalloc | 内存管理流程 )
  4. [No0000130]WPF 4.5使用标记扩展订阅事件
  5. SQLServer 查看耗时较多的SQL语句
  6. Angular单元测试框架karma-jasmine里类似ABAP unit框架的setup和class_setup方法
  7. 更强的压缩比!PostgreSQL开始支持Zstd
  8. 前端学习(3051):vue+element今日头条管理-表格组件基本使用
  9. Spring安装与入门
  10. 无法在此计算机上安装vmware,电脑中虚拟机无法安装VMware Tools提示D盘找不到setup.exe如何解决...
  11. CCF201903-1 小中大(100分)【序列处理】
  12. Python入门:局部变量与全局变量1
  13. springboot @value 默认值_原创 | 搞定默认值
  14. 高德定位获取经纬度,街道城市名称
  15. paip.一千 常用汉字 高频汉字 覆盖率90%
  16. 应变式传感器的原理与优点
  17. 带着问题看 react-redux 源码实现
  18. C++ 数学与算法系列之高斯消元法求解线性方程组
  19. Tableau联动之工作表联动
  20. ubuntu_pip-install_WARRING:XXX is not on PATH ...

热门文章

  1. os引导程序boot从扇区拷贝os加载程序loader文件到内存(boot copy kernel to mem in the same method)
  2. lambda层保存模型出错_保存您的lambda,以备不时之需-保存到文件
  3. java8多线程运行程序_线程,代码和数据–多线程Java程序实际运行的方式
  4. jetty设置双向ssl_在Jetty中设置SSL
  5. jdk11 默认收集器_JDK 11:新的默认收集方法toArray(IntFunction)
  6. 琥珀ai_琥珀项目:Java的未来暴露
  7. functor_纯Java中的Functor和Monad示例
  8. javafx阴影_JavaFX技巧来节省内存! 属性和可观察对象的阴影场
  9. java必读书籍_必读:Java Java
  10. jdk 9和jdk8_JDK 9 –给圣诞老人的信?