Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Delphi Новый топик    Ответить
 Datasnap client  [new]
RuslanSharipov
Member

Откуда:
Сообщений: 192
Добрый день. На нескольких хостах развернут сервер реализованный через datasnap. На клиенте мне нужно параллельно обращаться к каждому из серверов. Но складывается ощущение что в один момент времени клиент может открыть только одно соединение, и не важно что подключения создаются и осуществляются каждый в своем потоке, потому что как только один из хостов недоступен остальные потоки(TTask) "зависают" и в них просто ничего не происходит пока неработающий хост не прервется по таймауту. Вопрос:
действительно ли это так?возможно нужно выставить какой-то параметр у SQLConnection?или такой проблемы вообще нет и видимо ошибка где то в коде?
12 фев 20, 15:42    [22078449]     Ответить | Цитировать Сообщить модератору
 Re: Datasnap client  [new]
Sinemurius
Member

Откуда:
Сообщений: 123
Я предполагаю, что Ваш клиент уже в значительной степени написан, там много кода и его сложно использовать для отладки. Это так ?
12 фев 20, 16:00    [22078483]     Ответить | Цитировать Сообщить модератору
 Re: Datasnap client  [new]
RuslanSharipov
Member

Откуда:
Сообщений: 192
Sinemurius, да клиент написан, но при отладке я ничего не нахожу. судя по логам второй поток просто не стартует из-за того что в этот момент в другом потоке висит конекшн к другому серверу.
в основном потоке примерно:
procedure TProcessListenerController.AddListener(ANode: string; AAutoStart: Boolean = True; AAutoStop: Boolean = False);
begin
  ....
  ANodeListener := TNodeListener.Create(Self, ANode, FOnLog);  
  if AAutoStart then begin
    ANodeListener.Run(AAutoStop); //здесь TTask.Create, затем старт
  end;
end;

.........

for I := Low(AHosts) to High(AHosts) do begin
    FController.AddListener(AHosts[I], False);
end;


таким образом создаются например 2 потока(первым тот у которого хост отключен), task стартует(у второго тоже успевает вызваться метод старт), и потом второй таск просто не запускается как будто, "скажем так пул потоков лочится" пока первый таск не отвиснет.

Логи:

первый:
12.02.2020 16:09:51.489 ~dbg~ Created
12.02.2020 16:09:51.490 ~dbg~ TryConnect
12.02.2020 16:10:14.755 ~dbg~ connection timeout


второй:
12.02.2020 16:10:12.572 ~dbg~ Created
12.02.2020 16:10:12.572 ~dbg~ TryConnect


Если будет пять хостов и неработающий в списке посередине, первые два запускаются, начинают работать а потом просто виснут пока третий(с неработащим хостом) не вывалится с таймаутом.
12 фев 20, 16:23    [22078522]     Ответить | Цитировать Сообщить модератору
 Re: Datasnap client  [new]
Sinemurius
Member

Откуда:
Сообщений: 123
А не используете Synchronize или что-то в этом роде ?

Я обычно в таких случаях трачу минут 40, чтобы написать крайне упрощенный вариант клиента для отладки.
12 фев 20, 18:20    [22078676]     Ответить | Цитировать Сообщить модератору
 Re: Datasnap client  [new]
RuslanSharipov
Member

Откуда:
Сообщений: 192
Sinemurius, нет не использую
12 фев 20, 18:23    [22078679]     Ответить | Цитировать Сообщить модератору
 Re: Datasnap client  [new]
RuslanSharipov
Member

Откуда:
Сообщений: 192
Переписал с использованием TThread вместо TTask такой проблемы нет..причина не понятна
13 фев 20, 14:41    [22079288]     Ответить | Цитировать Сообщить модератору
 Re: Datasnap client  [new]
AlexeyM123
Member

Откуда:
Сообщений: 166
Может быть это связано с

There's a nasty bug in the System.Threading code that was introduced in Delphi 10.2
Tokyo. I certainly hope that it will be fixed in the next release, as it makes the Parallel
Programming Library hard to use. It sometimes causes new threads not to be created when
you start a task. That forces your tasks to execute one by one, not in parallel.

как это описано у Primož Gabrijelčič
в Delphi High Performance

Сообщение было отредактировано: 13 фев 20, 15:07
13 фев 20, 15:07    [22079307]     Ответить | Цитировать Сообщить модератору
 Re: Datasnap client  [new]
RuslanSharipov
Member

Откуда:
Сообщений: 192
AlexeyM123, нет. Нашел причину. Как оказалось потоки не при чем(просто повезло). Зачем-то в технологии datasnap они открывают конекшн в момент его создания:
function TDBXConnectionFactory.GetConnection(const DBXContext: TDBXContext;
  const ConnectionProperties: TDBXProperties): TDBXConnection;
var
  ConnectionBuilder:  TDBXConnectionBuilder;
  DelegatePath:       TDBXDelegateItem;
  CombinedProperties: TDBXProperties;
begin
  CombinedProperties := CombineDriverProperties(ConnectionProperties);
  DelegatePath := CreateDelegatePath('', CombinedProperties);
  ConnectionBuilder := TDBXConnectionBuilder.Create;
  try
    ConnectionBuilder.FDelegatePath               := DelegatePath;
    ConnectionBuilder.FConnectionFactory          := Self;
    ConnectionBuilder.FDBXContext                 := TDBXContext.Create(DBXContext);
    ConnectionBuilder.FInputConnectionName        := CombinedProperties[TDBXPropertyNames.ConnectionName];
    ConnectionBuilder.FInputConnectionProperties  := ConnectionProperties;
    ConnectionBuilder.FInputUserName              := CombinedProperties[TDBXPropertyNames.UserName];
    ConnectionBuilder.FInputPassword              := CombinedProperties[TDBXPropertyNames.Password];
    Result := ConnectionBuilder.CreateConnection;
    try
      Result.Open;
    except
      Result.Free;
      raise;
    end;
  finally
    ConnectionBuilder.Free;
  end;
end;

где TDBXConnectionFactory - singleton.
А выше в DoConnect:
    ConnectionFactory.Lock;
    try
      FDBXConnection := ConnectionFactory.GetConnection(ConnectionProps);
    finally
      ConnectionFactory.Unlock;
    end;

не понимаю к чему такая реализация, почему бы не пытаться открывать конекшн отдельно от лока, ведь экземпляр уже создан и на фабрику открытие никак не должно влиять. Буду смотреть дальше
14 фев 20, 10:15    [22079782]     Ответить | Цитировать Сообщить модератору
 Re: Datasnap client  [new]
_Vasilisk_
Member

Откуда: Украина, Харьков
Сообщений: 11498
RuslanSharipov
почему бы не пытаться открывать конекшн отдельно от лока
Я больше скажу, из приведенного участка кода лок нужен (если нужен) только для первых двух строк
14 фев 20, 18:24    [22080281]     Ответить | Цитировать Сообщить модератору
 Re: Datasnap client  [new]
X-Cite
Member

Откуда: Минск
Сообщений: 1634
Если вы используете датаснапом автогенерируемые датамодули, ну или что-то подобное делаете сами, то...
Один экземпляр модуля = 1 подключение = 1 поток.
Если надо 10 потоков, то придется создавать 10 экземпляров дата модуля/коннекшенов и.т.п.
14 фев 20, 19:03    [22080320]     Ответить | Цитировать Сообщить модератору
 Re: Datasnap client  [new]
RuslanSharipov
Member

Откуда:
Сообщений: 192
X-Cite, без датамодулей. А так всё верно на каждый поток - свои экземпляры. Проблема именно в реализации создания datasnap connection, и обойти ее нет возможности. Еще и таймаутом подключения нельзя управлять, приходится вначале через TIdTcpClient пробовать открывать коннекшн со своим таймаутом, и если все ок уже переходить к созданию datasnap connection, чтобы избежать длительного лока. Лучше решения не придумал
17 фев 20, 09:39    [22081002]     Ответить | Цитировать Сообщить модератору
Все форумы / Delphi Ответить