這兩天看了下hangout的代碼,雖然沒有運行體驗過,但是也算是學習了一點皮毛。
架構淺談
Hangout可以說是java版的Logstash,我是沒有測試過性能,不過據說是kafka這邊性能要高出Logstash5倍。不知道真的假的,不過看代碼,確實要比Logstash高效一點。
關於input,filter,output的關系
在Logstash里面,Input,filter,output是三個獨立的部分,每個部分通過Buffer存儲數據。
但是Hangout沒有采用這種思想,每個Input是獨立的input對象。每個input對象又由decoder、filter、output組成。事件由Input搜集產生,然后經由filter進行過濾解析,再交給output輸出。
這樣的關系,在組織結構上,使得filter、output與Input的關系變成了被包含的關系。
關於buffer
Logstash中input,filter,output之間都有一個Buffer用於暫存數據。所有的input數據會暫存到buffer里面,等待filter解析,filter解析后數據又會放入filter和output之間的Buffer,等待output去flush到目的地。
在Hangout中,則是直接取消掉了buffer這一概念,使得事件由Input直接經過filter,直接交給output。性能上肯定是更快速了一些;但是這樣也存在問題,就是每個input的數據不是同一存放的,filter、output其實會在不同的input中初始化多次,這就意味着其實浪費了一些資源,很多資源被重復利用了。
代碼學習
下面是今天抽空整理的hangout的類圖,可以提供點基本的代碼提示。由於以前沒怎么使用過反射,這次正好通過看代碼學習了一下。通過反射的方式,使得初始化這種模塊化程度很高的代碼,變得十分容易:
Iterator<Entry<String, Map>> inputIT = input.entrySet().iterator();
while (inputIT.hasNext()) {
Map.Entry<String, Map> inputEntry = inputIT.next();
String inputType = inputEntry.getKey();
Map inputConfig = inputEntry.getValue();
Class<?> inputClass = Class.forName("com.ctrip.ops.sysdev.inputs." + inputType);
Constructor<?> ctor = inputClass.getConstructor(Map.class,ArrayList.class, ArrayList.class);
BaseInput inputInstance = (BaseInput) ctor.newInstance(inputConfig, configs.get("filters"), configs.get("outputs"));
inputInstance.emit();
}
其中inputIT是獲得input配置集合,通過反射的方式拿到class
Class.forName("com.ctrip.ops.sysdev.inputs." + inputType);
設置它的構造方法,並初始化
Constructor<?> ctor = inputClass.getConstructor(Map.class,ArrayList.class, ArrayList.class);
BaseInput inputInstance = (BaseInput) ctor.newInstance(inputConfig, configs.get("filters"), configs.get("outputs"));
最后使用emit方法,啟動input輸入
inputInstance.emit();