ZBUS = MQ + RPC


http://git.oschina.net/rushmore/zbus

 http://my.oschina.net/sbz/blog

  Readme.md 18.02 KB

ZBUS = MQ + RPC

zbus解決的問題域

  1. 消息隊列 -- 應用解耦
  2. 分布式RPC -- 遠程方法調用
  3. 異構服務代理 -- 跨平台語言RPC改造,實現DMZ服務總線架構

zbus目前不解決

  1. 分布式事務

zbus特點

  1. 極其輕量級--單個Jar包無依賴 ~300K (可個性化適配各類log包,commons-pool包)
  2. 億級消息堆積能力、支持HA高可用
  3. 豐富的API--JAVA/C/C++/C#/Python/Node.JS多語言接入
  4. 兼容擴展HTTP協議接入(方便新增客戶端SDK)

QQ討論組:467741880 猛戳右上角Star加入;)

zbus啟動

zbus的角色是中間消息服務(Broker),默認分布式運行(當然也可以嵌入式單進程運作)

  1. 通過腳本直接運行 zbus-dist發行目錄下windows下對應zbus.bat, linux/mac 對應zbus.sh 運行腳本可以JVM參數優化,MQ存儲路徑等配置,如果運行發生錯誤,重點檢查 (1)是否正確配置JVM (2)端口是否占用
  2. 嵌入式直接 new MqServer 啟動

    MqServerConfig config = new MqServerConfig();
    config.serverPort = 15555;
    config.storePath = "./store";
    final MqServer server = new MqServer(config);
    server.start();

啟動后zbus可以通過瀏覽器直接訪問zbus啟動服務器15555端口的監控服務

zbus監控

zbus實現消息隊列

消息隊列是zbus的最基礎服務,MQ參與角色分為三大類

  1. Broker中間消息服務器
  2. Producer生產者
  3. Consumer消費者

Producer ==> Broker ==> Consumer

邏輯上解耦分離 1. 生產者只需要知道Broker的存在,負責生產消息到Broker,不需要關心消費者的行為 2. 消費者也只需要知道Broker的存在,負責消費處理Broker上某個MQ隊列的消息,不需要關心生產者的行為

不同的Broker實現在細節上會有些不同,但是在MQ邏輯解耦上基本保持一致,下面細節全部是以zbus特定定義展開

zbus與客戶端(生產者與消費者)之間通訊的消息(org.zbus.net.http.Message)為了擴展性采用了【擴展HTTP】消息格式。 zbus的消息邏輯組織是以MQ標識來分組消息,MQ標識在zbus中就是MQ名字,Message對象中可以直接指定。 物理上zbus把同一個下MQ標識下的消息按照FIFO隊列的模式在磁盤中存儲,隊列長度受限於磁盤大小,與內存無關。

編程模型上,分兩個視圖,生產者與消費者兩個視圖展開

  1. 生產者視圖
  2. 消費者視圖

生產者與消費者在編程模型上都需要首先產生一個Broker,Broker是對zbus本身的抽象,為了達到編程模型的一致,Broker可以是 單機版本的SingleBroker,也可以是高可用版本的HaBroker,甚至可以是不經過網絡的本地化JvmBroker,這些類型的Broker都是不同的實現,編程模型上不關心,具體根據實際運行環境而定,為了更加方便配置,ZbusBroker實現了上述幾種不同的Broker實現的代理包裝,根據具體Broker地址來決定最終的版本。

例如

Broker broker = new ZbusBroker("127.0.0.1:15555"); //SingleBroker
Broker broker = new ZbusBroker("127.0.0.1:16666;127.0.0.1:16667"); //HaBroker
Broker broker = new ZbusBroker("jvm"); //JvmBroker

Broker內部核心實現了: 1. 連接池管理 2. 同步異步API

所以Broker在JAVA中可以理解為類似JDBC連接池一樣的重對象,應該共享使用,大部分場景應該是Application生命周期。 而依賴Broker對象而存在的Producer與Consumer一般可以看成是輕量級對象(Consumer因為擁有鏈接需要關閉)

生產消息

//Producer是輕量級對象可以隨意創建不用釋放 
Producer producer = new Producer(broker, "MyMQ");
producer.createMQ();//確定為創建消息隊列需要顯示調用

Message msg = new Message();
msg.setBody("hello world");  //消息體底層是byte[]
msg = producer.sendSync(msg);

消費消息

Consumer consumer = new Consumer(broker, "MyMQ");  
consumer.start(new ConsumerHandler() { 
    @Override
    public void handle(Message msg, Consumer consumer) throws IOException { 
        //消息回調處理
        System.out.println(msg);
    }
}); 
//可控的范圍內需要關閉consumer(內部擁有了物理連接)

生產者可以異步發送消息,直接調用producer.sendAsync(),具體請參考examples中相關示例

消費者可以使用更底層的API控制怎么取消息,直接調用consumer.take()從zbus上取回消息

從上面的API來看,使用非常簡單,連接池管理,同步異步處理、高可用等相關主題全部留給了Broker抽象本身

消息隊列擴展主題

消息嚴格順序問題 參考文章

zbus實現RPC

MQ消息隊列用於解耦應用之間的依賴關系,一般認為MQ是從更廣泛的分布式RPC中演變而來的:在RPC場景下,如果某個遠程方法調用耗時過長,調用方不希望blocking等待,除了異步處理之外,更加常見的改造方式是采用消息隊列解耦調用方與服務方。

RPC的場景更加常見,RPC需要解決異構環境跨語言的調用問題,有非常多的解決方案,綜合看都是折中方案,zbus也屬其一。

RPC從數據通訊角度來看可以簡單理解為:

分布式調用方A --->命令序列化(method+params) ---> 網絡傳輸 --->  分布式式服務方B 命令反序列化(method+params)
       ^                                                                            | 
       |                                                                            v
       |<---結果反序列化(result/error)<----- 網絡傳輸 <----結果序列化(result/error) <---調用本地方法

網絡傳輸可以是純網絡傳遞消息也可以是其他服務器中轉,比如消息隊列

異構環境下RPC方案需要解決的問題包括以下核心問題

1. 跨語言,多語言平台下的消息通訊格式選擇問題
2. 服務端伺服問題,高性能處理模型
3. 分布式負載均衡問題

WebService采用HTTP協議負載,SOAP跨語言描述對象解決問題1

Windows WCF采用抽象統一WebService和私有序列化高效傳輸解決問題1

在服務端處理模型與分布式負載均衡方面並不多體現,這里不討論WebService,WCF或者某些私有的RPC方案的優劣之分,工程優化過程中出現了諸如Thrift,dubbo等等RPC框架,折射出來是的對已有的RPC方案中折中的不滿。

針對問題1,zbus的RPC采用的是JSON數據根式封裝跨語言平台協議,特點是簡單明了,協議應用廣泛(zbus設計上可以替換JSON)

針對問題2、問題3,zbus默認采用兩套模式,MQ-RPC與DirectRPC, MQ-RPC基於MQ消息隊列集中接入模式,DirectRPC則通過交叉直連模式

zbus的RPC方案除了解決上面三個問題之外,還有兩個重要的工程目標:

4. 極其輕量、方便二次開發
5. RPC業務本身與zbus解耦(無侵入,方便直接替換掉zbus)

zbus的RPC設計非常簡單,模型上對請求和應答做了基本的抽象

public static class Request{ 
    private String module = ""; //模塊標識
    private String method;      //遠程方法
    private Object[] params;    //參數列表
    private String[] paramTypes;
    private String encoding = "UTF-8";
}

public static class Response {  
    private Object result;  
    private Throwable error;
    private String stackTrace; //異常時候一定保證stackTrace設定,判斷的邏輯以此為依據
    private String encoding = "UTF-8";
}

非常直觀的抽象設計,就是對method+params 與 結果result/error 的JAVA表達而已。

RpcCodec的一個JSON協議實現---JsonRpcCodec完成將上述對象序列化成JSON格式放入到HTTP消息體中在網絡上傳輸

RPC調用方

RpcInvoker API核心

public class RpcInvoker{ 
    private MessageInvoker messageInvoker; 
    private RpcCodec codec; //RPC對象序列化協議

    public Response invokeSync(Request request){
        .....
    } 
}

完成將上述請求序列化並發送至網絡,等待結果返回,序列化回result/error。

//調用示例
RpcInvoker rpc = new RpcInvoker(...); //構造出RpcInvoker

//利用RpcInvoker 調用方法echo(String msg), 給定參數值 "test"

//1) 調用動態底層API
Request request = new Request();
request.setMethod("echo");
request.setParams(new Object[]{"test"});
Response response = rpc.invokeSync(request);

//2)強類型返回結果
String echoString = rpc.invokeSync(String.class, "echo", "test"); 

RpcInvoker同時適配MQ-RPC與DirectRPC,只需要給RpcInvoker指定不同的底層消息MessageInvoker,比如

  1. 點對點DirectRPC (MessageClient/Broker)
  2. 高可用DirectRPC (HaInvoker)
  3. MQ-RPC (MqInvoker)

點對點DirectRPC

//1) MessageClient是一種MessageInvoker,物理連接點對點
MessageInvoker client = new MessageClient("127.0.0.1:15555", ....);
RpcInvoker rpc = new RpcInvoker(client); //構造出RpcInvoker 

//2) Broker也是一種MessageInvoker, 因為Broker管理了連接池,這樣構造的RpcInvoker具有連接池能力
MessageInvoker broker = new ZbusBroker("127.0.0.1:15555"); 
RpcInvoker rpc = new RpcInvoker(broker); //構造出RpcInvoker 

//1)與2)本質上都是點對點的直連模式

高可用DirectRPC

//1) 接入到Trackserver的ZbusBroker,具備高可用選擇能力
MessageInvoker messageInvoker = new ZbusBroker("127.0.0.1:16666;127.0.0.1:16667");
//指定高可用服務器上的選擇標識,注冊為相同標識的服務提供方之間高可用
HaInvoker haInvoker = new HaInvoker(messageInvoker, "HaDirectRpc"); 
RpcInvoker rpc = new RpcInvoker(haInvoker); //構造出RpcInvoker 

MQ-RPC

//step 1 生成一個到zbus服務器的MessageInvoker
Broker broker = new ZbusBroker(); 
//step 2 類似Java IoStream封裝,在點對點基礎上可以適配出MQ能力的MessageInvoker
MessageInvoker mqInvoker = new MqInvoker(broker, "MyRpc"); //使用某個隊列實現的RPC,調用適配
RpcInvoker rpc = new RpcInvoker(mqInvoker); //構造出RpcInvoker 

以上三種RPC結構優缺點如下:

  • 點對點DirectRPC簡單單機性能高,但存在單點問題
  • 高可用DirectRPC解決點對點的單點問題,但是網絡連接是蜘蛛網狀
  • MQ-RPC集中式管理,多機負載均衡,但是因為所有消息都走了中間節點,性能有所下降

為了解決問題5,使得zbus在RPC業務解耦,zbus增加了動態代理類

RpcFactory API完成業務interface經過zbus的RPC動態代理類實現

public class RpcFactory {
    private final MessageInvoker messageInvoker; //底層支持的消息Invoker,完成動態代理    
    public <T> T getService(Class<T> api) throws Exception{
        ....
    }
}

通過RpcFactory則完成了業務代碼與zbus的解耦(通過spring等IOC容器更加徹底的把zbus完全隔離掉)

MessageInvoker invoker = new ... //DirectRPC或者MqRPC 選擇, 同上
//RpcFactory根據底層invoker來決定消息流
RpcFactory factory = new RpcFactory(invoker);   
//動態生成出InterfaceExample的實現類,RPC調用方不需要真正的實現類,客戶端與服務端都通interface解耦
InterfaceExample hello = factory.getService(InterfaceExample.class);

Spring的配置完全是上述代碼的XML翻譯,在此不做例子,具體參考examples下spring配置示例。

RPC服務方

RPC數據流圖中分布式服務提供方需要的兩件事情是

  1. 如何拿到請求RPC數據包
  2. 解釋好包如何調動本地對應的方法

對於問題1.如何拿到數據包,分兩大類處理方案:DirectRPC與MQ-RPC

DirectRPC則需要啟動網絡偵聽服務,被動處理請求RPC包;MQ-RPC則是使用Consumer從zbus的MQ隊列中主動取RPC請求包。

DirectRPC的服務zbus采用JAVA NIO服務器完成,對應org.zbus.rpc.direct.Service服務器完成NIO網絡伺服;MQ-RPC對應org.zbus.rpc.mq.Service,多Consumer線程從zbus的某個MQ隊列中並發取RPC請求包。

對於問題2,不管哪種模式的RPC都采用相同的處理方式--RpcProcessor

public class RpcProcessor implements MessageProcessor{ 
    private RpcCodec codec = new JsonRpcCodec(); //序列反序列化Request/Response
    private Map<String, MethodInstance> methods = new HashMap<String, MethodInstance>();  //業務方法映射表

    public void addModule(String module, Object... services){
        .....
    }
    public Message process(Message msg){ 
        .....
    }
}

RpcProcessor本質上是通過反射將業務邏輯對象中的方法組織成 method==>(Method對象,Instance)映射

RpcProcessor.addModule(module, BizObject...)完成這個映射的管理

process的過程如下:

1. 處理RPC的請求包,RpcCodec反序列化出Request對象
2. 根據Request對象找到合適的Method並嘗試調用
3. 調用結果組裝成合適的Response對象
4. RpcCodec反序列化Response對象返回RPC響應包

啟動RPC服務在zbus中變得非常簡單,分兩步完成

//1)構造RpcProcessor--准備好服務映射表 
RpcProcessor processor = new RpcProcessor();  
processor.addModule(new InterfaceExampleImpl()); //動態增加業務對象,提供真正的業務邏輯


//2)MQ-RPC或者DirectRPC的Service--容器運行上面的RpcProcessor
ServiceConfig config = new ServiceConfig();
config.setMessageProcessor(processor);  
//更多的配置
Service svc = new Service(config);
svc.start();  

Spring的配置完全是上述代碼的XML翻譯,在此不做例子,具體參考examples下spring配置示例。

zbus實現異構服務代理--服務總線

ZBUS = MQ+RPC

zbus總線

跨平台多語言+集中式節點控制,使得zbus適合完成服務總線適配工作。

為什么要采用總線架構適配已有服務? 1. 集中式接入控制 2. 標准化 3. 擴展引入zbus的多語言跨平台能力

總線架構的一個核心需求是提供便捷的服務適配能力,zbus通過MQ和RPC來完成,對

  1. 新服務 -- MQ-RPC模式完成,無侵入式
  2. 舊服務 -- 選擇舊服務支持的平台接入,通過MQ消息代理模式完成協議轉換

新服務接入參考zbus實現RPC部分

舊服務MQ代理模式適配數據流描述:

zbus標准RPC客戶端 <----> zbus(某個MQ隊列)------->consumer線程消費消息----RPC消息包解包---->舊協議組裝調用舊服務
                              ^                                                          |
                              |                                                          v
                              --------------consumer.route命令返回<-----組裝RPC消息包<----舊服務返回結果

代理模式一般在調用舊服務的時候采用異步模式,防止同步阻塞的場景發生 標准化RPC則采用zbus的JSON協議方式序列化消息與zbus消息交換,當然也可以私有的方式。

下面的子項目是多個語言平台實現MQ代理的案例

zbus底層編程擴展

接入zbus只需要遵循公開協議即可,目前已經支持的接入平台包括

zbus協議說明

zbus協議可以簡單描述為擴展HTTP協議,協議整體格式是HTTP格式,因為HTTP協議的廣泛應用,相對方便解釋與理解。但同時為了降低HTTP協議頭部負載與業務數據獨立於zbus控制數據,zbus采用了HTTP擴展協議:

  • 控制數據放在HTTP擴展頭部,比如增加mq: MyMQ\r\n擴展控制消息目標MQ
  • 業務數據放在HTTP消息體,不參與任何zbus消息控制,業務數據底層為byte[]二進制

因此zbus協議描述就是HTTP擴展的KeyValue描述

命令控制 cmd

zbus接收到消息Message做何種動作,由cmd KV擴展決定,支持的賦值(Protocol.java 中定義)

public static final String Produce   = "produce";   //生產消息命令
public static final String Consume   = "consume";   //消費消息命令
public static final String Route     = "route";     //路由回發送者命令
public static final String QueryMQ   = "query_mq";  //查詢消息隊列信息
public static final String CreateMQ  = "create_mq"; //創建消息隊列
public static final String RemoveMQ  = "remove_mq"; //刪除消息隊列 
public static final String AddKey    = "add_key";   //增加一個Key,用於判定某條消息是否重復,zbus簡單的KV服務
public static final String RemoveKey = "remove_key";//刪除一個Key 
//下面的命令是監控中使用到,test測試,data返回監控數據,jquery監控使用到的jquery.js
public static final String Auth      = "auth";  
public static final String Test      = "test";      
public static final String Data      = "data"; 
public static final String Jquery    = "jquery"; 

每個命令可能用到參數Key說明(Message.java)

public static final String MQ       = "mq";      //消息隊列標識 
public static final String SENDER   = "sender";  //消息發送者標識
public static final String RECVER   = "recver";  //消息接收者標識
public static final String ID       = "id";  //消息ID
public static final String RAWID    = "rawid";   //原始消息ID(消費消息時交換中用到)
public static final String SERVER   = "server";  //消息經過的broker地址
public static final String TOPIC    = "topic";   //消息發布訂閱主題, 使用,分隔 
public static final String ACK      = "ack";      //消息ACK
public static final String ENCODING = "encoding"; //消息body二進制編碼
public static final String KEY       = "key";      //消息的KEY
public static final String KEY_GROUP = "key_group"; //消息的KEY分組
public static final String MASTER_MQ  = "master_mq";   //消息隊列主從復制的主隊列標識
public static final String MASTER_TOKEN  = "master_token";  //主隊列訪問控制碼

具體每個命令對應使用到的參數,請參考MqAdaptor中對應每個命令的Handler

public class MqAdaptor extends IoAdaptor implements Closeable {
    public MqAdaptor(MqServer mqServer){ 
        ....
        registerHandler(Protocol.Produce, produceHandler); 
        registerHandler(Protocol.Consume, consumeHandler);  
        registerHandler(Protocol.Route, routeHandler); 

        registerHandler(Protocol.CreateMQ, createMqHandler);
        registerHandler(Protocol.QueryMQ, queryMqHandler);
        registerHandler(Protocol.RemoveMQ, removeMqHandler);

        registerHandler(Protocol.AddKey, addKeyHandler); 
        registerHandler(Protocol.RemoveKey, removeKeyHandler); 

        registerHandler("", homeHandler);  
        registerHandler(Protocol.Data, dataHandler); 
        registerHandler(Protocol.Jquery, jqueryHandler);
        registerHandler(Protocol.Test, testHandler);

        registerHandler(Message.HEARTBEAT, heartbeatHandler);   
    } 
}

zbus網絡編程模型

zbus底層通信基礎並沒有采用netty這樣的NIO框架,而是基於JAVA NIO做了一個簡單的封裝,盡管沒有使用到netty的大量開箱即用的功能,但是zbus也在通信基礎上獲取了些我們認為更加重要的東西: 1. 完全自主個性化的網絡事件模型 2. 輕量級通信底層

zbus的網絡通訊部分核心在org.zbus.net.core包中,org.zbus.net.http 提供了一個輕量級的HTTP擴展實現。

zbus的NIO通信模型的封裝非常簡單:

1. 網絡事件模型是由SelectorThread來完成,核心就是run方法中的多路復用檢測網絡IO事件
2. 在各個事件處理中(READ/WRITE/CONNECT/ACCEPT)中核心產生了Session處理
3. 事件處理公開機制靠IoAdaptor完成
4. 最外面由SelectorGroup完成多個SelectorThread的負載均衡與簡單管理,提高整體性能

上面的描述也是解讀代碼的先后順序

zbus在net.core包設計的基礎之上,為了方便使用方構建客戶端與服務器端程序,提供了Client、Server的基本封裝,同步異步處理Sync方便消息的同步異步轉換。

Client本質上就一個IoAdaptor應用案例,專門從連接客戶端角度處理網絡各項事件。 Server則提供了一個簡單機制,運行可被個性化的IoAdaptor實例。

Server端示例(簡潔性的體現)

//借助HTTP協議實現中的MessageAdaptor完成HTTP服務器,只需要簡單的
public static void main(String[] args) throws Exception {
    //1) SelectorGroup管理 
    final SelectorGroup group = new SelectorGroup();
    final Server server = new Server(group);
    //2)構建一個MessageAdaptor
    MessageAdaptor ioAdaptor = new MessageAdaptor();
    ioAdaptor.uri("/hello", new MessageProcessor() { 
        public Message process(Message request) {
            Message resp = new Message();
            resp.setStatus(200);
            resp.setBody("hello");
            return resp;
        }
    });
    //3)在8080端口上啟動這個IoAdaptor服務
    server.start(8080, ioAdaptor);
}

運行則直接可以統統瀏覽器訪問 http://localhost:8080/hello

這個示例並不是簡單的hello world,SelectorGroup使之具備高性能服務框架,在i7 CPU的box上能上10w+的QPS性能

具體請詳細參考examples下面的net示例

zbus高可用模式

zbus高可用采用類似zookeeper的跟蹤機制,但並沒有使用zookeeper。

zbus高可用由兩大節點群組成: 1. ZbusServer節點群 2. TrackServer節點群

ZbusServer節點群由單機版本的zbus組成,各個節點之間無狀態關聯,TrackServer節點群中各個節點也無任何狀態關聯,ZbusServer把節點狀態(諸如MQ信息)上報給所有的TrackServer。

這里面信息的一致性zbus是做了妥協的,可以理解為zookeeper一種簡化,典型配置是TrackServer全網配置兩台,所有的ZbusServer都向這兩台TrackServer上報各自的節點變化信息,包括某個節點MQ信息即時變化推送,定時(默認2s)重復更新。實用角度簡化設計的一種折中。

客戶端(生產者與消費者)仍然是直接鏈接到某個ZbusServer,但是選擇節點由訂閱TrackServer而給出的整體ZbusServer的節點拓撲信息決定,客戶端同時做了容錯處理,運行中所有的TrackServer失敗不影響已有拓撲信息的實用(本地緩存)

上述客戶端的復雜性由HaBroker封裝(最終由ZbusBroker統一類型選擇),API層面不受高可用選擇影響與單點zbus場景保持一致,同時高可用節點選擇算法也將陸續開放,方便二次開發個性化。

高可用HA環境的搭建 因為zbus HA方案中的節點無任何狀態聯系,因此HA環境搭建非常簡單,各個節點啟動無順序依賴,一般順序為:

  1. 啟動若干個(一般兩個)TrackServer群。
  2. 配置預先知道的TrackServer列表到ZbusServer(MqServer)的啟動項中,啟動若干個ZbusServer節點群。

整個HA的Broker環境就建立好了,例子可以參考zbus-dist/ha 目錄下的配置啟動,注意如果不按照先TrackServer啟動的順序,先啟動ZbusServer會臨時報無法找到某個TrackServer錯誤,直到TrackServer啟動正常,錯誤不影響使用。

HA最佳實踐指導:

  1. 生產者端(包括RPC客戶端)配置HaBroker,完全實現Failover與負載均衡
  2. 消費者端(包括RPC服務端)配置SingleBroker,不使用HaBroker的容錯,而是多機部署,這樣能運行確定節點分布。

上述HaBroker與SingleBroker都統一使用ZbusBroker,只是BrokerAddress的地址配置差異。

zbus性能測試數據

性能測試程序在test/performance目錄下,根據實際的機器測試給出。

一個參考數據,測試環境

MacBook Pro (Retina, 15-inch, Mid 2015)
Processor 2.5 GHz Intel Core i7
Memory 16 GB 1600 MHz DDR3

消息大小 "hello world"

  • 生產消息速度 (~4萬筆每秒)

測試代碼: org.zbus.performance.ProducerPerf.java

2016-03-16 14:50:08 INFO  Perf:73 - QPS: 42844.4874, Failed/Total=0/2660020(0.0000)
2016-03-16 14:50:09 INFO  Perf:73 - QPS: 42845.4515, Failed/Total=0/2670011(0.0000)
2016-03-16 14:50:09 INFO  Perf:73 - QPS: 42842.2988, Failed/Total=0/2680012(0.0000)
2016-03-16 14:50:09 INFO  Perf:73 - QPS: 42841.8991, Failed/Total=0/2690011(0.0000)
2016-03-16 14:50:09 INFO  Perf:73 - QPS: 42838.7834, Failed/Total=0/2700020(0.0000)
2016-03-16 14:50:10 INFO  Perf:73 - QPS: 42840.4312, Failed/Total=0/2710016(0.0000)
2016-03-16 14:50:10 INFO  Perf:73 - QPS: 42840.0428, Failed/Total=0/2720007(0.0000)
  • 消費消息速度(~4萬筆每秒)

測試代碼: org.zbus.performance.ConsumerPerf.java

2016-03-16 14:57:13 INFO  ConsumerPerf:47 - Consumed:150000, QPS: 43290.0433
2016-03-16 14:57:13 INFO  ConsumerPerf:47 - Consumed:160000, QPS: 43859.6491
2016-03-16 14:57:14 INFO  ConsumerPerf:47 - Consumed:170000, QPS: 43859.6491
2016-03-16 14:57:14 INFO  ConsumerPerf:47 - Consumed:180000, QPS: 43290.0433
2016-03-16 14:57:14 INFO  ConsumerPerf:47 - Consumed:190000, QPS: 43859.6491
2016-03-16 14:57:14 INFO  ConsumerPerf:47 - Consumed:200000, QPS: 44247.7876
2016-03-16 14:57:15 INFO  ConsumerPerf:47 - Consumed:210000, QPS: 43668.1223
2016-03-16 14:57:15 INFO  ConsumerPerf:47 - Consumed:220000, QPS: 44843.0493
2016-03-16 14:57:15 INFO  ConsumerPerf:47 - Consumed:230000, QPS: 44843.0493
  • HTTP響應速度(~6.6萬筆每秒)

測試代碼,服務器: org.zbus.examples.net.server.MyServer

壓力程序: ab -k -c 20 -n 1000000 http://localhost:8080/hello

Server Hostname:        localhost
Server Port:            8080

Document Path:          /hello
Document Length:        5 bytes

Concurrency Level:      20
Time taken for tests:   15.073 seconds
Complete requests:      1000000
Failed requests:        0
Keep-Alive requests:    1000000
Total transferred:      67000000 bytes
HTML transferred:       5000000 bytes
Requests per second:    66344.44 [#/sec] (mean)
Time per request:       0.301 [ms] (mean)
Time per request:       0.015 [ms] (mean, across all concurrent requests)
Transfer rate:          4340.90 [Kbytes/sec] received

項目點評 (15 條)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM