Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Почему может виснуть многопоточный сервер приложений? [D6, IB6.x]


Страницы:   1 2 3

Дмитрий Жуков ©   (2002-07-23 11:59:00) 

На D6 написан сервер приложений, к которому подключаются
несколько клиентов через DCOMConnection или SocketConnection.
Каждый клиент работает со своим RemoteDataModulem, на котором
есть свой Tdatabase и свой TSession. Базой данных является
InterBase 6.0. Также на сервере есть общий DataModul со своим
TDatabase, доступ к TQuery которого для всех потоков реализован
через критическиую секцию.
И вот вся эта конструкция периодически виснет в самые произвольные моменты работы с обхектами типа TQuery. Подскажите, пожалуйста, из-за чего это может происходить?


Polevi   (2002-07-24 10:23:00) [21]

2Digitman ©
Согласен, просто разные архитектуры


Polevi   (2002-07-24 10:12:00) [22]

сорри, не туда сделал пост


Polevi   (2002-07-24 10:09:00) [23]

2Digitman ©
Вот какие изменения внесены мной в SConnect - возможно тут больше 20 строк, но не намного

unit SConnect;
...

const

{ Action Signatures }
...
asSetCallbackInterface=$13;
...

TSocketConnection = class(TStreamedConnection)
...
public
CallbackInterface:IDispatch;
...

procedure TSocketConnection.DoConnect;
begin
...
inherited DoConnect;
SendCallbackInterface;
...
end


procedure TSocketConnection.SendCallbackInterface;
var
Data: IDataBlock;
begin
Data := TDataBlock.Create as IDataBlock;
FInterpreter.WriteVariant(CallbackInterface, Data);
Data.Signature := CallSig or asSetCallbackInterface;
Data := FInterpreter.FSendDataBlock.Send(Data, False);
end;



TDataBlockInterpreter = class
...
public
FCallbackObject:IClientCallbackDisp;
FAppServerModule:IAppServerModule;
...


procedure TDataBlockInterpreter.DoCreateObject(const Data: IDataBlock);
var
V: OleVariant;
VarFlags: TVarFlags;
I: Integer;
begin
V := CreateObject(ReadVariant(VarFlags, Data));
FAppServerModule:=IUnknown(V) as IAppServerModule;
...
end

procedure TDataBlockInterpreter.InterpretData(const Data: IDataBlock);
begin
...
asSetCallbackInterface: DoSetCallbackInterface(Data);
...
end


procedure TDataBlockInterpreter.DoSetCallbackInterface(
const Data: IDataBlock);
var
TmpFlags: TVarFlags;
begin
FCallbackObject:=IClientCallbackDisp(IDispatch(ReadVariant(TmpFlags,Data)));
FAppServerModule.SetClientCallback(FCallbackObject);
end;




Digitman   (2002-07-24 09:57:00) [24]

>Polevi

pooling кодовых потоков хорош лишь в тех случаях, когда не требуется хранить в АП AppServer"а промежуточные результаты контекста логически связанных последовательных запросов одного и того же клиента. Кр.того, невозможно обеспечить гибкость управления транзакциями


Polevi   (2002-07-24 09:37:00) [25]

2Набережных С.
Вот как создается объект в BSS

function TDataBlockInterpreter.CreateObject(const Name: string): OleVariant;
var
ClassID: TGUID;
begin
if (Name[1] = "{") and (Name[Length(Name)] = "}") then
ClassID := StringToGUID(Name) else
ClassID := ProgIDToClassID(Name);
if CanCreateObject(ClassID) then
Result := InternalCreateObject(ClassID) else
raise Exception.CreateResFmt(@SObjectNotAvailable, [GuidToString(ClassID)]);
end;

function TDataBlockInterpreter.InternalCreateObject(const ClassID: TGUID): OleVariant;
var
Unk: IUnknown;
begin
OleCheck(CoCreateInstance(ClassID, nil, CLSCTX_INPROC_SERVER or
CLSCTX_LOCAL_SERVER or CLSCTX_REMOTE_SERVER, IUnknown, Unk));
Result := Unk as IDispatch;
end;

2Digitman ©
Много переключений контекстов, достаточно 4-6 потоков в спуле (зависит от количества процессоров). К тому же гибель потока автоматически означает отключение клиента от сервера, если есть спул - данные приходящие в сокет просто станут обрабатываться другим потоком.


Digitman   (2002-07-24 08:16:00) [26]

>Polevi

>>BSS для каждого клиента создает отдельный поток - это не есть гуд

Почему же ? Поясни ....

Это ж - архитектура, на которой базируется любой мало-мальски серьезный SuperServer


Набережных С.   (2002-07-24 01:03:00) [27]


> Polevi © (24.07.02 00:02)

TApartmentThread - класс, реализующий поток при использовании апартаментной модели потоков в MIDAS. Описан в модуле VCLCom, как и соответствующая фабрика классов. И реализация нескольких клиентов в одном потоке + динамическая оптимизация числа клиентов на поток + пул потоков честно говоря не составляют особого труда. Как я уже упоминал, я плохо знаком со связкой мидас+сокеты, однако запуском потоков занимается фабрика классов, собственно поток - это TApartmentThread.Execute, и, основываясь на своих представлениях о СОМ и маршаллинге, я сильно сомневаюсь, что при SocetConnection что-то происходит иначе. Хотя, кто не ошибается? Да, и кстати, порт завершения здесь не всегда лучшее решение. Все-таки он делался несколько для других задач и здесь его применение снижает гибкость управления, на мой взгляд.


Polevi   (2002-07-24 00:02:00) [28]

2 Набережных С.
Не совсем понял что подразумевается под TApartmentThread..

BSS для каждого клиента создает отдельный поток - это не есть гуд, сейчас сам пытаюсь реализовать вышесказанное мной с помощью портов завершения ввода вывода, есть один нюансик - скорее всего придется писать модули, использующие Free модель, если кому интересно - пишите serg@finco.spb.ru, буду рад пообщаться на эту тему


Набережных С.   (2002-07-23 23:52:00) [29]


> Polevi © (23.07.02 23:19)

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


Polevi   (2002-07-23 23:19:00) [30]

а еще лучше ограничить количество потоков - сделать так чтобы несколько клиентов работали в одном потоке, но для этого надо писать свой BSS


Набережных С.   (2002-07-23 19:12:00) [31]

Можно организовать через BDE, но заморочек будет больше, чем выигрыш. Вкратце так:
С базой общается один поток, например, основной или специально выделенный. Назовем его базовым.
На каждого клиента запускаешь отдельный поток, а лучше по одному на несколько клиентов.
Клиентские потоки ставят свои запросы в очередь базового, тот по мере обработки ставит результаты в очередь соотв. клиентского потока, а тот уже возвращает их клиенту после требуемой обработки.

Все это может что-то дать при, например, медленном транспорте.
Главный недостаток - большое кол-во переключений потоковых контекстов. В принципе, надо оценивать предполагаемую "плотность" общения отдельного клиента с сервером.
P.S. Это придумано прямо сейчас и на практике не проверялось.


Digitman   (2002-07-23 18:55:00) [32]

Опустив на время из рассмотрения BDE (как промежуточное звено) можно сказать, что источник инф-ции - офиц.документация по ПО InterBase.

Касаемо же BDE и VCL-объектов для доступа к БД через BDE - те же ограничения. Вот они - в хэлпе :

If your application may be accessing the same database multiple times simultaneously, you must use multiple sessions to isolate these uses of the database. Failure to do so will disrupt the logic governing transactions on that database (including transactions created for you automatically). Applications risk simultaneous access when running concurrent queries or when using multiple threads. For more information about using multiple sessions, see Managing multiple sessions.

Тема : Using Sessions

TclientDataSet так же не является thread-safe и применять его в AppServer"e нежелательно да и неразумно - это класс для реализации чисто пользовательских ф-ций в "тонком клиенте"


Дмитрий Жуков   (2002-07-23 18:23:00) [33]

Не могли бы Вы указать источник этой информации. Или Вы с этой проблемой воевали сами? А могу ли я в таком случае для работы с общими данными использовать TClientDataset вместо TQuery и модифицировать там данные потоками через критические секции? Ведь TClientDataset насколько я знаю к BDE никаким боком не относится. Или в нем будут такие же проблемы, как и в BDE?


Digitman   (2002-07-23 17:23:00) [34]

Кто девушку обедает , тот ее и танцует)

Связка объектов session + database должна быть индивидуальна для каждого потока. Недопустимо открывать сессию в одном потоке, а открывать базу (с привязкой к этой сессии) и/или обращаться к ее объектам - в другом потоке. Крит.секции и прочие сист.объекты синхронизации не устраняют ограничений данной особенности


Дмитрий Жуков   (2002-07-23 16:24:00) [35]

к сожалению правда жизни такова, что виснет на разных железяках...


Proton   (2002-07-23 13:54:00) [36]

железку бенчмарками гонять пробывали - может проблемма аппаратная ?


Дмитрий Жуков   (2002-07-23 13:44:00) [37]

Каждый TDatabase имеет собственный TSession


kaif   (2002-07-23 12:32:00) [38]

Может, какие-то глобальные переменные или другие ресурсы незащищены... Не помню точно, но по-моему к каждому Query в потоке нужно создавать свой Session...


Alexandr   (2002-07-23 12:30:00) [39]

значит проблема не в том...


Дмитрий Жуков   (2002-07-23 12:25:00) [40]

tDatabase подключается к базе через алиас. В алиасе
Server Name=ntserver:e:\d\ibserver\ansi\search4.gdb


Страницы:   1 2 3

Наверх

Титульная страница Поиск, карта сайта Написать письмо