Использование HTTPBuilder и получение java.net.SocketException: нет доступного буферного пространства (достигнуто максимальное количество подключений?): подключиться

Я использую HTTPBuilder для создания клиента для REST API базы данных NoSQL. Он отлично работает, за исключением обработки большого набора данных. После большого количества вызовов клиент выдает это исключение:

java.net.SocketException: No buffer space available (maximum connections reached?): connect
at org.apache.http.conn.scheme.PlainSocketFactory.connectSocket(PlainSocketFactory.java:127)
at  org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:180)
at org.apache.http.impl.conn.ManagedClientConnectionImpl.open(ManagedClientConnectionImpl.java:294)
at org.apache.http.impl.client.DefaultRequestDirector.tryConnect(DefaultRequestDirector.java:640)
at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:479)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:906)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:805)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:784)
at groovyx.net.http.HTTPBuilder.doRequest(HTTPBuilder.java:446)
at groovyx.net.http.HTTPBuilder.doRequest(HTTPBuilder.java:417)
at groovyx.net.http.HTTPBuilder.request(HTTPBuilder.java:366)
at groovyx.net.http.HTTPBuilder$request.call(Unknown Source)
at scripts.groovy.prototypes.NeoClient.getRelationship(NeoClient.groovy:70)
at com.gsgenetics.genie.trait.Node$Edge.getTargetNode(Node.java:108)
at com.gsgenetics.genie.trait.Node$Edge.compareTo(Node.java:145)
at com.gsgenetics.genie.trait.Node$Edge.compareTo(Node.java:67)
at com.gsgenetics.genie.trait.Node.getEdges(Node.java:32)
at com.gsgenetics.genie.trait.Node.iterator(Node.java:384)
at com.gsgenetics.genie.GenomeStructuredGraph.add(GenomeStructuredGraph.java:131)
at com.gsgenetics.genie.GenomeStructuredGraph.add(GenomeStructuredGraph.java:197)
at com.gsgenetics.genie.GenomeStructuredGraph$add.call(Unknown Source)
at scripts.groovy.prototypes.read-ccds$_run_closure3.doCall(read-ccds.groovy:53)
at scripts.groovy.prototypes.read-ccds.run(read-ccds.groovy:50)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)

Похоже, некоторые ресурсы не выпускаются, но я не могу понять, что именно и как заставить их выпустить. Я использую это в Windows 7, но я получаю аналогичную ошибку при запуске в Linux.

Вот код, в котором я создаю и использую HTTPBuilder:

import groovyx.net.http.*
import net.sf.json.JSONArray
import net.sf.json.JSONObject

import static groovyx.net.http.ContentType.*
import static groovyx.net.http.Method.*

class NeoClient {

    static final URL = 'http://some IP address'
//    static def http = new HTTPBuilder( URL )
    static net.sf.json.JSONObject query(statement, params=null, success=null, error=null) {
        def http = new HTTPBuilder( URL )
        net.sf.json.JSONObject returnJson = []
        http.request( POST, JSON ) {
            uri.path = '/db/data/cypher/'
            headers.'X-Stream' = 'true'
            requestContentType = JSON
            body =  [ query : statement , params : params ?: [:] ]


            response.success = { resp, json ->
                if (success) success(json)
                else {
                    println "Status ${resp.statusLine} Columns ${json.columns}\nData: ${json.data}"
                }
                returnJson = json
            }

            response.failure = { resp, message ->
                def result=[status:resp.statusLine.statusCode,statusText:resp.statusLine.reasonPhrase]
                result.headers = resp.headers.collect { h -> [ (h.name) : h.value ] }
                result.message = message
                if (error) {
                    error(result)
                } else {
                    println "Status: ${result.status} : ${result.statusText} "
                    println "Headers: ${result.headers}"
                    println "Message: ${result.message}"
                }
                throw new Exception("Neo Client Exception");
            }
        }
    }
}

Обратите внимание, что я попытался создать один экземпляр HTTPBuilder в своем статическом классе NeoClient, а также создать новый экземпляр HTTPBuilder для каждого вызова «запроса», и в любом случае я получаю одно и то же исключение.

Любые идеи очень приветствуются.

Спасибо


person user2791581    schedule 18.09.2013    source источник
comment
Вы должны посмотреть на стороне сервера, чтобы узнать, открыты ли и не закрыты ли несколько соединений с базой данных NoSQL (скажем, MongoDB).   -  person dmahapatro    schedule 18.09.2013


Ответы (1)


Вы должны использовать HTTPBuilder .shutdown для освобождения любых системных ресурсов, удерживаемых этим экземпляром.

Кроме того, создание нового HTTPBuilder для каждого запроса — не лучший подход с точки зрения производительности и управления ресурсами. Лучшим подходом может быть наличие одного экземпляра HttpBuilder, который обрабатывает несколько запросов. Для этого вам нужно будет переопределить поведение HttpBuilder по умолчанию, чтобы использовать диспетчер соединений, безопасный для потоков:

private static class CustomHttpBuilder extends HttpBuilder {
    protected AbstractHttpClient createClient( HttpParams params ) {
       def connManager = new MultiThreadedHttpConnectionManager()
       def connManagerParams = new HttpConnectionManagerParams()
       connManagerParams.maxTotalConnections = 50 // default is 20
       connManagerParams.defaultMaxConnectionsPerHost = 50 // default is 2
       connManager.params = connManagerParams
       new HttpClient(connManager)
   }
} 

Я получил этот пример кода с форума пользователей Grails< /а>. Это позволит вам использовать один экземпляр CustomHttpBuilder для нескольких запросов.

person Dror Bereznitsky    schedule 18.09.2013