Подтвердить что ты не робот

Какова цель асинхронного 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 не масштабируется, не так ли?
4b9b3361

Ответ 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

Пропускная способность сервиса улучшается, если различные пулы потоков управляют обработкой ввода-вывода запроса и обработкой запроса. Освобождение потока запроса-ввода-вывода, управляемого контейнером, позволяет ему получать следующий запрос, подготовить его для обработки и подачи в пул запросов-потоков-потоков, когда поток обработки запроса был освобожден.