IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 网络协议 -> Netty学习笔记之WorkerGroup线程模型、任务队列、HTTP服务实例 -> 正文阅读

[网络协议]Netty学习笔记之WorkerGroup线程模型、任务队列、HTTP服务实例

系列文章目录

一、Netty编程实例


提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档


提示:以下是本篇文章正文内容,下面案例可供参考

一、WorkerGroup线程模型

BossGroup和WorkerGroup是如何确定自己有多少个EventGroup的?
bg和wg含有的子线程(NioEvent Group)的个数是默认CPU核数*2的 , 比如一台计算机是双CPU4核的,那么这个值就是8

NettyRuntime.availableProcessors()即可获取CPU的核数

假设创建有16个子线程 , 那么当第17个客户端连接的时候 , 是使用1号线程去处理的 , 也就是循环的处理

// bossGroup仅处理连接请求
NioEventLoopGroup bossGroup = new NioEventLoopGroup(1);
// workerGroup和客户端做业务处理
NioEventLoopGroup workerGroup = new NioEventLoopGroup();

这里通过1来限制BossGroup的线程数为1 , 因为BossGroup的线程数不需要有那么多

pipeline底层是一个双向链表,通过pipeline能获得channel(二者是相互包含的),还能反向拿到eventLoop

二、任务队列的Task定时和非定时两种使用场景

下面的两段代码都是基于 Netty编程实例做的修改 , 向NettyServerHandler加入了异步任务

1.用户自定义的普通任务;

代码如下(示例):

@Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        /**
         * 解决阻塞问题,存在长时间的操作的业务代码的时候 ,异步执行
         * */
        // 用户程序自定义的普通任务
        // 下面的任务会被提交到NIOEventLoop的taskQueue中去,"go on..."会被立即输出,然后再去执行execute方法
        // 也就是先执行后续的业务代码,再去回复客户端消息
        ctx.channel().eventLoop().execute(new Runnable() {
            @SneakyThrows
            @Override
            public void run() {
                Thread.sleep(10*1000);
                ctx.writeAndFlush(Unpooled.copiedBuffer("hello,cli",CharsetUtil.UTF_8));

            }
        });

        ctx.channel().eventLoop().execute(new Runnable() {
            @SneakyThrows
            @Override
            public void run() {
                Thread.sleep(10*1000);
                ctx.writeAndFlush(Unpooled.copiedBuffer("hello,cli",CharsetUtil.UTF_8));

            }
        });

        System.out.println("go on...");
    }

2.用户自定义定时任务

代码如下(示例):

//用户自定义定时任务
ctx.channel().eventLoop().schedule(new Runnable() {
    @SneakyThrows
    @Override
    public void run() {
        Thread.sleep(10*1000);
        ctx.writeAndFlush(Unpooled.copiedBuffer("hello,cli,3",CharsetUtil.UTF_8));
    }
},5, TimeUnit.SECONDS);

Netty抽象除了两组线程池, BossGroup专门负责接收客户端的连接,WorkerGroup专门负责网络读写操作


三、Future-Listener机制

  1. 当Future对象刚刚创建时, 处于非完成状态, 调用者可以通过返回的ChannelFutrue来获取操作执行的状态, 注册监听函数来执行完成后的操作
  2. 常见操作
    • isDone 判断当前操作是否完成
    • isSuccess 判断已完成的操作是否成功
    • getCause 获取已完成操作失败的原因
    • isCancelled 判断已完成的当前操作是否被取消
    • addListener 注册监听器

四、HTTP服务实例

代码实例

public class TestServer {
    public static void main(String[] args) {
        EventLoopGroup bossGroup = new NioEventLoopGroup(1);
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        try{
            ServerBootstrap serverBootstrap = new ServerBootstrap();
            serverBootstrap.group(bossGroup,workerGroup)
                    .channel(NioServerSocketChannel.class)
                    .childHandler(new TestServerInitializer());
            ChannelFuture cf = serverBootstrap.bind(4396).sync();
            cf.channel().closeFuture().sync();
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }
}
public class TestServerInitializer extends ChannelInitializer<SocketChannel> {

    @Override
    protected void initChannel(SocketChannel socketChannel) throws Exception {
        // 向管道加入处理器
        // 1. 得到管道
        ChannelPipeline pipeline = socketChannel.pipeline();
        // 2. 加入一个netty提供的httpServerCodec编解码器HttpServerCodec
        pipeline.addLast("myHttpServerCodec",new HttpServerCodec());
        // 3. 增加一个自定义的handler
        pipeline.addLast("myTestHttpServerHandler",new TestHttpServerHandler());
    }
}
public class TestHttpServerHandler extends SimpleChannelInboundHandler<HttpObject> {
    // 当有读取事件时,就会触发 , 用于读取客户端数据
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, HttpObject msg) throws Exception {
        // 判断msg 是不是http request请求
        if (msg instanceof HttpRequest){
            // msg真实类型是DefaultHttpRequest
            System.out.println("msg 类型 "+msg.getClass());
            System.out.println("客户端地址 "+ctx.channel().remoteAddress());

            // 通过uri过滤特定资源
            HttpRequest httpRequest = (HttpRequest) msg;
            // 获取uri
            URI uri = new URI((httpRequest.uri()));
            if ("/favicon.ico".equals(uri.getPath())){
                System.out.println("请求图标,不做响应");
                return;
            }
            // 回复信息给浏览器[要求满足http协议]
            ByteBuf content = Unpooled.copiedBuffer("hello world!", CharsetUtil.UTF_8);

            //构造http的响应
            DefaultFullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK, content);
            response.headers().set(HttpHeaderNames.CONTENT_TYPE,"text/plain");
            response.headers().set(HttpHeaderNames.CONTENT_LENGTH,content.readableBytes());

            // 将构建好的response返回
            ctx.writeAndFlush(response);

        }
    }
}

为什么浏览器只请求一次,但服务器显示两次请求

msg 类型 class io.netty.handler.codec.http.DefaultHttpRequest
客户端地址 /0:0:0:0:0:0:0:1:53907
msg 类型 class io.netty.handler.codec.http.DefaultHttpRequest
客户端地址 /0:0:0:0:0:0:0:1:53907

在这里插入图片描述
事实上,浏览器请求了两次服务器, 一次的请求浏览器图标, 一次是请求对应的接口

如何避免服务器响应除接口外的其它请求
HttpRequest httpRequest = (HttpRequest) msg;
// 获取uri
URI uri = new URI((httpRequest.uri()));
if ("/favicon.ico".equals(uri.getPath())){
    System.out.println("请求图标,不做响应");
    return;
}

* 每个浏览器对应的pipeline和handler是独立的

http协议不是长连接 , 用完就会断掉 , 所以同一个浏览器第二次请求时 , 会被认为是一个新的浏览器

  网络协议 最新文章
使用Easyswoole 搭建简单的Websoket服务
常见的数据通信方式有哪些?
Openssl 1024bit RSA算法---公私钥获取和处
HTTPS协议的密钥交换流程
《小白WEB安全入门》03. 漏洞篇
HttpRunner4.x 安装与使用
2021-07-04
手写RPC学习笔记
K8S高可用版本部署
mySQL计算IP地址范围
上一篇文章      下一篇文章      查看所有文章
加:2021-11-22 12:42:59  更:2021-11-22 12:43:58 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年7日历 -2024/7/3 21:28:24-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码