Netty之EventLoopGroup详解

news2024/10/2 20:22:57

目录

目标

Netty版本

Netty官方API

NioEventLoopGroup和DefaultEventLoop的区别

EventLoopGroup实现对内部EventLoop的轮询

EventLoop对普通任务和定时任务的实现

执行普通任务

执行定时任务

划分EventLoopGroup职责

简言

实现

指定EventLoopGroup操作ChannelHandler

简言

实现


目标

  • 了解io.netty.channel.nio.NioEventLoopGroupio.netty.channel.DefaultEventLoop的区别。
  • 掌握EventLoopGroup如何实现对内部EventLoop的轮询,以及EventLoop对普通任务和定时任务的实现方法。
  • 划分EventLoopGroup职责,指定EventLoopGroup操作ChannelHandler。

Netty版本

        <dependency>
			<groupId>io.netty</groupId>
			<artifactId>netty-all</artifactId>
			<version>4.1.87.Final</version>
		</dependency>

Netty官方API

Netty API Reference (4.1.87.Final)https://netty.io/4.1/api/index.html


NioEventLoopGroupDefaultEventLoop的区别

io.netty.channel.nio.NioEventLoopGroupio.netty.channel.DefaultEventLoop是较为常用的EventLoop,最大的区别在于前者可以处理IO事件、普通任务、定时任务;后者只能处理普通任务和定时任务


EventLoopGroup实现对内部EventLoop的轮询

package com.ctx.netty;

import io.netty.channel.DefaultEventLoopGroup;
import lombok.extern.slf4j.Slf4j;

@Slf4j
public class EventLoopTest {
    public static void main(String[] args) {
        //设置组内2个EventLoop
        DefaultEventLoopGroup defaultEventLoop = new DefaultEventLoopGroup(2);
        //循环输出5次
        for(int i=0;i<5;i++){
            //根据打印的结果,发现组内的2个对象被轮询了。
            log.info(String.valueOf(defaultEventLoop.next()));
        }
    }
}


EventLoop对普通任务和定时任务的实现

执行普通任务

package com.ctx.netty;

import io.netty.channel.DefaultEventLoopGroup;
import lombok.extern.slf4j.Slf4j;

@Slf4j
public class EventLoopTest {
    public static void main(String[] args) {
        DefaultEventLoopGroup defaultEventLoop = new DefaultEventLoopGroup(2);
        //执行普通任务
        //或者defaultEventLoop.next().submit(()->{});
        defaultEventLoop.next().execute(()->{
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            System.out.println("Hello World!");
        });
        
        System.out.println("main");
    }
}

结果


执行定时任务

package com.ctx.netty;

import io.netty.channel.DefaultEventLoopGroup;
import lombok.extern.slf4j.Slf4j;
import java.util.concurrent.TimeUnit;

@Slf4j
public class EventLoopTest {
    public static void main(String[] args) {
        DefaultEventLoopGroup defaultEventLoop = new DefaultEventLoopGroup(2);
        log.info(String.valueOf(System.currentTimeMillis()));
        //执行普通任务
        defaultEventLoop.next().scheduleAtFixedRate(
                //任务对象
                () -> {
                    log.info(String.valueOf(System.currentTimeMillis()));
                },
                //初始延迟时间,0表示不延迟(受到时间单位的影响)。
                1,
                //间隔执行时间(受到时间单位的影响)。
                2,
                //时间单位
                TimeUnit.MINUTES
        );

        System.out.println("main");
    }
}


划分EventLoopGroup职责

简言

我在之前的一篇文章《初识Netty并用Netty搭建最基本的网络服务器和客户端_我的身前一尺是我的世界的博客-CSDN博客》中例举了一组简单的服务端和客户端的实现。文章中的服务端我只用了一个EventLoopGroup,但是Netty更推荐将不同的事件划分给不同的EventLoopGroup。

实现

package com.ctx.netty;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import lombok.extern.slf4j.Slf4j;

@Slf4j
public class NettyServer {
    public static void main(String[] args) {
        //Netty服务端启动器
        ServerBootstrap serverBootstrap = new ServerBootstrap();
        /**
         * 官方API对group(EventLoopGroup parentGroup,EventLoopGroup childGroup)法的描述:
         * Set the EventLoopGroup for the parent (acceptor) and the child (client).
         * These EventLoopGroup's are used to handle all the events and IO for ServerChannel and Channel's.
         *
         * 译文:
         * parentGroup对ServerChannel负责,它处理accept事件;默认1个线程数。
         * childGroup对Channel负责,它处理读写操作;默认cpu核心数*2个线程。
         */
        serverBootstrap.group(new NioEventLoopGroup(),new NioEventLoopGroup(2));
        //选择服务器的ServerSocketChannel实现,这里我选择NIO。
        serverBootstrap.channel(NioServerSocketChannel.class);
        //设置事件类型
        serverBootstrap.childHandler(new ChannelInitializer<NioSocketChannel>() {
            @Override
            protected void initChannel(NioSocketChannel nioSocketChannel) throws Exception {
                //把ByteBuf解码为String
                nioSocketChannel.pipeline().addLast(new StringDecoder());
                //pipeline是流水线,Handler是工序,流水线可以有多个工序。
                //Handler分为入栈(Inbound)和出栈(Outbound)
                //自定义Handler
                nioSocketChannel.pipeline().addLast(new ChannelInboundHandlerAdapter(){
                    //处理读事件
                    @Override
                    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
                        log.info(msg.toString());
                    }
                });
            }
        });
        //设置服务器的监听端口
        serverBootstrap.bind(8999);
    }
}

指定EventLoopGroup操作ChannelHandler

简言

我们知道,pipeline是流水线,ChannelHandler相当于工序,一个或多个工序组成了流水线。不同的工序耗时可能不同,如果有的工序耗时太久,则会对其他工序的执行产生影响,为此,Netty为我们提供了指定EventLoopGroup操作ChannelHandler的API。


实现

package com.ctx.netty;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.DefaultEventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import lombok.extern.slf4j.Slf4j;

@Slf4j
public class NettyServer {
    public static void main(String[] args) {
        DefaultEventLoopGroup defaultEventLoopGroup = new DefaultEventLoopGroup();

        //Netty服务端启动器
        ServerBootstrap serverBootstrap = new ServerBootstrap();
        serverBootstrap.group(new NioEventLoopGroup(),new NioEventLoopGroup(2));
        //选择服务器的ServerSocketChannel实现,这里我选择NIO。
        serverBootstrap.channel(NioServerSocketChannel.class);
        //设置事件类型
        serverBootstrap.childHandler(new ChannelInitializer<NioSocketChannel>() {
            @Override
            protected void initChannel(NioSocketChannel nioSocketChannel) throws Exception {
                //把ByteBuf解码为String
                nioSocketChannel.pipeline().addLast(new StringDecoder());

                nioSocketChannel.pipeline().addLast("Handler",new ChannelInboundHandlerAdapter(){
                    //处理读事件
                    @Override
                    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
                        log.info(msg.toString());
                        //把msg传给下一个Handler
                        ctx.fireChannelRead(msg);
                    }
                }).addLast(defaultEventLoopGroup,"Handler2",new ChannelInboundHandlerAdapter(){
                    //处理读事件
                    @Override
                    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
                        log.info(msg.toString());
                    }
                });
            }
        });
        //设置服务器的监听端口
        serverBootstrap.bind(8999);
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/337793.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

手机上怎么在线生成gif?1分钟教你手机图片合成gif

怎样通过手机实现在线制作GIF图片的操作呢&#xff1f;接下来&#xff0c;给大家分享两招gif制作&#xff08;https://www.gif.cn/&#xff09;小窍门-【GIF中文网】不需要下载任何软件&#xff0c;小白也能轻松上手。支持原画质导出&#xff0c;图片无损处理。一起来看看具体步…

前端教学视频分享(视频内容与市场时刻保持紧密相连,火热更新中。。。)

⚠️获取公众号 本次要想大家推荐一下本人的公众号&#xff0c;在微信中搜索公众号 李帅豪在对话框中输入前端视频四个字即可立即获取所有视频&#xff0c;不收费无广告&#xff01;&#xff01;&#xff01; 本公众号收集了近两年来前端最新最优秀的学习视频&#xff0c;涵盖…

大数据技术架构(组件)30——Spark:Optimize--->Submit

2.1.9、Optimize--->Submit调优工作主要从CPU、内存、网络开销和IO四方面入手2.1.9.0、Spark On Yarn2.1.9.0.1、Jar包管理及本地性调优spark.yarn.jars :将jar包放到hdfs上&#xff0c;避免每次driver启动的时候都要进行jar包的分发。yarn.nodemanager.localizer.cache.cle…

ChatGPT告诉你智能制造

ChatGPT自上线以来&#xff0c;几乎得到了外界的一致好评&#xff0c;上线两个月&#xff0c;获得1亿月活跃用户&#xff0c;成为增长最快的面向消费者的应用。 面对ChatGPT拟人一般的问答能力&#xff0c;很多人认为它代表着AlphaGo之后&#xff0c;人工智能应用的第二次浪潮…

电子技术——MOS差分输入对

电子技术——MOS差分输入对 差分输入系统因其极高的共模抑制能力&#xff0c;差分输入几乎是是构建所有通用模拟IC的基本前级输入&#xff0c;也是现代信号传输理论的基础。本节我们讲解MOS差分输入对。 MOS差分输入对 下图展示了MOS差分输入对的基本原理图&#xff1a; 一个…

数据采集协同架构,集成马扎克、西门子、海德汉、广数、凯恩帝、三菱、海德汉、兄弟、哈斯、宝元、新代、发那科、华中各类数控以及各类PLC数据采集软件

文章目录 前言一、采集协同架构是什么&#xff1f;可以做什么&#xff08;数控、PLC配置采集&#xff09;&#xff1f;二、使用步骤 1.打开软件&#xff0c;配置MQTT或者数据库&#xff08;支持sqlserver、mysql等&#xff09;存储转发消息规则2.配置数控系统所采集的参数、转…

项目(今日指数)

一 项目架构1.1 今日指数技术选型【1】前端技术【2】后端技术栈【3】整体概览3.2 核心业务介绍1】业务结构预览【2】业务功能简介1.定时任务调度服务XXL-JOB通过RestTemplate多线程动态拉去股票接口数据&#xff0c;刷入数据库&#xff1b; 2.国内指数服务 3.板块指数服务 4.涨…

使用Harbor构建docker私有仓库

一、概述1、什么是HarborHarbor 是VMware公司开源的云本地 registry 仓库&#xff0c;有可视化的Web管理界面&#xff0c;可以方便的管理和储存 Docker 镜像。Harbor 支持在多个仓库直接进行复制镜像&#xff0c;提供用户管理和访问控制和活动审计。2、Harbor的优势基于角色控制…

mysql高级(事务、存储引擎、索引、锁、sql优化、MVCC)

文章目录1.事务1.1 四大特性ACID1.2 并发事务2.存储引擎2.1 InnoDB2.2 MyISAM2.3 Memory2.4 存储引擎特点2.5 存储引擎的选择3.性能分析3.1 查看执行频次3.2 慢查询日志3.3 profile3.4 explain4.索引4.1 索引结构B-TreeBTreeHash面试题4.2 索引分类思考题4.3 语法4.4 使用规则最…

抖音电商-安全带为例分析

为什么来抖音抖音对好货的扶持力度很大好商品对抖音商城至关

Python-项目实战--飞机大战-英雄登场(7)

目标设计英雄和子弹类使用pygame.key.get_pressed()移动英雄发射子弹1.设计英雄和子弹类1.1英雄需求游戏启动后&#xff0c;英雄出现在屏幕的水平中间位置&#xff0c;距离屏幕底部120像素英雄每隔0.5秒发射一次子弹&#xff0c;每次连发三枚子弹英雄默认不会移动&#xff0c;需…

vulnhub之CLOVER: 1

1.信息收集 输入arp-scan 192.168.239.0/24进行主机存活探测&#xff0c;可以看到192.168.239.171主机存活。 对192.168.239.171主机进行端口扫描&#xff0c;可以看到20、21、22、82、110、443、5781、8080。 发现21端口可以匿名登录&#xff0c;输入&#xff1a;anonymous…

牛客网Python篇数据分析习题(一)

1.现有一个Nowcoder.csv文件&#xff0c;它记录了牛客网的部分用户数据&#xff0c;包含如下字段&#xff08;字段与字段之间以逗号间隔&#xff09;&#xff1a; Nowcoder_ID&#xff1a;用户ID Level&#xff1a;等级 Achievement_value&#xff1a;成就值 Num_of_exercise&a…

春招快来了,杭电研究生学长聊聊踩过的坑,助你成功上岸

引言 大家好&#xff0c;我是James&#xff0c;由于之前文章内容浏览量太少以及这几个月的繁忙&#xff0c;一直没有静下心输出一些内容&#xff0c;随着疫情放开&#xff0c;新春来临&#xff0c;年后百业待兴&#xff0c;马上又是一年春季招聘。作为一个参加过2022年春&…

golang 通道类型

文章目录一、什么是通道类型二、通道产生的原因三、声明channel四、创建channel五、channel相关操作1、发送值2、接收值3、关闭通道3.1 注意3.2 特点四、通道类型1、无缓冲通道2、有缓冲通道五、单向通道一、什么是通道类型 Go 语言中的通道&#xff08;channel&#xff09;是一…

【ChatGpt】使用感受分享

作者&#xff1a;狮子也疯狂 专栏&#xff1a;《基础知识查漏》 坚持做好每一步&#xff0c;幸运之神自然会降临在你的身上 目录一. &#x1f981; 前言二. &#x1f981; 使用详情Ⅰ. &#x1f407; 使用过程Ⅱ. &#x1f407; 使用感受Ⅲ. &#x1f407; 遇到的问题3.1 我遇…

Allegro172版本如何用自带的功能实现快速在1MMBGA下方等距放置电容

Allegro172版本如何用自带的功能实现快速在1MMBGA下方等距放置电容 在做PCB设计的时候,在1MM中心间距的BGA背面放置电容,是非常常见的设计,如何快速把电容等距放在BGA下方,除了借助辅助工具外,在Allegro升级到了172版本的时候,可以借助本身自带的功能实现快速放置,以下图…

【云原生】解读Kubernetes三层网络方案

在上一篇文章中&#xff0c;我以网桥类型的 Flannel 插件为例&#xff0c;为你讲解了 Kubernetes 里容器网络和 CNI 插件的主要工作原理。不过&#xff0c;除了这种模式之外&#xff0c;还有一种纯三层&#xff08;Pure Layer 3&#xff09;网络方案非常值得你注意。其中的典型…

【RabbitMQ五】——RabbitMQ路由模式(Routing)

RabbitMQ路由模式前言RabbitMQ模式的基本概念为什么要使用Rabbitmq 路由模式RabbitMQ路由模式组成元素路由模式完整代码Pom文件引入RabbtiMQ依赖RabbitMQ工具类生产者消费者1消费者2运行结果截图前言 通过本篇博客能够简单使用RabbitMQ的路由模式。 本篇博客主要是博主通过官网…

ROS运行机C++程序,移动

流程&#xff1a; 1.创建工作空间 mkdir catkin_ws cd catkin_ws mkdir src cd src catkin_init_workspace 2编译工作空间 cd ~/catkin_ws/ catkin_make catkin_make install 首先对ROS进行创建一个元功能包 3.设置环境变量 source devel/setup.bash source devel/setup.b…