Apache Thrift:多任务单服务器和客户端

时间:2017-03-03 08:50:44

标签: python multithreading communication thrift

我已阅读thisthis。但是,我的情况有所不同。我不需要服务器上的多路服务,也不需要多个服务器连接。

背景
 对于我的大数据项目,我需要计算给定大数据的核心集。 Coreset 是大数据的一个子集,可保留大数据最重要的数学关系。

工作流:

  • 将大量数据切割成较小的块
  • 客户端解析chunk并将其发送到服务器
  • 服务器计算核心集并保存结果

我的问题:
整个过程就像单个执行线程一样。 客户端解析一个块,然后等待服务器完成核心集的计算,然后解析另一个块,依此类推。

目标:
利用多处理。客户端同时解析多个块,并且对于每个compute coreset请求,服务器任务一个线程来处理它。线程数量有限的地方。像游泳池的东西。

我知道我需要使用与TSimpleServer不同的协议并转向TThreadPoolServer或TThreadedServer。我不能让我注意选择哪一个似乎不适合我?。

  

TThreadedServer为每个客户端连接生成一个新线程,每个线程都保持活动状态,直到客户端连接关闭。

  

在TThreadedServer中,每个客户端连接都有自己的专用服务器线程。客户端关闭连接以供重用后,服务器线程返回到线程池。

我不需要每个连接一个线程,我想要一个连接,并且服务器同时处理多个服务请求。的 Visiualization:

Client:
Thread1: parses(chunk1) --> Request compute coreset
Thread2: parses(chunk2) --> Request compute coreset
Thread3: parses(chunk3) --> Request compute coreset

Server: (Pool of 2 threads)
Thread1: Handle compute Coreset
Thread2: handle compute Coreset
.
. 
Thread1 becomes available and handles another compute coreset

代码:
api.thrift:

struct CoresetPoint {
    1: i32 row,
    2: i32 dim,
}

struct CoresetAlgorithm {
    1: string path,
}

struct CoresetWeightedPoint {
    1: CoresetPoint point,
    2: double weight,
}

struct CoresetPoints {
    1: list<CoresetWeightedPoint> points,
}

service CoresetService {

    void initialize(1:CoresetAlgorithm algorithm, 2:i32 coresetSize)

    oneway void compressPoints(1:CoresetPoints message)

    CoresetPoints getTotalCoreset()
}


服务器(为了更好看,已删除了实施)

class CoresetHandler:
    def initialize(self, algorithm, coresetSize):

    def _add(self, leveledSlice):

    def compressPoints(self, message):

    def getTotalCoreset(self):


if __name__ == '__main__':
    logging.basicConfig()
    handler = CoresetHandler()
    processor = CoresetService.Processor(handler)
    transport = TSocket.TServerSocket(port=9090)
    tfactory = TTransport.TBufferedTransportFactory()
    pfactory = TBinaryProtocol.TBinaryProtocolFactory()

    server = TServer.TThreadedServer(processor, transport, tfactory, pfactory)

    # You could do one of these for a multithreaded server
    # server = TServer.TThreadedServer(processor, transport, tfactory, pfactory)
    # server = TServer.TThreadPoolServer(processor, transport, tfactory, pfactory)

    print 'Starting the server...'
    server.serve()
    print 'done.'


客户端:

try:
    # Make socket
    transport = TSocket.TSocket('localhost', 9090)

    # Buffering is critical. Raw sockets are very slow
    transport = TTransport.TBufferedTransport(transport)

    # Wrap in a protocol
    protocol = TBinaryProtocol.TBinaryProtocol(transport)

    # Create a client to use the protocol encoder
    client = CoresetService.Client(protocol)

    # Connect!
    transport.open()


    // Here data is sliced, and in a loop I move on all files 
       Saved in the directory I specified, then they are parsed and
       client.compressPoints(data) is invoked.

       SliceFile(...)
       p = CoresetAlgorithm(...)
       client.initialize(p, 200)
       for filename in os.listdir('/home/tony/DanLab/slicedFiles'):
           if filename.endswith(".txt"):
               data = _parse(filename)
               client.compressPoints(data)
       compressedData = client.getTotalCoreset()


# Close!
    transport.close()

except Thrift.TException, tx:
    print '%s' % (tx.message)

问题: 在Thrift有可能吗?我应该使用什么协议? 我解决了客户端等待服务器完成计算的部分问题,方法是将oneway添加到函数声明中 表示客户端只发出请求,而不是等待任何响应。

1 个答案:

答案 0 :(得分:1)

从性质来看,这更像是一个架构问题,而不是一个Thrift问题。鉴于前提

  

我不需要每个连接一个线程,我想要一个连接,并且服务器同时处理多个服务请求。 Visiualization:

  

我解决了客户端等待服务器完成计算的部分问题,方法是单向添加一个函数声明来指示客户端只发出请求而不等待任何响应。

准确描述用例,你想要这个:

+---------------------+
| Client              |
+---------+-----------+
          |
          |
+---------v-----------+
| Server              |
+---------+-----------+
          |
          |
+---------v-----------+          +---------------------+
| Queue<WorkItems>    <----------+ Worker Thread Pool  |
+---------------------+          +---------------------+

服务器唯一的任务是获取请求,并尽快将其插入工作项列表。这些工作项由独立的工作线程池处理,否则完全独立于服务器部分。唯一的共享部分是工作项队列,当然需要正确同步的访问方法。

关于serevr选择:如果服务器足够快地提供请求,即使是TSimpleServer也可以。