一、Netty介绍
Netty是基于Java NIO的网络应用框架,是一个NIO client-server(客户端服务器)框架,使用Netty可以快速开发网络应用,例如服务器和客户端协议。Netty的内部实现是很复杂的,但是Netty提供了简单易用的api从网络处理代码中解藕业务逻辑。Netty是完全基于NIO实现的,所以整个Netty都是异步的。
二、为什么使用Netty?
Netty提供了高层次的抽象来简化TCP和UDP服务器的编程,但是你仍然可以使用底层地API。
三、Netty的功能非常丰富
下图是Netty框架的组成。
Netty除了提供传输和协议,在其他各领域都有发展,Netty为开发者提供了一套完整的工具,看下面的表格:
四、异步设计
异步处理提倡更有效的使用资源,它允许你创建一个任务,当有事件发生时将获得通知并等待事件完成。这样就不会阻塞,不管事件完成与否都会及时返回,资源利用率高,程序可以利用剩余的资源做一些其他的事情。
五、Callbacks(回调)
回调一般是异步处理的一种技术。一个回调是被传递到并且执行完该方法。你可能认为这种模式来自JavaScript,在Javascript中,回调是它的核心。下面的代码显示了如何适用这种技术来获取数据。下面代码是一个简单的回调:
package netty.in.action;
/**
* Created by Administrator on 15-4-10.
*/
public class Worker {
public void doWork(){
Fetcher fetcher = new MyFetcher(new Data(1,0));
fetcher.fetchData(new FetcherCallback() {
@Override
public void onData(Data data) throws Exception {
System.out.println("Data received: " + data);
}
@Override
public void onError(Throwable cause) {
System.out.println("An error accour: " + cause.getMessage());
}
});
}
public static void main(String[] args){
Worker w = new Worker();
w.doWork();
}
}
package netty.in.action;
/**
* Created by Administrator on 15-4-10.
*/
public class MyFetcher implements Fetcher {
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;
/**
* Created by Administrator on 15-4-10.
*/
public interface Fetcher {
void fetchData(FetcherCallback callback);
}
package netty.in.action;
/**
* Created by Administrator on 15-4-10.
*/
public interface FetcherCallback {
void onData(Data data) throws Exception;
void onError(Throwable cause);
}
package netty.in.action;
/**
* Created by Administrator on 15-4-10.
*/
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() {
return "Data{" +
"n=" + n +
", m=" + m +
'}';
}
}
上面的例子只是一个简单的模拟回调,要明白其所表达的含义。Fetcher.fetchData()方法需传递一个FetcherCallback类型的参数,当获得数据或发生错误时被回调。对于每种情况都提供了同意的方法:
FetcherCallback.onData(),接收数据时被调用
FetcherCallback.onError(),发生错误时被调用
因为可以将这些方法的执行从“caller”线程移动到其他的线程执行;但也不会保证FetcherCallback的每个方法都会被执行。回调过程有个问题就是当你使用链式调用很多不同的方法会导致线性代码;有些人认为这种链式调用方法会导致代码难以阅读,但是我认为这是一种风格和习惯问题。例如,基于Javascript的Node.js越来越受欢迎,它使用了大量的回调,许多人都认为它的这种方式利于阅读和编写。
六、Futures
第二种技术是使用Futures。Future上是一个抽象的概念,它表示一个值,该值可能在某一点变得可用。一个Future要么获得计算完的结果,要么获得计算失败后的异常。Java在java.util.concurrent包中附带了Future接口,它使用Executor异步执行。例如下面的代码,每传递一个Runnable对象到ExecutorService.submit()方法就会得到一个回调的Future,你能使用它检测是否执行完成。
package netty.in.action;
import javax.security.auth.callback.Callback;
import java.util.concurrent.*;
/**
* Created by Administrator on 15-4-10.
*/
public class FutureExample {
public static void main(String[] args) throws ExecutionException, InterruptedException {
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 {
//do something
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.");
}
//waiting task2 completed
while(f2.isDone()){
System.out.println("return value by task2:" + f2.get());
break;
}
}
}
七、跨平台和兼容性问题
八、扩展ByteBuffer
ByteBuffer是一个数据容器,但是可惜的是JDK没有开发ByteBuffer实现的源码;ByteBuffer允许包装一个byte[]来获得一个实例,如果你希望尽量减少内存拷贝,那么这种方式是非常有用的。若你想将ByteBuffer重新实现,那么不要浪费你的时间了,ByteBuffer的构造韩式是私有的,所以它不能被扩展。Netty提供了自己的ByteBuffer实现,Netty通过一些简单的APIS对ByteBuffer进行构造、使用和操作,以此来解决NIO中一些限制。
九、NIO对缓冲区的聚合和分散操作可能会操作内存泄露