我目前了解Java和Ruby,但从未使用过JRuby.我想在Rack(sinatra)Web应用程序中使用一些RAM和计算密集型Java代码.特别是,此Java代码将大约200MB的数据加载到RAM中,并提供了使用此内存数据进行各种计算的方法.
我知道可以在JRuby中从Ruby调用Java代码,但就我而言,还有一个附加要求:该Java代码需要加载一次,保存在内存中,并可以作为sinatra代码的共享资源使用(被多个Web请求触发).
问题
>这样的设置是否可能?
>我需要做些什么来完成它?我什至不确定这是JRuby问题本身,还是需要在Web服务器中配置的问题.我在Passenger和Unicorn / nginx方面有经验,但是在Java服务器方面没有经验,因此,如果这确实涉及Java服务器(例如Tomcat)的配置,则有关此方面的任何信息都会有所帮助.
我真的不确定从哪里开始寻找东西,或者是否有更好的方法来解决此问题,因此不胜感激所有建议或相关链接.
解决方法:
是的,可以进行设置(有关部署,请参见下文),要完成该设置,我建议使用Singleton
Jruby的单身人士
关于问题:best/most elegant way to share objects between a stack of rack mounted apps/middlewares?我同意Colin Surprenant的回答,即单例模块模式,我更喜欢使用单例mixin
例
我在这里发布了一些测试代码,您可以将其用作概念证明:
JRuby sinatra方面:
#file: sample_app.rb
require 'sinatra/base'
require 'java' #https://github.com/jruby/jruby/wiki/CallingJavaFromJRuby
java_import org.rondadev.samples.StatefulCalculator #import you java class here
# singleton-as-module loaded once, kept in memory
module App
module Global extend self
def calc
@calc ||= StatefulCalculator.new
end
end
end
# you could call a method to load data in the statefull java object
App::Global.calc.turn_on
class Sample < Sinatra::Base
get '/' do
"Welcome, calculator register:#{App::Global.calc.display}"
end
get '/add_one' do
"added one to calculator register, new value:#{App::Global.calc.add(1)}"
end
end
您可以使用特立尼达的tomcat或仅使用rackup config.ru来启动它,但您需要:
#file: config.ru
root = File.dirname(__FILE__) # => "."
require File.join( root, 'sample_app' ) # => true
run Sample # ..in sample_app.rb ..class Sample < Sinatra::Base
关于Java Side的一些信息:
package org.rondadev.samples;
public class StatefulCalculator {
private StatelessCalculator calculator;
double register = 0;
public double add(double a) {
register = calculator.add(register, a);
return register;
}
public double display() {
return register;
}
public void clean() {
register = 0;
}
public void turnOff() {
calculator = null;
System.out.println("[StatefulCalculator] Good bye ! ");
}
public void turnOn() {
calculator = new StatelessCalculator();
System.out.println("[StatefulCalculator] Welcome !");
}
}
请注意,这里的寄存器仅是双精度的,但是在实际代码中,实际情况下您可以拥有大数据结构
部署方式
您可以使用Mongrel,Thin(实验性),Webrick(但谁会这样做)以及甚至以Java为中心的应用程序容器(例如Glassfish,Tomcat或JBoss)进行部署. source: jruby deployments
与在JBoss Application Server上构建的TorqueBox一起使用.
JBoss AS包含高性能的集群,缓存和消息传递功能.
trinidad是一个RubyGem,允许您在嵌入式Apache Tomcat容器中运行任何基于Rack的applet wrap
线程同步
Sinatra将使用Mutex#synchronize方法在每个请求上放置一个锁,以避免线程之间的竞争情况.如果您的sinatra应用程序是多线程的并且不是线程安全的,或者您使用的任何gem都不是线程安全的,则需要设置:lock,true,以便在给定的时间仅处理一个请求. ..否则默认情况下lock为false,这意味着同步将直接屈服于该块.
来源:https://github.com/zhengjia/sinatra-explained/blob/master/app/tutorial_2/tutorial_2.md