Demon на Delphi

Запросы, планы, оптимизация запросов, ...

Модераторы: kdv, CyberMax

Закрыто
avenger
Сообщения: 141
Зарегистрирован: 25 окт 2005, 11:53

Demon на Delphi

Сообщение avenger » 30 июн 2006, 11:37

Здравствуйте!

Собираюсь писать Демона, для своего чата.
N (10..200) пользователей держат ПОСТОЯННОЕ соединение с демоном (на каждого пользователя создается отдельный поток).
Каждый пользователь может писать сообщения, которые помещаются в таблицу Messages.

Код: Выделить всё

CREATE TABLE Messages (
    MessageID INTEGER NOT NULL, // Generator
    DateTime INTEGER NOT NULL,
    UserFK INTEGER NOT NULL,
    PrivateUID INTEGER,
    "Message" VARCHAR(5000) NOT NULL,
    ReplyMID INTEGER,
    Status SMALLINT NOT NULL CHECK (Status in (0,1,2,3,4)),
    ChannelFK INTEGER NOT NULL,
    CONSTRAINT PK_Messages PRIMARY KEY (MessageID)
);
Как лучше реализовать отсылку новых сообщений пользователям?

У меня есть 2-а варианта:
1. Висит дополнительный поток, который проверяет наличие новых сообщений в таблице. Если есть новые сообщения, то он помещает их в динамическую структуру типа Record (схожа с описанием таблицы Messages). Далее для каждого пользователя в "его" потоке фильтруются "его" сообщения из динамического массива и отсылаются на клиент.
Т.е., в этом случае в каждом из № потоков происходит поиск в массиве.
2. При появлении нового сообщения в каждом из N потоке происходит SELECT из таблицы Messages (100 пользователей - 100 селектов)
Далее сообщения отсылаются клиенту.
Т.е., в этом случае в каждом из № потоков происходит выборка из базе.

P.S. Так как это демон, то с базой работает одно физическое соединение.

В системе есть возможность цитирования, т.е. когда один пользователь цитирует сообщения другого пользователя.

Код: Выделить всё

ALTER TABLE Messages
    ADD CONSTRAINT Messages_Messages_FK_ReplyMID FOREIGN KEY (ReplyMID) REFERENCES Messages (MessageID) ON DELETE CASCADE;
На примере: 100 пользователей.
Пользователь с ID=1 отправил сообщение, которое получило № в базе MessageID = 123. Все 100 пользователей должны получить это сообщение.
Пользователь с ID=2 процетировал сообщение с MessageID = 123. Все 100 пользователей должны получить это сообщение + получить сообщение, которое процецировано.

В первом случае реализации его можно выбрать пробежав по массиву в каждом из 100 потоков.
Во втором случае реализации его можно получить дополнительным Select, т.е. их уже будет 200 (100 раз одно и тоже сообщение + 100 раз одну и туже цитату)

Как рациональнее организовать работу демона?


С уважением, Иван.

kdv
Forum Admin
Сообщения: 6595
Зарегистрирован: 25 окт 2004, 18:07

Сообщение kdv » 30 июн 2006, 12:19

по-моему чат, это когда каждый пишет свое, а некий сервис ВСЕМ показывает ОДНО И ТО ЖЕ. Поэтому не вижу необходимости в 100 запросах, и уж тем более если 100 клиентов, то не делают 100 коннектов к базе. Достаточно пула коннектов в 10 штук.

CyberMax
Заслуженный разработчик
Сообщения: 638
Зарегистрирован: 31 янв 2006, 09:05

Сообщение CyberMax » 30 июн 2006, 12:36

Зачем брать сообщения из базы? По идее, туда должен класть сообщения (для глобальной хистори, например) только сам демон.
Если это не надо, можно вообще без sql-сервера обойтись...

avenger
Сообщения: 141
Зарегистрирован: 25 окт 2005, 11:53

Сообщение avenger » 30 июн 2006, 12:57

Может, я не совсем правильно выразился.

Сейчас вот как все работает. Есть 100 пользователей, у каждого пользователя свой компьютер. Чат написан на php. Сообщение которое написал пользователь отправляется средствами протокола http на сервер. Скрипт выполняется на сервере (input_message.php) и записывает сообщение этого пользователя в базу.

Но пользователь же помимо написания сообщений должен их и получать. Для этого у каждого пользователя каждые 5-ть секунд создается запрос (средствами JS) к серверу (скрипт refresh.php). Сервер выбирает новые сообщения и отправляет их пользователю.

Так вот я хочу написать Демон, к которому пользователи будут подключены ПОСТОЯННО, а не как сейчас каждые 5-ть секунд.

Т.е. на входе у демона 100 ПОСТОЯННЫХ соединений с клиентами + одно соединение с базой => на выходе - новые сообщения каждому клиенту.

Пример:
В базе 100 сообщений:
у пользователя №1 загружено 95 сообщений, у 2 - 98 сообщений.
Тогда у этих 2-х пользователей будет два разных selecta. В первом случае:

Код: Выделить всё

SELECT M.* FROM  MESSAGES M WHERE MESSAGEID > 95 ORDER BY M.DATETIME - 20%
Во втором:

Код: Выделить всё

SELECT M.* FROM  MESSAGES M WHERE MESSAGEID > 98 ORDER BY M.DATETIME - 80%
100 пользователей - по статистике 20% разных селектов. Т.к. 80% выгружает одни и теже данные.

Вопрос: как выбирать данные? - либо 100 селектов (80% которых одинаковые), либо массив, который придется перебрать 100 раз.
Может есть другие варианты, к примеру выгружать таблицу messages в memorytable?
Последний раз редактировалось avenger 30 июн 2006, 13:13, всего редактировалось 4 раза.

avenger
Сообщения: 141
Зарегистрирован: 25 окт 2005, 11:53

Сообщение avenger » 30 июн 2006, 13:00

kdv писал(а):по-моему чат, это когда каждый пишет свое, а некий сервис ВСЕМ показывает ОДНО И ТО ЖЕ.
Основная задача Демона выбрать новые сообщения и отослать клиенту.

CyberMax
Заслуженный разработчик
Сообщения: 638
Зарегистрирован: 31 янв 2006, 09:05

Сообщение CyberMax » 30 июн 2006, 13:14

Я не специалист по созданию чатов, но как проектировщик могу сказать точно - у тебя изначально неправильная архитектура проекта.
Почему у тебя КЛИЕНТ (!) инициирует процесс получения новых сообщений?
Служба чат-сервера (он же демон) при получении сообщения от клиента должна сама отправлять его всем подключенным пользователям (причем только сам текст).
Когда ты сделаешь это, автоматически отпадет сама проблема с выборкой.

avenger
Сообщения: 141
Зарегистрирован: 25 окт 2005, 11:53

Сообщение avenger » 30 июн 2006, 13:17

CyberMax писал(а):Почему у тебя КЛИЕНТ (!) инициирует процесс получения новых сообщений?
Интернет-технология. Только клиент может создать запрос к серверу. А сервер к клиенту запроса создать не может. Как ты работаешь в интернете? - именно ты заходишь на сайт (написав URL в строке браузера), а не сайт заходит к тебе...

avenger
Сообщения: 141
Зарегистрирован: 25 окт 2005, 11:53

Сообщение avenger » 30 июн 2006, 13:19

CyberMax писал(а):Служба чат-сервера (он же демон) при получении сообщения от клиента должна сама отправлять его всем подключенным пользователям (причем только сам текст).
Постоянное соединение именно для этого мне и нужно.
CyberMax писал(а):должна сама отправлять его всем подключенным пользователям (причем только сам текст).
А если это приватное сообщение, т.е. предназначенное только нескольким пользователям.

Вопрос в том как работать с данными Демоном, где их хранить, как выбирать.

kdv
Forum Admin
Сообщения: 6595
Зарегистрирован: 25 окт 2004, 18:07

Сообщение kdv » 30 июн 2006, 13:32

Но пользователь же помимо написания сообщений должен их и получать. Для этого у каждого пользователя каждые 5-ть секунд создается запрос (средствами JS) к серверу (скрипт refresh.php). Сервер выбирает новые сообщения и отправляет их пользователю.
блин. еще раз. чат - это когда ВСЕ пользователи видят ОДНО И ТО ЖЕ (по крайней мере в пределах одной чат-"комнаты").
То есть, выбирать из базы мало того что не должен каждый (!) пользователь, но и даже выбирать из базы тут вообще ничего не надо. У демона должен быть пул последних сообщений активных чатов в памяти, который и рассылается клиентам по их запросам.

kdv
Forum Admin
Сообщения: 6595
Зарегистрирован: 25 окт 2004, 18:07

Сообщение kdv » 30 июн 2006, 13:35

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

CyberMax
Заслуженный разработчик
Сообщения: 638
Зарегистрирован: 31 янв 2006, 09:05

Сообщение CyberMax » 30 июн 2006, 13:37

А, вон как. Я предполагал, что у тебя чат наподобие IRC.
Вот тематическая ссылка:
http://www.wmate.ru/publics/article177.html

P.S. Вопрос "Как рациональнее организовать работу демона?" не входит в понятие "Общие проблемы".
Если нет возражений, закрою тему.

avenger
Сообщения: 141
Зарегистрирован: 25 окт 2005, 11:53

Сообщение avenger » 30 июн 2006, 13:43

Всем спасибо!

Закрыто