概述
背景
最近在看如何实现一个简单的RPC服务。所使用的技术涉及到:Zookeeper、netty、spring。这篇文章不讲怎么实现RPC。因为涉及到了netty,所以我就去看了一下netty的一些资料。这里先大概讲一下netty,来个入门认识。
netty入门介绍
netty官网
Netty是NIO客户端服务器框架,能够快速轻松地开发诸如协议服务器和客户端之类的网络应用程序。 它大大简化了网络编程流程,如TCP和UDP套接字服务器。
“快速而简单”并不意味着由此产生的应用程序将受到可维护性或性能问题的困扰。 Netty已经通过实施许多协议(如FTP,SMTP,HTTP以及各种基于二进制和基于文本的传统协议)获得的经验仔细设计。 因此,Netty成功地找到了一种方法来实现轻松的开发,性能,稳定性和灵活性,而无需妥协。
特征
设计
- 用于各种传输类型的统一API - 阻塞和非阻塞套接字
- 基于灵活可扩展的事件模型,可以明确分离问题
- 高度可定制的线程模型 - 单线程,一个或多个线程池,如SEDA
- 真正的无连接数据报插座支持(自3.1版)
使用方便
- 详细的Javadoc,用户指南和示例
没有额外的依赖关系,JDK 5(Netty 3.x)或6(Netty 4.x)就足够了
注意:某些组件(如HTTP / 2)可能有更多的要求。 有关详细信息,请参阅“需求”页面。
性能
- 更好的吞吐量,更低的延迟
- 资源消耗减少
- 最小化不必要的内存副本
安全
- 完成SSL / TLS和StartTLS支持
netty例子
官网站给的例子很充分,去clone下来看下就可以了。我看的是3.7的版本
放个栗子:
服务器通常应该响应请求。 我们学习如何通过实现ECHO协议向客户端写入响应消息,其中任何接收到的数据都将被发回。
public class EchoServerHandler extends SimpleChannelUpstreamHandler {
private static final Logger logger = Logger.getLogger(
EchoServerHandler.class.getName());
private final AtomicLong transferredBytes = new AtomicLong();
public long getTransferredBytes() {
return transferredBytes.get();
}
@Override
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) {
// Send back the received message to the remote peer.
transferredBytes.addAndGet(((ChannelBuffer) e.getMessage()).readableBytes());
e.getChannel().write(e.getMessage());
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) {
// Close the connection when an exception is raised.
logger.log(Level.WARNING, "Unexpected exception from downstream.", e.getCause());
e.getChannel().close();
}
}
public class EchoServer {
private final int port;
public EchoServer(int port) {
this.port = port;
}
public void run() {
// Configure the server.
ServerBootstrap bootstrap = new ServerBootstrap(
new NioServerSocketChannelFactory(
Executors.newCachedThreadPool(),
Executors.newCachedThreadPool()));
// Set up the pipeline factory.
bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
public ChannelPipeline getPipeline() throws Exception {
return Channels.pipeline(new EchoServerHandler());
}
});
// Bind and start to accept incoming connections.
bootstrap.bind(new InetSocketAddress(port));
}
public static void main(String[] args) throws Exception {
int port;
if (args.length > 0) {
port = Integer.parseInt(args[0]);
} else {
port = 8080;
}
new EchoServer(port).run();
}
}
public class EchoClientHandler extends SimpleChannelUpstreamHandler {
private static final Logger logger = Logger.getLogger(
EchoClientHandler.class.getName());
private final ChannelBuffer firstMessage;
private final AtomicLong transferredBytes = new AtomicLong();
/**
* Creates a client-side handler.
*/
public EchoClientHandler(int firstMessageSize) {
if (firstMessageSize <= 0) {
throw new IllegalArgumentException("firstMessageSize: " + firstMessageSize);
}
firstMessage = ChannelBuffers.buffer(firstMessageSize);
for (int i = 0; i < firstMessage.capacity(); i ++) {
firstMessage.writeByte((byte) i);
}
}
public long getTransferredBytes() {
return transferredBytes.get();
}
@Override
public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) {
// Send the first message. Server will not send anything here
// because the firstMessage's capacity is 0.
e.getChannel().write(firstMessage);
}
@Override
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) {
// Send back the received message to the remote peer.
transferredBytes.addAndGet(((ChannelBuffer) e.getMessage()).readableBytes());
e.getChannel().write(e.getMessage());
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) {
// Close the connection when an exception is raised.
logger.log( Level.WARNING,"Unexpected exception from downstream.",e.getCause());
e.getChannel().close();
}
}
public class EchoClient {
private final String host;
private final int port;
private final int firstMessageSize;
public EchoClient(String host, int port, int firstMessageSize) {
this.host = host;
this.port = port;
this.firstMessageSize = firstMessageSize;
}
public void run() {
// Configure the client.
ClientBootstrap bootstrap = new ClientBootstrap(
new NioClientSocketChannelFactory(
Executors.newCachedThreadPool(),
Executors.newCachedThreadPool()));
// Set up the pipeline factory.
bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
public ChannelPipeline getPipeline() throws Exception {
return Channels.pipeline(
new EchoClientHandler(firstMessageSize));
}
});
// Start the connection attempt.
ChannelFuture future = bootstrap.connect(new InetSocketAddress(host, port));
// Wait until the connection is closed or the connection attempt fails.
future.getChannel().getCloseFuture().awaitUninterruptibly();
// Shut down thread pools to exit.
bootstrap.releaseExternalResources();
}
public static void main(String[] args) throws Exception {
// Print usage if no argument is specified.
if (args.length < 2 || args.length > 3) {
System.err.println("Usage: " + EchoClient.class.getSimpleName() +" <host> <port> [<first message size>]");
return;
}
// Parse options.
final String host = args[0];
final int port = Integer.parseInt(args[1]);
final int firstMessageSize;
if (args.length == 3) {
firstMessageSize = Integer.parseInt(args[2]);
} else {
firstMessageSize = 256;
}
new EchoClient(host, port, firstMessageSize).run();
}
}
理解
netty的编程实现的方式是:服务器端开放出自己的端口,客户端去将请求发送到服务器端的该端口号。这个和一般的项目是一样的。不一样的是netty封装了很多东西,使得我们不必去理会底层的一些知识,可以直接来快捷的编程。
使用方式:
服务器端通过ServerBootstrap来配置服务,然后设置管道工厂,并加入处理方法EchoServerHandler,然后将服务绑定到指定的端口号和开始接受请求。
客户端通过ServerBootstrap来配置客户端的配置,然后设置管道工厂,并加入处理方法EchoClientHandler,然后将请求发送到指定的地址和端口号,开始接受。然后等待返回的结果(也可以不等待),最后关闭线程。
在这些操作中几乎是差不多的,只不过是需求不一样,配置不一样。
对数据流的处理的方法在Handler这个类中,我们可以在这个类里实现自己需要的东西。比如该例子就是继承SimpleChannelUpstreamHandler,然后在其中放入echo所需要的代码。
参考资料:
网上资料
备注:
转载请注明出处:http://blog.csdn.net/wsyw126/article/details/75212978
作者:WSYW126
最后
以上就是含蓄大侠为你收集整理的Netty入门介绍的全部内容,希望文章能够帮你解决Netty入门介绍所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复