Если это независимые базы без согласованного распределения данных, разные реплики users-api будут видеть разное состояние. Обычная балансировка запросов начнёт возвращать противоречивые результаты.
Соберите людей по ключу lastname в LinkedHashMap, при коллизии оставляя старое значение. Затем верните список values: так сохранятся первые представители и их порядок.
Поставьте перед users-api балансировщик с единым адресом, на который будет обращаться webApp. Он выбирает доступную реплику по round-robin, least-connections или другому алгоритму.
Stream одноразовый: первый collect завершает его использование, второй нарушает контракт. Соберите результат один раз в List, затем создайте Set из списка.
Будет выведено только [dog, cat, parrot]. У стрима нет терминальной операции, поэтому sorted, peek и map не выполняются; исходный список не изменяется.
Ничего не будет напечатано. Оба map — промежуточные ленивые операции, а терминальной операции в цепочке нет, поэтому обработка элементов не начинается.
Разделите controller и in-memory service. Все изменения списка и получение его снимка защищайте одним lock; наружу возвращайте неизменяемые записи, а не внутреннюю коллекцию.
Начните с падающего теста одного поведения, реализуйте минимальное решение, затем улучшайте структуру при зелёных тестах. Повторяйте цикл для валидации, чтения и ошибок.
Это определяется контрактом API: синхронный ответ содержит готовый результат расчёта, асинхронный — идентификатор принятой операции и способ узнать статус. Наличие очереди внутри не даёт ответа само по себе.
Версионируют прежде всего несовместимые изменения контракта: путь /v1, заголовок или media type. Совместимые добавления часто можно выпускать без новой версии при аккуратном контракте.
Объясните реальные требования, из-за которых выбрали Java/Spring: интеграцию с кодом, специфические политики или компетенции команды. Сам по себе Spring Web не является готовым API Gateway.