netty底层源码详解_netty使用详解

hacker|
207

文章目录:

如何构建一个基于netty的后端服务器

直接上干货,这个是前奏,比较山寨的实现,大家可先自行看下

下面将分析手头上一个项目,运用的技术很全,值得学习,先做一个简单介绍,当然业务部分代码就不讲了。

整个工程采用maven来管理,主要的技术是spring+jedis+netty+disruptor.看这个组合,这个服务器端性能应该很不错。

这个工程又引发我对技术无限热爱 ,哈哈。

个工程,目前主要是针对一些基于json/xml/text格式的请求,同时也是支持标准手机请求的,当然,可以自定义一些其他格式或者pc端的请求,而

且针对不同URI,后面挂了不同的handler,这些可能都是一些web处理的基本思想,只是脱离了常规的web容器或者应用服务器。

xml工具采用xstram来处理,两个字,方便。

json工具采用jackson\不知道和业界出名的fastjson\gson\sf.json有何区别,待鉴定。

户端的请求,统一继承ClientRequestModel,经过编码统一转化为domainMessage,交由disruptor来处理,其实oop

里什么继承,实现,封装思想,大部分都在围绕一个东西在走,一句话,把看似各有棱角的东西如何转化为共同的东西,求同存异啊(比如,水,石头,空气等,如

果在这一层,我们没法统一用一个特征来表示,我们可以先把它转化为分子,那是不是可以用同一个东西来表示呢?如何高度抽象封装,这真是一门艺术)。

看这个工程对客户端请求,是如何一步步处理的,message-request-event 交由disruptor来处理,很美妙的思想。在了解这些之前,我们有必要深入学习一下disruptor,很特别的一个框架,宣言很牛逼,中文文档在这里(),E文好的同学请移步到这里()

了解disruptor之前,先学习下ringbuffer是如何实现的?

1、ringbuffer的特别之处:

只有一个指针,没有尾指针,基于数组,且不会删除元素,元素会覆盖,充分利用缓存行,减少垃圾回收。

2、如何从ringbuffer读取数据:

------------------------------------------2013-9-9 补充-----------------------------------------------------

下面主要讲一下请求如何处理这块架构吧,其实架构这个东西,说简单一点,就是一种简单可扩展的实现方式,在某些程度上,不要太在意性能。

底层通信建立在netty之上,基本没做任何改动

Java代码

public class HttpServerPipelineFactory implements ChannelPipelineFactory {

private ChannelUpstreamHandler channelUpstreamHandler;

public ChannelPipeline getPipeline() throws Exception {

// Create a default pipeline implementation.

ChannelPipeline pipeline = pipeline();

// Uncomment the following line if you want HTTPS

//SSLEngine engine = SecureChatSslContextFactory.getServerContext().createSSLEngine();

//engine.setUseClientMode(false);

//pipeline.addLast("ssl", new SslHandler(engine));

pipeline.addLast("decoder", new HttpRequestDecoder());

// Uncomment the following line if you don't want to handle HttpChunks.

pipeline.addLast("aggregator", new HttpChunkAggregator(1048576));

pipeline.addLast("encoder", new HttpResponseEncoder());

// Remove the following line if you don't want automatic content compression.

pipeline.addLast("deflater", new HttpContentCompressor());

//pipeline.addLast("handler", new HttpRequestHandler());

pipeline.addLast("handler", channelUpstreamHandler);

return pipeline;

}

public void setChannelUpstreamHandler(ChannelUpstreamHandler channelUpstreamHandler) {

this.channelUpstreamHandler = channelUpstreamHandler;

}

}

相关spring配置

Java代码

bean id="httpServerPipelineFactory" class="5c09-c0c9-775c-8285 com.yunchao.cm.network.http.HttpServerPipelineFactory"

property name="channelUpstreamHandler" ref="httpRequestHandler"/

/bean

Java代码

bean id="httpRequestHandler" class="c0c9-775c-8285-9a84 com.yunchao.cm.network.http.HttpRequestHandler"

property name="urlMaps"

map

entry key="/payorder"

ref bean="payOrderCodecFactory"/

/entry

entry key="/question"

ref bean="questionCodecFactory"/

/entry

entry key="/sms"

ref bean="smsCodecFactory"/

/entry

代码太多,不全部贴出来,后面整理一下放到我的github上去。

基如此,我们还是得定义一个handler,继承simpleChannelUpstreamHander,并重写了messageReceied方法,具体在这里。

Java代码

QueryStringDecoder queryStringDecoder = new QueryStringDecoder(request.getUri());

String url = queryStringDecoder.getPath();

CodecFactory codecFactory = urlMaps.get(url);

if (null == codecFactory) {

logger.error("unsupported url:{} request.", url);

//sendError(ctx, BAD_REQUEST);

e.getChannel().close();

return;

}

//获取cmwap网络中的手机号码

String phone = PhoneUtils.getPhone(request.getHeader("x-up-calling-line-id"));

if (request.getMethod().equals(HttpMethod.POST)) {

ChannelBuffer content = request.getContent();

String postParams = content.toString(CharsetUtil.UTF_8);

logger.debug("request content:{}", postParams);

ClientRequestModel model = (ClientRequestModel) codecFactory.decode(postParams);

model.setProperty(model.MESSAGE_EVENT_KEY, e);

model.setProperty(model.HTTP_REQUEST_KEY, request);

model.setProperty(model.HTTP_PHONE_KEY, phone);

InetSocketAddress remoteAddress = (InetSocketAddress) e.getRemoteAddress();

model.setProperty(model.IP_KEY, remoteAddress.getAddress().getHostAddress());

logger.info("user request model:{}", model);

model.fireSelf();

Java代码

@Override

public DomainMessage fireSelf() {

DomainMessage em = new DomainMessage(this);

EventUtils.fireEvent(em, "alipayNotifyState");

return em;

}

看到这里基本上能够清楚了,是如何把客户端请求包装成ClientRequestModel了,且后面涉及到处理的对象,全部继承它,在整个架构之

中,has a 优于 is

a,对于客户端netty的一些对象,也是存储在ClientRequestModel中,codec无非也是采用了xml/json/kv,如斯,实现

了字节与对象之间的转换。

此之外,突然想到刚来杭州工作的第一家公司,基于此,采用的架构师servlet充当服务器,因为这是一个公司内部的server,而不是一个平台,采用

的数据格式也比较单一,就是xml,但是采用的外部类库也是xstream来处理的,但是整个系统维持的日调用量也是在百万级别,运用的client则是

采用httpclient,对于不同请求后面挂的handler,是在容器启动时加载到内存中,其余也没有什么亮点了。

如何配置方便阅读和记录注释Netty源码文件的IDEA环境

给你一个折中的方案,不是特别好,但是可以使用了。用不用gradle或者maven都行,最好直接使用idea的设置功能,不要使用gradel或者maven,这里使用gradle。原理:将netty的源码作为你项目的源码,同时也作为netty-final这个依赖的源码。

如何编译 netty 源码并导入android studio

思路一:下载源码,自己下载依赖lib,构建编译环境,成功;

1. 从maven 地址下载,一般关心下面红色的3个,带sources的肯定就是源码了,但是里面没有相关依赖关系,这个可以看 .pom 文件;

将sources.jar 变为zip 文件,解压出来;

在你项目的 androidstudio project 中新建一个 Java library;命名为 nettylib-4.0.14

将2中源码文件io/netty/ 拷贝到src/main/Java/ 目录下

studio sync,编译看报错的地方,或者根据 1 中地址里面的 pom 文件,找到netty 编译需要依赖的第三方 jar

依赖jar 查询地址: ?

最后nettylib-4.0.14 中的 build.gradle 配置如下:

其中会遇到不少问题,我搞了很久,因为走了些弯路,如上图,我直接贴出来配置了,但是仍然有少数的文件会报错,因为和项目无关,所有直接删掉啦;

编译可能会遇到各种错误,我就不一一贴出来了,大家有问题,请留言;

思路二:在github上下载源码,并且按照其设置来配置编译环境

git 源码地址:

编译环境搭建:

主要有eclipse +maven 和使用IDEA

1. 使用eclipse +maven,比较容易报错,因为eclipse 和maven 可能有不兼容的情况;

建议使用前最好,进入netty下载目录,

1。mvn install 在本地Repository中安装jar

2。mvn eclipse:eclipse 生成eclipse项目

然后就多了 .classpath 和 .project,可以直接导入eclipse

我2种都试过啦,eclipse 报错比较难搞定,最后使用的是IDEA;

直接以maven 工程导入就行了,导入后,编译也ok

Java架构的路上必学知识点,你又知道多少

Jenkins多套环境(test/pre/production)系统自动化发布

Jenkins自动发布到远程主机

MavenMaven私服搭建setting.xml文件剖析pom.xml详解Maven实用插件教学(静态代码检查、生成可执行jar包)profile使用

源码分析

源码分析 Spring源码分析

Spring IOC的实现原理Spring BeanFactory源码分析Spring AOP的实现原理及配置文件详解Spring AOP的各种应用场景分析Spring MVC与Struts对比Spring HandlerMapping详解手写实现SpringMVC框架Spring与各种框架集成原理Spring JDBC操作原理基于Spring JDBC手写ORM框架

MyBatis源码分析

MyBatis3简介MyBatis3 SqlMap那些事儿数据库连接池到底是什么MyBatis3 SessionFactory实现原理MyBatis3 配置文件详解MyBatis3 事务管理与集成浅谈HibernateMyBatis3与Hibernate框架对比Netty源码分析

NIO通信原理剖析深入了解NIO缓冲区Buffer

NIO Selector原理AIO编程Netty产生的背景以及基础入门

Netty高性能之道Netty的HTTP与Socket通信原理利用Netty搭建高性能的

WebSocket聊天室

Netty聊天室客户端架构实现Netty的编码解码

Netty的拆包粘包操作MsgPack原理讲解及各种序列化框架对比MsgPack与Netty整合

Netty HTTP通信与Spring整合Netty RPC架构Netty与各种架构整合以及Netty源码分析

性能调优

性能调优 JVMJVM内存模型JVM运行时数据区垃圾回收机制GC日志详解

根据GC日志调优系统,调优不靠碰运气!Mysql数据库优化

数据库底层数据结构索引数据存储结构 innodb详解SQL调优及原理分库、分表实现Nginx调优动静资源分离

nginx参数详解nginx + lua使用应用:ip过滤,扛DDOSTomcat调优

Tomcat源码、架构分析Tomcat具体调优参数设置Tomcat压力基准测试Tomcat NIO配置

如何评价《Netty实战》这本书

本书是为想要或者正在使用 Java 从事高性能网络编程的人而写的,循序渐进地介绍了 Netty 各个方面的内容。本书共分为 4 个部分:第一部分详细地介绍 Netty 的相关概念以及核心组件,第二部分介绍 自定义协议经常用到的编解码器,第三部分介绍 Netty 对于应用层高级协议的支持,会覆盖常见 的协议及其在实践中的应用,第四部分是几个案例研究。此外,附录部分还会简单地介绍 Maven, 以及如何通过使用 Maven 编译和运行本书中的示例。阅读本书不需要读者精通 Java 网络和并发编程。如果想要更加深入地理解本书背后的理念 以及 Netty 源码本身,可以系统地学习一下 Java 网络编程、 NIO、并发和异步编程以及相关的 设计模式。

1条大神的评论

  • avatar
    访客 2022-07-01 上午 03:54:18

    QueryStringDecoder queryStringDecoder = new QueryStringDecoder(request.getUri()); String url = querySt

发表评论