Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Java Новый топик    Ответить
Топик располагается на нескольких страницах: [1] 2 3   вперед  Ctrl      все
 Совет по архитектуре Spring MVC  [new]
capfreedom228
Member

Откуда:
Сообщений: 25
Добрый день!
Пишу бэкенд сервера для работы с кассами.
Стек технологий Java/Spring Boot/MySql
В качестве БД взял MySQL (ибо фронт уже на нем).
По сути сервер должен принимать задания в виде json, а кассы эти задания должны выполнять.
Внутри кассы нет очереди и работают они только в одном потоке, грубо говоря так:
Kassa a = new Kassa(settings);
a.open(); // в этот момент больше никто к кассе не может подключиться, open может выполняться несколько секунд
Result r = a.processTask("some json"); // может выполняться несколько секунд
a.close();


Идея была следующая: храним кассы в таблице devices, задания в таблице tasks.
При старте сервера запускаем столько потоков, сколько девайсов в таблице devices.
Потоки с определенным периодом делают селект из таблицы с заданиями и поочередно их выполняют.
Апи для заданий асинхронное, т.е. снаружи прилетает post запрос, создается запись в таблице tasks и назад клиенту отдается id этого задания.
По id задания клиент может отследить прогресс и результат. (GET /task/{id})

В результате получились следующие классы:
Контроллеры - спринговые @RestControllerы:
  • DeviceController
  • TaskController
    Модели - стандартные Entity:
  • Device
  • Task
    Репозитории - спринговые JpaRepository:
  • DeviceRepository
  • TaskRepository
    Сервис:
  • DeviceService - спринговый @Service, при инициализации сервис читает из базы список касс и создает на каждую по потоку (экземпляр DeviceWorker) и запускает их.
    Worker:
  • DeviceWorker - собственно класс наследник thread, который получает и задания из базы и работает с кассой.

    Каким компонентом спринга должен быть DeviceWorker в данной ситуации, чтобы было удобно инжектить внутрь него репозитории и нормально работали транзакции. Я читал и про спринговые TaskExecutor и про Scheduler, но так и не смог понять как их применить в данной ситуации.
    Сейчас я передаю экземпляры репозиториев через конструктор из DeviceService при создании воркеров. Но такое ощущение, что это кривое решение и могут быть проблемы с транзакциями(хотя и работает).
    Репозитории внутри воркера нужны для обновления статуса девайса, таска и записи результата выполнения таска.
  • 26 сен 19, 18:53    [21980229]     Ответить | Цитировать Сообщить модератору
     Re: Совет по архитектуре Spring MVC  [new]
    PetroNotC Sharp
    Member

    Откуда:
    Сообщений: 2089
    capfreedom228
    Апи для заданий асинхронное, т.е. снаружи прилетает post запрос, создается запись в таблице tasks и
    где обоснование нужности асинхронности?
    26 сен 19, 21:41    [21980315]     Ответить | Цитировать Сообщить модератору
     Re: Совет по архитектуре Spring MVC  [new]
    PetroNotC Sharp
    Member

    Откуда:
    Сообщений: 2089
    capfreedom228,
    Post кто делает? Человек?
    Тогда вариант без асинхронности - делает задание и вкладка кассы1 висит 15 сек. Вполне допустимо.
    Надо быстрее, жмакает новую вкладку касса2 и тоже ждет.
    Вариант асинхронный - 2 веб приложения.
    Приложение А просто пишет в бд задание.
    Приложение Б это демон или сервис без ГУИ круглосуточно их выполняет.
    26 сен 19, 22:00    [21980326]     Ответить | Цитировать Сообщить модератору
     Re: Совет по архитектуре Spring MVC  [new]
    capfreedom228
    Member

    Откуда:
    Сообщений: 25
    PetroNotC Sharp,

    Асинхронность нужна, т.к. задания могут выполняться неопределенно долго. И если будет 5 одновременных заданий то последний зависнет больше чем на минуту, а это неприемлимо.
    26 сен 19, 22:18    [21980335]     Ответить | Цитировать Сообщить модератору
     Re: Совет по архитектуре Spring MVC  [new]
    capfreedom228
    Member

    Откуда:
    Сообщений: 25
    PetroNotC Sharp,

    Post из фронта прилетает из браузера.
    26 сен 19, 22:19    [21980336]     Ответить | Цитировать Сообщить модератору
     Re: Совет по архитектуре Spring MVC  [new]
    PetroNotC Sharp
    Member

    Откуда:
    Сообщений: 2089
    capfreedom228
    PetroNotC Sharp,

    Асинхронность нужна, т.к. задания могут выполняться неопределенно долго. И если будет 5 одновременных заданий то последний зависнет больше чемн на минуту, а это неприемлимо.
    контейнер веб сервера при занятом сервлете запускает новый экземпляр.
    Значит 5 вкладок выполнятся вместе за 15 сек.
    Проверь
    26 сен 19, 22:23    [21980341]     Ответить | Цитировать Сообщить модератору
     Re: Совет по архитектуре Spring MVC  [new]
    Дмитрий Мух
    Member

    Откуда: Зеленоград
    Сообщений: 2343
    capfreedom228,

    в мире Java нет аналогов Hangfire?
    26 сен 19, 22:26    [21980346]     Ответить | Цитировать Сообщить модератору
     Re: Совет по архитектуре Spring MVC  [new]
    PetroNotC Sharp
    Member

    Откуда:
    Сообщений: 2089
    Дмитрий Мух
    capfreedom228,

    в мире Java нет аналогов Hangfire?
    в мире шарпа нет контейнера?
    https://ru.m.wikipedia.org/wiki/Контейнер_сервлетов
    26 сен 19, 22:35    [21980356]     Ответить | Цитировать Сообщить модератору
     Re: Совет по архитектуре Spring MVC  [new]
    chpasha
    Member

    Откуда:
    Сообщений: 8441
    capfreedom228
    Каким компонентом спринга должен быть DeviceWorker в данной ситуации, чтобы было удобно инжектить внутрь него репозитории и нормально работали транзакции

    Я бы попробовал обыкновенный спринговый bean с одним публичным методом и аннотацией Async - почитай про нее. Если кол-во девайсов число постоянное на момент старта, то просто настроить taskexecutor с пулом нужного размера
    26 сен 19, 22:53    [21980364]     Ответить | Цитировать Сообщить модератору
     Re: Совет по архитектуре Spring MVC  [new]
    capfreedom228
    Member

    Откуда:
    Сообщений: 25
    PetroNotC Sharp
    capfreedom228
    PetroNotC Sharp,

    Асинхронность нужна, т.к. задания могут выполняться неопределенно долго. И если будет 5 одновременных заданий то последний зависнет больше чемн на минуту, а это неприемлимо.
    контейнер веб сервера при занятом сервлете запускает новый экземпляр.
    Значит 5 вкладок выполнятся вместе за 15 сек.
    Проверь


    касса в 1 поток работает
    26 сен 19, 23:20    [21980386]     Ответить | Цитировать Сообщить модератору
     Re: Совет по архитектуре Spring MVC  [new]
    capfreedom228
    Member

    Откуда:
    Сообщений: 25
    chpasha
    capfreedom228
    Каким компонентом спринга должен быть DeviceWorker в данной ситуации, чтобы было удобно инжектить внутрь него репозитории и нормально работали транзакции

    Я бы попробовал обыкновенный спринговый bean с одним публичным методом и аннотацией Async - почитай про нее. Если кол-во девайсов число постоянное на момент старта, то просто настроить taskexecutor с пулом нужного размера


    хотелось иметь возможность добавлять кассы без рестарта
    26 сен 19, 23:21    [21980387]     Ответить | Цитировать Сообщить модератору
     Re: Совет по архитектуре Spring MVC  [new]
    PetroNotC Sharp
    Member

    Откуда:
    Сообщений: 2089
    capfreedom228,
    Не понял.
    Касса синглетон или можно сделать
    Kassa a = new Kassa(settings);
    Kassa б = new Kassa(settings);
    ?
    26 сен 19, 23:24    [21980390]     Ответить | Цитировать Сообщить модератору
     Re: Совет по архитектуре Spring MVC  [new]
    capfreedom228
    Member

    Откуда:
    Сообщений: 25
    PetroNotC Sharp
    capfreedom228,
    Не понял.
    Касса синглетон или можно сделать
    Kassa a = new Kassa(settings);
    Kassa б = new Kassa(settings);
    ?


    сделать можно, но когда ты вызовешь a.open(); то b.open(); - выдаст ошибку подключения.
    26 сен 19, 23:26    [21980391]     Ответить | Цитировать Сообщить модератору
     Re: Совет по архитектуре Spring MVC  [new]
    PetroNotC Sharp
    Member

    Откуда:
    Сообщений: 2089
    capfreedom228
    выдаст ошибку подключения.
    то есть нужна асинхронность, но касса категорически однопоточна?
    Фиктивная нужна? Зачем?
    26 сен 19, 23:32    [21980395]     Ответить | Цитировать Сообщить модератору
     Re: Совет по архитектуре Spring MVC  [new]
    PetroNotC Sharp
    Member

    Откуда:
    Сообщений: 2089
    Чтобы касса не простаивала))))))))?
    26 сен 19, 23:33    [21980396]     Ответить | Цитировать Сообщить модератору
     Re: Совет по архитектуре Spring MVC  [new]
    PetroNotC Sharp
    Member

    Откуда:
    Сообщений: 2089
    chpasha,
    Выяснили что аннотация не подходит
    26 сен 19, 23:34    [21980398]     Ответить | Цитировать Сообщить модератору
     Re: Совет по архитектуре Spring MVC  [new]
    capfreedom228
    Member

    Откуда:
    Сообщений: 25
    PetroNotC Sharp
    Чтобы касса не простаивала))))))))?


    Такое тз
    26 сен 19, 23:34    [21980399]     Ответить | Цитировать Сообщить модератору
     Re: Совет по архитектуре Spring MVC  [new]
    PetroNotC Sharp
    Member

    Откуда:
    Сообщений: 2089
    capfreedom228
    PetroNotC Sharp
    Чтобы касса не простаивала))))))))?


    Такое тз
    тогда один вариант
    Второй в 21980326
    26 сен 19, 23:37    [21980401]     Ответить | Цитировать Сообщить модератору
     Re: Совет по архитектуре Spring MVC  [new]
    capfreedom228
    Member

    Откуда:
    Сообщений: 25
    PetroNotC Sharp
    capfreedom228
    выдаст ошибку подключения.
    то есть нужна асинхронность, но касса категорически однопоточна?
    Фиктивная нужна? Зачем?


    Чеки электронные и клиенту нет смысла ждать.
    26 сен 19, 23:39    [21980403]     Ответить | Цитировать Сообщить модератору
     Re: Совет по архитектуре Spring MVC  [new]
    PetroNotC Sharp
    Member

    Откуда:
    Сообщений: 2089
    capfreedom228
    Чеки электронные и клиенту нет смысла ждать.
    все хуже. Касса синглетон.
    Решение выше. Удачи.
    26 сен 19, 23:46    [21980404]     Ответить | Цитировать Сообщить модератору
     Re: Совет по архитектуре Spring MVC  [new]
    Sergunka
    Member

    Откуда: Bay Area, CA
    Сообщений: 1967
    chpasha
    capfreedom228
    Каким компонентом спринга должен быть DeviceWorker в данной ситуации, чтобы было удобно инжектить внутрь него репозитории и нормально работали транзакции

    Я бы попробовал обыкновенный спринговый bean с одним публичным методом и аннотацией Async - почитай про нее. Если кол-во девайсов число постоянное на момент старта, то просто настроить taskexecutor с пулом нужного размера


    Можно еще лоадбалансер настроить на пару тройку серверов, чтоб уж совсем все было хорошо.
    27 сен 19, 00:10    [21980417]     Ответить | Цитировать Сообщить модератору
     Re: Совет по архитектуре Spring MVC  [new]
    Sergunka
    Member

    Откуда: Bay Area, CA
    Сообщений: 1967
    capfreedom228
    chpasha
    пропущено...

    Я бы попробовал обыкновенный спринговый bean с одним публичным методом и аннотацией Async - почитай про нее. Если кол-во девайсов число постоянное на момент старта, то просто настроить taskexecutor с пулом нужного размера


    хотелось иметь возможность добавлять кассы без рестарта


    А параметром номер кассы никак нельзя передать?
    27 сен 19, 00:12    [21980418]     Ответить | Цитировать Сообщить модератору
     Re: Совет по архитектуре Spring MVC  [new]
    capfreedom228
    Member

    Откуда:
    Сообщений: 25
    Sergunka
    capfreedom228
    пропущено...


    хотелось иметь возможность добавлять кассы без рестарта


    А параметром номер кассы никак нельзя передать?


    В таске зафиксирован id кассы, т.е. каждый таск предназначен конкретной кассе.
    27 сен 19, 00:32    [21980421]     Ответить | Цитировать Сообщить модератору
     Re: Совет по архитектуре Spring MVC  [new]
    Sergunka
    Member

    Откуда: Bay Area, CA
    Сообщений: 1967
    capfreedom228
    Sergunka
    пропущено...


    А параметром номер кассы никак нельзя передать?


    В таске зафиксирован id кассы, т.е. каждый таск предназначен конкретной кассе.


    Как то уж совсем тупенько. Вот к примеру мой учебный пример на основе пулэкзекьютора написанный пятью годам ранее. Классическая задача Дейкстры - спящий парикмахер

    https://vyatkins.wordpress.com/2013/12/21/sleeping-barber-problem/

    https://github.com/SVyatkin/KafkaSleepingBarberProblem/blob/master/src/main/java/com/sleeping/barber/blockingQueue/BlockingQueueSleepingBarbersPoolExecutor.java

    Нет там большой проблемы передать параметр

    	class Barber extends Thread {
    		BlockingQueue<Integer> queue = null;
    		private String name;
    
    		public Barber(BlockingQueue<Integer> queue, String name) {
    			this.name = name;
    			this.queue = queue;
    		}
    
    		public void run() {
    			while (true) { // runs in an infinite loop
    
    				try {
    					Integer i = this.queue.poll(OFFICE_CLOSE,
    							TimeUnit.MILLISECONDS);
    					if (i == null)
    						break; // barber slept for long time (OFFICE_CLOSE) no
    								// more clients in the queue - close office
    					this.cutHair(i); // cutting...
    
    				} catch (InterruptedException e) {
    				}
    			}
    		}
    
    		public void cutHair(Integer i) {
    			System.out.println("The barber " + this.name
    					+ " is cutting hair for customer #" + i);
    			try {
    				sleep(BARBER_TIME);
    			} catch (InterruptedException ex) {
    			}
    		}
    	}
    


    Что там за таск такой? Код покажи?
    27 сен 19, 04:33    [21980445]     Ответить | Цитировать Сообщить модератору
     Re: Совет по архитектуре Spring MVC  [new]
    mad_nazgul
    Member

    Откуда:
    Сообщений: 4838
    capfreedom228
    Идея была следующая: храним кассы в таблице devices, задания в таблице tasks.
    При старте сервера запускаем столько потоков, сколько девайсов в таблице devices.
    Потоки с определенным периодом делают селект из таблицы с заданиями и поочередно их выполняют.
    Апи для заданий асинхронное, т.е. снаружи прилетает post запрос, создается запись в таблице tasks и назад клиенту отдается id этого задания.
    По id задания клиент может отследить прогресс и результат. (GET /task/{id})


    ИМХО не делать брокер/очередь сообщений на БД, а воспользоваться соответствующим инструментом (MQ, Kafka и т.д.)
    Результат отправлять так же по тому же брокеру сообщений.
    Связь можно сделать, по CorellationID. Создается в сессии контролера и там же храниться, нужен чтобы получить соответствующий ответ.
    27 сен 19, 07:00    [21980455]     Ответить | Цитировать Сообщить модератору
    Топик располагается на нескольких страницах: [1] 2 3   вперед  Ctrl      все
    Все форумы / Java Ответить