thrift-processor

TProcessor 是服務調用組件。
負責從 TProtocol 輸入流讀取消息,寫入到 TProtocol 輸出流。
在這裏插入圖片描述

TProcessor

public interface TProcessor {
  public boolean process(TProtocol in, TProtocol out)
    throws TException;
}

TBaseProcessor

TBaseProcessor 提供了 TProcessor 的默認實現。

public abstract class TBaseProcessor<I> implements TProcessor {
  private final I iface;
  // 方法名到 ProcessFunction 的映射
  private final Map<String,ProcessFunction<I, ? extends TBase>> processMap;

  protected TBaseProcessor(I iface, Map<String, ProcessFunction<I, ? extends TBase>> processFunctionMap) {
    this.iface = iface;
    this.processMap = processFunctionMap;
  }

  public Map<String,ProcessFunction<I, ? extends TBase>> getProcessMapView() {
    return Collections.unmodifiableMap(processMap);
  }

  @Override
  public boolean process(TProtocol in, TProtocol out) throws TException {
    TMessage msg = in.readMessageBegin();
    ProcessFunction fn = processMap.get(msg.name);
    if (fn == null) {
      TProtocolUtil.skip(in, TType.STRUCT);
      in.readMessageEnd();
      TApplicationException x = new TApplicationException(TApplicationException.UNKNOWN_METHOD, "Invalid method name: '"+msg.name+"'");
      out.writeMessageBegin(new TMessage(msg.name, TMessageType.EXCEPTION, msg.seqid));
      x.write(out);
      out.writeMessageEnd();
      out.getTransport().flush();
      return true;
    }
    fn.process(msg.seqid, in, out, iface);
    return true;
  }
}

Processor

由 thrift 自動生成,實現自 TProcessor。

  public static class Processor<I extends Iface> extends org.apache.thrift.TBaseProcessor<I> implements org.apache.thrift.TProcessor {
    private static final Logger LOGGER = LoggerFactory.getLogger(Processor.class.getName());
    public Processor(I iface) {
      super(iface, getProcessMap(new HashMap<String, org.apache.thrift.ProcessFunction<I, ? extends org.apache.thrift.TBase>>()));
    }

    protected Processor(I iface, Map<String,  org.apache.thrift.ProcessFunction<I, ? extends  org.apache.thrift.TBase>> processMap) {
      super(iface, getProcessMap(processMap));
    }

    private static <I extends Iface> Map<String,  org.apache.thrift.ProcessFunction<I, ? extends  org.apache.thrift.TBase>> getProcessMap(Map<String,  org.apache.thrift.ProcessFunction<I, ? extends  org.apache.thrift.TBase>> processMap) {
      processMap.put("sayHello", new sayHello());
      return processMap;
    }

    public static class sayHello<I extends Iface> extends org.apache.thrift.ProcessFunction<I, sayHello_args> {
      public sayHello() {
        super("sayHello");
      }

      public sayHello_args getEmptyArgsInstance() {
        return new sayHello_args();
      }

      protected boolean isOneway() {
        return false;
      }

      public sayHello_result getResult(I iface, sayHello_args args) throws org.apache.thrift.TException {
        sayHello_result result = new sayHello_result();
        // public com.meituan.model.Response success;
        // public com.meituan.model.Request req;
        // 執行真正的調用邏輯
        result.success = iface.sayHello(args.req);
        return result;
      }
    }
  }

ProcessFunction

ProcessFunction 對象是實際方法的抽象

public abstract class ProcessFunction<I, T extends TBase> {
  // thrift 方法調用沒有利用到反射,故 methodName 在方法調用中沒有太大的作用
  private final String methodName;
  private static final Logger LOGGER = LoggerFactory.getLogger(ProcessFunction.class.getName());

  public ProcessFunction(String methodName) {
    this.methodName = methodName;
  }

  public final void process(int seqid, TProtocol iprot, TProtocol oprot, I iface) throws TException {
    T args = getEmptyArgsInstance();
    try {
      // 讀取請求參數
      // 對消息的編解碼操作由相應的 Tbase 類實現
      args.read(iprot);
    } catch (TProtocolException e) {
      iprot.readMessageEnd();
      TApplicationException x = new TApplicationException(TApplicationException.PROTOCOL_ERROR, e.getMessage());
      oprot.writeMessageBegin(new TMessage(getMethodName(), TMessageType.EXCEPTION, seqid));
      x.write(oprot);
      oprot.writeMessageEnd();
      oprot.getTransport().flush();
      return;
    }
    // org.apache.thrift.TBaseProcessor#process 執行了 readMessageBegin 方法
    iprot.readMessageEnd();
    TBase result = null;

    try {
      result = getResult(iface, args);
    } catch(TException tex) {
      LOGGER.error("Internal error processing " + getMethodName(), tex);
      TApplicationException x = new TApplicationException(TApplicationException.INTERNAL_ERROR, "Internal error processing " + getMethodName());
      oprot.writeMessageBegin(new TMessage(getMethodName(), TMessageType.EXCEPTION, seqid));
      x.write(oprot);
      oprot.writeMessageEnd();
      oprot.getTransport().flush();
      return;
    }

    // 不是單向調用
    // 單向調用沒有返回值
    if(!isOneway()) {
      // seqid 和請求保持一致
      // 對消息的編解碼也是依賴相應的 Tbase
      oprot.writeMessageBegin(new TMessage(getMethodName(), TMessageType.REPLY, seqid));
      result.write(oprot);
      oprot.writeMessageEnd();
      // 刷新緩存池
      oprot.getTransport().flush();
    }
  }

  // 是否是單向RPC,只調用不要求返回
  protected abstract boolean isOneway();
  
  // 獲得返回值的抽象方法,實現由 thrift 自動生成
  public abstract TBase getResult(I iface, T args) throws TException;
  
	// 獲得空的參數 
  public abstract T getEmptyArgsInstance();
	
  // 獲得方法名
  public String getMethodName() {
    return methodName;
  }
}

TMultiplexedProcessor

允許單個 TServer 提供多種服務

public class TMultiplexedProcessor implements TProcessor {
    private final Map<String,TProcessor> SERVICE_PROCESSOR_MAP
            = new HashMap<String,TProcessor>();

    public void registerProcessor(String serviceName, TProcessor processor) {
        SERVICE_PROCESSOR_MAP.put(serviceName, processor);
    }

    public boolean process(TProtocol iprot, TProtocol oprot) throws TException {
        TMessage message = iprot.readMessageBegin();

        if (message.type != TMessageType.CALL && message.type != TMessageType.ONEWAY) {
            throw new TException("This should not have happened!?");
        }

        int index = message.name.indexOf(TMultiplexedProtocol.SEPARATOR);
        if (index < 0) {
            throw new TException("Service name not found in message name: " + message.name + ".  Did you " +
                    "forget to use a TMultiplexProtocol in your client?");
        }

        String serviceName = message.name.substring(0, index);
        TProcessor actualProcessor = SERVICE_PROCESSOR_MAP.get(serviceName);
        if (actualProcessor == null) {
            throw new TException("Service name not found: " + serviceName + ".  Did you forget " +
                    "to call registerProcessor()?");
        }

        TMessage standardMessage = new TMessage(
                message.name.substring(serviceName.length()+TMultiplexedProtocol.SEPARATOR.length()),
                message.type,
                message.seqid
        );

        return actualProcessor.process(new StoredMessageProtocol(iprot, standardMessage), oprot);
    }

    private static class StoredMessageProtocol extends TProtocolDecorator {
        TMessage messageBegin;
        public StoredMessageProtocol(TProtocol protocol, TMessage messageBegin) {
            super(protocol);
            this.messageBegin = messageBegin;
        }
        @Override
        public TMessage readMessageBegin() throws TException {
            return messageBegin;
        }
    }
}

使用

public class MultiServer {
    public static void main(String[] args) throws TTransportException {
        TMultiplexedProcessor processor = new TMultiplexedProcessor();
        processor.registerProcessor( "helloService1", new HelloService.Processor<HelloService.Iface>(new HelloServiceImpl()));
        processor.registerProcessor( "helloService2", new HelloService.Processor<HelloService.Iface>(new HelloServiceImpl()));
        TServerSocket serverTransport = new TServerSocket(8888);
        TServer.Args tArgs = new TServer.Args(serverTransport);
        tArgs.processor(processor);
        tArgs.protocolFactory(new TBinaryProtocol.Factory());
        TServer server = new TSimpleServer(tArgs);
        server.serve();
    }
}


public class TestClient {
    public static void main(String[] args) throws TException {
        TSocket transport = new TSocket("localhost", 8888);
        transport.open();
        TBinaryProtocol protocol = new TBinaryProtocol(transport);
        TMultiplexedProtocol mp = new TMultiplexedProtocol(protocol, "helloService1");
        HelloService.Client service = new HelloService.Client(mp);
        Request request = new Request();
        request.setName("lgh");
        request.setAge(27);
        System.out.println(service.sayHello(request));
    }
}

TMultiplexedProcessor 通過讀取消息頭區分調用的哪一個服務
在這裏插入圖片描述
在這裏插入圖片描述
serviceName:helloService1

標準的 thrift 消息頭
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章