Форум программистов, компьютерный форум, киберфорум
Наши страницы
Java EE (J2EE)
Войти
Регистрация
Восстановить пароль
 
 
Рейтинг 5.00/3: Рейтинг темы: голосов - 3, средняя оценка - 5.00
alecss131
31 / 24 / 7
Регистрация: 11.08.2017
Сообщений: 132
1

Общее хранилище для нескольких потоков сервера

21.09.2019, 22:09. Просмотров 608. Ответов 20

Пишу программу, в ней появилась надобность обработки http запросов, значит нужен сервер. Сначала написал на sun.net.httpserver.HttpServer на нем данные хранил в классе EchoHandler implements HttpHandler. Сейчас переделал сервер на java.net.ServerSocket и пока тоже однопоток. Думаю сделать многопоток но возникает проблема, надо передавать в потоки класс с настройками и rsa ключами, а так же где-то хранить данные, общие на весь сервер. А вот с этим проблема.
Использовать внешнюю базу данных не вариант, сложно и слишком громоздко. В первом варианте сервера (назову его просто http) и однопоточном socket держать базу данных можно в виде отдельного статик класса с полями в виде JsonObject и в конструктор обработчика событий передавать класс с ключами.
И еще пару вопросов, не будет проблем если передавать классы в потоки? При условии что потоки только читают поля этих классов (не final) но не пишут в них? К примеру:
Java
1
2
3
4
5
6
Config config = new Config();
config.read();
Keys keys = new Keys();
keys.load();
...
new Thread(new SocketProcessor(s, config, keys)).start(); //s - socket
Проблем в плане что потоки будут одновременно читать поля классов. Каждый раз заново в новом потоке читать ключи из файлов и файл настроек не хочу. Нагрузка на сервер будет не большая (большую часть времени один клиент) и сокет закрывается после отправки ответа на запрос. И в случае однопоточного сервера сервер на сокете создает очередь из обращений к нему или просто отклоняет запросы к нему если занят?
Что мне нужно от хранения данных, видов данных всего 3 пары строк и надо получать данные по запросу на первый элемент пары. В этом плане json подходят идеально со своей структурой {"id1":"name1", "id2":"name2",...}, где обращаясь с конкретным id получаешь на выходе name привязанный к этому id. А при заполнении при одинаковых id запись будет переписываться
Гуглю данные вопросы но ничего конкретно по моим вопросам не нахожу.
0
QA
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
21.09.2019, 22:09
Ответы с готовыми решениями:

Создание webdav-сервера java - Получение файла по его абсолютному пути в хранилище
Необходимо создать программу, возвращающую webdav-протокол для одной операции - получение файла по...

Патерн: общий объект для пула потоков как хранилище информации, кто такой видел
Собственно есть пул потоков и иногда нужно записывать временные данные в потоке, что бы был доступ...

Java общая переменная для нескольких потоков
Всем здравствуйте, вообщем у меня есть массив. Я его хочу расшарить между потоками. import...

Сокет сервера для нескольких клиентов без потоков?
Нужно с помощью select() Помогите разобраться с кодом - в main. //Подключаем библиотеку WinSock...

Использование нескольких потоков для игры
Пишу игру на C++. Мне нужно использовать два объекта: игрока и противника. Противник должен...

20
KEKCoGEN
Эксперт Java
2258 / 2103 / 538
Регистрация: 28.12.2010
Сообщений: 8,304
21.09.2019, 22:51 2
alecss131, а ты не задавал себе вопрос не изобретатешь ли ты велосипед? Может быть все твои проблемы высосаны из пальца и надо всего лишь использовать готовое решение? Как ты думаешь, ты первый человек в мире, которому нужен небольшой веб сервер?
0
alecss131
31 / 24 / 7
Регистрация: 11.08.2017
Сообщений: 132
26.09.2019, 19:17  [ТС] 3
И почему я изобретаю? Мне нужен небольшой интегрированный в программу http сервер. Причем не полноценный http а с урезанным функционалом, он получает get и post запросы и в ответ отдает только либо json строки либо картинки.
Использовать внешнюю базу данных не вижу смысла, у меня программка весит около 1мб (со всеми ресурсами и зависимостями) и тянуть к ней еще зависимости в виде бд размером в несколько моих программ для одной платформы (а у меня кроссплатформа). И данных в базе будет не много (на 1 пользователя 3 пары ключ-значение) и почти все время будет 1 пользователь, но возможны варианты нескольких пользователей с обработкой запросов в разных потоков. В связи с этим возникает необходимость хранить и писать данные потокобезопасно.
0
KEKCoGEN
Эксперт Java
2258 / 2103 / 538
Регистрация: 28.12.2010
Сообщений: 8,304
26.09.2019, 20:35 4
alecss131, ты пытаешься оправдать свои костыли. Если не готов признать проблему, тебе никто не поможет её решить.
0
26.09.2019, 20:35
ViktorFX
296 / 199 / 51
Регистрация: 11.12.2016
Сообщений: 961
26.09.2019, 20:37 5
Цитата Сообщение от alecss131 Посмотреть сообщение
Мне нужен небольшой интегрированный в программу http сервер. Причем не полноценный http а с урезанным функционалом, он получает get и post запросы и в ответ отдает только либо json строки либо картинки.
Тема конечно интересна, и я вообще не в теме. Есть некое представление о сервлетах но о сервере ничего не знаю (в глаза не видел). Вот что нагуглил
https://stackoverflow.com/questions/...ts-in-parallel https://www.programcreek.com/java-ap...od=setExecutor https://codereview.stackexchange.com...g-optimization
но к сожалению еще не читал (пишу с желанием в будущем самому обратить на это внимание).
Касательно темы. Почему нельзя реализовать вами задуманое с помощью обычных сервлетов? Если объяснить идею на пальцах, то запрос доходит до метода, например, doGet(), затем вы делаете синхронайз к объекту DAO (остальные клиенты будут вынуждены ждать пока освободится монитор, а все клиентские запросы асинхронны значит подождут пару секунд, время ожидания ответа больше) и этот объект делает что надо (читает/записывает, возвращает картинку и проч.). Я бы даже сделал несколько таких объектов, например на случай если запрос только на чтение то нет смысла его блочить. Ну и хранил бы в файлах в формате JSON или прости в проперти файле.
0
alecss131
31 / 24 / 7
Регистрация: 11.08.2017
Сообщений: 132
26.09.2019, 20:37  [ТС] 6
Какие костыли? У меня уже все реализовано кроме хранения данных. Готовые базы данных слишком громоздкие и требуют установки доп по, а мне это не нужно.
0
KEKCoGEN
Эксперт Java
2258 / 2103 / 538
Регистрация: 28.12.2010
Сообщений: 8,304
26.09.2019, 20:38 7
Цитата Сообщение от alecss131 Посмотреть сообщение
new Thread(new SocketProcessor(s, config, keys)).start(); //s - socket
этот кусок кода выглядит как издевательство над здравым смыслом....просто в глаза бросилось

Добавлено через 34 секунды
Цитата Сообщение от alecss131 Посмотреть сообщение
Какие костыли? У меня уже все реализовано кроме хранения данных. Готовые базы данных слишком громоздкие и требуют установки доп по, а мне это не нужно.
как скажешь...
0
alecss131
31 / 24 / 7
Регистрация: 11.08.2017
Сообщений: 132
26.09.2019, 20:48  [ТС] 8
Сервер у меня написан уже. Я со встроенного http в яву перешел на сокеты. И хотелось бы использовать его возможность многопоточности, да и я не знаю есть ли у него очередь в случае одного потока. У него поточность меняет всего 1 строку кода.

Добавлено через 5 минут
Какое издевательство? Это код выполняется при подключении клиента. В инете видел кучу примеров сокет серверов (простейших) именно с такой строчкой (я добавил передачу еще классов в процессор).
Изучать неблокирующий сервер для простого сервера не вижу смысла.
По сути тема сводится к потокобезопасности
0
Gungala
bakayaro konoyaro
668 / 341 / 120
Регистрация: 18.08.2013
Сообщений: 1,418
Записей в блоге: 1
26.09.2019, 20:54 9
Цитата Сообщение от KEKCoGEN Посмотреть сообщение
этот кусок кода выглядит как издевательство над здравым смыслом
Поясните, пожалуйста. Я прост ваще не шарю, но мне очень интересно
0
KEKCoGEN
Эксперт Java
2258 / 2103 / 538
Регистрация: 28.12.2010
Сообщений: 8,304
26.09.2019, 21:36 10
Gungala, это не про функционал, а про то чтобы назвать переменную - s, а потом в комментарием пояснить что s это socket вместо того чтобы просто дать переменной вменяемое имя
1
korvin_
2763 / 2034 / 365
Регистрация: 28.04.2012
Сообщений: 6,939
26.09.2019, 22:19 11
Цитата Сообщение от alecss131 Посмотреть сообщение
Какие костыли?
Вот эти костыли:
Цитата Сообщение от alecss131 Посмотреть сообщение
Сначала написал на sun.net.httpserver.HttpServer на нем данные хранил в классе EchoHandler implements HttpHandler. Сейчас переделал сервер на java.net.ServerSocket и пока тоже однопоток
Цитата Сообщение от alecss131 Посмотреть сообщение
Мне нужен небольшой интегрированный в программу http сервер. Причем не полноценный http а с урезанным функционалом, он получает get и post запросы и в ответ отдает только либо json строки либо картинки.
Есть куча микрофреймворков, типа того же sparkjava.com

Цитата Сообщение от alecss131 Посмотреть сообщение
и тянуть к ней еще зависимости в виде бд размером в несколько моих программ для одной платформы (а у меня кроссплатформа).
Для какой одной платформ? Окстись, большинство современных БД достаточно кроссплатформенны.
Во-вторых, возьми, например, h2 и не сношай мозг ни себе, ни людям.

Цитата Сообщение от alecss131 Посмотреть сообщение
у меня программка весит около 1мб (со всеми ресурсами и зависимостями)
А JRE по-твоему ничего не весит?
0
alecss131
31 / 24 / 7
Регистрация: 11.08.2017
Сообщений: 132
08.10.2019, 10:07  [ТС] 12
Всем моим запросам удовлетворяет уже написанный сервер на сокетах. А ваш вариант по объему кода выходит не меньше и еще надо разбираться и подключать лишние библиотеки. Переписывать еще раз сервер не собираюсь.

Как вы не поймете что мне не нужна полноценная база данных? Их еще надо учить и разбираться, что мне совсем не нужно. Мне не нужен весь их функционал, у меня сервер легкий и маленький и часто перезапускается и при перезапуске бд должна очищаться. Все эти sqlite и прочее занимают кучу места (по десятку мегабайт на платформу, в итоге 30мб мусора) и не факт что их упакуешь в jar и используешь их оттуда без распаковки. Бд на диске мне не нужно хранить. Ява рантайм это из другой оперы, без него вообще никак. А сервер у меня опциональная часть программы и весит пару сотен кб, что еще больше делает бессмысленным использование мегабайт внешних бд.

По сути мой вопрос сводится к обмену данными между параллельными потоками одной программы и хранение этой инфы в памяти. А внешние бд это все равно что использование промышленного комбайна для уборки полей на дачном участке где он сам больше всего участка.
0
KEKCoGEN
Эксперт Java
2258 / 2103 / 538
Регистрация: 28.12.2010
Сообщений: 8,304
08.10.2019, 13:44 13
alecss131,
готовые решения это не всегда какие-то тяжелые (ого аж 30Мб в 2019 году) либы.

Вот многопоточный сервер из одного класса
https://gist.githubusercontent.com/s...TTPServer.java

Вот чуть более навороченный с возможностью маппинга
https://github.com/devashish234073/Java-Socket-Http-Server

С БД практические тоже самое. Есть БД в памяти, есть на диске, есть овердофига всяких вариантов под любые нужды
0
alecss131
31 / 24 / 7
Регистрация: 11.08.2017
Сообщений: 132
08.10.2019, 13:56  [ТС] 14
Цитата Сообщение от KEKCoGEN Посмотреть сообщение
Вот многопоточный сервер из одного класса
https://gist.githubusercontent.com/s...TTPServer.java
Знакомый код, нечто очень похожее я и взял в основу своего сервера, вырезал лишний функционал, добавил нужное, а так за исключением обработки самих запросов 3-4 небольших класса (разделил на несколько, один класс для внешнего запуска, один чисто сервер с циклом while и его настройками и один класс для работы с соединениями, чтение из inputstream и запись в outputstream с вызовом между ними класса обработчика запросов).

А вот нужных бд не находил, везде попадается sql, sqllite и прочее. Собственно мой вопрос не в написании сервера, а в написании/поиске простейшей бд.
Требования к бд:
-очень желательно средствами встроенными в яву, либо если либы то jar
-никаких внешних динамических библиотек (например dll) специфичных для каждой ос (что обнаружилось у sql lite)
-хранение базы в памяти (с возможностью сохранять на диск и грузить с диска, но это как плюшка а не основной функционал)
-корректная работа с многопоточным обращением
-простота (основное хранилище состоит из 3 пар ключ-значение, где и ключи и значения типа String и используются данные и из ключей и из значений)
0
KEKCoGEN
Эксперт Java
2258 / 2103 / 538
Регистрация: 28.12.2010
Сообщений: 8,304
08.10.2019, 14:06 15
Цитата Сообщение от alecss131 Посмотреть сообщение
простота (основное хранилище состоит из 3 пар ключ-значение, где и ключи и значения типа String и используются данные и из ключей и из значений)
то есть БД то тебе и не нужна выходит. То есть ты не собираешься использовать SQL чтобы делать выборку данных и другие возможности баз данных, а нужно тебе всего лишь хранилище пар ключ-значение. В памяти или на диске.
Другими словами тебе достаточно обычного кеша.
Вариантов кеша есть много.
По запросу в гугле java simple cache with overflow to disk бери и смотри.
Все из них (как и вообще все зависимости в джава) являются jar-ами

Вот пару примеров
https://jankotek.gitbooks.io/mapdb/content/quick-start/
https://commons.apache.org/proper/commons-jcs/
https://cache2k.org/
https://www.ehcache.org/documentatio...e-options.html
0
xoraxax
2021 / 1792 / 531
Регистрация: 05.07.2013
Сообщений: 8,686
Завершенные тесты: 2
08.10.2019, 14:08 16
Цитата Сообщение от alecss131 Посмотреть сообщение
А вот нужных бд не находил,
Цитата Сообщение от korvin_ Посмотреть сообщение
Во-вторых, возьми, например, h2 и не сношай мозг ни себе, ни людям.
...
0
alecss131
31 / 24 / 7
Регистрация: 11.08.2017
Сообщений: 132
08.10.2019, 14:25  [ТС] 17
Цитата Сообщение от KEKCoGEN Посмотреть сообщение
Другими словами тебе достаточно обычного кеша.
Проблем с многопоточностью не будет? В плане одновременное чтение одних и тех же значений или одновременная запись (но не одного и того же значения) данных.
У меня по сути функционал такой:
первый запрос пользователя по сути это его регистрация, то есть занесение в базу 2-3 пар с данными и все
все последующие запросы используют эти внесенные ранее данные для генерации ответов
То есть каждый пользователь создает о себе 2-3 пары ключ-значение (в зависимости от запроса 2 или 3). И каждая пара хранится в своем месте.
Сейчас для однопотока использую 3 JsonObject и просто добавляю/читаю у них свойства.
0
KEKCoGEN
Эксперт Java
2258 / 2103 / 538
Регистрация: 28.12.2010
Сообщений: 8,304
08.10.2019, 14:38 18
Цитата Сообщение от alecss131 Посмотреть сообщение
Проблем с многопоточностью не будет?
думаю стоит выбрать технологию и далее уже читать про неё.
Все кеши которые я знаю нормально работают с многопоточностью. Было бы странно если бы они не работали так.
0
alecss131
31 / 24 / 7
Регистрация: 11.08.2017
Сообщений: 132
12.10.2019, 12:39  [ТС] 19
KEKCoGEN, А что посоветуете тогда кэш (из всех вариантов понравился cache2k) или использования synchronized-методов/volatile-полей?
Сейчас читаю про synchronized/volatile и не очень понимаю, в разных местах пишут по разному, разное в плане незнакомого мне понятия атомарность.
Вот что я понял: синхронизированные методы не могут выполнятся одновременно разными потоками, а волатиль поля игнорируют кэш потока и сразу в память.
Сейчас для однопотока я использую следующий код
Кликните здесь для просмотра всего текста
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
 
public class Data {
    private static JsonObject namesbase = new JsonObject();
    private static JsonObject modelsbase = new JsonObject();
    private static JsonObject serversbase = new JsonObject();
    
    public static void add(int base, String key, String value) {
        switch (base) {
        case 0 : {
            namesbase.addProperty(key, value);
            break;
        }
        case 1 : {
            modelsbase.addProperty(key, value);
            break;
        }
        case 2 : {
            serversbase.addProperty(key, value);
            break;
        }
        }
    }
    
    public static String get(int base, String key) {
        JsonElement data;
        switch (base) {
        case 0 : {
            data = namesbase.get(key);
            if (data != null) {
                return data.getAsString();
            }
            break;
        }
        case 1 : {
            data = modelsbase.get(key);
            if (data != null) {
                return data.getAsString();
            }
            break;
        }
        }
        return "";
    }
    
    public static boolean contain(int base, String key) {
        switch (base) {
        case 0 : {
            if (namesbase.get(key) != null) {
                return true;
            }
            break;
        }
        case 1 : {
            if (modelsbase.get(key) != null) {
                return true;
            }
            break;
        }
        case 2 : {
            if (serversbase.get(key) != null) {
                return true;
            }
            break;
        }
        }
        return false;
    }
}

И думаю либо поля сделать volatile либо методы synchronized. Ведь по сути это как раз для многопоточности и существует и не нужно использовать сторонние средства. Склоняюсь ближе к volatile но где то читал что оно лучше для базовых типов а у меня JsonObject
0
KEKCoGEN
Эксперт Java
2258 / 2103 / 538
Регистрация: 28.12.2010
Сообщений: 8,304
12.10.2019, 21:33 20
Я даже не знаю как ещё можно донести мысль не изобретать велосипед. Наверно это бесполезно. Пиши синхронизацию. Синхронизация решит твою проблему.
0
12.10.2019, 21:33
Answers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
12.10.2019, 21:33

Общее меню для нескольких форм C++ Builder
Хочу получить одно меню компонента MainMenu на 8 формах. Явно, что копировать обработчики и делать...

Общее управление анимацией для нескольких объектов
Делаю лабу, надо что-бы 3 объекта двигались по одной траектории (через код). Движение сделал. Но...

Для нескольких форм сделать общее контекстное меню
Добрый день. Возникла задача - для нескольких форм сделать общее контекстное меню. Особо не...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2019, vBulletin Solutions, Inc.