Thrift - 每个Socket的不同Handler实例

时间:2011-07-08 09:45:39

标签: c++ sockets cassandra thrift

我在Thrift开发一个'代理'服务器。我的问题是,与代理相关的每个连接都使用Handler的相同实例。代理的客户端实现在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();

有没有办法实现服务器,为每个服务器套接字创建一个Handler的新实例,而不是使用相同的处理程序?

感谢您的任何建议或帮助, @

3 个答案:

答案 0 :(得分:4)

我设法解决了这个问题。有一个已经用Java实现的解决方案。我使用了相同的想法,并在C ++中实现。

我做的第一件事是我创建了一个TProcessorFactory而不是TTransport类。这将处理每个连接的TProcessors。它有一个映射结构,因此它的'get函数为每个TTransport返回相应的TProcessor。每个客户的相应(唯一)TProcessor。

我必须创建一个新的TServer,因此它会接受新创建的参数TProcessorFactory而不是TProcessor。在TServer中还需要更改几个函数调用。你的getProcessor函数将不再返回TProcessor而是返回TProcessorFactory(因此更改返回类型并重命名)。

你要做的最后一件事是实现一个允许实例化的服务器,一个TServer的派生类。我建议使用TNonblockingServer(更难以实现更改)或TThreadPoolServer。你必须改变几个函数调用。在TProcessorFactory上使用带有TTransport参数的get函数来获取所需的TProcessor。 TTransport参数对于每个线程都是唯一的,每个客户端连接由一个线程处理。

还要确保删除旧的TProcessors,因为thrift会重复使用(至少在TNonblockingServer上)TTransport,所以如果你不删除它们并且客户端连接,他可能会在之前的会话中获得一个非活动状态而你可能不会我想要它。如果您使用共享指针,只需将它们从地图结构中删除,当客户端断开连接时,如果thrift不再需要它们,它们将被破坏。

我希望这对任何遇到同样问题的人都有帮助。如果你不知道节俭的内部结构,这里有一个很好的指南:http://diwakergupta.github.com/thrift-missing-guide/

我希望Thrift开发人员在不久的将来能够实现类似但更复杂和抽象的解决方案。

@

答案 1 :(得分:1)

我知道这是一个旧线程,但是如果它对任何人都有用 - 我已经对Thrift的C#实现做出了改变以解决这个问题......

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

除了将TProcessor作为第一个参数传递给线程服务器的旧方法之外,现在可以设置像

这样的东西。
new ThreadPoolServer(processorFactory,serverTransport,
                                    transportFactory,protocolFactory);

其中'processorFactory'是TProcessorFactory。

我已经创建了TPrototypeProcessorFactory&lt; TProcessor,Handler&gt;(object [] handlerArgs),其设置如下:

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

'MyHandlerClass'实现了ThriftGenerated.Iface。 (可选)如果此类接受参数,则可以将它们作为对象数组添加到处理器工厂。 内部 - 对于每个新客户端连接,此处理器工厂将:

  1. 使用任何参数创建“MyHandlerClass”的新实例 提供(使用Activator.CreateInstance)

  2. 如果'MyHandlerClass'实现'TControllingHandler',它将设置它 'server'属性到父TServer(例如,允许控制。) 使用thve客户端的TServer)

  3. 返回ThriftGenerated.Processor(处理程序)的新实例

  4. 因此,对于C#,您将获得 n个客户 - &gt; n个插座 - &gt; n个处理程序 - &gt; n个插座 - &gt; 1台服务器

    我希望这对其他人有用 - 它肯定为我解决了一个问题。

答案 2 :(得分:0)

您可以将其作为通用TCP代理,为每个传入连接打开一个新的TCP连接,而不是让您的代理服务器与thrift相关。