2017-11-08 17 views
0

JRuby (jruby-openssl 0.9.21을 사용하여 9.1.8.0)를 사용하여 큰 JSON 파일 (~ 300MB)을 Solr에 스트리밍하려고합니다. 원격 Solr 서버가 SSL 인증을 사용 중입니다. 아래 스크립트를 포함 시켰습니다.JRuby가 SSL을 통한 스팀 전송으로 높은 메모리 사용량을 초래합니다.

JRuby를 사용할 때 기본값 500MB를 사용하여 거의 즉시 힙 공간이 부족합니다. MRI를 사용하면 사용량이 40MB를 넘지 않습니다. SSL을 사용하지 않으면 JRuby가 정상적으로 작동합니다. 필자는 순수 Java로 유사한 프로세스를 수행했지만 이런 종류의 문제는 없었습니다. ... 여기에 어떤 제안에 대한

감사합니다 ... 무슨 일이 일어나고 있는지 확실하지

require 'openssl' 
require 'net/http' 
require 'json' 

PEM_FILE = ENV["CLIENT_CERT"] 
SOLR_URL = ENV["SOLR_URL"] 

class SolrClient 

    DEFAULT_OPTIONS = { 
    use_ssl: true, 
    verify_mode: OpenSSL::SSL::VERIFY_PEER, 
    keep_alive_timeout: 30, 
    cert: OpenSSL::X509::Certificate.new(IO.read(PEM_FILE)), 
    key: OpenSSL::PKey::RSA.new(IO.read(PEM_FILE)), 
    } 


    def initialize(http = nil) 
    if http 
     @http = http 
    else 
     @http = Net::HTTP.start('my.solr.url', 443, DEFAULT_OPTIONS) 
    end 
    end 

    def update() 
    bytes = File.open('index_batch.json', 'rb').bytes.count.to_s 
    stream = File.open('index_batch.json', 'rb') 
    puts "starting request..." 
    request = Net::HTTP::Post.new "/solr/archivesspace/update" 
    request['Content-Type'] = 'application/json' 
    request['Content-Length'] = bytes 
    request.body_stream = stream 

    response = @http.request request 
    puts response.body 
    end 

end 


SolrClient.new.update 
+0

힙 크기를 50으로 설정하고 있습니까? 0 메가 바이트 또는 500 메가 바이트라고 생각하십니까? – pvg

+0

아니요. -J-Xmx 플래그없이 스크립트를 실행하기 만하면 요청을 보내기 시작할 때 즉시 중지됩니다. -J-Xmx1024m을 사용하여 스크립트를 실행하면 1 분 정도 실행 된 다음 실행이 중단됩니다 ... 2048m까지 올라가면 조금 더 오래갑니다 ... 등 – fitz

+0

VisualVM 또는 비슷한 도구를 사용해보십시오 (예 : https://stackoverflow.com/questions/9154785/how-to-find-memory-leaks-using-visualvm) jruby-openssl을 디버깅하는 데 특히 관심이 없으면 찾을 수 있습니다. 자바에서이 특별한 것을 재 작성하기 쉽다. – pvg

답변

0

는 JRuby에서의 GitHub의에 문제를 게시하고 즉시 응답을 얻었다 : A와

https://github.com/jruby/jruby/issues/4842

임시 픽스, 패치 중입니다. http :

class Net::HTTPGenericRequest 

    def send_request_with_body_stream(sock, ver, path, f)                                  
    unless content_length() or chunked?                                      
     raise ArgumentError,                                         
      "Content-Length not given and Transfer-Encoding is not `chunked'"                             
    end                                              
    supply_default_content_type                                        
    write_header sock, ver, path                                        
    wait_for_continue sock, ver if sock.continue_timeout                                  
    if chunked?                                            
     chunker = Chunker.new(sock)                                        
     IO.copy_stream(f, chunker)                                        
     chunker.finish                                           
    else                                              
     # copy_stream can sendfile() to sock.io unless we use SSL.                                
     # If sock.io is an SSLSocket, copy_stream will hit SSL_write()                               
     if sock.io.is_a? OpenSSL::SSL::SSLSocket                                    
     IO.copy_stream(f, sock.io, 16 * 1024 * 1024) until f.eof?                                
     else                                             
     IO.copy_stream(f, sock.io)                                       
     end                                              
    end                                              
    end                                               
end