gpt4 book ai didi

java - JRuby:从 Rack 应用程序调用 Java 代码并将其保存在内存中

转载 作者:塔克拉玛干 更新时间:2023-11-02 08:18:20 26 4
gpt4 key购买 nike

我目前了解 Java 和 Ruby,但从未使用过 JRuby。我想在 Rack (sinatra) web 应用程序中使用一些 RAM 和计算密集型 Java 代码。特别是,这段 Java 代码将大约 200MB 的数据加载到 RAM 中,并提供了使用这些内存数据进行各种计算的方法。

我知道可以在 JRuby 中从 Ruby 调用 Java 代码,但在我的例子中还有一个额外的要求:该 Java 代码需要加载一次,保存在内存中,并作为共享资源供调用的 sinatra 代码(由多个 Web 请求触发)。

问题

  1. 这样的设置是否可行?
  2. 我需要做什么才能完成它?我什至不确定这本身是一个 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的答案,即单例作为模块模式,我更喜欢使用单例混合

例子

我在这里发布了一些测试代码,您可以将其用作概念验证:

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 中使用 trinidad 或简单地使用 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 方面的一些事情:

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

请注意,这里的register只是一个double,但在您的真实代码中,您可以在真实场景中拥有大数据结构

部署

您可以使用 Mongrel、Thin(实验性)、Webrick(但谁会这样做?),甚至以 Java 为中心的应用程序容器(如 Glassfish、Tomcat 或 JBoss)进行部署。 source: jruby deployments

使用基于 JBoss 应用服务器构建的 TorqueBox。JBoss AS 包括高性能集群、缓存和消息传递功能。

trinidad是一个 RubyGem,允许您在嵌入式 Apache Tomcat 容器中运行任何基于 Rack 的小程序包装

线程同步

Sinatra 将使用 Mutex#synchronize 方法在每个请求上放置一个锁,以避免线程之间的竞争条件。如果你的 sinatra 应用程序是多线程的并且不是线程安全的,或者你使用的任何 gem 不是线程安全的,你会想要设置 :lock, true 这样只有一个请求在给定时间处理。 .. 否则默认情况下 lockfalse,这意味着 synchronize 将直接让步给 block 。

来源:https://github.com/zhengjia/sinatra-explained/blob/master/app/tutorial_2/tutorial_2.md

关于java - JRuby:从 Rack 应用程序调用 Java 代码并将其保存在内存中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16201075/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com