首页 > 编程知识 正文

netty的应用场景,netty框架使用场景

时间:2023-05-04 06:38:51 阅读:11414 作者:4257

摘要Netty是JBOSS提供的java开源框架,是一个高性能、可扩展的异步事件驱动的网络APP应用程序框架,包括TCP、UDP客户端和服务器开发NIO有下面的缺点:JDK的NIO基础是由epoll实现的,由于恶性的selex null轮询导致的错误导致CPU 100 %上升NIO的API复杂,使用麻烦,因此选择电机而且,要编写高质量的NIO代码,必须熟悉Java多线程编程和网络编程。 开发的工作量和难易度都非常高。 例如客户端断开重新连接、网络闪回、半分组读取、缓存失败等问题。 出现了像Netty这样优秀的开发源框架

设计特性统一的API,支持支持多种传输类型、阻塞和无阻塞的简单强大的线程模型,真正的非连接数据报套接字基于灵活、可扩展的事件模型,易于明确隔离使用,详细说明JDK5(netty3.x )或6 )6(Netty 4.x )就足够了。 (某些可选功能可能需要Java1.7或其他依赖项)性能比Java核心API具有更高的吞吐量,低延迟可受益于池化和复用。 通过最大限度地减少资源消耗和最大限度地减少不必要的内存复制内存回收,内存不足错误消除了高速网络中nio APP应用中常见的不公平读/写比率(由于速度慢、速度快或过载)

整体图支持So

cket等多种传输方式netty分为三大模块

支持多种传输方法(如tcp udphttp )并提供多种协议的编解码器实现核心设计包括事件处理模型、API处理模型和零拷贝机制字节缓冲器扩展。 在nio的扩展Netty核心组件Channel:netty中定义的Channel扩展通道概念EventLoop:是线程驱动的,Channel的所有I/o处理事件轮询的ChannelPiepleline:事件处理程序ChannelHandler:事件处理程序ByteBuf:扩展ByteBuffer缓冲区Bootstrap:启动器,Netty

ependencygroupidio.net ty/groupidartifactidnetty-all/artifactidversion4.1. 68.final/version/dependency

netty-all中包含的所有模块都包含核心,如buffer channel handler,并根据需要选择不同的maven依赖关系

这里面包含了netty的各个部分。

使用一个netty作为一个例子将例子启动起来

publicclassnettystarter { publicstaticvoidmain (字符串[ ] args ) throwsinterruptedexception(/主线程组是客户连接nioeventlll 处理来自客户端的请求nioeventloopgroupsubgroup=newnioeventloopgroup (); 创建//启动器并配置serverbootstrapboostrap=new server bootstrap (); boostrap.group (主组,subGroup ).option channel option.so _ backlog,1024 ).channel nioserversocketchannel 拦截channeal释放,线程组channel.closeFuture ().addlisteners () future-{ main group.shut down gracefully ) ); subGroup.shutdownGracefully (; ); }通过创建主线程组和子线程组创建启动器来配置启动器启动

动器绑定好端口既可启动该netty了 。等待服务端channel关闭并释放资源

并且netty是可以使用bio的程序需要修改 线程组,这是netty提供的类,这个修改也是非常简单的

// 主线程组 处理客户都安连接OioEventLoopGroup mainGroup = new OioEventLoopGroup(1);// 工人线程组,处理客户端的请求 读取 和写入OioEventLoopGroup subGroup = new OioEventLoopGroup();

至于为什么 要加主线程组以及子线程组,可以看一下下面篇博客 

Reactor网络编程模型解析

netty 在github源代码

netty github的源代码及例子实现

Netty线程模型 为了让NIO处理,更好的利用多线程特性,Netty实现了Reactor线程模型。 Reactor模型中有四个核心概念: Resources 资源(请求/任务) Synchronized Event Demultiplexer 同步事件复用器  事件不停的死循环查找是否死循环 分配器 dispatcherRequest Handler 请求处理器

请求流程

客户端发起请求,首先到达操作系统操作系统会转发给jvm  netty是启动着,最先找到设置的NioEventLoopGroup 主线程 默认为1 持有连接连接注册到register 分配到选择 对应的workgroup 的NioEventLoopGroup 线程去读取请求数据   创建的线程默认是cpu的2倍 每个线程都有个 queue  存放任务, 当用户线程不空闲时,过来的请求会放到queue中每个IO的工作线程都有个死循环去读取数据,这个select 会阻塞 释放cpu的 NioEventLoopGroup初始化过程

 NioEventLoopGroup 初始化过程从源码中看 NioEventLoopGroup subGroup = new NioEventLoopGroup(); 父类的MultithreadEventLoopGroup 类中初始化时创建对应的线程数 默认就是 cpu的两倍,NettyRuntime.availableProcessors()获取cpu数  全局的系统参数 io.netty.eventLoopThreads  可以在外部指定 static { DEFAULT_EVENT_LOOP_THREADS = Math.max(1, SystemPropertyUtil.getInt( "io.netty.eventLoopThreads", NettyRuntime.availableProcessors() * 2)); if (logger.isDebugEnabled()) { logger.debug("-tzdlt.netty.eventLoopThreads: {}", DEFAULT_EVENT_LOOP_THREADS); } } protected MultithreadEventLoopGroup(int nThreads, Executor executor, Object... args) { super(nThreads == 0 ? DEFAULT_EVENT_LOOP_THREADS : nThreads, executor, args); } 父类的MultithreadEventLoopGroup   最核心的初始化方法

     1. 首先做了创建线程执行器  和 事件执行器数组

protected MultithreadEventExecutorGroup(int nThreads, Executor executor, EventExecutorChooserFactory chooserFactory, Object... args) { checkPositive(nThreads, "nThreads"); //线程执行器 ,如果在创建eventLoopGroup时没有指定,则使用netty提供的默认执行器 if (executor == null) { executor = new ThreadPerTaskExecutor(newDefaultThreadFactory()); } //创建 事件执行器的数组 children = new EventExecutor[nThreads]; //创建事件轮询器 for (int i = 0; i < nThreads; i ++) { boolean success = false; try { children[i] = newChild(executor, args); success = true; } catch (Exception e) { // TODO: 创建失败 throw new IllegalStateException("failed to create a child event loop", e); } finally { //等等就省略掉 } } }

从这个newChild方法上追寻下去 是由NioEventLoopGroup里面实现 这里使用了模板模式 创建NioEventLoop其实上面做了一些操作,和我们初始化并不是特别大的关联就不看了

在NioEventLoop初始化就能看到里面做的一些事情了

包括比较重要的newTaskQueue 选择提供器 和 selector  provider  提供器,如果不太清楚的话可以看一下 nio 中selector.open()方法也是通过provider方法 去创建selector对象

public static Selector open() throws IOException { return SelectorProvider.provider().openSelector(); }

2.继续创建一个选择器 

//创建选择器chooser = chooserFactory.newChooser(children);

这个选择器的作用用于连接过来时选择不同的工作线程 也就是NioEventLoop 

从MultithreadEventLoopGroup的实现来看出 netty包括下面几种实现创建evntLoop事件驱动器

MultithreadEventExecutorGroup 的register Channel 通道流程  

该方法主要用于选择那个工作子线程进行读取 数据

@Override public ChannelFuture register(Channel channel) { return next().register(channel); }

而这里的next 方法就是刚才 创建选择器的 方法

@Override public EventExecutorChooser newChooser(EventExecutor[] executors) { if (isPowerOfTwo(executors.length)) { return new PowerOfTwoEventExecutorChooser(executors); } else { return new GenericEventExecutorChooser(executors); } }

随便点DefaultEventExecutorChooserFactory 这个进去就能很容易看到选择线程的方式

public EventExecutor next() { return executors[Math.abs(idx.getAndIncrement() % executors.length)]; } EventLoop 的启动 EventLoop自身实现了Executor接口,当调用executor方法提交任务时,则判断是否启动,未启 动则调用内置的executor创建新线程来触发run方法执行。

查看NioEventLoop 的继承体系 public final class NioEventLoop extends SingleThreadEventLoop { 而SingleThreadEventLoop 继续继承  public abstract class SingleThreadEventLoop extends SingleThreadEventExecutor implements EventLoop { 在 SingleThreadEventExecutor 中有 执行方法

 在启动线程中 到doStartThread 方法中 private void doStartThread() { assert thread == null; executor.execute(new Runnable() { @Override public void run() { thread = Thread.currentThread(); if (interrupted) { thread.interrupt(); } boolean success = false; updateLastExecutionTime(); try { SingleThreadEventExecutor.this.run(); success = true; } catch (Throwable t) { logger.warn("Unexpected exception from an event executor: ", t); } finally { for (;;) { int oldState = state; if (oldState >= ST_SHUTTING_DO

 这里做的就是不断的死循环,队列里面的方法。

Channel概念 Netty中的Channel是一个抽象的概念,可以理解为对JDK NIO Channel的增强和拓展。 增加了很多属性和方法,完整信息可以看代码注释,下面罗列几个常见的属性和方法:

总结 本篇文章主要介绍netty的入门,以及基本的启动代码,介绍netty特性,概述等; Reactor多线程模式的设计,是Netty高性能很重要的一个原因!

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。