thrift

  • Post author:
  • Post category:其他


压缩格式

Thrift中支持多种压缩类型,包括:

  1. TBinaryProtocol:二进制格式,不进行压缩,传输效率高,但占用带宽较大。

  1. TCompactProtocol:紧凑格式,采用了可变长度的整数编码方式,对于小的整数和布尔值可以采用更紧凑的编码,传输效率较高,占用带宽较小。

  1. TJSONProtocol:JSON格式,采用了Unicode编码,可读性强,但传输效率低,占用带宽较大。

  1. TSimpleJSONProtocol:简化版的JSON格式,采用了ASCII编码,传输效率较高,但不够灵活,只支持基本数据类型和struct类型。

其中,TCompactProtocol是最常用的压缩类型之一,它采用了可变长度的整数编码方式,对于小的整数和布尔值可以采用更紧凑的编码,传输效率较高,占用带宽较小。但相应的,TCompactProtocol的编解码过程会比TBinaryProtocol慢一些,所以在需要最大化传输效率的情况下,可以选择TCompactProtocol作为压缩类型。

需要注意的是,在使用压缩类型时,虽然可以减少传输数据的大小,但也会增加编解码的时间开销,因此需要根据具体的应用场景来选择合适的压缩类型。

server端

在实现了服务接口和具体服务逻辑后,我们需要启动Thrift服务器,将服务注册到服务器上。在Java中,Thrift提供了多种服务器类型可供选择,如TSimpleServer、TThreadPoolServer、TNonblockingServer等。

在服务器端实现Thrift服务主要有以下几个步骤:

  1. 定义Thrift服务接口IDL文件,例如MyService.thrift。

  1. 使用Thrift编译器生成对应的Java代码,例如使用thrift -r –gen java MyService.thrift命令生成Java代码。

  1. 实现Thrift服务接口,编写服务的具体逻辑。

  1. 启动Thrift服务,将实现的服务注册到服务器上。

以下是一个简单的Thrift服务示例,实现了一个简单的Calculator服务,包括Add、Subtract、Multiply和Divide四个方法:

  1. 定义Thrift服务接口IDL文件Calculator.thrift:

namespace java com.example.calculator

service Calculator {
  i32add(1:i32 num1,2:i32 num2),i32 subtract(1:i32 num1,2:i32 num2),i32 multiply(1:i32 num1,2:i32 num2),double divide(1:i32 num1,2:i32 num2) throws (1:InvalidOperation io)
}

exception InvalidOperation {
  1:i32 what,2:string why
}
  1. 使用Thrift编译器生成对应的Java代码:

thrift -r --gen java Calculator.thrift
  1. 实现Thrift服务接口CalculatorHandler.java:

package com.example.calculator;
import org.apache.thrift.TException;
public class CalculatorHandler implements Calculator.Iface {
@Overridepublicintadd(int num1, int num2)throws TException {
    return num1 + num2;
}

@Overridepublicintsubtract(int num1, int num2)throws TException {
    return num1 - num2;
}

@Overridepublicintmultiply(int num1, int num2)throws TException {
    return num1 * num2;
}

@Overridepublicdoubledivide(int num1, int num2)throws InvalidOperation, TException {
    if (num2 == 0) {
        InvalidOperationio=newInvalidOperation();
        io.setWhat(1);
        io.setWhy("Cannot divide by zero");
        throw io;
    }
    return (double) num1/ num2;

    }

}


4. 启动Thrift服务,将实现的服务注册到服务器上。以下是一个简单的服务器实现:

package com.example.calculator;


import org.apache.thrift.TProcessor;

import org.apache.thrift.protocol.TBinaryProtocol;

import org.apache.thrift.server.TServer;

import org.apache.thrift.server.TSimpleServer;

import org.apache.thrift.transport.TServerSocket;

import org.apache.thrift.transport.TServerTransport;

import org.apache.thrift.transport.TTransportException;


public class CalculatorServer {


public static void main(String[] args) {
    try {
        // 创建Thrift服务器处理器
        TProcessor processor = new Calculator.Processor<>(new CalculatorHandler());

        // 创建服务器传输方式
        TServerTransport serverTransport = new TServerSocket(9090);

        // 创建服务器协议方式
        TBinaryProtocol.Factory protocolFactory = new TBinaryProtocol.Factory();

        // 创建Thrift服务器
        TServer server = new TSimpleServer(new TServer.Args(serverTransport)
                .processor(processor)
                .protocolFactory(protocolFactory));

        // 启动服务器
        System.out.println("Starting the calculator server...");
        server.serve();
    } catch (TTransportException e) {
        e.printStackTrace();
    }
}

}

```


在上面的示例中,我们创建了一个TSimpleServer服务器,并将计算器服务注册到服务器上。实际应用中,我们可以根据具体需求来选择合适的服务器类型和配置。

客户端池化技术

在Java中使用fbthrift实现客户端逻辑时,也可以使用资源池来提高性能和可靠性。以下是一个示例代码,展示了如何使用Apache Commons Pool实现fbthrift客户端资源池:

import org.apache.commons.pool2.impl.GenericObjectPool;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.apache.thrift.TServiceClient;
import org.apache.thrift.protocol.TBinaryProtocol;
import org.apache.thrift.protocol.TCompactProtocol;
import org.apache.thrift.protocol.TProtocol;
import org.apache.thrift.transport.TFramedTransport;
import org.apache.thrift.transport.TSocket;
import org.apache.thrift.transport.TTransport;
import org.apache.thrift.transport.TTransportException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class ThriftClientPool<T extends TServiceClient> {
    private static final Logger LOG = LoggerFactory.getLogger(ThriftClientPool.class);

privatefinal GenericObjectPool<T> pool;

publicThriftClientPool(Class<T> clazz, String host, int port) {
    this(clazz, host, port, newGenericObjectPoolConfig());
}

publicThriftClientPool(Class<T> clazz, String host, int port, GenericObjectPoolConfig config) {
    this.pool = newGenericObjectPool<>(newThriftClientFactory<>(clazz, host, port), config);
}

public T borrowObject()throws Exception {
    return pool.borrowObject();
}

publicvoidreturnObject(T client) {
    pool.returnObject(client);
}

publicvoidclose() {
    pool.close();
}

privatestaticclassThriftClientFactory<T extendsTServiceClient> extendsBasePooledObjectFactory<T> {
    privatefinal Class<T> clazz;
    privatefinal String host;
    privatefinalint port;

    publicThriftClientFactory(Class<T> clazz, String host, int port) {
        this.clazz = clazz;
        this.host = host;
        this.port = port;
    }

    @Overridepublic T create()throws Exception {
        TTransporttransport=newTFramedTransport(newTSocket(host, port));
        transport.open();

        TProtocolprotocol=newTCompactProtocol(transport);

        return clazz.getConstructor(TProtocol.class).newInstance(protocol);
    }

    @Overridepublic PooledObject<T> wrap(T obj) {
        returnnewDefaultPooledObject<>(obj);

        }


    @Override
    public void destroyObject(PooledObject<T> p) throws Exception {
        T client = p.getObject();
        if (client != null) {
            TTransport transport = client.getInputProtocol().getTransport();
            if (transport.isOpen()) {
                transport.close();
            }
        }
    }

    @Override
    public boolean validateObject(PooledObject<T> p) {
        T client = p.getObject();
        if (client != null) {
            TTransport transport = client.getInputProtocol().getTransport();
            return transport.isOpen();
        }
        return false;
    }
}

}


// 使用示例

ThriftClientPool<MyService.Client> pool = new ThriftClientPool<>(MyService.Client.class, "localhost", 9090);

MyService.Client client = pool.borrowObject();

try {

    client.ping();

} catch (TTransportException e) {

    // 可能发生网络错误

} finally {

    // 释放资源

    pool.returnObject(client);

}

pool.close();

在上面的示例代码中,我们使用了Apache Commons Pool库来创建资源池。该库提供了一个GenericObjectPool类,可以用于池化任意类型的对象。我们使用了ThriftClientFactory来创建和销毁客户端对象,使用ThriftClientPool来管理客户端资源池。

使用资源池可以有效地减少资源的创建和销毁次数,提高客户端请求的响应速度和吞吐量。在实际应用中,我们可以根据具体需求来调整资源池的大小和配置,以达到最佳的性能和可靠性。



版权声明:本文为oYiMiYangGuang123原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。