9

Java Simple Server для микросервисов?1

Серия Java Simple Server

Главное помни - эта либа не подойдёт для разработки сложной бизнес логики.
©Я

Возможно кому-то, кроме меня, пригодится такая реализация java сервера. Это opensource библиотека, распространяемая по лицензии Apache (возможно стоит сменить лицензию?), которая была создана в тот момент, когда стало понятно, что я раз за разом использую один и тот же код. Базируется эта либа на com.sun.net.httpserver и доступна в Maven Central.

Запустим сервер!

Довольно просто и быстро. Сервер запускается на указанном порту и создает thread executor с пулом потоков равным количеству потоков процессора. При запуске вешает родительский поток в ожидание на две секунды. В stdout плюнет вот такое:

Теперь можно проверить работает ли сервер. Делается предельно просто. Открыть браузер и стукнуть по адресу http://localhost:8080/alife. В ответ придет текст life. (Думаю всем понятно, что GET запрос можно не только браузером сделать).

Добавим endpoint!
Main.java

Hello.java

После запуска, в stdout плюнет

Это был пример создания конечной точки с методом GET. С методом POST создается схожим образом.
Для всего остального есть мастеркард HttpHandler. Почему так? Ну мне другое пока не особо нужно, вот и не добавил. По той же причине ответы принимают String (я в основном с json работаю).

Короче кому надо - юзайте на здоровье. Кто хочет помочь - прошу на GitHub проекта. Есть пожелания - пишите тут или в issue на гите.

P.S.
Попытка попасть на habr

Лига программистов

2.1K постов11.9K подписчиков

Правила сообщества

- Будьте взаимовежливы, аргументируйте критику

- Приветствуются любые посты по тематике программирования

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

1
Автор поста оценил этот комментарий

А что, если железо слабенькое и двух секунд будет не достаточно?

раскрыть ветку (1)
2
Автор поста оценил этот комментарий
В этом случае можно самостоятельно добавить задержку потока. А так я буду добавлять в либу возможность указать время задержки и размер пула потоков сервтера.
3
Автор поста оценил этот комментарий

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


Это чисто лайтовый троллинг.) Триггернула страшно звучащая фраза.))

раскрыть ветку (1)
2
Автор поста оценил этот комментарий
Так я не в обиде))
Просто комментарий для тех, кто может испугаться по настоящему)
3
Автор поста оценил этот комментарий

"При запуске вешает родительский поток..."


Вот после этого на секундочку страшно стало))

раскрыть ветку (1)
2
Автор поста оценил этот комментарий
Это необходимо, чтобы успел завестись сервер. В данном случае стоит в отдельном потоке начать запуск сервера и подключение к нему эндпоинтов. Хотя может есть другие предложения?)
показать ответы
1
Автор поста оценил этот комментарий

1. При чём тут микросервисы? Для микросервисов лучше сразу использовать Spring, т.к. в твоей либе нет базы для коммуникации микросервисов, а тащить в Spring экосистему огрызок, который не имеет стартера такое себе. Ведь самое сложное в микросервисах - создание архитектуры развёртывания и взаимодействия и к хеллоу ворлдам она отношения не имеет.

2. Зачем использовать этот многословный огрызок, в котором нет PUT, PATCH, DELETE, также часто используемые и который не умеет нативно работать с JSON и XML. Я понимаю что для всего перечисленного можно написать функционал самому, отдебажить его и поддерживать, но зачем, если всё есть в spring-boot-starter-web.


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


Попробуй сделать из неё тот же spring-boot-starter-web в целях саморазвития, но без подсматривания.

раскрыть ветку (1)
1
Автор поста оценил этот комментарий

Спасибо за комментарий и критику. Такое помогает понять, что нужно другим, а не мне лично)

1. Просто кликбейтный заголовок. Кстати судя по статистике в sonatype - человек 50 решили пощупать либу)
2. Я не заставляю. Пост был создан как раз для получения критики.

Добавление PUT, PATCH, DELETE есть в планах, а до тех пор подразумевается создание HttpHandler.

Писать еще один спринг не вижу смысла. Он уже есть)

Попробуй сделать из неё тот же spring-boot-starter-web в целях саморазвития, но без подсматривания.

starter можно реализовать двумя способами.
1. Явно вызвать метод библиотеки (то как оно есть).
2. Создать в библиотеке static блок в котором описать логику запуска. Все, что останется сделать пользователю - унаследовать свой класс от класса библиотеки (то, что я уже делаю).

А еще благодаря критике я уже выпустил версию 1.6 (отдельным постом расскажу, но на гите уже все есть).

показать ответы
0
Автор поста оценил этот комментарий

Это я читал. Это словесные обороты без явного перечисления плюсов и минусов

раскрыть ветку (1)
1
Автор поста оценил этот комментарий
Ну я явно не возьмусь говорить, что моя либа 100% лучше)
Причины не использовать спринг - необходимость втаскивать в проект тяжелый фреймворк, необходимость написания конфигураций, использование большого кол-во аннотаций (я их не люблю. Личный заеб). При этом спринг запускает встроенный в него веб сервер, который мне не особо нужен.

Например при написании тех-же плагинов для серверов майнкрафт у меня возникает необходимость поднять один - два эндпоинта и при этом не делать плагин слишком тяжелым. В таком случае я нахожу спринг излишним. Моя либа работает с пакетом sun httpserver, который по умолчанию существует в установке java, а значит не тянет лишних зависимостей и не делает плагин тяжелее (в java 17, этот пакет вроде как вырезали). Потом уже я начал использовать свою либу и в других проектах, где не требуется слишком сложная логика и большое кол-во эндпоинтов (возможно это просто привычка)

Вот как-то так)
показать ответы
5
Автор поста оценил этот комментарий

Эээ... а чего бы не создать экземпляр сервера в конструкторе потока, чтобы сразу был доступен объект для навешивания эндпоинтов, а потом уже пусть открывает сокет сколько влезет?

А если порт занят/недоступен текущему юзеру?
А если мне нужно вернуть клиенту ответ не 200?
А если мне нужно какой-то заголовок вернуть?
А если я хочу DELETE?
А если клиент спросит HEAD?
А если я хочу передать в POST QUERY-параметры?
А если клиент мне octet-stream пришлет на двадцать два гигабайта, как я это буду из стринги выковыривать буду(хотя поставим вопрос по другому - как я узнаю, что поток от этого по OOM упал)?
А если я хочу почитать логи?
А как этот сервер выключить?

Без обид, но для заявленной версии 1.5 это чрезвычайно сыро и малофункционально, статический роутинг и отсутствие хотя бы зачатков MVC в 2023 году - ну такое себе. Приемлемо как учебный проект, для продакшена даже в виде сервера под кроватью - категорически противопоказано.

Вот навскидку проект 10-летней давности, умеющий динамические роуты, какую-никакую обработку ошибок и поддерживающий все актуальные методы.

https://github.com/storytellersoftware/java-httpserver/tree/...

раскрыть ветку (1)
1
Автор поста оценил этот комментарий
И да, спасибо за развернутый комментарий!
1
Автор поста оценил этот комментарий
ответный пост

Продолжим собирать критику.

Погнали)


После прочтения комментариев к прошлому посту (особенно от @Deadwire, @MJcom и @user5097930) внес ряд изменений в библиотеку.

Коротко:

  1. Аннотации. Да они появились (аж целых две)

  2. Логирование. Пока не везде, но уже имеется.

  3. Автостартер сервера.

Есть два варианта запуска библиотеки:

  1. С аннотациями

  2. Без аннотаций

С аннотациями

Без наследования

С наследованием

Итого надо запомнить, что:

  1. Метод или класс, который запускает сервер, должен быть аннотирован @InitWebServer.

  2. @InitWebServer принимает два параметра: port и threads. По умолчанию port равен 8080, а threads равен 1.

  3. Метод, который реализует логику конечной точки, должен быть аннотирован @Endpoint.

  4. @Endpoint принимает четыре параметра: path, httpMethod, statusCode и filterContentLength. По умолчанию httpMethod равен HttpMethod.GET, statusCode равен 200, а filterContentLength равен -1.

Без аннотаций

Запуск без аннотаций больше похож на старый подход (тем не менее старая реализация помечена как устаревшая в первую очередь из-за изменений в классе Server. Теперь используется класс ServerNext).

Ничего умнее для названия класса ServerNext в голову не пришло.

Кто хочет - может кинуть в меня тапком. Для этого даже есть канал в дискорде))

Кидать в ZooMMaX`а

https://github.com/ZooMMaX/SimpleServer/wiki/ru

https://github.com/ZooMMaX/SimpleServer

Показать полностью 3
комментарии (32)
5
Автор поста оценил этот комментарий

Эээ... а чего бы не создать экземпляр сервера в конструкторе потока, чтобы сразу был доступен объект для навешивания эндпоинтов, а потом уже пусть открывает сокет сколько влезет?

А если порт занят/недоступен текущему юзеру?
А если мне нужно вернуть клиенту ответ не 200?
А если мне нужно какой-то заголовок вернуть?
А если я хочу DELETE?
А если клиент спросит HEAD?
А если я хочу передать в POST QUERY-параметры?
А если клиент мне octet-stream пришлет на двадцать два гигабайта, как я это буду из стринги выковыривать буду(хотя поставим вопрос по другому - как я узнаю, что поток от этого по OOM упал)?
А если я хочу почитать логи?
А как этот сервер выключить?

Без обид, но для заявленной версии 1.5 это чрезвычайно сыро и малофункционально, статический роутинг и отсутствие хотя бы зачатков MVC в 2023 году - ну такое себе. Приемлемо как учебный проект, для продакшена даже в виде сервера под кроватью - категорически противопоказано.

Вот навскидку проект 10-летней давности, умеющий динамические роуты, какую-никакую обработку ошибок и поддерживающий все актуальные методы.

https://github.com/storytellersoftware/java-httpserver/tree/...

раскрыть ветку (1)
1
Автор поста оценил этот комментарий
Да, да и еще раз да, но.
В этом случае Вы возьмёте например Spring))

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

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

"Втискивать, "тяжелый"  - просто слова, оценочное суждение. Веб-сервер спринга на пустом проекте стартует за 5-6 секунд. Быстрее - мы же не на бирже? - и не надо.

Спринг "тяжелый" из-за обилия доп. билиотек? Так их все равно придется подключать, если захочется сделать хоть боле-менее что-то работающее.


Не нравятся аннотации? Так они заменяют кучу кода. А ты решил провернуть стрелочку и заменить аннотации кучей однотипного кода.


необходимость написания конфигураций

Каких? Если только надо запустить сервер, то добавил зависмость на веб-стартер и все. Конфиг там есть дефолтный. Ну ок, можешь указать порт сервера.


Моя либа работает с пакетом sun httpserver, который по умолчанию существует в установке java, а значит не тянет лишних зависимостей и не делает плагин тяжелее

Место в памяти сейчас чуть ли не бесплатное, то есть килобайты никто скурпулезно не считает.


В общем, выводы:

1. Ты - молодец, взялся за проект и сделал его. Это дано не каждому

2. Ты не побоялся критики (даже справедливой), так что респект.

3. ИМХО - сфера применения твоего проекта непонятна и туманна.

раскрыть ветку (1)
0
Автор поста оценил этот комментарий

1. Спасибо)
2. Глупо её бояться.
3. Тут уж скорее по принципу "авось кому пригодится".

Место в памяти сейчас чуть ли не бесплатное, то есть килобайты никто скурпулезно не считает.

Я тоже так думал, пока не столкнулся с магазином плагинов от SpigotMC (в котором в придачу нельзя обфусцированный jar выложить) и серверами майна на панельных хостингах😵‍💫

1
Автор поста оценил этот комментарий

Название эндпоинта alife - так себе

раскрыть ветку (1)
0
Автор поста оценил этот комментарий
Как переименовать?)
показать ответы
1
Автор поста оценил этот комментарий

Меня смущает, что создает количество потоков, равно количеству ядер процессора (если правильно понял). Классически N - 1

раскрыть ветку (1)
0
Автор поста оценил этот комментарий
Обычно да, но.
Одно ядро (точнее поток процессора - по умолчанию java берет не кол-во ядер, а кол-во потоков камня т.к. нынче существуют multi threading процы) оставляют не тронутым для того, чтобы при высоконагруженных операциях не повесить ПК к чертям собачьим. Моя реализация сервера не предполагает сверхвысоких нагрузок (мы же вроде не майнингом занимаемся). Это не целесообразно по причине существования того же Spring Web, который больше подойдёт для создания тяжелых прог. Тем не менее я буду встраивать настраиваемое кол-во потоков в либу.
1
Автор поста оценил этот комментарий

Скажи, пожалуйста, а в чем выгода использовать этот сервер, а не спринг веб?

раскрыть ветку (1)

Темы

Политика

Теги

Популярные авторы

Сообщества

18+

Теги

Популярные авторы

Сообщества

Игры

Теги

Популярные авторы

Сообщества

Юмор

Теги

Популярные авторы

Сообщества

Отношения

Теги

Популярные авторы

Сообщества

Здоровье

Теги

Популярные авторы

Сообщества

Путешествия

Теги

Популярные авторы

Сообщества

Спорт

Теги

Популярные авторы

Сообщества

Хобби

Теги

Популярные авторы

Сообщества

Сервис

Теги

Популярные авторы

Сообщества

Природа

Теги

Популярные авторы

Сообщества

Бизнес

Теги

Популярные авторы

Сообщества

Транспорт

Теги

Популярные авторы

Сообщества

Общение

Теги

Популярные авторы

Сообщества

Юриспруденция

Теги

Популярные авторы

Сообщества

Наука

Теги

Популярные авторы

Сообщества

IT

Теги

Популярные авторы

Сообщества

Животные

Теги

Популярные авторы

Сообщества

Кино и сериалы

Теги

Популярные авторы

Сообщества

Экономика

Теги

Популярные авторы

Сообщества

Кулинария

Теги

Популярные авторы

Сообщества

История

Теги

Популярные авторы

Сообщества