2011-07-08 15 views
5

Estoy desarrollando un servidor 'proxy' en Thrift. Mi problema es que cada conexión que entra al proxy utiliza la misma instancia del controlador. La implementación del proxy por parte del cliente está en el controlador, por lo que todos los clientes se comunican a través de la misma conexión al servidor final.Thrift - instancia diferente de Handler para cada socket

Tengo: n clientes -> n tomas de corriente -> 1 controlador -> 1 socket -> 1 servidor Lo que quiero implementar: n clientes -> n tomas de corriente -> n controladores -> n sockets -> 1 servidor

Ahora el problema es que si un cliente cambia un parámetro de 'local' (algo que se define para cada cliente de forma independiente) en el servidor, otros clientes trabajarán con el nuevo entorno también.

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(); 

¿Hay una manera de implementar un servidor, que crea una nueva instancia del manejador para cada socket de servidor en lugar de utilizar el mismo controlador?

Gracias por cualquier sugerencia o ayuda, @

Respuesta

4

He logrado resolver este problema. Había una solución ya implementada en Java. Utilicé la misma idea y la implementé en C++.

Lo primero que hice es creé una TProcessorFactory lugar de la clase TTransport. Esto maneja los TProcessors para cada conexión. Tiene una estructura de mapa, por lo que su función get devuelve el TProcessor correspondiente para cada TTransport. El TProcessor correspondiente (único) para cada cliente.

tuve que crear una nueva TServer, por lo que sería aceptar la TProcessorFactory parámetro de nueva creación en lugar del TProcessor. En TServer también es necesario cambiar un par de llamadas de función. Su función getProcessor ya no devolverá un TProcessor sino un TProcessorFactory (por lo tanto, cambie el tipo de devolución y cambie el nombre).

Lo último que hay que hacer es implementar un servidor que permite la instanciación, una clase deriva de TServer. Sugiero usar el TNonblockingServer (un poco más difícil para implementar el cambio) o el TThreadPoolServer. Tienes que cambiar un par de llamadas de función. Use una función get en TProcessorFactory con un parámetro TTransport para obtener un TProcessor cuando sea necesario. El parámetro TTransport es único para cada subproceso, cada conexión de cliente se maneja con un subproceso.

También asegúrese de eliminar los TProcessors antiguos, porque el ahorro reutiliza (al menos con el TNonblockingServer) el TTransport, de modo que si no los elimina y un cliente se conecta, probablemente obtendrá una sesión anterior inactiva y probablemente se ponga no lo quiero Si usa punteros compartidos, simplemente elimínelos de la estructura del mapa, cuando el cliente se desconecte y si ya no los necesita por ahorro, serán destruidos.

espero que esto ayude a nadie, que se encuentra con el mismo problema que yo. Si no se conoce la estructura interna de ahorro, aquí una buena guía: http://diwakergupta.github.com/thrift-missing-guide/

espero que los desarrolladores de segunda mano van a implementar algo similar, pero la solución más sofisticada y resumen en un futuro próximo.

@

+0

¿Alguna vez ha realizado una solicitud de ticket/issue/feature @ apache thrift? Creo que esto también podría usarse para permitir la comunicación full-duplex/bidirectional muy fácilmente. – BatteryBackupUnit

0

En lugar de hacer su proxy charla servidor de ahorro, que sólo podría hacerlo un proxy TCP genérico que se abre una nueva conexión TCP para cada conexión entrante.

+0

he pensado en eso, sin embargo necesito los paquetes sin embalar para que pueda reenviar el paquete al servidor correcto en base a la información que contiene. Sería una gran cantidad de trabajo implementarlo sin ahorro. –

1

Sé que esto es un hilo viejo, pero en caso de que alguna vez haya de utilidad para cualquiera - he contribuido un cambio en el C# aplicación de Ahorro para resolver este problema ...

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

Además del viejo método de pasar un TProcessor como primer argumento a los servidores roscados, ahora se puede establecer algo así como

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

Donde 'processorFactory' es un TProcessorFactory.

He creado TPrototypeProcessorFactory < TProcessor, Handler > (Object [] handlerArgs) que se instalan de esta manera:

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

El 'MyHandlerClass' implementa su ThriftGenerated.Iface. Opcionalmente, si esta clase tiene argumentos, se pueden agregar como una matriz de objetos a la fábrica del procesador. Internamente - Para cada nueva conexión de cliente, esta fábrica procesador:

  1. crear una nueva instancia de 'MyHandlerClass' usando cualquier argumento suministrado (usando Activator.CreateInstance)

  2. Si implementa '' MyHandlerClass 'TControllingHandler' fijará su propiedad 'servidor' al padre TServer (por ejemplo, para permitir el control de la TServer utilizando un cliente thift)

  3. devolver una nueva instancia de Thrif tGenerated.Processor (manejador)

tanto para C# que presentamos lo n clientes -> n enchufes -> n manipuladores -> n enchufes -> 1 servidor

espero que esto llega a ser útil para otras personas - Ciertamente me ha solucionado un problema.

Cuestiones relacionadas