thrift实现订阅服务

问题提出

thrift正常的客户端调用服务端情况是直接返回的。这种情况对于订阅来说并不满足(客户端发起订阅, 服务器异步处理,再不断推送给客户端)。
客户端发起订阅(如行情,指标等),服务端实现推送。

解决

  1. 这里给出了一个比较笨的方法:
    https://www.cnblogs.com/liaocheng/p/4978371.html
    也就是客户端也起了一个服务,这样和服务端互为客户端和服务端。实现服务端向客户端推送数据。
    问题:客户端起服务不稳定。服务器未必能推送过去(测试过都在本机没问题,客户端放另一台机器就有连接问题)。同一台机器起多个客户端,还需找本机ip和一个可用的端口(本机起服务器),再发送给服务器让服务器连接过来。麻烦。
  2. 这里给出了一个好一些的方法:
    http://www.360doc.com/content/20/0104/17/21698786_884131548.shtml
    通过重写服务端类TBufferedTransportFactory,主要是重载getTransport函数。这个函数每当客户端有连接过来时都会调用到,从而获取到TTransport,根据TTransport构建client,实现服务端调用客户端的函数,以实现不断推送数据。

重写类:

class TBufferedTransportFactoryMy : public TTransportFactory {
public:
    TBufferedTransportFactoryMy(std::shared_ptr<IndexServerHandler> serverHandler)
        :m_indexServerHandler(serverHandler)
    {
    };

    virtual ~TBufferedTransportFactoryMy() {};

    /**
     * Wraps the transport into a buffered one.
     */
    virtual stdcxx::shared_ptr<TTransport> getTransport(stdcxx::shared_ptr<TTransport> trans);
private:
    std::shared_ptr<IndexServerHandler> m_indexServerHandler;
};

重载函数getTransport,用TTransport构建client放到全局变量中,在服务需用推送数据的时候用。

//IndexSubscribeClient thrift中定义的客户端接收服务,以接收服务端推送过来得数据。
std::map<stdcxx::shared_ptr<TTransport>, std::shared_ptr<IndexSubscribeClient> > g_lstIndexSubscribeClient;
stdcxx::shared_ptr<TTransport> TBufferedTransportFactoryMy::getTransport(stdcxx::shared_ptr<TTransport> trans) 
{
    if (trans->isOpen() && g_lstIndexSubscribeClient.find(trans) == g_lstIndexSubscribeClient.end())
    {
        std::shared_ptr<TProtocol> protocol(new TBinaryProtocol(trans));
        std::shared_ptr<IndexSubscribeClient> client(new IndexSubscribeClient(protocol));
        { 
            g_lstIndexSubscribeClient[trans]=client;
        }
        if (m_indexServerHandler)
        {
            m_indexServerHandler->setTransport(trans);
        }
    }
    return stdcxx::shared_ptr<TTransport>(new TBufferedTransport(trans));
}

服务端的main:

int main(int argc, char** argv)
{
    const int workerCount = 100;  //支持的连接数

    std::shared_ptr<ThreadManager> threadManager = ThreadManager::newSimpleThreadManager(workerCount);
    threadManager->threadFactory(std::make_shared<PlatformThreadFactory>());
    threadManager->start();

    std::shared_ptr<IndexServerHandler> handler(new IndexServerHandler()); //全局只有一个server,一个serverhandler。多个连接线程
    std::shared_ptr<TProcessor> processor(new IndexServerProcessor(handler));
    std::shared_ptr<TServerTransport> serverTransport(new TServerSocket(9090));
    std::shared_ptr<TTransportFactory> transportFactory(new TBufferedTransportFactoryMy(handler));
    std::shared_ptr<TProtocolFactory> protocolFactory(new TBinaryProtocolFactory());
    
    TThreadPoolServer server(processor, serverTransport, transportFactory,protocolFactory, threadManager);

    std::cout<<"Starting the server"<<std::endl;
    server.serve();
    return 0;
}

以上,整体代码恕不能放送,涉及到实际项目。上面连接的给的代码挺全的了。

第二种方式问题:这种方式需要客户端起一个不断阻塞监听的线程,这样相当于把客户端到服务端的连接独占了。会引起别的非推送方式直接调用服务端方法的异常。
处理1:加锁处理。但是一但服务端一直不推送数据,一直阻塞着,占用着锁,也有问题。
处理2:客户端起两个到服务端的连接。 大概能ok。 小问题,服务端并不知道这两个连接的区别,相应的就起了两个到客户端的client,都推送了。后续可以细分,删去不可用的那个。

结语

寻求更好thrift实现订阅服务方法!如像回调函数那样的?

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值