中介軟體、MetaQ入門學習

Andrew.Hann發表於2014-09-14

目錄

1. 中介軟體技術
2. MetaQ中介軟體
3. MetaQ程式設計實踐

 

1. 中介軟體技術

0x1: 中介軟體簡介

中介軟體(Middleware)是提供系統軟體和應用軟體之間連線的軟體,以便於軟體各部件之間的溝通,特別是應用軟體對於系統軟體的集中的邏輯,在現代資訊科技應用框架如Web服務、面向服務的體系結構等中應用比較廣泛,如:

1. 資料庫
2. Apache的Tomcat
3. IBM公司的WebSphere
4. BEA公司的WebLogic[[應用伺服器]
5. 東方通公司的Tong系列中介軟體
6. Kingdee公司的等

都屬於中介軟體,中介軟體技術本質上就是在計算機系統不同層次的模組之間的異構、跨協議的通訊問題
嚴格來講,中介軟體技術已經不侷限於應用伺服器、資料庫伺服器。中介軟體技術建立在對應用軟體部分常用功能的抽象上,將常用且重要的

1. 過程呼叫
2. 分散式元件
3. 訊息佇列
4. 事務
5. 安全
6. 連結器
7. 商業流程
8. 網路併發
9. HTTP伺服器
10. Web Service

等功能集於一身或者分別在不同產品中分別完成 ,我國學術界一般認可的定義是中介軟體是指網路環境下處於作業系統、資料庫等系統軟體和應用軟體之間的一種起連線作用的分散式軟體,主要解決異構網路環境下分散式應用軟體的互連與互操作問題,提供標準介面、協議,遮蔽實現細節,提高應用系統易移植性

0x2: 中介軟體的特徵(內涵)

總的來說,中介軟體有幾個非常重要的特徵

1. 平臺化
所謂平臺就是能夠獨立執行並自主存在,為其所支撐的上層系統和應用提供執行所依賴的環境。中介軟體是一個平臺,因此中介軟體是必須獨立存在,是執行時刻的"系統軟體",它為上層的網路應用系統提供一個執行環境,並通過標準的介面和API來隔離其支撐的系統,實現其獨立性,也就是平臺性。J2EE應用伺服器提供JAVA應用的執行環境,就是經典的中介軟體

2. 應用支撐
中介軟體的最終目的是解決上層應用系統的問題,而且也是軟體技術發展到今天對應用軟體提供最完善徹底的解決方案。
    1) 高階程式設計語言的發明,使得軟體開發變成一個獨立的科學和技術體系,而作業系統平臺的出現,使得應用軟體通過標準的API介面,實現了軟體與硬體的分離。
      2) 現代面向服務(SOA)的中介軟體在軟體的模型、結構、互操作以及開發方法等四個方面提供了更強的應用支撐能力:
          2.1) 模型:構件模型彈性粒度化
        通過抽象層度更高的構件模型,實現具備更高結構獨立性、內容自包含性和業務完整性的可複用構件,即服務(RESTFUL API就是一個最好的例子)。並且在細粒度服務基礎上,提供了更粗粒度的服務封裝方式,即業務層面的封裝,形成業務元件,就可以實現從元件模型到業務模型的全生命週期企業建模的能力。
          2.2) 結構:結構鬆散化
        將"服務描述""服務功能實現"分離,將"服務的使用者""提供者"分離,從而避免分散式應用系統構建和整合時常見的技術、組織、時間等不良約束。
          2.3) 互操作:互動過程標準化
        將與互操作相關的內容進行標準化定義,如服務封裝、描述、釋出、發現、呼叫等契約,通訊協議以及資料交換格式等等。最終實現訪問互操作、連線互操作和語義互操作(RESTFUL、SOAP、WPF、WebService、SCA/SDO)
          2.4) 開發整合方法:
        應用系統的構建方式由程式碼編寫轉為主要通過服務間的快捷組合及編排,完成更為複雜的業務邏輯的按需提供和改善,從而大大簡化和加速應用系統的搭建及重構過程(一種典型的輕耦合思想)而要最終解決軟體的質量問題、效率問題、互操作問題、靈活應變問題這四大問題,需要在軟體技術的內在結構(Structure)、架構(Architecture)層面進行思考。解決這些問題,技術的本質是複用、鬆耦合、互操作(標準)等軟體技術的內在機制。這也是中介軟體技術和產品的本質特徵

3. 軟體複用
軟體複用,即軟體的重用,也叫再用,是指同一事物不作修改或稍加改動就多次重複使用。從軟體複用技術的發展來看,就是不斷提升抽象級別,擴大複用範圍。最早的複用技術是子程式,人們發明子程式,就可以在不同系統之間進行復用了。但是,子程式是最原始的複用,因為這種複用範圍是一個可執行程式內複用,靜態開發期複用,如果子程式修改,意味著所有呼叫這個子程式的程式必須重新編譯、測試和釋出
複用物件複用範圍
    1) 子程式: 一個可執行程式內複用: 靜態開發期複用
    2) 元件(DLL、Com..): 系統內複用,動態執行期複用
    3) 企業物件元件(Com+、.NET、EJB..): 企業網路內複用,不同系統之間複用
    4) 服務(RESTFUL、SOAP、WPF、WebService、SCA/SDO): 不同企業之間、跨系統、跨異構環境複用,動態可配置

4. 耦合關係 
    1) 分散式物件技術將"連線邏輯"進行分離
    2) 訊息中介軟體將"連線邏輯"進行非同步處理,增加了更大的靈活性
    3) 訊息代理和一些分散式物件中介軟體將資料轉換也進行了分離
    4) 而SOA架構,通過服務的封裝,實現了業務邏輯與網路連線、資料轉換等進行完全的解耦

5. 互操作性
在軟體的互操作方面,傳統中介軟體只是實現了訪問互操作,即通過標準化的API實現了同類系統之間的呼叫互操作,而連線互操作還是依賴於特定的訪問協議,如JAVA使用RMI,CORBA使用IIOP等。而SOA通過標準的、支援Internet、與作業系統無關的SOAP協議實現了連線互操作。而且,服務的封裝是採用XML協議,具有自解析和自定義的特性,這樣,基於SOA的中介軟體還可以實現語義互操作
總之,服務化體現的是中介軟體在完整業務複用、靈活業務組織方面的發展趨勢,其核心目標是提升IT基礎設施的業務敏捷性。因此,中介軟體將成為SOA的主要實現平臺

Relevant Link:

http://zh.wikipedia.org/wiki/%E4%B8%AD%E9%97%B4%E4%BB%B6
http://kb.cnblogs.com/page/196448/
http://jm.taobao.org/

 

2. MetaQ中介軟體

0x1: MetaQ的應用場景

假設我們有這麼一個應用場景,為了完成一個使用者註冊操作,可能需要將使用者資訊寫入到使用者庫中,然後通知給紅包中心給使用者發新手紅包,然後還需要通知部落格系統給使用者準備對應的部落格賬號,進行合法性驗證,告知SNS系統給使用者匯入新的使用者等10步操作。
那麼針對這個場景,一個最簡單的設計方法就是序列的執行整個流程

//全稱序列操作
使用者註冊->通知給紅包中心給使用者發新手紅包->部落格系統給使用者準備對應的部落格賬號->進行合法性驗證->告知SNS系統給使用者匯入新的使用者 

通過業務分析我們能夠得知,使用者的實際的核心流程其實只有一個,就是使用者註冊。而後續的準備部落格帳號,通知SNS等操作雖然必須要完成,但卻是不需要讓使用者等待的。
這種模式有個專業的名詞,就叫"最終一致",即實際上這並不是一個嚴格強制的序列操作,從業務的角度上來說,有很多步驟完全是可以非同步完成的,只要最終的結果是"最終一致"的就可以

0x2: MetaQ技術原理

METAQ是一款完全的佇列模型訊息中介軟體,伺服器使用Java語言編寫,可在多種軟硬體平臺上部署。客戶端支援Java、C++程式語言

MetaQ對外提供的是一個佇列服務,內部實現也是完全的佇列模型,這裡的佇列是持久化的磁碟佇列,具有非常高的可靠性,並且充分利用了作業系統cache來提高效能

1. MetaQ是一個佇列模型的訊息中介軟體,具有高效能、高可靠、高實時、分散式特點。
2. Producer、Consumer、佇列都可以分散式。
3. 能夠保證嚴格的訊息順序
4. 提供豐富的訊息拉取模式
5. 高效的訂閱者水平擴充套件能力
6. 實時的訊息訂閱機制
7. 億級訊息堆積能力

MetaQ的儲存結構是根據大規模網際網路應用需求,完全重新設計的一套儲存結構,使用這套儲存結構可以支援上萬的佇列模型,並且可以支援訊息查詢、分散式事務、定時佇列等功能

MetaQ內部大部分功能都靠佇列來驅動,那麼必須支援足夠多的佇列,才能更好的滿足業務需求,MetaQ可以在單機支援上萬佇列,這裡的佇列全部為持久化磁碟方式,從而對IO效能提出了挑戰。MetaQ是這樣解決的

1. Message全部寫入到一個獨立的佇列,完全的順序寫
2. Message在檔案的位置資訊寫入到另外的檔案,序列方式寫

通過以上方式,既做到資料可靠,又可以支援更多的佇列

Relevant Link:

http://blog.csdn.net/blogdevteam/article/details/8449916
https://github.com/killme2008/Metamorphosis/wiki
http://m.bianceng.cn/web/Skills/201407/42090.htm
http://www.bkjia.com/ASPjc/871354.html 

 

3. MetaQ程式設計實踐

訊息中介軟體中有兩個角色: "訊息生產者(Producer)"和"訊息消費者(Consumer)"。Meta裡同樣有這兩個概念,訊息生產者負責建立訊息併傳送到Meta伺服器(Broker),Meta伺服器會將訊息持久化到磁碟,訊息消費者從Meta伺服器拉取訊息並提交給應用消費

回顧我們之前說的MetaQ的架構圖

要使用MetaQ進行分散式訊息通訊程式設計學習,就必須要實現最基本的架構搭建

0x1: 配置Zookeeper叢集

MetaQ使用zookeeper釋出和訂閱服務,並預設使用zookeeper儲存消費者offset,因此,你需要首先安裝一個zookeeper到某臺機器上,或者使用某個現有的zk叢集

/mate-queue/taobao/metamorphosis-server-wrapper/conf/server.ini

使用內建的zookeeper伺服器進行搭建

[zookeeper]
zk.zkConnect=localhost:2181
zk.zkSessionTimeoutMs=30000
zk.zkConnectionTimeoutMs=30000
zk.zkSyncTimeMs=5000

0x2: 啟動Zookeeper

//停止local模式啟動的broker1,並重新以叢集模式啟動
bin/metaServer.sh start 

0x3: 引入MetaQ需要依賴的JAR包

http://fnil.net/downloads/index.html

包括client、server的

0x4: Producer.java

package com.taobao.metamorphosis.example;

import java.io.BufferedReader;
import java.io.InputStreamReader;

import java.io.BufferedReader;
import java.io.InputStreamReader;

import com.taobao.metamorphosis.Message;
import com.taobao.metamorphosis.client.MessageSessionFactory;
import com.taobao.metamorphosis.client.MetaClientConfig;
import com.taobao.metamorphosis.client.MetaMessageSessionFactory;
import com.taobao.metamorphosis.client.producer.MessageProducer;
import com.taobao.metamorphosis.client.producer.SendResult;
import com.taobao.metamorphosis.utils.ZkUtils.ZKConfig;

public class Producer {
    public static void main(String[] args) throws Exception {
        final MetaClientConfig metaClientConfig = new MetaClientConfig();
        final ZKConfig zkConfig = new ZKConfig();
        //設定zookeeper地址
        zkConfig.zkConnect = "192.168.207.128:2181";
        metaClientConfig.setZkConfig(zkConfig);
        // New session factory,強烈建議使用單例
        MessageSessionFactory sessionFactory = new MetaMessageSessionFactory(metaClientConfig);
        /*
         *  create producer,強烈建議使用單例
         *  訊息生產者的介面是MessageProducer,你可以通過它來傳送訊息
         */
        MessageProducer producer = sessionFactory.createProducer();
        // publish topic
        final String topic = "test";
        /*
         * 這一步在傳送訊息前是必須的,你必須釋出你將要傳送訊息的topic
         * 這是為了讓會話工廠幫你去查詢接收這些topic的meta伺服器地址並初始化連線
         * 這個步驟針對每個topic只需要做一次,多次呼叫無影響
         */
        producer.publish(topic);

        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
        String line = null;
        while ((line = reader.readLine()) != null) 
        {
            /*
             * send message
             * 在Meta裡,每個訊息物件都是Message類的例項,Message表示一個訊息物件,它包含這麼幾個屬性:
             * 1) id: Long型的訊息id,訊息的唯一id,系統自動產生,使用者無法設定,在傳送成功後由伺服器返回,傳送失敗則為0。
             * 2) topic: 訊息的主題,訂閱者訂閱該主題即可接收傳送到該主題下的訊息,生產者通過指定釋出的topic查詢到需要連線的伺服器地址,必須。
             * 3) data: 訊息的有效載荷,二進位制資料,也就是訊息內容,meta永遠不會修改訊息內容,你傳送出去是什麼樣子,接收到就是什麼樣子。訊息內容通常限制在1M以內,我的建議是最好不要傳送超過上百K的訊息,必須。資料是否壓縮也完全取決於使用者。
             * 4) attribute: 訊息屬性,一個字串,可選。傳送者可設定訊息屬性來讓消費者過濾。
             */
            SendResult sendResult = producer.sendMessage(new Message(topic, line.getBytes()));
            // check result
            if (!sendResult.isSuccess()) 
            {
                System.err.println("Send message failed,error message:" + sendResult.getErrorMessage());
            }
            else {
                System.out.println("Send message successfully,sent to " + sendResult.getPartition());
            }
        }
    }

}

0x5: AsyncConsumer.java

package com.taobao.metamorphosis.example;

import java.util.concurrent.Executor;

import com.taobao.metamorphosis.Message;
import com.taobao.metamorphosis.client.MessageSessionFactory;
import com.taobao.metamorphosis.client.MetaClientConfig;
import com.taobao.metamorphosis.client.MetaMessageSessionFactory;
import com.taobao.metamorphosis.client.consumer.ConsumerConfig;
import com.taobao.metamorphosis.client.consumer.MessageConsumer;
import com.taobao.metamorphosis.client.consumer.MessageListener;
import com.taobao.metamorphosis.utils.ZkUtils.ZKConfig;

public class AsyncConsumer {
    public static void main(String[] args) throws Exception {
        final MetaClientConfig metaClientConfig = new MetaClientConfig();
        final ZKConfig zkConfig = new ZKConfig();
        //設定zookeeper地址
        zkConfig.zkConnect = "192.168.207.128:2181";
        metaClientConfig.setZkConfig(zkConfig);
        // New session factory,強烈建議使用單例
        MessageSessionFactory sessionFactory = new MetaMessageSessionFactory(metaClientConfig);
        // subscribed topic
        final String topic = "test";
        // consumer group
        final String group = "meta-example";
        /*
         * create consumer,強烈建議使用單例
         * 通過createConsumer方法來建立MessageConsumer,注意到我們傳入一個ConsumerConfig引數,
         * 這是消費者的配置物件。每個訊息者都必須有一個ConsumerConfig配置物件,
         * 我們這裡只設定了group屬性,這是消費者的分組名稱。
         * Meta的Producer、Consumer和Broker都可以為叢集。
         * 消費者可以組成一個叢集共同消費同一個topic,發往這個topic的訊息將按照一定的負載均衡規則傳送給叢集裡的一臺機器。
         * 同一個消費者叢集必須擁有同一個分組名稱,也就是同一個group。我們這裡將分組名稱設定為meta-example
         */
        MessageConsumer consumer = sessionFactory.createConsumer(new ConsumerConfig(group));
        /*
         * subscribe topic
         * 訂閱訊息通過subscribe方法,這個方法接受三個引數 
         * 1) topic,訂閱的主題
         * 2) maxSize,因為meta是一個消費者主動拉取的模型,這個引數規定每次拉取的最大資料量,單位為位元組,這裡設定為1M,預設最大為1M。
         * 3) MessageListener,訊息監聽器,負責訊息訊息。
         */
        consumer.subscribe(topic, 1024 * 1024, new MessageListener() {

            public void recieveMessages(Message message) {
                System.out.println("Receive message " + new String(message.getData()));
            }


            public Executor getExecutor() {
                // Thread pool to process messages,maybe null.
                return null;
            }
        });
        // complete subscribe
        consumer.completeSubscribe();
    }
}

Relevant Link:

https://github.com/killme2008/Metamorphosis/wiki/%E5%A6%82%E4%BD%95%E5%BC%80%E5%A7%8B
http://www.it165.net/admin/html/201402/2409.html

 

Copyright (c) 2014 LittleHann All rights reserved

 

相關文章