Grizzly : Speedup the ProtocolFilter response time
Suppose that you are dealing with sql query that you send to a database. Some query could take few seconds to run, that will block a Thread. Even if you have few Threads in your pool, they could all be stuck there too. To avoid that you can use the Producer/Consumer pattern.
Take a look at this snippets.
....
// default Pipeline settings
Pipeline pipeline = new DefaultPipeline();
pipeline.setMaxThreads(5);
controller.setPipeline(pipeline);
// the ParserProtocolFilter that will parse the query
QuoteQueryProtocolFilter protocolParser = new QuoteQueryProtocolFilter();
// the ProtocolFilter that will process the query
QuoteQueryManagerFilter quoteManagerFilter = new QuoteQueryManagerFilter();
final ProtocolChain protocolChain = new DefaultProtocolChain();
protocolChain.addFilter(protocolParser);
protocolChain.addFilter(quoteManagerFilter);
....
Suppose we want to simulate a waiting IO, you can do a sleep for 30 seconds. The effect will be that the manager will wait
public class QuoteQueryManagerFilter implements ProtocolFilter {
public boolean execute(Context context) throws IOException {
String query = (String) context.removeAttribute(ProtocolParser.MESSAGE);
......
// that will simulate that the database take 30 sec to complete the query
try {
Thread.sleep(30000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// call the database
//databaseManager.execute(query);
return true;
}
If you send 10 query to your application, the application will block after 5 query (pipeline threads). The 6th query will be executed after 30 sec.
We can change that behaviour easily.
We will need a Producer and a Consumer with a queue. You can take a LinkedBlockingQueue as a queue.
Here the snippets for the Consumer : (the Thread.sleep is only for testing)
public class Consumer implements IConsumer, Runnable {
protected BlockingQueue<String> blockingQueue;
....
public void run(){
.....
while(!Thread.currentThread().isInterrupted()){
try {
String query = blockingQueue.take();
System.out.println(" took item=" + query);
// now call your database
// that will simulate that the database take 30 sec to complete
try {
Thread.sleep(30000);
} catch (InterruptedException e) {
e.printStackTrace();
}
databaseManager.process(command);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
.....
}
For the Producer, I use my databaseManager.
public class DatabaseManager {
protected BlockingQueue<QueueCommand> blockingQueue;
....
public void init(){
ThreadGroup tg = new ThreadGroup("Producer/Consumer");
quoteConsumer = new QuoteConsumer(this, blockingQueue);
new Thread(tg, quoteConsumer,"QuoteConsumer").start();
}
public void addtoQueue(String query) {
System.out.println("add item=" + query);
blockingQueue.add(query);
}
....
}
and don't forget the change the QuoteQueryManagerFilter :
public boolean execute(Context context) throws IOException {
String query = (String) context.removeAttribute(ProtocolParser.MESSAGE);
......
// call the database
databaseManager.addToQueue(query);
return true;
}
If you try this, the database will still take 30 seconds to run, but your application will be able to handle the requests.
- Login or register to post comments
- Printer-friendly version
- survivant's blog
- 902 reads





