Отражение для async api

У нас есть 2 службы, давайте позвоним, затем S и G. S выполняет последовательность шагов, например, a, b, c, d, e, f, и на шаге d он выполняет вызов службы G. G часто занимает много времени ( занимает несколько минут) для обработки вызова, что приводит к множеству проблем с тайм-аутом. Чтобы решить эту проблему, мы планируем сделать API G асинхронными. G имеет почти 20 API, которые нужно сделать асинхронными. При разработке у меня есть 2 вопроса:

  1. идеальный способ сделать эти асинхронные - использовать тему SQS или SNS и заставить S слушать их. Но это навязчивое изменение и потребует большого объема рефакторинга кода, в данном случае разделения шагов a, b, c, d, e, f. Мы ищем что-то быстрое. Следовательно, мы планируем сохранить идентификатор запроса в некотором хранилище значений ключа и позволить API G возвращать успех после базовой проверки работоспособности и в фоновом режиме продолжать обработку запроса. Как только это будет сделано, результат обновляется в хранилище "ключ-значение", а G тем временем продолжает опрашивать хранилище через равные промежутки времени. Это похоже на правильный подход?

  2. Чтобы сделать API G асинхронными, нам пришлось бы изменить / написать весь код для всех 20 API. Я думал об открытии одного API, который использует отражение, чтобы определить, какой метод вызывать во время выполнения. Я знаю о проблемах, связанных с отражением, таких как отсутствие обнаружения ошибок во время компиляции, сложность рефакторинга, более низкая производительность, и, поскольку мы вводим отражение в API, обращенном к внешним клиентам, возникнет много проблем с проверкой корректности передаваемого имени метода. Единственный плюс - это делает мой код намного чище с минимальным вмешательством.

Я хотел бы знать, что я должен делать дальше, чтобы решить указанную выше проблему.

Спасибо

Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
0
81
1

Ответы 1

Асинхронность API G не делает его быстрым. Это позволяет запускать его только параллельно с шагами e и f. Если эти шаги не займут много времени, то общее время существенно не уменьшится.

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

Когда вы решите, что распараллеливание имеет смысл, вы можете выбрать для каждой параллельной ветви, будет ли она реализована как поток или как вызов асинхронной процедуры (APC). Потоки легче программировать, но они потребляют некоторый объем памяти (0,5–1,0 мегабайта на поток). Обычно асинхронное программирование стоит применять, если в вашем графике выполнения есть сотни и тысячи параллельных ветвей. Я не вижу в вашей задаче столько параллелизма, поэтому рекомендую использовать потоки вместо асинхронных процедур.

И никогда не используйте опрос - и многопоточность, и асинхронное программирование имеют достаточно средств для своевременной реакции на события.

Что касается второго вопроса, то все равно потребуется некоторая ручная работа. Допустим, у вас есть API:

interface SyncApi {
    boolean isPositive(int v1);
    int sum(int v1, int v2);
}

тогда ты должен написать

interface AsyncApi {
    Future<Boolean> isPositive(int v1);
    Future <Integer> sum(int v1, int v2);
}

Вы можете создать инструмент, который создает AsyncApi.java, когда надоедает SyncApi.java, но в любом случае вам понадобится интерфейс AsyncApi во время компиляции, чтобы иметь возможность писать вызов этого интерфейса.

Адаптер для создания экземпляра AsyncApi при наличии экземпляра SyncApi может быть создан во время выполнения с использованием оборудования Прокси Java.

Я согласен с тем, что это не ускоряет работу, но помогает повысить доступность системы. Мы еще не уверены, какое влияние распараллеливание окажет на бизнес-вариант использования. S не получает много запросов, и, следовательно, мы можем позволить потоку подождать некоторое время, пока результат не будет обработан. И каково ваше мнение по второму вопросу?

katherine 17.10.2018 06:14

Значит, вы не поддерживаете здесь использование отражения?

katherine 17.10.2018 08:50

@katherine class Proxy является частью пакета отражения. То есть, если вы хотите использовать отражение, я предлагаю использовать java.lang.reflect.Proxy.

Alexei Kaigorodov 17.10.2018 09:05

Другие вопросы по теме