Jersey Client opens too many Connections - connection

i run in some problems with my jersey rest api and a client.
This is how im using the methods on a server side:
#POST
#Path("/seed")
#Produces(MediaType.APPLICATION_JSON)
#Consumes(MediaType.APPLICATION_JSON)
public Response addSeed(Seed seed) throws InterruptedException {
if (!Validator.isValidSeed(seed)) {
return Response.status(400).entity("{\"message\":\"Please verify your JSON!\", \"stat\":\"failed\"}")
.build();
}
save(seed);
return Response.status(200).build();
}
If i run a Jersey client in a while(true) loop, there are connections open and won't close. So im running into a problem i have a lot of connections open and my network crashes. So i can't use my server any more. After the connections are closed i can connect to the server.
This is a client:
ClientConfig config = new DefaultClientConfig();
Client client = Client.create(config);
WebResource service = client.resource(getBaseURI()).path("api/seed");
while (true) {
ClientResponse cr = service.header("Content-Type", "application/json").post(ClientResponse.class, seed);
System.out.println(cr);
cr.close();
My Questions are:
What can i do on the server side, to prevent clients open a new connection?
How can i specify a max number of connections?
And how should i implement the jersey client to reuse open connection?

I don't know of a way to limit Jersey resources at the web-app level. If you upgrade to GlassFish EE, you can make your resources EJBs #Stateless #StatelessDeployment(maxInstances=16)
The pile up of connections could be because of Keep-Alive settings. In Tomcat 6 there are two you can tune your connector with:
maxKeepAliveRequests, which defaults to 100. It's the maximum number of HTTP requests which can be pipelined until the connection is closed by the server. Setting this attribute to 1 will disable HTTP/1.0 keep-alive, as well as HTTP/1.1 keep-alive and pipelining. Setting this to -1 will allow an unlimited amount of pipelined or keep-alive HTTP requests.
keepAliveTimeout, which defaults to connectionTimeout which defaults to 60k ms. It it the number of milliseconds this Connector will wait for another HTTP request before closing the connection.

Related

Flickering HttpClient sometimes throwing IOException

I'm using java.net.http.HttpClient.newHttpClient() under Java 19 (Temurin) and perform sendAsync(...) requests from different treads on the same instance. I assume this is ok, as the javadoc states:
Once built, an HttpClient is immutable...
However, some requests fail with:
java.io.IOException: HTTP/1.1 header parser received no bytes
The weird thing is, it depends on the speed of my requests:
Requests every 5 seconds: 30% failure
Requests every 3 seconds: 0% failure
I've written a test for it:
private final HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://..."))
.setHeader("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofByteArray("[]".getBytes()))
.build();
#ParameterizedTest
#ValueSource(ints = {3, 5})
void httpClientTest(int intervalSeconds) throws Exception {
HttpClient httpClient = HttpClient.newHttpClient();
httpClient.sendAsync(request, HttpResponse.BodyHandlers.ofByteArray()).get();
Thread.sleep(Duration.ofSeconds(intervalSeconds));
httpClient.sendAsync(request, HttpResponse.BodyHandlers.ofByteArray()).get();
Thread.sleep(Duration.ofSeconds(intervalSeconds));
httpClient.sendAsync(request, HttpResponse.BodyHandlers.ofByteArray()).get();
Thread.sleep(Duration.ofSeconds(intervalSeconds));
httpClient.sendAsync(request, HttpResponse.BodyHandlers.ofByteArray()).get();
Thread.sleep(Duration.ofSeconds(intervalSeconds));
httpClient.sendAsync(request, HttpResponse.BodyHandlers.ofByteArray()).get();
}
I've already tried the following:
Doing the same with curl on the command line. No requests fail whatever interval I try. So it's probably not a problem with the server.
Running the tests multiple times in parallel. Still the 5-second-intervals fail (then multiple times in parallel). So it's probably not a problem with the server.
Creating an HttpClient.newHttpClient() for every request. No requests fail whatever interval. So it's probably not a problem with the server but with an internal state of the HttpClient (although it claims to be immutable?).
Do you have an idea what I could do, without needing to create a new HttpClient for every request?
Here is the answer for the record: the java.net.HttpClient has a long default HTTP/1.1 keepAlive time, which is longer than what usual servers are configured with. This often results in the server closing idle HTTP/1.1 connections before the client does. If the server closes the connection at about the same time than the client tries to reuse it, some IOException might get raised.
If such exceptions are observed too frequently applications should consider adapting the default keepAlive time in the client to some value shorter than what the servers it connects to are using.
A default value for the HttpClient HTTP/1.1 keepAlive time can be specified on the command line with: -Djdk.httpclient.keepalive.timeout=duration-in-seconds
So for instance - if a server is configured with a keepAlive time of 5s, you could consider supplying -Djdk.httpclient.keepalive.timeout=3 or -Djdk.httpclient.keepalive.timeout=4 on the client's java command line.

How to get the remote host from a rsocket

I now receive an rsocket connection in my spring project, and then I want to get its remote address and port, how should I get it?Similar to using socket.getRemoteSocketAddress() to get the remote address of the socket.
#ConnectMapping
public void connectMapping(RSocketRequester requester) {
// there is a resockt connect, how can i get the remote host from it
RSocket rSocket = requester.rsocket();
// TODO
logger.info("host port");
}
Unfortunately, I think even if you grab the RSocketRequester in #ConnectMapping or #MessageMapping method it is an internal detail. io.rsocket.core.RSocketRequester via RequesterResponderSupport holds the DuplexConnection which represents a connection over tcp, web socket or in-process. It is not exposed via a public API.
This is a worthy request but you will need to file a feature request to get this added unless I'm missing something obvious.
It isn't clear that there is a hook in https://docs.spring.io/spring-boot/docs/2.3.0.RELEASE/api/org/springframework/boot/rsocket/server/RSocketServerCustomizer.html to let you see the DuplexConnection (tcp or web socket etc) as it's established.

Change socket timeout for grails 3 RestBuilder client post request

I have a grails 3 application using the grails.plugins.rest.client plugin to make calls to another API.The api performs some actions and responds in 40 to 50 seconds. The grails application timeout and returns a server error in 30 seconds. How can I change the timeout to wait for a response 60 seconds. My code is as follows:
import grails.plugins.rest.client.RestBuilder
import grails.plugins.rest.client.RestResponse
private RestBuilder rest = new RestBuilder()
RestResponse resp = rest.post(url) {
header 'Accept', "application/json"
json(data)
}
// more code
If you want to increase the socket timeout the grails rest client supports two options.
connectionTimeout
readTimeout
These options are to be set on the RestBuilder when it is instantiated. You cannot change this for request
types which is a shame.
To set them, you can use the below format. But bear in mind that it requires a change to the code and rebuilding the war file.
private RestBuilder rest = new RestBuilder(readTimeout: 180000, proxy: Proxy.NO_PROXY)
180000 = 180 seconds = 3 mins readTimeout
You can also set the connectionTimeout here, but most likely you will be limited by the connectiontimeOut property on the servlet container like Tomcat or CDN like cloudfront or cloudflare.
If you are also using tomcat, you may need to increase the async timeout like in the below example in directive. Hope this helps others looking to solve the same problem.
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
asyncTimeout="60000"
redirectPort="8443" />

Jenkins JNLP port exposes internal ip

We have configured our Jenkins server to use a fixed port and JNLP 4.
Our info sec team has flagged that if one were to open a web browser pointing at the JNLP port, the internal properties below are listed which includes the internal ip of the Jenkins server.
Jenkins-Agent-Protocols:
Jenkins-Version:
Jenkins-Session:
Client:
Server:
Remoting-Minimum-Version:
Is this information necessary? Is this something which can be suppressed?
From the source: https://github.com/jenkinsci/jenkins/blob/master/core/src/main/java/hudson/TcpSlaveAgentListener.java
It looks like there is no mechanism to turn it off, and according to the comments, it seems to be only for testing:
String header = new String(head, Charsets.US_ASCII);
if (header.startsWith("GET ")) {
// this looks like an HTTP client
respondHello(header,s);
return;
}
// otherwise assume this is AgentProtocol and start from the beginning
(...)
/**
* Respond to HTTP request with simple diagnostics.
* Primarily used to test the low-level connectivity.
*/
private void respondHello(String header, Socket s) throws IOException {
(...)
If infosec requires you to turn this off, you might need to open a support ticket with cloudbees.

Connection in RabbitMQ server auto lost after 600s

I'm using rabbitMQ server with amq.
I am having a difficult problem. After leaving the server alone for about 10 min, the connection is lost.
What could be causing this?
If you look at the Erlang client documentation http://www.rabbitmq.com/erlang-client-user-guide.html you will see a section titled Connecting To A Broker
This gives you a few different options that you can specify when setting up your connection to the RabbitMQ server, one of the options is the heartbeat, as you can see the default is 0 so no heartbeat is specified.
I don't know the exact Erlang notation, but you will need to do something like:
{ok, Connection} = amqp_connection:start(#amqp_params_network{heartbeat = 5})
The heartbeat timeout is specified in seconds. So this would cause your consumer to heartbeat back to the server every 5seconds.
Also take a look at this discussion: https://groups.google.com/forum/?fromgroups=#!topic/rabbitmq-discuss/u227xzvqOr8
The default connection timeout for the RabbitMQ connection factory is 600 seconds (at least in the Java client API), hence your 10 minutes. You can change this by specifying to the connection factory your timeout of choice.
It is good practice to ensure your connection is release and recreated after a specific amount of time, to prevent eventual leaks and excessive resournces. Your code should ensure that it seeks a valid connection that is not close to be timed-out, and re-establish a new connection on the ones that did time-out. Overall, adopt a connection-pooling approach.
- Java example:
ConnectionFactory factory = new ConnectionFactory();
factory.setHost(this.serverName);
factory.setPort(this.serverPort);
factory.setUsername(this.userName);
factory.setPassword(this.userPassword);
factory.setConnectionTimeout( YOUR-TIMEOUT-IN-SECONDS );
Connection = factory.newConnection();

Resources