从xxl-job源码中学习Netty的使用

1. 启动与Spring实例化

com.xxl.job.core.executor.impl.XxlJobSpringExecutor.java类 

继承SmartInitializingSingleton 类,在afterSingletonsInstantiated 实例化后方法中

调用initJobHandlerMethodRepository 把所有的xxljob任务管理起来;

  private void initJobHandlerMethodRepository(ApplicationContext applicationContext) {
        if (applicationContext == null) {
            return;
        }
        // init job handler from method
        //扫描所有的bean,并获取XxlJob的注解,registJobHandler加入到 一个 map  中
        // 见jobHandlerRepository
        String[] beanDefinitionNames = applicationContext.getBeanNamesForType(Object.class, false, true);
        for (String beanDefinitionName : beanDefinitionNames) {
            Object bean = applicationContext.getBean(beanDefinitionName);

            Map<Method, XxlJob> annotatedMethods = null;   // referred to :org.springframework.context.event.EventListenerMethodProcessor.processBean
            try {
                annotatedMethods = MethodIntrospector.selectMethods(bean.getClass(),
                        new MethodIntrospector.MetadataLookup<XxlJob>() {
                            @Override
                            public XxlJob inspect(Method method) {
                                return AnnotatedElementUtils.findMergedAnnotation(method, XxlJob.class);
                            }
                        });
            } catch (Throwable ex) {
                logger.error("xxl-job method-jobhandler resolve error for bean[" + beanDefinitionName + "].", ex);
            }
            if (annotatedMethods==null || annotatedMethods.isEmpty()) {
                continue;
            }

            for (Map.Entry<Method, XxlJob> methodXxlJobEntry : annotatedMethods.entrySet()) {
                Method executeMethod = methodXxlJobEntry.getKey();
                XxlJob xxlJob = methodXxlJobEntry.getValue();
                if (xxlJob == null) {
                    continue;
                }

                String name = xxlJob.value();
                if (name.trim().length() == 0) {
                    throw new RuntimeException("xxl-job method-jobhandler name invalid, for[" + bean.getClass() + "#" + executeMethod.getName() + "] .");
                }
                if (loadJobHandler(name) != null) {
                    throw new RuntimeException("xxl-job jobhandler[" + name + "] naming conflicts.");
                }

                // execute method
                /*if (!(method.getParameterTypes().length == 1 && method.getParameterTypes()[0].isAssignableFrom(String.class))) {
                    throw new RuntimeException("xxl-job method-jobhandler param-classtype invalid, for[" + bean.getClass() + "#" + method.getName() + "] , " +
                            "The correct method format like \" public ReturnT<String> execute(String param) \" .");
                }
                if (!method.getReturnType().isAssignableFrom(ReturnT.class)) {
                    throw new RuntimeException("xxl-job method-jobhandler return-classtype invalid, for[" + bean.getClass() + "#" + method.getName() + "] , " +
                            "The correct method format like \" public ReturnT<String> execute(String param) \" .");
                }*/

                executeMethod.setAccessible(true);

                // init and destory
                Method initMethod = null;
                Method destroyMethod = null;

                if (xxlJob.init().trim().length() > 0) {
                    try {
                        initMethod = bean.getClass().getDeclaredMethod(xxlJob.init());
                        initMethod.setAccessible(true);
                    } catch (NoSuchMethodException e) {
                        throw new RuntimeException("xxl-job method-jobhandler initMethod invalid, for[" + bean.getClass() + "#" + executeMethod.getName() + "] .");
                    }
                }
                if (xxlJob.destroy().trim().length() > 0) {
                    try {
                        destroyMethod = bean.getClass().getDeclaredMethod(xxlJob.destroy());
                        destroyMethod.setAccessible(true);
                    } catch (NoSuchMethodException e) {
                        throw new RuntimeException("xxl-job method-jobhandler destroyMethod invalid, for[" + bean.getClass() + "#" + executeMethod.getName() + "] .");
                    }
                }

                // registry jobhandler
                //扫描所有的jobhandler
                registJobHandler(name, new MethodJobHandler(bean, executeMethod, initMethod, destroyMethod));
            }
        }

    }

2. 调用父类的start() 方法 启动netty服务端

com.xxl.job.core.executor.XxlJobExecutor#initEmbedServer

核心代码见com.xxl.job.core.server.EmbedServer#start

 // start server 服务端
                    ServerBootstrap bootstrap = new ServerBootstrap();
                    bootstrap.group(bossGroup, workerGroup)
                            .channel(NioServerSocketChannel.class)
                            .childHandler(new ChannelInitializer<SocketChannel>() {
                                @Override
                                public void initChannel(SocketChannel channel) throws Exception {
                                    channel.pipeline()
                                            //心跳机制
                                            .addLast(new IdleStateHandler(0, 0, 30 * 3, TimeUnit.SECONDS))  // beat 3N, close if idle
                                            // 使用 http 协议
                                            .addLast(new HttpServerCodec())
                                            // 拆包粘包
                                            .addLast(new HttpObjectAggregator(5 * 1024 * 1024))  // merge request & reponse to FULL
                                            // 业务处理EmbedHttpServerHandler
                                            .addLast(new EmbedHttpServerHandler(executorBiz, accessToken, bizThreadPool));
                                }
                            })
                            .childOption(ChannelOption.SO_KEEPALIVE, true);

                    // bind
                    ChannelFuture future = bootstrap.bind(port).sync();

                    logger.info(">>>>>>>>>>> xxl-job remoting server start success, nettype = {}, port = {}", EmbedServer.class, port);

                    // start registry
                    startRegistry(appname, address);

                    // wait util stop
                    future.channel().closeFuture().sync();

3. 定时任务发起一个任务执行 调用netty server段的接口

此处以手动调用为一个例子; 定时任务&时间轮见下回分析

com.xxl.job.admin.core.thread.JobTriggerPoolHelper#trigger

@startuml tomcat
JobInfoController -> JobTriggerPoolHelper: trigger()
JobTriggerPoolHelper -> XxlJobTrigger:trigger()
XxlJobTrigger ->  XxlJobTrigger: processTrigger()
XxlJobTrigger -> XxlJobTrigger : runExecutor()
XxlJobTrigger -> ExecutorBizImpl :run()
@enduml

最终调用

 @Override
    public ReturnT<String> run(TriggerParam triggerParam) {
        return XxlJobRemotingUtil.postBody(addressUrl + "run", accessToken, timeout, triggerParam, String.class);
    }

4. 其他netty 详细内容见下回分析;

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

.net8系列-图文并茂手把手教你使用Nlog记录.net日志

Nlog是什么&#xff1f; NLog是一个为.NET平台设计的灵活且免费的日志记录库。它适用于包括.NET Framework、.NET Core和.NET Standard在内的多种.NET环境。 Nlog有什么好处或者特点&#xff1f; 配置灵活&#xff1a;NLog允许开发者通过配置文件&#xff08;通常是NLog.conf…

串口触摸屏分割字符串

分割字符串的方法1、split2、indexOf()3、substr(start,length) 分割字符串的方法 1、split&#xff1a;将一个字符串分割为子字符串&#xff0c;然后将结果作为字符串数组返回。 2、indexOf() &#xff1a;返回某个指定的字符串值在字符串中首次出现的位置&#xff08;从左向右…

机器人、人工智能相关领域 news/events (专栏目录)

Some Insights 一些机器人、人工智能或相关领域的news、events等 1. 智能制造 - 你需要了解的 10 个基本要素 2. 现实世界中的人工智能&#xff1a;工业制造的 4 个成功案例研究 3. 企业使用人工智能情况调查 4. 未来工厂中的人工智能&#xff1a;人工智能加速制造成果规模…

用React编写一个密码组件表单

theme: condensed-night-purple highlight: atelier-cave-light 背景介绍 我们在使用网站或者应用程序的登录界面或创建帐户界面时&#xff0c;往往避免不了需要用户输入密码这一步骤&#xff0c;而用户是否可以选择看见他们输入的密码是十分重要的一项功能。尤其是在当输入的…

QT绘图项目 - 汽车表盘

目录 前言: 整体代码 widget.h widget.cpp 效果演示 实现刻度文字正确排版 优化代码 达到效果 封装整理代码结构: widget.h widget.cpp 指针样式美化 优化后的指针API 效果演示 设置高速刻度为红色 优化刻度API 效果演示 速度显示优化 给内圈画上黑色 优化速度…

【学习-华为HCIA数通网络工程师真题(持续更新)】(2024-6-16更)

1、在 VRP 平台上&#xff0c;可以通过下面哪种方式访向上条历史命令&#xff1f; 上光标 &#xff08;ctrlU 为自定义快捷键&#xff0c;ctrlP 为显示历史缓存区的前一条命令&#xff0c;左光标为移动光标&#xff09; 2、主机 A &#xff08;10.1.1.2/24&#xff09;和主机 B…

在亚马逊云上部署WordPress:一个完整的LAMP环境安装教程

什么是LAMP LAMP是一个流行的开源软件堆栈&#xff0c;用于网站和网络应用程序的开发和部署。LAMP是几个主要组件的首字母缩写&#xff0c;包括&#xff1a; Linux&#xff1a;操作系统层&#xff0c;LAMP通常部署在Linux操作系统上&#xff0c;但它也可以使用其他类似Unix的…

Golang | Leetcode Golang题解之第155题最小栈

题目&#xff1a; 题解&#xff1a; type MinStack struct {stack []intminStack []int }func Constructor() MinStack {return MinStack{stack: []int{},minStack: []int{math.MaxInt64},} }func (this *MinStack) Push(x int) {this.stack append(this.stack, x)top : thi…

牛客周赛 Round 47 解题报告 | 珂学家

前言 题解 这真的是牛客周赛&#xff1f; 哭了 欢迎关注 珂朵莉 牛客周赛专栏 珂朵莉 牛客小白月赛专栏 A. 小红的葫芦 签到题 但是写起来有点变扭&#xff0c;方法应该蛮多的 统计分组 有2组一组长度为2&#xff0c;一组长度为3 def check(arr):arr.sort()if arr[0] …

Git学习2 -- VSCode中的Git

看了下&#xff0c;主要的插件有3个。自带的Source Control。第1个是Gitlens&#xff0c;第2个是Git Graph。第三个还有个git history。 首先是Source Control。界面大概是这样的。 还是挺直观的。在第一栏source control&#xff0c;可以进行基本的git操作。主要的git操作都是…

MongoDB~高可用集群介绍:复制集群(副本集)、分片集群

背景 MongoDB 的集群主要包括副本集&#xff08;Replica Set&#xff09;和分片集群&#xff08;Sharded Cluster&#xff09;两种类型。 副本集 组成&#xff1a;通常由一个主节点&#xff08;Primary&#xff09;和多个从节点&#xff08;Secondary&#xff09;构成。 功…

Objective-C 学习笔记 | init

Objective-C 学习笔记 | init Objective-C 学习笔记 | init编写 init 方法禁用 init 方法 Objective-C 学习笔记 | init init 是实例方法&#xff0c;负责初始化对象&#xff0c;并返回初始化后的对象的地址。 编写 init 方法 完整代码见于&#xff1a;UestcXiye/Objective-…

【前端:HTML+CSS+JavaScript】HTML基础(下)

一、表格标签 1.1 表格的主要作用 表格主要用于显示、展示数据。因为她可以让数据显示的非常频繁&#xff0c;可读性非常好。特别是后台展示数据的时候&#xff0c;能够熟练运用表格就线程显得很重要。表格不是用来布局页面的。而是用来展示数据的。 1.2 表格的基本语法 <…

windows11 x64 23H2 企业纯净版2024.6.16

闲来无事试安装了下da_nao_yan的 【6月12日更新】Windows11 22631.3737企业版 23H2 自用优化版 &#xff08;原版地址&#xff1a;https://bbs.pcbeta.com/viewthread-1985546-1-1.html&#xff09;&#xff0c;感觉比原版流畅多了&#xff0c;重新按照自己习惯封装了下&#x…

Nvidia芯片Jetson系列 系统烧录环境 搭建

一、序言 Jetson 系列产品烧录系统的方法一般有两种&#xff1a; 一种为使用 NVIDIA 官方提供 的 SDK manager 软件给 Jetson 设备烧录系统&#xff08;请查看说明文档《Jetson 产品使用 SDKmanager 烧录系统》&#xff09;。 另一种即为当前文档所描述的&#xff0c;在安装 Ub…

Azure数据分析Power BI

Azure数据分析Power BI 一、Power BI简介二、Power BI 如何匹配角色三、Power BI 构建基块四、使用 Power BI 服务一、Power BI简介 Microsoft Power BI 是一系列的软件服务、应用和连接器,这些软件服务、应用和连接器协同工作,将不相关的数据源转化为合乎逻辑、视觉上逼真的…

Java实现俄罗斯方块-初始化游戏界面的JPanel

目录 技术实现&#xff1a; 2.初始化游戏界面&#xff1b; 2.1 什么是游戏界面 2.2 JPanel面板 2.3 流布局管理器【FlowLayout】 2.4 网络布局管理器 【GridLayout】 2.5 边界布局管理器 技术实现&#xff1a; 1.初始化游戏窗口&#xff1b; 2.初始化游戏界面&#xff…

Docker的基本操作 及 容器与外部机互相通讯(持续更新中)

Docker入门&#xff1a; Docker 入门教程 - 阮一峰的网络日志 (ruanyifeng.com)docker入门&#xff0c;这一篇就够了。-CSDN博客Docker 容器使用 | 菜鸟教程 (runoob.com)Docker自定义网络和运行时指定IP_docker run ip-CSDN博客 基本命令 链接&#xff1a;docker入门&#…

Java面向对象-final关键字

Java面向对象-final关键字 一、final1、修饰变量2、修饰方法3、修饰类4、案例 一、final 可以修饰变量、方法、类 1、修饰变量 final修饰一个变量&#xff0c;变量的值不可以改变&#xff0c;这个变量就变成一个字符常量&#xff0c;约定俗称的规定&#xff1a;名字大写。 f…

【高端精品】最新手机版微信小程序(拼多多+京东)全自动操作项目

现代互联网经济的发展带来了新型的盈利方式&#xff0c;通过微信小程序的拼多多和京东进行商品自动巡视&#xff0c;为商家带来增的流量&#xff0c;同时为使用者带来利润。这种盈利方式无需复杂操作&#xff0c;用户仅需启动相应程序&#xff0c;商品信息便会被系统自动收集。…