Какова цель асинхронного JAX-RS
Я читаю книгу "RESTful Java с JAX-RS 2.0". Я полностью смущен асинхронным JAX-RS, поэтому я задаю все вопросы в одном. Книга пишет асинхронный сервер следующим образом:
@Path("/customers")
public class CustomerResource {
@GET
@Path("{id}")
@Produces(MediaType.APPLICATION_XML)
public void getCustomer(@Suspended final AsyncResponse asyncResponse,
@Context final Request request,
@PathParam(value = "id") final int id) {
new Thread() {
@Override
public void run() {
asyncResponse.resume(Response.ok(new Customer(id)).build());
}
}.start();
}
}
Netbeans создает асинхронный сервер следующим образом:
@Path("/customers")
public class CustomerResource {
private final ExecutorService executorService = java.util.concurrent.Executors.newCachedThreadPool();
@GET
@Path("{id}")
@Produces(MediaType.APPLICATION_XML)
public void getCustomer(@Suspended final AsyncResponse asyncResponse,
@Context final Request request,
@PathParam(value = "id") final int id) {
executorService.submit(new Runnable() {
@Override
public void run() {
doGetCustomer(id);
asyncResponse.resume(javax.ws.rs.core.Response.ok().build());
}
});
}
private void doGetCustomer(@PathParam(value = "id") final int id) {
}
}
Те, кто не создает фоновые потоки, используют некоторые методы блокировки для хранения объектов ответа для дальнейшей обработки. Этот пример предназначен для отправки котировок акций клиентам:
@Path("qoute/RHT")
public class RHTQuoteResource {
protected List<AsyncResponse> responses;
@GET
@Produces("text/plain")
public void getQuote(@Suspended AsyncResponse response) {
synchronized (responses) {
responses.add(response);
}
}
}
responses
объект будет использоваться совместно с некоторыми фоновыми заданиями, и он отправит котировку всем клиентам, когда он будет готов.
Мои вопросы:
- В примере 1 и 2 поток веб-сервера (тот, который обрабатывает запрос) умирает
и мы создаем еще один фоновый поток. Вся идея
асинхронный сервер предназначен для уменьшения потоков в режиме ожидания. Эти примеры
не уменьшая простоя. Один поток умирает, а другой рождается.
- Я думал, что создание неуправляемых потоков внутри контейнера - плохая идея.
Мы должны использовать только управляемые потоки, используя утилиты concurrency в
Java EE 7.
- Опять одна из идей, стоящих за асинхронными серверами, - масштабирование. Пример 3 не масштабируется, не так ли?
Ответы
Ответ 1
Резюме: Вы слишком задумываетесь об этом.
В примере 1 и 2 поток веб-сервера (тот, который обрабатывает запрос) умирает, и мы создаем другой фоновый поток. Вся идея асинхронного сервера заключается в уменьшении потоков простоя. Эти примеры не уменьшают простоя потоков. Один поток умирает, а другой рождается.
Ничего особенного, честно говоря. В производственной службе вы не будете удерживать исполнителя в приватном поле, как это, но вместо этого оно будет иметь отдельный объект (например, его собственный Spring bean). С другой стороны, такой сложный пример будет довольно сложным для вас, если вы не поймете больше контекста; приложения, состоящие из систем beans/управляемых ресурсов, должны быть построены таким образом с самого начала. Это также не очень важно для мелкомасштабной работы, чтобы быть очень осторожным в этом, и что много веб-приложений.
Захватывающая рука заключается в том, что восстановление с перезагрузки сервера на самом деле не является чем-то, что беспокоит слишком много в первую очередь. Если сервер перезагрузится, вы все равно проиграете все соединения, и если те объекты AsyncResponse
не будут Serializable
каким-либо образом (не гарантируют, что они есть или нет), вы не можете хранить их в базы данных для восстановления. Лучше не беспокоиться об этом слишком много, так как вы не можете много сделать! (Клиенты также собираются тайм-аут через некоторое время, если они не получат ответа, вы не можете держать их на неопределенный срок.)
Я думал, что создание неуправляемых потоков внутри контейнера - плохая идея. Мы должны использовать только управляемые потоки, используя утилиты concurrency в Java EE 7.
Это пример! Поставляйте исполнителя снаружи, но вы хотите, чтобы ваша фантастическая производственная система.
Опять одна из идей, стоящих за асинхронными серверами, - масштабирование. Пример 3 не масштабируется, не так ли?
Он просто помещает объект в список, что совсем не очень медленная операция, особенно по сравнению со стоимостью всех сетей и десериализации/сериализации. То, что он не показывает, это другие части приложения, которые снимают данные с этого списка, выполняют обработку и возвращают результат; они могут быть плохо реализованы и вызывать проблемы, или они могут быть выполнены тщательно, и система работает хорошо.
Если вы можете сделать это лучше в своем коде, непременно сделайте это. (Просто имейте в виду, что вы не можете хранить рабочие элементы в базе данных или, по крайней мере, вы не можете точно знать, что вы можете это сделать, даже если это действительно возможно. Однако я сомневаюсь, что вероятная информация о сетевом соединении TCP там, и это никогда не будет легко хранить и восстанавливать полностью.)
Ответ 2
Я разделяю ваше мнение, выраженное в вопросе 1. Позвольте мне просто добавить немного подробностей о том, что поток веб-сервера не умирает, он обычно поступает из пула и освобождается для другого веб-запроса. Но это существенно не влияет на эффективность асинхронной обработки. В этих примерах асинхронная обработка просто используется для передачи обработки из одного пула потоков в другой. Я не вижу в этом ничего общего.
Но есть один случай использования, где я думаю, что aync имеет смысл, например. когда вы хотите зарегистрировать несколько клиентов для ожидания события и отправить ответ всем им после возникновения события. Это описано в этой статье: http://java.dzone.com/articles/whats-new-jax-rs-20
Ответ 3
Пропускная способность сервиса улучшается, если различные пулы потоков управляют обработкой ввода-вывода запроса и обработкой запроса. Освобождение потока запроса-ввода-вывода, управляемого контейнером, позволяет ему получать следующий запрос, подготовить его для обработки и подачи в пул запросов-потоков-потоков, когда поток обработки запроса был освобожден.