1. 程式人生 > >Netty實戰-Netty介紹

Netty實戰-Netty介紹

1. 為什麼使用Netty

      Netty是基於Java NIO的網路應用框架,它是一個NIO client-server(客戶端伺服器)框架,使用Netty可以快速開發網路應用,例如伺服器和客戶端協議。Netty提供了一種新的方式使開發網路應用程式具有更高的易用性和更強的擴充套件性。Netty的內部實現是很複雜的,但是Netty提供了簡單易用的api從網路處理程式碼中解耦業務邏輯。Netty是完全基於NIO實現的,所以整個Netty都是非同步的。

1.1 Netty框架組成

Netty除了提供傳輸和協議,在其他各領域都有發展,Netty為開發者提供了一套完整的工具

開發區域Netty特性
Design(設計)各種傳輸型別,阻塞和非阻塞套接字統一的API
使用靈活
簡單但功能強大的執行緒模型
無連線DatagramSocket支援
鏈邏輯,易於重用
Easy of Use(易用)提供大量的文件和例子
除了依賴jdk1.6+,沒有額外的依賴關係。某些功能依賴jdk1.7+,其他特性可能有相關依賴,但都是可選的
Performance(效能)比Java APIS更好的吞吐量和更低的延遲
因為執行緒池和重用所有消耗較少的資源
儘量減少不必要的記憶體拷貝
Robustness(魯棒性)魯棒性,可以理解為健壯性
連結快或慢或超載不會導致更多的OutOfMemoryError
在高速的網路程式中不會有不公平的read/write
Security(安全性)
完整的SSL/TLS和StartTLS支援
可以在如Applet或OSGI這些受限制的環境中執行
Community(社群)版本釋出頻繁
社群活躍
      除了上述功能外,Netty為Java NIO中的bug和限制也提供瞭解決方案。我們需要深刻理解Netty的功能以及它的非同步處理機制和它的架構。NIO和Netty都大量使用了非同步程式碼,並且封裝的很好,我們無需瞭解底層的時間選擇機制。

1.2 非同步設計

       整個Netty的API都是非同步的,非同步處理不是一個新的機制。對於網路應用來說,IO一般是效能的瓶頸,使用非同步IO可以較大程度上提高程式效能,因為非同步變的越來越重要。非同步處理提倡更有效的使用資源,它允許你建立一個任務,當有事件發生時將獲得通知並等待時間完成,這樣就不會阻塞,不管事件完成與否都會及時返回,資源利用率更高,程式可以利用剩餘的資源做一些其它的事情。下面的是API的兩個最常用的方法,並討論這些技術之間的差異。

1.2.1 Callbacks(回撥)

       回撥一般是非同步處理的一種技術。下面的程式程式碼展示的是一個簡單的回撥:

      獲取角色介面:

package netty.in.action;

public interface FetcherRole {
    void fetchData(FetcherCallBack callback);
}

      實現的獲取角色

package netty.in.action;

import netty.in.action.Data;

public class MyFetcher implements FetcherRole{
    final Data data;

    public MyFetcher(Data data)
    {
        this.data=data;
    }

    @Override
    public void fetchData(FetcherCallBack callback)
    {
        try
        {
            callback.onData(data);
        }catch(Exception e)
        {
            callback.onError(e);
        }
    }
}

        回撥函式介面:

package netty.in.action;

public interface FetcherCallBack {
    void onData(Data data) throws Exception;
    void onError(Throwable cause);
}

      定義資料結構:

package netty.in.action;

public class Data {
    private int n;
    private int m;

    public Data(int n,int m)
    {
        this.n=n;
        this.m=m;
    }

    @Override
    public String toString()
    {
        int r=n/m;
        return n+"/"+m+"="+r;
    }
}

        執行:

package netty.in.action;

public class Client {
    public static void main(String[] args)
    {
        WorkerRole w=new WorkerRole();
        w.doWork();
    }
}

執行結果如下:


除數為零,報錯,回撥成功執行;修改m值為1後的執行結果下,程式成功執行;

     上面的例子是一個簡單的模擬回撥,Fetcher.fetchData()方法需傳遞一個FetcherCallback型別的引數,當獲得資料或發生錯誤時被回撥,對不同的情況提供了統一的方法:

      FetcherCallback.onData(),在接受資料是被呼叫

      FetcherCallback.onError(),發生錯誤時被呼叫。

1.2.2 Futures

第二種技術是使用Futures。Futures是一個抽象的概念,它表示一個值,改值可能在某一點變得可用。一個Future要麼獲得計算完的結果,要麼獲得計算失敗的異常。Java在java.util.concurrent包中附帶了Future介面,它使用Executor非同步執行。下面的例子,每傳遞一個Runnable物件到ExecutorService.submit()方法就會得到一個回撥的Future,你能使用它檢測是否執行完成。

package netty.in.action;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class FutureExample {
    public static void main(String[] agrs) throws Exception
    {
        ExecutorService executor=Executors.newCachedThreadPool();
        Runnable task1=new Runnable() {
            @Override
            public void run() {
                //do something
                System.out.println("i am task1 ....");
            }
        };
        Callable<Integer> task2=new Callable<Integer>() {
            @Override
            public Integer call() throws Exception {
                return new Integer(100);
            }
        };
        Future<?> f1=executor.submit(task1);
        Future<Integer> f2=executor.submit(task2);
        System.out.println("task1 is completed? "+f1.isDone());
        System.out.println("task2 is completed? "+f2.isDone());
        //waiting task1 completed
        while(f1.isDone())
        {
            System.out.println("task1 completed");
            break;
        }
        while(f2.isDone())
        {
            System.out.println("return value by task2 "+f2.get());
            break;
        }
    }
}