07-Thrift高级

11 篇文章 0 订阅
11 篇文章 0 订阅

Thrift高级

在之前的案例中,使用的都是TCP服务,但是在实际网络中,TCP端口要求很严,我们不可能为每个微服务都提供一个端口,这也是近几年HTTP越来越占主流的一个很重要原因。这里,我们研究一下 Thrift Over HTTP。

依赖与感谢

版本必须为最新0.10.0,这个版本提供了THttpServer和THttpClient这两个核心类。

这里要感谢QQ群【thrift技术交流群】里的loading,他给予了我很多帮助。他的Demohttps://github.com/cdmeister/Thrift-Javascript-to-CPP

服务器改造


#include "MathService.h"
#include <thrift/protocol/TBinaryProtocol.h>
#include <thrift/server/TSimpleServer.h>
#include <thrift/server/TNonblockingServer.h>
#include <thrift/server/TThreadedServer.h>
#include <thrift/transport/TServerSocket.h>
#include <thrift/transport/TBufferTransports.h>
#include <thrift/transport/THttpServer.h>
#include <thrift/protocol/TJSONProtocol.h>

using namespace ::apache::thrift;
using namespace ::apache::thrift::protocol;
using namespace ::apache::thrift::transport;
using namespace ::apache::thrift::server;

using boost::shared_ptr;

class MathServiceHandler : virtual public MathServiceIf {
public:
    MathServiceHandler() {
        // Your initialization goes here
    }
    // Add 函数的服务器实现
    int32_t Add(const int32_t A, const int32_t B) {
        printf("Add %d + %d\n", A, B);
        return A + B;
    }

};

int main(int argc, char **argv) {
    int port = 9090;
    shared_ptr<MathServiceHandler> handler(new MathServiceHandler());
    shared_ptr<TProcessor> processor(new MathServiceProcessor(handler));
    shared_ptr<TServerTransport> serverTransport(new TServerSocket(port));
    shared_ptr<TTransportFactory> transportFactory(new THttpServerTransportFactory());
    shared_ptr<TProtocolFactory> protocolFactory(new TBinaryProtocolFactory()); // 协议JSON和Bin都行  

    TThreadedServer _server(processor, serverTransport, transportFactory,
        protocolFactory); 

    _server.serve();
    return 0;
}

客户端改造

#include "MathService.h"
#include <thrift/protocol/TBinaryProtocol.h>
#include <thrift/transport/TSocket.h>
#include <thrift/transport/TBufferTransports.h>
#include <thrift/transport/THttpClient.h>
#include <thrift/protocol/TJSONProtocol.h>

using namespace ::apache::thrift;
using namespace ::apache::thrift::protocol;
using namespace ::apache::thrift::transport;

using boost::shared_ptr;

int main(int argc, char **argv) {
    int port = 9090;

    shared_ptr<TTransport> clientTransport2(new THttpClient("127.0.0.1",port,"/")); // 这里有大坑
    shared_ptr<TProtocol> clientProtocol(new TBinaryProtocol(clientTransport2));

    MathServiceClient client(clientProtocol);

    try
    {
        clientTransport2->open();
        printf("Open Remote Transport, wait call it!\n");
        //getchar();
        long tmCur = clock();
        for (int i = 0; i < 100; i++)
        {
            int nRet = client.Add(i, i);
            printf("[%03d] %d + %d = %d\n", i, i, i, nRet);
        }
        long lTm = clock() - tmCur;
        printf("Used Time: %d\r\n", lTm);
    }
    catch (TException& e)
    {
        printf("ERROR:%s\n", e.what());
    }
    system("pause");
    return 0;
}

坑与总结

说到这里,不得不提一下这个大坑,new THttpClient("127.0.0.1",port,"/") ,它的原型为THttpClient(boost::shared_ptr<TTransport> transport, std::string host, std::string path = ""); 其中 path 的默认值为空,这样,Client请求时,一定会失败,但是你又不能不填。这里建议默认使用"/"

在参考的Git Demo中,这里时随意填写的,可能会有一些误导。

只要这里搞定,这个例子就已经基本没啥问题了。下面,还需要做一个实验,来验证URL path的用途。

深入测试

既然是thrift over HTTP,那么path这个参数肯定是有用的,它用来在进行http请求时,提交请求的url地址,我们在通过nginx一类的代理改变子url时,就显得很重要了。

首先,配置一个nginx:

worker_processes  1;

events {
    worker_connections  1024;
}

http {
    # 省略很多不关心的内容 

    server {
        listen       80;
        server_name  localhost;

        location / {
            root   html;
            index  index.html index.htm;
        }

        location = /thrift {
            proxy_pass   http://127.0.0.1:9090/;
        }
    }
}

在nginx中将http://127.0.0.1/thrift这个url转向到http://127.0.0.1:9090/,当我们进行thrift客户端访问时,如果path参数不正确shared_ptr<TTransport> clientTransport2(new THttpClient("127.0.0.1",80,"/thrift2"));,就会发生如下错误:

D:\CodePakage\vsSrc\thriftTest\Debug>thriftTest.exe
Open Remote Transport, wait call it!
ERROR:Bad Status: HTTP/1.1

如果path参数正确shared_ptr<TTransport> clientTransport2(new THttpClient("127.0.0.1",80,"/thrift"));则调用成功!

按照这种方式组合服务程序,则可以很方便地通过一个端口(如80)进行多个服务的整合。如果可以再利用TMultiplexedxxxxx进行端口复用,则基本上能够组合出我们想要的任何服务形式了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值