Aumentando a eficiência do Web Container usando chamadas Assíncronas
1. Aumentando a eficiência do Web Container usando
chamadas Assíncronas
Trilha – Java
Rafael Torres Coelho Soares (Tuelho)
rafaelcba@gmail.com
@rafaeltuelho
Globalcode – Open4education
2. Agenda
Web 2.0
Web Assíncrona
Servlet 3.0 (JSR 315)
Demo
Globalcode – Open4education
3. Tuelho
Trabalho com Java desde 2004
Desenvolvimento (back-end)
Infraestrutura Java
JBoss.org
rhq-project (contributor)
Red Hat (2010-2012)
Serviços e consultoria
Oracle Fusion Middleware
Weblogic Application Server (consultoria)
Globalcode – Open4education
12. Web Assíncrona: problemas e
motivações
Long Running Requests
Real time updates
Globalcode – Open4education
13. Servlet 3.0: melhorias
JSR 315 (2009)
Asynchronous support
Ease of configuration
Annotations
Pluggability/Modularization: web fragments
Enhancements to existing APIs
Globalcode – Open4education
14. Async Context
Javax.servlet.AsyncContext.start()
“Causes the container to dispatch a thread, possibly from a
managed thread pool, to run the specified Runnable.”
e daí? O que faço com isso?
Globalcode – Open4education
15. Ciclo de uma requsição
assíncrona
① Cliente envia uma requisição
② Servidor invoca um Servlet (nova thread alocada)
③ O Servlet invoca request.startAsync(), salva AsyncContext, e
retorna
④ A thread alocada é liberada, mas o response permanece aberto
⑤ Outra thread (pool separado) utiliza o AsyncContext para
concluir a resposta (asyncContext.complete() ou
asyncContext.dispatch())
⑥ Cliente recebe a resposta do servidor.
Globalcode – Open4education
20. ThreadPoolExecutor
Thread pool
Work queue
Bounded
Unbounded
Handler (saturation policy)
Defaults: RejectedExecutionException runtime exception
Thread Factory
Globalcode – Open4education
21. Executor: main steps
① Criar uma instância de Executor
② Criar uma task
Runnable ou Callable
③ Submeter a task para execução
④ Executar a task
⑤ Finalizar o Executor
Globalcode – Open4education
22. ServletContextListener
@WebListener
public class ServletContextListener implements
javax.servlet.ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent sce) {
Executor executor = new ThreadPoolExecutor(10, 100, 60000L,
TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>(100));
sce.getServletContext().
setAttribute("threadPoolExecutor", executor);
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
ThreadPoolExecutor executor =
(ThreadPoolExecutor)sce.getServletContext()
.getAttribute("threadPoolExecutor");
executor.shutdownNow();
}
} Globalcode – Open4education
Interfaces maisricas e atrativas, maiorusabilidade e interação com o usuário.Evolução dos web browsers: suporte a JavaScript e CSSImpactonacomunicaçãocliente/servidor: maiortráfico de recursos, conexõesmaislongas, maiorconsumo de recursosoperacionais (cpu/mem), tanto no clientecomo no servidor.----- Meeting Notes (19/10/12 13:38) -----modelo síncrono não suporta essa iteratividadeporque não começar a palestra a partir daqui.
Browsers modernos.Novasmídias (mime types).Novasabordagens de utilização: Java Script jánãomaisutilizadoapenasparavalidação de forms…
Http 1.0: paracadarecursosolicitadopelocliente (ex: um gif), um nova conexão no servidorécriada e fechada (cicloreqeust/response).paracada nova conexão: handshake TCP/IP, nova thread (CPU swich e memalloc)…Http 1.1: persistent connection, keep alive: umaconexãopermaneceabertapor um períodoestabelecido e podeserreutilizadaparaváriasrequisições de um mesmocliente.
Thread per connection: a escalabilidadedestemodelodepende da capacidade do hardware. thread pools tem um número de thradsdisponíveisfixo. thread stavationenfileramento de thrads o consumo de memóriaédiretamenteproporcionalaonúmero de thradsalocadas.emambienteslinux x64 uma thread java podeocupar 8mb fora a do heap (stack size: ulimit -s) page-by-page model: clientesolicitamrecursosesporadicamente, ouseja, a conexãopresaaoclientenestecasoésubutilizada (keep alive). diseperdício de recursos (threads em idle state)
Thread per request:nestemodelo a thread nãopermanecebloqueadaaté o fim da conexão (keep alive timeout). a thread éliberadaimediatamenteaofim do processamento da requisição. Nessemomento a thread idle érecicladaparaatenderoutrarequisição e a conexãopersistenteécolocadaemumaárea de seleçãomonitoradapelomecanismo NIO quedetectanovasrequisiçõessemconsumiruma thread separada.Essemodeloescalamuitomaisque o modelobloqueate (per connection) e jáéimplementado de forma transparentepelos java web server maismodernos (glassfish, tomcat, jetty, etc)----- Meeting Notes (19/10/12 13:38) -----mostrar primeiro este slide
Focaremos no primeirocaso (Long Running Requests): comopossoaumentar a eficiência do meu web server nestescasos.Nãopossosimplesmenteignorar o fato de queemalgumponto mina app necessitaesperarporumarespostademorada…----- Meeting Notes (19/10/12 13:38) -----Exem,plo de fotos no facebook ou uma nova msg no gtalkFalar sobre o modelo de comunicação sync.
“Even as a mid-level API ensconced in modern UI component-based Web frameworks and Web services technologies, the incoming Servlet 3.0 specification (JSR 315) will have groundbreaking impact on Java Web application developmentThe Java Servlet specification is the common denominator for most server-side Java Web technologies, including JavaServer Pages (JSP), JavaServer Faces (JSF), numerous Web frameworks, SOAP and RESTful Web services APIs, and newsfeeds. The servlets running underneath these technologies make them portable across all Java Web servers (servlet containers). Any proposed changes to this widely accepted API for handling HTTP communications will potentially affect all affiliated server-side Web technologies.”JSR 315: - Asynchronous support - Ease of configuration - Pluggability - Enhancements to existing APIsTo be read: http://weblogs.java.net/blog/mode/archive/2008/12/asynchronous_su.html
“AsyncContext is a standard way defined in Servlet 3.0 specification to handle HTTP requests asynchronously. Basically HTTP request is no longer tied to an HTTP thread, allowing us to handle it later, possibly using fewer threads.” ref: http://nurkiewicz.blogspot.com.br/2012/05/javaxservletservletrequeststartasync.html
“so the value is in selectively spawning separate threads where async processing can alleviate the burden on the Servlet container thread pool in exchange for a thread pool tuned to application-specific needs.”
Java 5.0 and Thread PoolsJava 5.0 comes with its own thread pool implementation – within the Executor and ExecutorService interfaces. This makes it easier for you to use thread pools within your own programs.An Executor provides application programs with a convenient abstraction for thinking about tasks. Rather than thinking in terms of threads, an application now deals simply with instances of Runnable, which it then passes to an Executor to process.The ExecutorService interface extends the simplistic Executor interface, by adding lifecycle methods to manage the threads in the pool. For instance, you can shutdown the threads in the pool.In addition, while the Executor lets you submit a single task for execution by a thread in the pool, the ExecutorService lets you submit a collection of tasks for execution, or to obtain a Future object that you can use to track the progress of that task.Runnable and CallableThe Executor framework represents tasks using instances of either Runnable or Callable. Runnable‘s run() method is limiting in that it cannot return a value, nor throw a checked exception. Callable is a more functional version, and defines a call() method that allows the return of some computed value, and even throwing an exception if necessary.Controlling your TasksYou can get detailed information about your tasks using the FutureTask class, an instance of which can wrap either a Callable or a Runnable. You can get an instance of this as the return value of the submit() method of an ExecutorService, or you can manually wrap your task in a FutureTask before calling the execute() method.The FutureTask instance, which implements the Future interface, gives you the ability to monitor a running task, cancel it, and to retrieve its result (as the return value of a Callable‘s call() method).” ref: http://www.softwareengineeringsolutions.com/blogs/2010/07/21/implementing-thread-pools-using-java-executors/
“executors and executor services – the key building blocks of aysnchronous processing in Java.Task: umaunidade de trabalho com início, processamento e fim.Thread: umainstância de Task emexecução.Synchronous: a task éexecutadana thread corrente. A thread atualprecisaaguardarsuaconclusãoparaprosseguir.Asynchronous: a thread correntedelega a execução da task paraoutra thread separada.Thread pool: threads prontasparaexecutar tasks. Evita o custo de criar e destruir threads todavezqueuma nova tarefanecessitaserexecutada.At this point, it is important to note that there are three critical mechanisms at work here – there’s the arrival of tasks to be processed (someone is requesting some units of work to be done), there is the submission of tasks to some holding tank, and then there’s the actual processing of each task. The Executor framework in Java separates the latter two mechanisms – submission and processing.
Apóscriarmeu managed pool com usando a API Executor do Java precisoarmazená-lo emalgumcontexto.No caso do servlet o local ideal é o ServletContext.
“Comet (streaming and long polling) always occupies a channel waiting on the server to push back state changes. The same channel can't be reused by the client to send ordinary requests. So Comet applications typically work with two connections per client. If the application stays in thread-per-request mode, an outstanding thread will be associated with each Comet connection, resulting in more threads than the number of users. Comet applications that use the thread-per-request approach can scale only at the prohibitive expense of huge thread consumption.” ref: http://www.javaworld.com/javaworld/jw-02-2009/jw-02-servlet3.htmlTraditional PollingThe browser keeps sending requests to check for new information and the server responds immediately each time.Long Polling“The browser keeps sending requests but the server doesn't respond until it has new information to send. From a client perspective this is identical to traditional polling. From a server perspective this is very similar to a long-running request and can be scaled using the technique discussed in Part 1.How long can the response remain open? Browsers are set to time out after 5 minutes and network intermediaries such as proxies can time out even sooner. So even if no new information arrives, a long polling request should complete regularly to allow the browser to send a new request. This IETF document recommends using a timeout value between 30 and 120 seconds but the actual value to use will likely depend on how much control you have over network intermediaries that separate the browser from server.Long polling can dramatically reduce the number of requests required to receive information updates with low latency, especially where new information becomes available at irregular intervals. However, the more frequent the updates are the closer it gets to traditional polling.” ref: http://blog.springsource.org/2012/05/08/spring-mvc-3-2-preview-techniques-for-real-time-updates/HTTP StreamingThe browser sends a request to the server and the server responds when it has information to send. However, unlike long polling, the server keeps the response open and continues to send more updates as they arrive.WebSocket ProtocolThe browser sends an HTTP request to the server to switch to the WebSocket protocol and the server responds by confirming the upgrade. Thereafter browser and server can send data frames in both directions over a TCP socket.