当前位置: 首页 > news >正文

PowerJob的server启动都经历了哪些?代码不多也很简单,咱们来逐一理解。

这是一篇让你受益匪浅的文章,点个关注交流一下吧~

PowerJob如何使用,官方文档已经说的很详细了,即使没学过计算机的人,按照那上面的步骤来也是可以搭建出一个可以使用的例子来,所以今天就不在这里重复前人的工作,直接开始就开始将这个源代码中的原理吧。

 

powerjob框架主要分成两个分部,server和worker,这两部分需要分别去启动,而且需要先启动server,后启动worker,否则,worker会因为找不到可用的server,而启动失败。作为一个server启动的时候工作自然是非常繁重的,主要有以下几个步骤:

  1. 读取配置文件

  2. 启动Akka服务

  3. 启动Vertx服务

  4. 启动Spring

详细的启动代码如下所示:

private static final String TIPS = "\n\n" +"******************* PowerJob Tips *******************\n" +"如果应用无法启动,我们建议您仔细阅读以下文档来解决:\n" +"if server can't startup, we recommend that you read the documentation to find a solution:\n" +"https://www.yuque.com/powerjob/guidence/problem\n" +"******************* PowerJob Tips *******************\n\n";public static void main(String[] args) {pre();//下方的私有静态方法AkkaStarter.init();//启动AkkaVertXStarter.init();//启动Vertx//启动Springtry {SpringApplication.run(PowerJobServerApplication.class, args);} catch (Throwable t) {log.error(TIPS);throw t;}
}private static void pre() {log.info(TIPS);//将上方的常量字符串打印出来PropertyUtils.init();//读取配置文件
}

读取配置文件

PropertyUtils.init();//读取配置文件

这一步特别简单,仅仅涉及到server.common.utils包中的PropertyUtils。主要代码段如下:

public static void init() {URL propertiesURL =PropertyUtils.class.getClassLoader().getResource("application.properties");Objects.requireNonNull(propertiesURL);try (InputStream is = propertiesURL.openStream()) {PROPERTIES.load(is);}catch (Exception e) {ExceptionUtils.rethrow(e);}
}

因为代码也不是很多,就直接把该方法的所有代码全部展示出来。

代码中第二行,方法里第一行有这么一段代码

PropertyUtils.class.getClassLoader().getResource("application.properties");

这个代码就是读取配置文件中的内容,下面是powerjob的文件目录层次,看图就知道该段代码到底读的是哪一部分。

说句实话,最开始的时候,我认为读取的是上面红色箭头指的地方,因为他代码里getResource,这个地方我认为就是读取resource文件夹下面的文件,但是.getClassLoader无法解释,后来自己跑一下这个代码就明白了,读取的是编译完的文件路径,而不是编译之前的路径。

读取的和配置文件里面的一模一样,一条不多一条不少~,springboot正常也会读取配置文件,这里为什么要单独执行一下读取,作用是什么?在这里先不说,看到后面遇到了,再来解答,留作问题1。

启动Akka服务

 

AkkaStarter.init();

powerjob里面主要使用的akka-remote,就是用来通信的,说白了就是手机,用来给彼此打电话汇报信息的。

Akka框架的介绍,请移步akka的官网自己去欣赏,这里只将代码的作用做一个讲解。

这个AkkaStarter是在server.remote.transport.starter包里,init方法代码如下:

public static void init() {//一个计时的方法,就不用在开始与结束的时候使用System获取时间,然后再进行相减了。Stopwatch stopwatch = Stopwatch.createStarted();log.info("[PowerJob] PowerJob's akka system start to bootstrap...");// 解析配置文件Config akkaFinalConfig = parseConfig();//创建一个Akka的actor系统,相当于建立了一个公司,之后所有的actor行动都在这个公司内进行actorSystem = ActorSystem.create(RemoteConstant.SERVER_ACTOR_SYSTEM_NAME, akkaFinalConfig);//创建了一个actor。actorSystem.actorOf(FriendRequestHandler.defaultProps(), RemoteConstant.SERVER_FRIEND_ACTOR_NAME);log.info("[PowerJob] PowerJob's akka system started successfully, using time {}.", stopwatch);}

解析配置文件

解析配置文件的代码如下所示:

private static Config parseConfig() {//这一步是获取了启动第一步的读取配置文件后获取的配置内容,这也就回答了问题1。Properties properties = PropertyUtils.getProperties();//获取配置文件中oms.akka.port字段的内容,如果没有该配置,则默认为10086端口int port = Integer.parseInt(properties.getProperty(PowerJobServerConfigKey.AKKA_PORT, String.valueOf(OmsConstant.SERVER_DEFAULT_AKKA_PORT)));//这个是通过jvm启动时配置oms.akka.port的参数,例如:启动时候的java -Doms.akka.port=30086...String portFromJvm = System.getProperty(PowerJobServerConfigKey.AKKA_PORT);//如果配置了jvm启动的配置,则将其覆盖配置文件的akka端口,也就是说jvm配置优先级高于配置文件的配置if (StringUtils.isNotEmpty(portFromJvm)) {log.info("[PowerJob] use port from jvm params: {}", portFromJvm);port = Integer.parseInt(portFromJvm);}// 启动 ActorSystemMap<String, Object> overrideConfig = Maps.newHashMap();//获取本地的ip地址,下面会详细进入到代码中说一下,这里面还挺深的String localIp = NetUtils.getLocalHost();//将关键字放到一个map映射中overrideConfig.put("akka.remote.artery.canonical.hostname", localIp);overrideConfig.put("akka.remote.artery.canonical.port", port);//ip和端口组成了akka的通信地址actorSystemAddress = localIp + ":" + port;log.info("[PowerJob] akka-remote server address: {}", actorSystemAddress);//获取oms-server.akka.conf配置文件里面的配置,ConfigFactory为akka自带方法Config akkaBasicConfig = ConfigFactory.load(RemoteConstant.SERVER_AKKA_CONFIG_NAME);//overrideConfig里面有的配置内容,按照overrideConfig走,没有的,按照配置文件akkaBasicConfig走return ConfigFactory.parseMap(overrideConfig).withFallback(akkaBasicConfig);
}

获取本地地址

String localIp = NetUtils.getLocalHost();

在解析配置文件中,其实真正有点内容的就是这个获取本地地址这个方法,之前我没有去细研究之前,可把我给坑毁了,因为我想用局域网的ip进行来回通信,但是因为这个获取地址里面的默认策略,导致每一次使用的都不是我想用的IP地址,当我研究完了这个代码之后,终于是柳暗花明又一村了,直接就可以指定地址了。

先看源码如下所示:

public static String getLocalHost() {
//这个代码就是在获取了地址之后,就直接将地址存起来,下一次再用就可以直接返回了if (HOST_ADDRESS != null) {return HOST_ADDRESS;}//获取jvm启动时,设置的powerjob.network.local.address关键字的地址,通过这个就可以直接绑定ip了String addressFromJVM = System.getProperty(PowerJobDKey.BIND_LOCAL_ADDRESS);if (StringUtils.isNotEmpty(addressFromJVM)) {log.info("[Net] use address from[{}]: {}", PowerJobDKey.BIND_LOCAL_ADDRESS, addressFromJVM);return HOST_ADDRESS = addressFromJVM;}//如果上一步没有绑定地址,那就在通过getLocalAddress来获取地址。InetAddress address = getLocalAddress();if (address != null) {return HOST_ADDRESS = address.getHostAddress();}return LOCALHOST_VALUE;
}

大概知道了获取host的思路,下一篇文章我们再详细介绍里面的具体流程,因为里面的流程相对来说有那么一点点的不简单,在这里讲的话会稍显冗长,所以我准备另开一篇,详细说一下。

启动Actor

actorSystem = ActorSystem.create(RemoteConstant.SERVER_ACTOR_SYSTEM_NAME, akkaFinalConfig); actorSystem.actorOf(FriendRequestHandler.defaultProps(), RemoteConstant.SERVER_FRIEND_ACTOR_NAME);

第一个就是建立actor系统,参数一个是系统的名字,类似于电话号码后四位那么一个东西,另一个是akka的配置,这个在解析配置文件步骤中获取。

第二个是创建actor,这里创建的是FriendRequestHandler的Actor,调用其defaultProps()方法,源代码如下:

public static Props defaultProps() {return Props.create(FriendRequestHandler.class)//这一步是设置派发器的配置。//读取配置文件oms-server.akka.conf中akka.friend-request-actor-dispatcher的关键字.withDispatcher("akka.friend-request-actor-dispatcher")//路由配置.withRouter(new RoundRobinPool(Runtime.getRuntime().availableProcessors() * 4).withResizer(new DefaultResizer(Runtime.getRuntime().availableProcessors() * 4,Runtime.getRuntime().availableProcessors() * 10,1,0.2d,0.3d,0.1d,10)));
}    

到这里,这个Akka服务就算是启动完成了

总结

 

最后的vertx的启动基本没什么东西,就是vertx的默认启动,一行代码就OK了,其余的内容和akka启动时基本相同。

vertx = Vertx.vertx();

Server的启动相对来说没有那么的复杂,代码读起来也是非常的通俗易懂,这里面只出现了一个问题

springboot自带读配置文件的功能,为什么启动的时候要先读取配置文件?

因为启动akka和vertx的时候,需要配置文件的内容,而这个时候spring还没有读取该配置文件。

相关文章

https://blog.csdn.net/i_mycode/article/details/108382597 【getClassLoader().getResource() 】

http://doc.yonyoucloud.com/doc/akka-doc-cn/2.3.6/scala/book/chapter1/01_what_is_akka.html 【AKKA 2.3.6 Scala 文档】

相关文章:

PowerJob的server启动都经历了哪些?代码不多也很简单,咱们来逐一理解。

这是一篇让你受益匪浅的文章&#xff0c;点个关注交流一下吧~ PowerJob如何使用&#xff0c;官方文档已经说的很详细了&#xff0c;即使没学过计算机的人&#xff0c;按照那上面的步骤来也是可以搭建出一个可以使用的例子来&#xff0c;所以今天就不在这里重复前人的工作&#…...

分享好玩的h5小游戏制作步骤_怎么做h5微信小游戏

近年来&#xff0c;市面上一直流行各种h5游戏&#xff0c;例如投票、答题、刮刮乐、大转盘等等等等&#xff0c;而且我在各种营销场景下经常看到它们的身影&#xff0c;是做促销&#xff0c;引流和宣传的神器之一&#xff01;那么&#xff0c;怎么做好玩的h5游戏&#xff1f;还…...

代理模式--设计模式

为什么要学习代理模式&#xff1f; 因为这是SpringAOP的底层&#xff01; 1、定义&#xff1a; 在不改变源码的情况下&#xff0c;实现对目标对象的功能扩展 根据代理类的生成时间不同可以将代理分为静态代理和动态代理两种 静态代理 角色分析 抽象角色&#xff1a;一般会…...

【RSTP的原理和配置】

一、RSTP 概述 RSTP使用了IEEE 802.1W协议&#xff0c;视为STP的改进版本&#xff0c;收敛速度快&#xff0c;兼容STP。 RSTP可以兼容STP&#xff0c;但是会丧失快速收敛等优势&#xff1b; 1、RSTP对STP的改进&#xff1b; 1.1、端口角色的增补、简化了生成树协议的理解及部…...

Doom流量回放工具导致的测试环境服务接口无响应的排查过程

Doom流量回放工具导致的测试环境服务接口无响应的排查过程 现象描述&#xff1a; a)部分接口&#xff08;A组接口&#xff09;无响应 b)部分接口&#xff08;B组接口&#xff09;正常响应 c)还有一部分接口&#xff08;C组接口&#xff09;,场景1无响应&#xff0c;场景2正常响…...

2023年留学基金委(CSC)西部/地方合作项目选派办法及解读

2023年2月13日国家留学基金委&#xff08;CSC&#xff09;官方网站发布了2023年西部地区人才培养特别项目、地方合作项目通知。知识人网小编现将其选派工作流程及选派办法原文转载并加以解读、提出建议。知识人网建议1. 邀请函是公派申请的必备条件。对于外语语言证明未达标者&…...

ILSSI国际研讨会将为您呈现六西格玛技术的未来与前景

ILSSI 欢迎世界各地的精益六西格玛专业人士参加即将举行的2023年国际精益六西格玛研讨会&#xff0c;这次研讨会将邀请到世界各地的专家学者&#xff0c;分享他们的专业知识和经验&#xff0c;并就精益六西格玛等相关议题进行探讨和交流。 这是一个绝佳的机会&#xff0c;让您…...

KDJ日周月金叉共振指标

昨天介绍了MACD多周期共振指标公式&#xff0c;KDJ通过类似的写法&#xff0c;也可以共振。本文介绍的KDJ日周月金叉共振指标包含日周金叉共振、日月金叉共振、周月金叉共振、日周月金叉共振四种类型。 需要注意的问题依然是周、月金叉的信号漂移&#xff0c;接近周末月末的信…...

线程私有变量ThreadLocal详解

本文已收录至Github&#xff0c;推荐阅读 &#x1f449; Java随想录 烈火试真金&#xff0c;逆境试强者。——塞内加 文章目录什么是ThreadLocalThreadLocal 原理set()方法get()方法remove()方法ThreadLocal 的Hash算法ThreadLocal 1.7和1.8的区别ThreadLocal 的问题ThreadLoca…...

如何保证数据库和缓存双写一致性

前言 数据库和缓存(比如:redis)双写数据一致性问题,是一个跟开发语言无关的公共问题。尤其在高并发的场景下,这个问题变得更加严重。 我很负责的告诉大家,该问题无论在面试,还是工作中遇到的概率非常大,所以非常有必要跟大家一起探讨一下。 今天这篇文章我会从浅入深,…...

一文搞懂:JS严格模式“use strict”

什么是JS的严格模式 JS严格模式概念是在ES5中引入的&#xff0c;在此模式下&#xff0c;JS对语法的要求会变的严格&#xff0c;某些不太严谨的代码在严格模式下将不能运行。 如何启用严格模式 只需要JS代码的起始添加 "use strict"即可。如&#xff1a; "use…...

Linux的ACL(扩展权限)规划:setfacl、getfacl

目录 什么是ACL与如何支持启动ACL ACL设置技巧&#xff1a;getfacl、setfacl getfacl命令用法 setfacl命令用法 最简单的【u&#xff1a;账号&#xff1a;权限】设置 使用默认权限设置目录未来文件的ACL权限继承 什么是ACL与如何支持启动ACL ACL是Access Control List的…...

HTML预格式化文本pre标签

文章目录参考white-spaceword-breakfont-family参考 https://blog.csdn.net/weixin_44368963/article/details/120054949 https://www.zhangxinxu.com/wordpress/2017/03/css-font-family-chinese-english/ pre 元素可定义预格式化的文本。被包围在 pre 元素中的文本通常会保留…...

基于机器学习的心脏病预测方法(11)——梯度提升机(GBM)

一、梯度提升机介绍 GBM(Gradient Boosting Machine)算法是Boosting(提升)算法的一种。主要思想是,串行地生成多个弱学习器,每个弱学习器的目标是拟合先前累加模型的损失函数的负梯度, 使加上该弱学习器后的累积模型损失往负梯度的方向减少。 且它用不同的权重将基学习器…...

Linux多版本python切换以及多版本pip对应 (cloud studio Ubuntu16.04)

linux && cloud studio && Ubuntu16.04 简单解决多版本python切换以及多版本pip对应问题 1.python2切换成python 多版本python: 更改前先查看版本号 $ python -V Python 2.7.12 $ python2 -V Python 2.7.12 $ python3 -V Python 3.5.2 通过下面的命令看到py…...

【并发编程】LockSupport源码详解

目录 一、前言 1.1 简介 1.2 为什么说LockSupport是Java并发的基石&#xff1f; 二、LockSupport的用途 2.1 LockSupport的主要方法 2.2 使用案例 2.3 总结 三、LockSupport 源码分析 3.1 学习原理前的前置知识 3.1.1 Unsafe.park()和Unsafe.unpark() 3.1.2wait和notify/notify…...

元宇宙之声:新鸿基公司

在本期节目中&#xff0c;新鸿基团队讲述了他们在农历新年季中展示的元宇宙最新创作&#xff01; 为什么将体验命名为「乘风启航」&#xff1f;什么是 「Scallywag」&#xff1f; 香港专业离岸帆船队新鸿基 Scallywag 队由新鸿基公司赞助&#xff0c;其团队精神与公司的精神相呼…...

Linux中定时监控Tomcat服务器进程并在进程结束时重启Tomcat服务器

目录一、问题二、解决方法1、创建定时任务文件2、修改Tomcat的部分文件3、添加系统的定时调度4、执行monitor.sh文件5、查看脚本执行的日志文件一、问题 当我们的Tomcat配置完成后投入使用后&#xff0c;在用户使用一定时间后&#xff0c;Tomcat可能会出现一些问题导致进程结束…...

快速部署私有云笔记,免费享受多端同步

一、老Q笔记之一路坎坷 市面上的笔记软件非常多&#xff0c;有些是本地编辑功能特别强大但是不支持云同步&#xff0c;有些是支持上云但是编辑功能不够完善。选择一款合适的云笔记软件&#xff0c;无疑能让我们工、学习的时候更加顺心、顺手。 这么多年来老Q使用过很多云笔记…...

python生成 2048位随机质数 Miller-Rabin质数测试算法

Miller-Rabin质数测试算法是一种基于随机化的算法&#xff0c;用于判断一个数是否为质数。该算法具有高效性和强健性&#xff0c;通常被用于加密算法中生成大素数。 该算法基于以下两个事实&#xff1a;对于质数ppp和任意整数aaa&#xff0c;有ap−1≡1(modp)a^{p-1} \equiv 1…...

RestClient

什么是RestClient RestClient 是 Elasticsearch 官方提供的 Java 低级 REST 客户端&#xff0c;它允许HTTP与Elasticsearch 集群通信&#xff0c;而无需处理 JSON 序列化/反序列化等底层细节。它是 Elasticsearch Java API 客户端的基础。 RestClient 主要特点 轻量级&#xff…...

Leetcode 3576. Transform Array to All Equal Elements

Leetcode 3576. Transform Array to All Equal Elements 1. 解题思路2. 代码实现 题目链接&#xff1a;3576. Transform Array to All Equal Elements 1. 解题思路 这一题思路上就是分别考察一下是否能将其转化为全1或者全-1数组即可。 至于每一种情况是否可以达到&#xf…...

Xshell远程连接Kali(默认 | 私钥)Note版

前言:xshell远程连接&#xff0c;私钥连接和常规默认连接 任务一 开启ssh服务 service ssh status //查看ssh服务状态 service ssh start //开启ssh服务 update-rc.d ssh enable //开启自启动ssh服务 任务二 修改配置文件 vi /etc/ssh/ssh_config //第一…...

盘古信息PCB行业解决方案:以全域场景重构,激活智造新未来

一、破局&#xff1a;PCB行业的时代之问 在数字经济蓬勃发展的浪潮中&#xff0c;PCB&#xff08;印制电路板&#xff09;作为 “电子产品之母”&#xff0c;其重要性愈发凸显。随着 5G、人工智能等新兴技术的加速渗透&#xff0c;PCB行业面临着前所未有的挑战与机遇。产品迭代…...

.Net框架,除了EF还有很多很多......

文章目录 1. 引言2. Dapper2.1 概述与设计原理2.2 核心功能与代码示例基本查询多映射查询存储过程调用 2.3 性能优化原理2.4 适用场景 3. NHibernate3.1 概述与架构设计3.2 映射配置示例Fluent映射XML映射 3.3 查询示例HQL查询Criteria APILINQ提供程序 3.4 高级特性3.5 适用场…...

8k长序列建模,蛋白质语言模型Prot42仅利用目标蛋白序列即可生成高亲和力结合剂

蛋白质结合剂&#xff08;如抗体、抑制肽&#xff09;在疾病诊断、成像分析及靶向药物递送等关键场景中发挥着不可替代的作用。传统上&#xff0c;高特异性蛋白质结合剂的开发高度依赖噬菌体展示、定向进化等实验技术&#xff0c;但这类方法普遍面临资源消耗巨大、研发周期冗长…...

1688商品列表API与其他数据源的对接思路

将1688商品列表API与其他数据源对接时&#xff0c;需结合业务场景设计数据流转链路&#xff0c;重点关注数据格式兼容性、接口调用频率控制及数据一致性维护。以下是具体对接思路及关键技术点&#xff1a; 一、核心对接场景与目标 商品数据同步 场景&#xff1a;将1688商品信息…...

佰力博科技与您探讨热释电测量的几种方法

热释电的测量主要涉及热释电系数的测定&#xff0c;这是表征热释电材料性能的重要参数。热释电系数的测量方法主要包括静态法、动态法和积分电荷法。其中&#xff0c;积分电荷法最为常用&#xff0c;其原理是通过测量在电容器上积累的热释电电荷&#xff0c;从而确定热释电系数…...

回溯算法学习

一、电话号码的字母组合 import java.util.ArrayList; import java.util.List;import javax.management.loading.PrivateClassLoader;public class letterCombinations {private static final String[] KEYPAD {"", //0"", //1"abc", //2"…...

C++.OpenGL (14/64)多光源(Multiple Lights)

多光源(Multiple Lights) 多光源渲染技术概览 #mermaid-svg-3L5e5gGn76TNh7Lq {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-3L5e5gGn76TNh7Lq .error-icon{fill:#552222;}#mermaid-svg-3L5e5gGn76TNh7Lq .erro…...