I am trying to develop a high load generating async HttpClient using Jetty 9 HttpClient API. I have written the basic code for doing POST requests
public void connectHttp() throws Exception {
HttpClient client = new HttpClient();
// Configure HttpClient here
client.setMaxConnectionsPerDestination(1000);
try {
client.start();
} catch(Exception e) {
System.out.println("Caught Exception in Client Start : ");
e.printStackTrace();
throw e;
}
try {
for(int i = 0 ; i<1000;i++) {
client.POST("http://localhost:8080/privaterestservice/jersey/privatedata/writedata")
.timeout(3, TimeUnit.SECONDS)
.file(Paths.get("stats_kestrel.txt"),"text/plain").send(new BufferingResponseListener() {
#Override
public void onComplete(Result res) {
System.out.println("Got Response : "+res.isSucceeded());
}
});
}
}
finally {
//client.stop();
}
System.out.println("I am Done!!");
System.out.println(client.getState());
}
I need to bombard the server with lot of requests. But when i run this code, it fails for the last few requests. I checked using Jmeter and there is no problem with the server. Also the code does not stop even after all the requests are completed.
How to make the code quit after all the responses are received instead of the threads going to sleep state?
Any help is greatly appreciated :)
You should use CountDownLatch, something like:
public void connectHttp() throws Exception {
HttpClient client = new HttpClient();
// Configure HttpClient here
client.setMaxConnectionsPerDestination(1000);
CountDownLatch countDown = new CountDownLatch(1000);
try {
client.start();
} catch(Exception e) {
System.out.println("Caught Exception in Client Start : ");
e.printStackTrace();
throw e;
}
try {
for(int i = 0 ; i<1000;i++) {
client.POST("http://localhost:8080/privaterestservice/jersey/privatedata/writedata")
.timeout(3, TimeUnit.SECONDS)
.file(Paths.get("stats_kestrel.txt"),"text/plain").send(new BufferingResponseListener() {
#Override
public void onComplete(Result res) {
System.out.println("Got Response : "+res.isSucceeded());
countDown.countDown();
}
#Override
public void onFailure(Response response, Throwable failure) {
countDown.countDown();
}
});
}
}
finally {
//client.stop();
}
countDown.await();
System.out.println("I am Done!!");
System.out.println(client.getState());
}
It will wait until all responses will complete.
Related
Thanks for this opportunity to ask questions here.
Summary
I have a spring boot application which runs on Tomcat. I'm subscribing ActiveMQ topic with StompClient. After connected i get messages via StompHandler's handleFrame method.
In that method i create MessageUtils which implements Runnable interface. In MessageUtils run method, creating new thread with ExecutorService and do the task generateMessage which send messages to kafka topic.
Problem
When I shutdown the tomcat, threads are still alive. In catalina.out;
A web application appears to have started a thread named [foo] but has failed to stop it. This is very likely to create a memory leak
So the tomcat cannot shutdown properly.
Code Samples
#Service
StompService.class
#EventListener(ApplicationReadyEvent.class)
public void start() {
logI("Service run Client Methods");
List<String> topics = Arrays.asList(topicListString.split(","));
for (String topic : topics) {
StompClient client = new StompClient(topic, username, password, url, topic, bootstrapAddress);
try {
client.run();
runMap.put(topic, client);
boolean connected = client.getSession().isConnected();
logI("Topic: " + topic + " is connected: " + connected);
} catch (InterruptedException e) {
logE("InterruptedException during start of stomp client: ", e);
} catch (TimeoutException e) {
logE("TimeoutException during start of stomp client: ", e);
} catch (ExecutionException e) {
logE("ExecutionException during start of stomp client: ", e);
} catch (Exception e) {
logE("Unexpected exception during start of stomp client: ", e);
}
}
}
StompClient.class
public void run() throws ExecutionException, TimeoutException, InterruptedException {
WebSocketClient client = new StandardWebSocketClient();
WebSocketStompClient stompClient = new WebSocketStompClient(client);
ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();
taskScheduler.afterPropertiesSet();
StompHeaders connectHeaders = new StompHeaders();
connectHeaders.add("login", this.userName);
connectHeaders.add("passcode", this.password);
stompClient.getDefaultHeartbeat();
stompClient.setTaskScheduler(taskScheduler);
stompClient.setMessageConverter(new StringMessageConverter());
stompClient.setAutoStartup(true);
StompSessionHandler sessionHandler = new StompHandler(this.topic, this.bootstrapAddress);
StompSession stompSession = null;
try {
stompSession = stompClient.connect(url, new WebSocketHttpHeaders(), connectHeaders, sessionHandler)
.get(5, TimeUnit.SECONDS);
} catch (Exception e) {
logE("Cannot connect with stomp client." , e);
}
this.setSession(stompSession);
}
StompHandler.class which extends StompSessionHandlerAdapter
#Override
public void handleFrame(StompHeaders headers, Object payload) {
String msg = (String) payload;
MessageUtils message = new MessageUtils();
message.setHeaders(headers);
message.setTopic(topic);
message.setMsg(msg);
message.setBootstrapAddress(bootstrapAddress);
message.run();
}
MessageUtils.class
#Override
public void run() {
ExecutorService executorService = Executors.newSingleThreadExecutor();
executorService.execute(new Runnable() {
public void run() {
generateMessage(getMsg().toString());
}
});
executorService.shutdown();
try {
executorService.awaitTermination(200, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
logI("InterruptedException during await termination", e);
}
}
I am currently in the process of writing an app which has the phone connect to a server.
Both client and server are using the Kryonet framework.
The problem ist the following :
When the server is running and I then start up the client, the client immediately disconnects from the server but the Programm itself keeps running so it is only possible that the client Thread died for whatever reason.
I am using kryonet-2.21 on both server and client.
I tried my code on Android aswell as on pc.
I also tried to troubleshoot everything I could and tried everything I found searching for my problem.
The Client code :
public class LogicHandler extends Thread {
private Client client;
public LogicHandler() {
}
public Client getClient() {
return client;
}
public void run() {
client = new Client(33554432, 33554432);
new Thread(client).start();
try {
getClient().connect(5000, "localhost", 54555, 54777);
} catch (IOException e) {
e.printStackTrace();
}
Packets.register(getClient());
getClient().addListener(new Listener() {
public void received(Connection connection, Object object) {
System.out.println("received " + object);
if (object instanceof ConnectionResponse) {
}
if (object instanceof ScheduleResponse) {
}
}
public void disconnected(Connection connection) {
}
});
getClient().sendTCP(new ConnectionRequest());
}
public static void main(String[] args) {
new LogicHandler().start();
while(true) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("wait");
}
}
}
The Server code :
public class ServerLogicHandler {
private Server server;
private List<Client> clients;
private List<Connection> connections;
public ServerLogicHandler() {
System.out.println("Server is starting!");
server = new Server(33554432, 33554432);
server.start();
try {
server.bind(54555, 54777);
} catch (Exception e) {
server.stop();
System.out.println("Port belegt. Server wird gestoppt!");
System.exit(0);
}
Packets.register(server);
clients = new ArrayList<Client>();
connections = new ArrayList<Connection>();
server.addListener(new Listener() {
public void received(Connection connection, Object object) {
System.out.println("got packet");
if (object instanceof ConnectionRequest) {
System.out.println("size " + connection.sendTCP(new ScheduleResponse()));
}
}
public void disconnected(Connection connection) {
System.out.println("Disco " + connection.getID());
}
public void connected(Connection connection) {
System.out.println(connection.getRemoteAddressTCP().getPort() + " "
+ connection.getRemoteAddressTCP().getAddress());
}
});
System.out.println("Server started!");
}
public Server getServer() {
return server;
}
public static void main(String... args) {
new ServerLogicHandler();
}
}
The client doesn't output anything apart from the 'wait' every second. This means that either the server didn't send any packet or the client closed already. My guess is that the latter happened because the server outputs the following :
Server is starting!
Server started!
54408 /127.0.0.1
Disco 1
When I start a new client the last 2 lines would just repeat e.g. '54890 /127.0.0.1
Disco 2
'
From this I guess that the client closes for whatever reason before even sending any packets. None of my Google searches brang up any success.
I'm trying to implement a Server-Sent-Events Client using Jersey 2.5.1 (can't upgrade to a later version), and the connection keeps getting closed, with no events being read.
I've reduced the code to what I believe is the simplest following possible from the manual, but without success.
I have tested my client against other servers, and the behaviour is the same, so I believe my problem is client based.
The client connects to the resource, and the server starts sending events. But no events are received, and the connection is closed prematurely.
I've also tried using EventSource instead of EventInput, but the results are the same.
Can someone please tell me what I'm missing? Thanks.
Server Code:
#Path("events")
public class SseResource {
/**
* Create stream.
* #return chunkedOutput of events.
*/
#GET
#Produces(SseFeature.SERVER_SENT_EVENTS)
public EventOutput getServerSentEvents() {
System.out.println("Received GetEvent");
final EventOutput eventOutput = new EventOutput();
new Thread(new Runnable() {
#Override
public void run() {
try {
for (int i = 0; i < 10; i++) {
final OutboundEvent.Builder eventBuilder = new OutboundEvent.Builder();
eventBuilder.name("message-to-client");
eventBuilder.data(String.class, "Hello world " + i + "!");
final OutboundEvent event = eventBuilder.build();
eventOutput.write(event);
System.out.println("Wrote event " + i);
// ... code that waits 1 second
try {
TimeUnit.MILLISECONDS.sleep(10);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
} catch (IOException e) {
System.out.println("Error when writing the event" + e);
throw new RuntimeException("Error when writing the event.", e);
} finally {
try {
eventOutput.close();
} catch (IOException ioClose) {
System.out.println("Error when closing the eventOuput" + ioClose);
throw new RuntimeException("Error when closing the event output.", ioClose);
}
}
}
}).start();
return eventOutput;
}
}
Client Code:
import org.glassfish.jersey.media.sse.EventInput;
import org.glassfish.jersey.media.sse.InboundEvent;
import org.glassfish.jersey.media.sse.SseFeature;
...
public final void simpleClientTest() {
final Client client = ClientBuilder.newBuilder().register(SseFeature.class).build();
final WebTarget target = client.target("http://localhost:8182/events");
final EventInput eventInput = target.request().get(EventInput.class);
while (!eventInput.isClosed()) {
final InboundEvent inboundEvent = eventInput.read();
if (inboundEvent == null) {
// connection has been closed
break;
}
System.out.println(inboundEvent.getName() + "; " + inboundEvent.readData(String.class));
}
System.out.println("eventInput finished");
}
I have, finally, found the cause of the problem. The server-startup code (not given above) did not include the SseFeature.class resource. Including here in-case someone else has this issue....
public void startServer() throws IOException {
final URI baseUri = UriBuilder.fromUri("http://0.0.0.0").port(serverPort).build();
System.out.println("Starting media server at: " + baseUri);
final ResourceConfig config = new ResourceConfig(SseResource.class, SseFeature.class);
server = GrizzlyHttpServerFactory.createHttpServer(baseUri, config);
}
I am attempting to use the Okhttp library to connect my android app to my server via API.
My API call is happening on a button click and I am receiving the following android.os.NetworkOnMainThreadException. I understand that this is due the fact I am attempting network calls on the main thread but I am also struggling to find a clean solution on Android as to how make this code use another thread (async calls).
#Override
public void onClick(View v) {
switch (v.getId()){
//if login button is clicked
case R.id.btLogin:
try {
String getResponse = doGetRequest("http://myurl/api/");
} catch (IOException e) {
e.printStackTrace();
}
break;
}
}
String doGetRequest(String url) throws IOException{
Request request = new Request.Builder()
.url(url)
.build();
Response response = client.newCall(request).execute();
return response.body().string();
}
Above is my code, and the exception is being thrown on the line
Response response = client.newCall(request).execute();
I've also read that Okhhtp supports Async requests but I really can't find a clean solution for Android as most seem to use a new class that uses AsyncTask<>?
To send an asynchronous request, use this:
void doGetRequest(String url) throws IOException{
Request request = new Request.Builder()
.url(url)
.build();
client.newCall(request)
.enqueue(new Callback() {
#Override
public void onFailure(final Call call, IOException e) {
// Error
runOnUiThread(new Runnable() {
#Override
public void run() {
// For the example, you can show an error dialog or a toast
// on the main UI thread
}
});
}
#Override
public void onResponse(Call call, final Response response) throws IOException {
String res = response.body().string();
// Do something with the response
}
});
}
& call it this way:
case R.id.btLogin:
try {
doGetRequest("http://myurl/api/");
} catch (IOException e) {
e.printStackTrace();
}
break;
Im trying to return a boolean value from a runnable method within a Thread. I need to know whether a HTTPRequest method succeeded or not. The problem is I know the request is successful but I always get false as the response.
public boolean SmsDelivery;
SmsDelivery=sendSMS(prefix, number);
if(SmsDelivery){
//Do stuff
}
//The method itself
private boolean sendSMSinThread(final String str){
final AtomicBoolean b = new AtomicBoolean(false);
Thread thread = new Thread(new Runnable(){
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost(str);
#Override
public void run() {
try {
// Execute HTTP Post Request
//HttpResponse response = httpclient.execute(httppost);
httpclient.execute(httppost);
b.set(true);
} catch (ClientProtocolException e) {
// TODO Auto-generated catch block
Log.e("Thread:","Unable to generate call"+e);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
Log.e("Thread:","Unable to generate call"+e);
}
}
});
thread.start();
return b.get();
}
UPDATE
Based on the advices here i managed to get the desired result, however, I dont know which method is more suitable for my needs. Can someone recommend whats the best usage in my case? Using AsyncTask or a Thread + join method.
First method is using AsyncTask in the following manner:
SmsTask smsTask = new SmsTask();
try{
smsResult = smsTask.execute(urlString).get();
}catch (InterruptedException e){
e.printStackTrace();
}catch (ExecutionException e){
e.printStackTrace();
}
//the class itself
class SmsTask extends AsyncTask<String,Void, Boolean> {
final AtomicBoolean b = new AtomicBoolean(false);
#Override
protected Boolean doInBackground(String... params) {
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost(params[0]);
try {
httpclient.execute(httppost);
b.set(true);
} catch (IOException e) {
e.printStackTrace();
}
return b.get();
}
#Override
protected void onPostExecute(Boolean result) {
// result holds what you return from doInBackground
Log.i("result from async: ",""+result);
super.onPostExecute(result);
}
}
Second method, almost as I initially posted but with the 'thread.join()' method:
thread.start();
try {
thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
return b.get();
You should wait until task will be performed. In this case you should run this code in single thread (new Thread is useless) or use Android's AsyncTask-like class and process result in onPostExecute method.
You could use some Observer pattern or something.
Something like this:
// have a custom Runnable
public class HTTPRequestRunnable implements Runnable {
HttpClient httpclient;
HttpPost httppost;
private HTTPRequestListner listner;
public HTTPRequestRunnable(String str, HTTPRequestListner listner) {
httpclient = new DefaultHttpClient();
httppost = new HttpPost(str);
this.listner = listner;
}
#Override
public void run() {
try {
// Execute HTTP Post Request
//HttpResponse response = httpclient.execute(httppost);
httpclient.execute(httppost);
if (listner != null)
listner.onSuccess();
} catch (ClientProtocolException e) {
if (listner != null)
listner.onFail();
Log.e("Thread:", "Unable to generate call" + e);
} catch (IOException e) {
if (listner != null)
listner.onFail();
e.printStackTrace();
Log.e("Thread:", "Unable to generate call" + e);
}
}
public void setListner(HTTPRequestListner listner) {
this.listner = listner;
}
/**
* here is your observer class
*/
public interface HTTPRequestListner {
void onSuccess();
void onFail();
}
}
Then use it like this in your method:
public void sendSMSinThread(final String str){
HTTPRequestRunnable httpRequestRunnable = new HTTPRequestRunnable(str,new HTTPRequestListner() {
#Override
public void onSuccess() {
//DO your logic here on success
}
#Override
public void onFail() {
//DO your logic here on fail
}
});
Thread thread = new Thread(httpRequestRunnable);
thread.start();
}
Here you go and i hope it will help you
There are multiple ways to achieve this.
Use a callable, instead of runnable, as callable's call method can return result
Stick to your approach, but before returning the result, call thread.join()
thread.start();
thread.join();
return b.get();
Drawbacks
If there are thousands of SMS to be sent, it will create those many threads.
There is no use of thread creation here as you can the incoming thread itself to send SMS.
Use Runnable and Future.
a. For each SMS create a SendSms object,
b. It will create a maximum of 10 threads.
c. The send SMS and getSMSdelivery will be synchronous events. So for each SMS sent, you can get the delivery status if that's your requirement.
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class SendSms
{
private static ExecutorService pool = Executors.newFixedThreadPool(10);
public boolean submitSms(String message,String phNo)
{
Runnable run = new SendSMSThread(message,phNo);
Future future = pool.submit(run);
try {
if(null ==future.get())
{
return true;
}
} catch (InterruptedException | ExecutionException e) {
// SMS Sending failed.
e.printStackTrace();
return false;
}
return false;
}
private class SendSMSThread implements Runnable
{
String message;
String phNo;
public SendSMSThread(String message,String phNo)
{
this.message = message;
this.phNo = phNo;
}
public void run()
{
//Send SMS
}
}
}
All the above three solution are blocking. So it will keep the threads in BLOCKING state, thereby posing significant threat to scalability of system.
a. Use a BlockingQueue.
b. For each SMS request, add a SMSObject to BlockingQueue.
c. Use a threadpool and process the objects in Queue.
d. Once the SMS is sent successfully, save the result to another data-structure.
e. Use a threadpool, read the data from above data-structure and notify about successful SMS delivery.
Try this
thread.start();
thread.join();
return b.get();