I'm using socket.io-client java library version 1.0.0 (included it via pom.xml)
I want to do a stress/performance-test to a socket.io based server in nodejs (the server seems to work well, not of interest here).
I'm experiencing a very strange behaviour when I establish my connections doing
a Thread.sleep between each new connection.
If establish the connection all at once, there is no problem. The problems occur when I wait (Thead.sleep()) some milliseconds.
Always after the 5th established connection, the connections need unusual long until they are established (connected callback received). The next connection seems to wait until the first one disconnects, but thereafter several connections are established. And a lot of connections aren't established at all, no matter how long I wait. This is really strange. Why does this happen?
It does not matter, if I establish the connections asynychronously (doing each connection in a separate thread starting all threads immediately) or synchronously one after another - it works fine if I don't wait between each new socket/thread creation.
This is the complete code:
import io.socket.client.IO;
import io.socket.client.Socket;
import io.socket.emitter.Emitter;
import java.net.URISyntaxException;
public class SocketStressTest
{
private static final String SOCKET_URI = "http://test.mydomain.com/";
public static int AMOUNT_OF_SOCKETS = 100;
IO.Options opts;
private int connectionCounter = 0;
private int disConnectionCounter = 0;
public static void main(String[] args)
{
new SocketStressTest().start();
}
private void start()
{
opts = new IO.Options();
opts.forceNew = true;
opts.reconnection = false;
Thread thread = new Thread(new Runnable()
{
public void run()
{
initSockets();
}
});
thread.start();
System.out.println("Generated all sockets");
}
private void initSockets()
{
for (int i = 0; i < AMOUNT_OF_SOCKETS; i++)
{
//when I comment out sleeping and try-catch below, everything works fine
try
{
Thread.sleep(400);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
createSocket(i);
}
}
private void createSocket(final int nr)
{
//does not matter if I do this threaded or not:
Thread thread = new Thread(new Runnable()
{
public void run()
{
try
{
System.out.println("nr " + nr + " creating socket");
final Socket socket = IO.socket(SOCKET_URI, opts);
socket
.on(Socket.EVENT_CONNECT, new Emitter.Listener()
{
public void call(Object... args)
{
connectionCounter++;
System.out.println("nr " + nr + " connected id:" + socket.id() + " concounter:" + connectionCounter);
if (connectionCounter == AMOUNT_OF_SOCKETS)
System.out.println("===> ALL connected!");
}
})
.on(Socket.EVENT_DISCONNECT, new Emitter.Listener()
{
public void call(Object... args)
{
disConnectionCounter++;
System.out.println("nr " + nr + " disconnected. discounter=" + disConnectionCounter);
if (disConnectionCounter == AMOUNT_OF_SOCKETS)
System.out.println("<=== ALL DISCONNECTED!");
}
});
socket.connect();
System.out.println("nr " + nr + " connect called");
}
catch (URISyntaxException e)
{
e.printStackTrace();
}
}
});
thread.start();
}
}
This is example output(shortened), waiting 400ms inside the loop:
Generated all sockets
nr 0 creating socket
nr 0 connect called
nr 1 creating socket
nr 1 connect called
nr 0 connected id:7JLvH0hHNF0pg36mAAW3 concounter:1
nr 1 connected id:5fj3I_bFIa1JeUlXAAW4 concounter:2
nr 2 creating socket
nr 2 connect called
nr 2 connected id:RQTLEjftWna2JPuFAAW5 concounter:3
nr 3 creating socket
nr 3 connect called
nr 3 connected id:dg1xL9ddnLqwAlDsAAW6 concounter:4
nr 4 creating socket
nr 4 connect called
nr 4 connected id:y_zIvI4BXdhmEiuwAAW7 concounter:5
nr 5 creating socket
nr 5 connect called
nr 6 creating socket
nr 6 connect called
...
nr 25 creating socket
nr 25 connect called
nr 26 creating socket
nr 26 connect called
nr 0 disconnected. discounter=1
nr 1 disconnected. discounter=2
nr 5 connected id:zCoCg1qG1vJA7pezAAW8 concounter:6
nr 6 connected id:QZJA3yhcXzpRzCwgAAW9 concounter:7
nr 7 connected id:aNZMGdiY8bTeylz3AAW- concounter:8
nr 8 connected id:vitG7xSlEXO5AhnoAAW_ concounter:9
nr 9 connected id:kWirqWwxE5V4ITRiAAXA concounter:10
nr 10 connected id:gCbDdV62pzPRq71qAAXB concounter:11
nr 11 connected id:4ERh1JvC654ky96AAAXC concounter:12
nr 12 connected id:4QMQni7Ohjk0IO7XAAXD concounter:13
nr 27 creating socket
nr 27 connect called
nr 13 connected id:Xb8i-VeDaE_G9N2PAAXE concounter:14
nr 14 connected id:AccfpvKWkWoGY7TEAAXF concounter:15
example output without waiting (commented out the sleep(400) (shortened):
Generated all sockets
nr 0 creating socket
nr 1 creating socket
...
nr 97 creating socket
nr 99 creating socket
nr 24 connect called
nr 21 connect called
nr 52 connect called
...
nr 78 connect called
nr 18 connect called
nr 24 connected id:N4MyGCp4IIWwMtJhAAXV concounter:1
nr 85 connected id:0ahc2QOlGpzPqUwjAAXW concounter:2
nr 68 connected id:W280V6PpH-gUxogOAAXX concounter:3
...
nr 38 connected id:_4c8Ll0cCM_1oQYzAAY2 concounter:98
nr 11 connected id:lIyRiuxK8pmb9voAAAY3 concounter:99
nr 12 connected id:pZkW0Y5DxXgw-Sy6AAY4 concounter:100
===> ALL connected!
I tried it on 2 different machines. Same behaviour.
My goal was to adjust my stresstests with some waiting, but with this behaviour no testing is possible. Anyone any ideas? Am I doing something significantly wrong?
I'm doing the tests on windows 10.
I also created a jar from it and tested it on a debian system. Same behaviour.
I also created a similar javascript test for doing simultanously over 500 socket-connections - works like a charm.
So is there something strange coded in this socket.io java client library that disallows more than 5 connections simultanously?
Related
all.
I'd developed AWS S3 multipart upload function.
And because of this source code, the number of TCP connections is increased slowly.
I found there are received packets data from s3 which is not handled using netstat.
tcp6 263112 0 000.0.000.000:53634 [Storage ip]:443 ESTABLISHED
tcp6 253957 0 000.0.000.000:23800 [Storage ip]:443 ESTABLISHED
Could you help me with letting me know which part is causing the problem?
private void completeMultipartUploadThread(String filePath, String uploadPath, int pageMarker) {
partETagList.clear();
while(true)
{
LOG.debug("pageMarker : " + pageMarker);
PartListing pl = s3.listParts(new ListPartsRequest(bucketName, uploadPath, uploadId).withPartNumberMarker(pageMarker*1000));
List<PartSummary> partList = pl.getParts();
for(PartSummary p : partList) {
partETagList.add(new PartETag(p.getPartNumber(),p.getETag()));
tmpEtagList.add(p.getETag());
}
if(partList.size() < 1000)
break;
else
pageMarker++;
}
this.setCalEtagList(tmpEtagList);
LOG.debug("Total Part Count : "+partETagList.size());
try {
CompleteMultipartUploadRequest completeRequest = new CompleteMultipartUploadRequest(bucketName, uploadPath, uploadId, partETagList);
s3.completeMultipartUpload(completeRequest);
} catch(Exception e) {
AbortMultipartUploadRequest amur = new AbortMultipartUploadRequest(bucketName,uploadPath,uploadId);
s3.abortMultipartUpload(amur);
e.printStackTrace();
}
}
Thanks!
I have recently started using JedisCluster for my application. There is little to no documentation and examples for the same. I tested a use case and the results are not what I expected
public class test {
private static JedisCluster setConnection(HashSet<HostAndPort> IP) {
JedisCluster jediscluster = new JedisCluster(IP, 30000, 3,
new GenericObjectPoolConfig() {{
setMaxTotal(500);
setMinIdle(1);
setMaxIdle(500);
setBlockWhenExhausted(true);
setMaxWaitMillis(30000);
}});
return jediscluster;
}
public static int getIdleconn(Map<String, JedisPool> nodes){
int i = 0;
for (String k : nodes.keySet()) {
i+=nodes.get(k).getNumIdle();
}
return i;
}
public static void main(String[] args) {
HashSet IP = new HashSet<HostAndPort>() {
{
add(new HostAndPort("host1", port1));
add(new HostAndPort("host2", port2));
}};
JedisCluster cluster = setConnection(IP);
System.out.println(getIdleconn(cluster.getClusterNodes()));
cluster.set("Dummy", "0");
cluster.set("Dummy1", "0");
cluster.set("Dummy3", "0");
System.out.println(getIdleconn(cluster.getClusterNodes()));
try {
Thread.sleep(60000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(getIdleconn(cluster.getClusterNodes()));
}
}
The output for this snippet is:
0
3
3
Questions=>
I have set the timeout to 30000 JedisCluster(IP, 30000, 3,new GenericObjectPoolConfig() . I believe this is the connection timeout which means Idle connections are closed after 30 seconds. Although this doesn't seem to be happening. After sleeping for 60 seconds, the number of idle connections is still 3. What I am doing/understanding wrong here? I want the pool to close the connection if not used for more than 30 seconds.
setMinIdle(1). Does this mean that regardless the connection timeout, the pool will always maintain one connection?
I prefer availability more than throughput for my app. What should be the value for setMaxWaitMillis if conn timeout is 30 secs?
Though rare, the app fails with redis.clients.jedis.exceptions.JedisNoReachableClusterNodeException: No reachable node in cluster. This i think is connected to 1. How to prevent this?
30000 or 30 seconds here refers to (socket) timeout; the timeout for single socket (read) operation. It is not related with closing idle connections.
Closing idle connections are controlled by GenericObjectPoolConfig. So check the parameters there.
Yes (mostly).
setMaxWaitMillis is the timeout for getting a connection object from a connection object pool. It is not related to 30 secs and not really solve you anything in terms of availability.
Keep your cluster nodes available.
There has been changes in Jedis related to this. You can try a recent version (4.x, even better 4.2.x).
I am working on homework about thread synchronization. The method reduceLoad() cannot be accessed when I call this method. All print function inside the reduceLoad() method are never called. If I can't run this method, the key will never be released.
It might be caused by Semaphore.accquire() and Semaphore.realse(). So I tried to delete all Semaphore methods that may cause the problem.
Protion of the program result below:
As you can see the program is held after all threads print "disembarks from ferry at port "
..... omit some result here....
Arrive at port 1 with a load of 5 vehicles
Auto 4 arrives at port 0
Ambulance 1 arrives at port 1
Ambulance 1 boards the ferry at port 1
Auto 6 boards on the ferry at port 1
Auto 8 boards on the ferry at port 1
Auto 0 disembarks from ferry at port 1
Auto 2 disembarks from ferry at port 1
Auto 1 disembarks from ferry at port 1
Ambulance 0 disembarks the ferry at port 1
Auto 7 boards on the ferry at port 1
Auto 3 disembarks from ferry at port 1
This is where the function is called
// Arrive at the next port
port = 1 - port;
// wait for ferry arrives
while (fry.getPort() != port) {
try {
sleep(1000);
} catch (Exception e) {
}
}
// disembarking
System.out.println("Auto " + id_auto + " disembarks from ferry at port " + port);
logger.check(fry.getPort() == port, "error unloading at wrong port");
fry.reduceLoad(); // Reduce load
System.out.println("Auto " + id_auto + " successfully disembarks from ferry at port " + port);
This method reduceLoad() should release a key when the ferry is empty, this key is used to notify other threads to continue adding more cars into the ferry
public synchronized void reduceLoad() {
logger.check(load > 0, "error unloading an empty Ferry!");
load = load - 1;
System.out.println("removed load, now " + load);
if (load == 0) {
unloadingDone.release();
}
}
I am developing a multiplayer game in Java built around my own client-server architecture. In short, the client requests a copy of the server's World object 30 times a second and, upon receiving it, sets its client-side copy to the response. This is all done using Java's standard net API.
The issue I am having is that I also store an ArrayList of Player objects in the world, and when I add a Player to this list, the client doesn't get the update. It still receives a copy of the world from the server, but its not up to date.
I experienced a similar problem in a past project that was caused by write/readObject and fixed it by using write/readUnshared, but even that isn't working.
Here's the important stuff from the server end of the communication:
String message;
int sum = 0;
while(active)
{
message = "";
try {
message = in.readUTF();
} catch (IOException e) {
active = false;
System.out.println("Lost connection with client " + socket.getInetAddress());
}
if(message.equals("GETWORLD"))
{
try {
sum++;
if(sum == 100)
main.world.addPlayer(999, 2, 2);
System.out.println("Client requested world (#" + sum + ")");
System.out.println(main.world.players.size());
out.writeUnshared(main.world);
out.flush();
System.out.println("Sent client world (#" + sum + ")");
} catch (IOException e) {
active = false;
System.out.println("Lost connection with client " + socket.getInetAddress());
}
}
if(message.equals("DISCONNECT"))
{
active = false;
System.out.println("Client " + socket.getInetAddress() + " requested disconnect");
}
}
And then the client end:
Object read = null;
int sum = 0;
while(active)
{
try {
Thread.sleep((long)(1000 / 30.0));
if(connected)
{
sum++;
System.out.println("Asking server for world (#" + sum + ")");
out.writeUTF("GETWORLD");
out.flush();
read = in.readUnshared();
if(read instanceof World)
{
World temp = (World)read;
System.out.println(temp.players.size());
frame.panel.updateWorld((World)read);
System.out.println("Got world from server (#" + sum + ")");
}
}
} catch (InterruptedException | ClassNotFoundException e1) {
active = false;
e1.printStackTrace();
} catch (IOException e2) {
active = false;
System.out.println("Lost connection with server # " + socket.getInetAddress());
frame.dispose();
System.exit(0);
}
}
Obviously the sum variable is for debugging.
I further tested this with some output, here's what is scaring me:
Client log:
...
Asking server for world (#99)
1
Got world from server (#99)
Asking server for world (#100)
1
Got world from server (#100)
Asking server for world (#101)
1
Got world from server (#101)
...
Server log:
...
Client requested world (#99)
1
Sent client world (#99)
Client requested world (#100)
2
Sent client world (#100)
Client requested world (#101)
2
Sent client world (#101)
...
You can see here that even though the request numbers match up, there's a clear discrepancy between the number of Player objects in the World object.
Here's the important stuff from the World and Player classes for those curious:
public class World implements Serializable
{
public ArrayList<Room> rooms;
public ArrayList<Player> players;
private QuickMaths qm;
...
public class Player implements Serializable
{
private double xPos;
private double yPos;
private Color color;
int id;
...
I apologize if this is a long yet easy problem. I'm not sure if it's a referencing issue or some other network quirk, but it's really driving me nuts. Thanks in advance.
Your problem is with writeUnshared which is a little misleading.
Read here:
"Note that the rules described above only apply to the base-level
object written with writeUnshared, and not to any transitively
referenced sub-objects in the object graph to be serialized. "
This means that the player object will not be written twice but the old reference to that object in the serialization tree will be used.
The solution to this would be to call the reset method after each write call to ensure that the old written objects will not be referenced again.
So:
out.writeUnshared(main.world);
out.flush();
out.reset();
I am developing eclipse plugin for our organization . We are opening multiple servers[minimum 10 servers] on a user machine using this plugin via eclipse . For starting servers we want port numbers which has been not already binded . For that , I am using serversocket to check this . I think it's a costly operation to open a serversocket object . Internally serversocket will check the port is already binded or not It takes minimum 50 milliseconds . Here is my code to return a free port . Is there any way to find already occupied ports without using OS Commands and opening ServerSocket ?
/**
*Tries 100 times
* #param port
* modes
* 1.increment - 1
* This mode increment the port with your start value . But it's costly operation because each time we open a socket and check the port is free .
* 2.decrement - 2
* Invert of increment.
* 3.random - 3
* Randomly choose based on your starting point
* #return
*/
public static String getDefaultPort(int port , int mode){
int retry = 100;
int random = 3;
int increment = 1;
int decrement = 2;
while(true){
//this is for preventing stack overflow error.
if(retry < 1){ //retries 100 times .
break;
}
if(mode==increment){
port++;
}else if(mode == decrement){
port--;
}else if(mode == random){
port = (int) (port+Math.floor((Math.random()*1000)));
}
if(validate(port+"")){
long end = System.currentTimeMillis();
return port+"";
}
}
return "";
}
public boolean validate(String input) {
boolean status = true;
try {
int port = Integer.parseInt(input);
ServerSocket ss = new ServerSocket(port);
ss.close();
}
catch (Exception e) {
status = false;
}
return status;
}
The quickest way would be to run native netstat command and parse the output. It's available on Windows as well and Linux platform. A typical netstat command output is as follows
Proto Local Address Foreign Address State
TCP MYHOST:8080 MYHOST.mydomain.co.in:0 LISTENING
TCP MYHOST:9090 MYHOST.mydomain.co.in:0 LISTENING
TCP MYHOST:3389 MYHOST.mydomain.co.in:0 LISTENING
TCP MYHOST:7717 MYHOST.mydomain.co.in:0 LISTENING
TCP MYHOST:51114 MYHOST.mydomain.co.in:0 LISTENING
TCP MYHOST:netbios-ssn MYHOST.mydomain.co.in:0 LISTENING
TCP MYHOST:netbios-ssn MYHOST.mydomain.co.in:0 LISTENING
TCP MYHOST:2573 hj-lyncfe.mydomain.co.in:5061 ESTABLISHED
TCP MYHOST:2591 mail.mydomain.co.in:8502 ESTABLISHED
TCP MYHOST:2593 mail.mydomain.co.in:8502 ESTABLISHED
The ports of your interest are in the column Local Address with State in LISTENING