Thrift - разные экземпляры Handler для каждого сокета - PullRequest
5 голосов
/ 08 июля 2011

Я занимаюсь разработкой прокси-сервера в Thrift. Моя проблема в том, что каждое соединение, не связанное с прокси-сервером, использует один и тот же экземпляр обработчика. Клиентская реализация прокси находится в Handler, поэтому все клиенты обмениваются данными через одно и то же соединение с конечным сервером.

У меня есть: n клиентов -> n сокетов -> 1 обработчик -> 1 сокет -> 1 сервер Что я хочу реализовать: n клиентов -> n сокетов -> n обработчиков -> n сокетов -> 1 сервер

Теперь проблема в том, что если клиент изменяет «локальный» параметр (что-то, что определяется для каждого клиента независимо) на сервере, другие клиенты также будут работать в измененной среде.

shared_ptr<CassProxyHandler> handler(new CassProxyHandler(adr_s,port_s,keyspace));
shared_ptr<TProcessor> processor(new CassandraProcessor(handler));
shared_ptr<TServerTransport> serverTransport(new TServerSocket(port));
shared_ptr<TTransportFactory> transportFactory(new TFramedTransportFactory());
shared_ptr<TProtocolFactory> protocolFactory(new TBinaryProtocolFactory());
TThreadedServer server(processor, serverTransport, transportFactory, protocolFactory);
server.serve();

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

Спасибо за любые предложения или помощь, @

Ответы [ 3 ]

4 голосов
/ 25 августа 2011

Мне удалось решить эту проблему. В Java уже было реализовано решение. Я использовал ту же идею и реализовал ее в C ++.

Первое, что я сделал, я создал TProcessorFactory вместо класса TTransport. Это обрабатывает TProcessors для каждого соединения. В нем есть структура карты, поэтому ее функция get возвращает соответствующий TProcessor для каждого TTransport. Соответствующий (уникальный) TProcessor для каждого клиента.

Мне пришлось создать новый TServer, чтобы он принимал вновь созданный параметр TProcessorFactory вместо TProcessor. В TServer также необходимо изменить пару вызовов функций. Ваша функция getProcessor больше не будет возвращать TProcessor, а TProcessorFactory (поэтому измените тип возвращаемого значения и переименуйте).

Последнее, что вам нужно сделать, - это реализовать сервер, который позволяет создавать экземпляры, производный класс TServer. Я предлагаю использовать TNonblockingServer (немного сложнее реализовать изменение) или TThreadPoolServer. Вы должны изменить пару вызовов функций. Используйте функцию get в TProcessorFactory с параметром TTransport, чтобы получить TProcessor, где это необходимо. Параметр TTransport уникален для каждого потока, каждое клиентское соединение обрабатывается одним потоком.

Также убедитесь, что вы удалили старые TP-процессоры, потому что они повторно используют (по крайней мере, с TNonblockingServer) TTransport, поэтому, если вы не удалите их и клиент подключится, он, вероятно, получит неактивный предыдущий сеанс, и вы, вероятно, не не хочу этого Если вы используете общие указатели, просто удалите их из структуры карты, когда клиент отключится, и если они больше не нужны для экономии, они будут уничтожены.

Надеюсь, это поможет любому, кто столкнулся с той же проблемой, что и я. Если вы не знаете внутреннюю структуру комиссионных, вот хороший гид: http://diwakergupta.github.com/thrift-missing-guide/

Я надеюсь, что разработчики Thrift собираются реализовать нечто подобное, но более сложное и абстрактное решение в ближайшем будущем.

@

1 голос
/ 30 декабря 2015

Я знаю, что это старый поток, но на случай, если он кому-нибудь пригодится - я внес изменение в реализацию Thrift для C #, чтобы решить эту проблему ...

https://issues.apache.org/jira/browse/THRIFT-3397

В дополнение к старому способу передачи TProcessor в качестве первого аргумента многопоточным серверам, теперь можно настроить что-то вроде

new ThreadPoolServer(processorFactory,serverTransport,
                                    transportFactory,protocolFactory);

Где «ProcessFactory» - это TProcessorFactory.

Я создал TPrototypeProcessorFactory (object [] handlerArgs), который будет настроен так:

TProcessorFactory processorFactory = 
      new TPrototypeProcessorFactory<ThriftGenerated.Processor, MyHandlerClass>(); 

MyHandlerClass реализует ваш ThriftGenerated.Iface. Необязательно, если этот класс принимает аргументы, они могут быть добавлены в виде массива объектов на фабрику процессоров. Внутренне - для каждого нового клиентского соединения эта фабрика процессоров будет:

  1. Создать новый экземпляр 'MyHandlerClass', используя любые аргументы поставляется (с использованием Activator.CreateInstance)

  2. Если MyHandlerClass реализует TControllingHandler, он установит его свойство 'server' для родительского TServer (например, чтобы разрешить управление TServer, использующий thift-клиент)

  3. Возвращает новый экземпляр ThriftGenerated.Processor (обработчик)

Поэтому для C # вы получаете n клиентов -> n сокетов -> n обработчиков -> n сокетов -> 1 сервер

Я надеюсь, что это станет полезным для других людей - это определенно решило проблему для меня.

0 голосов
/ 23 июля 2011

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

...