当前位置: 首页 > 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…...

JavaSec-RCE

简介 RCE(Remote Code Execution)&#xff0c;可以分为:命令注入(Command Injection)、代码注入(Code Injection) 代码注入 1.漏洞场景&#xff1a;Groovy代码注入 Groovy是一种基于JVM的动态语言&#xff0c;语法简洁&#xff0c;支持闭包、动态类型和Java互操作性&#xff0c…...

FFmpeg 低延迟同屏方案

引言 在实时互动需求激增的当下&#xff0c;无论是在线教育中的师生同屏演示、远程办公的屏幕共享协作&#xff0c;还是游戏直播的画面实时传输&#xff0c;低延迟同屏已成为保障用户体验的核心指标。FFmpeg 作为一款功能强大的多媒体框架&#xff0c;凭借其灵活的编解码、数据…...

vscode(仍待补充)

写于2025 6.9 主包将加入vscode这个更权威的圈子 vscode的基本使用 侧边栏 vscode还能连接ssh&#xff1f; debug时使用的launch文件 1.task.json {"tasks": [{"type": "cppbuild","label": "C/C: gcc.exe 生成活动文件"…...

django filter 统计数量 按属性去重

在Django中&#xff0c;如果你想要根据某个属性对查询集进行去重并统计数量&#xff0c;你可以使用values()方法配合annotate()方法来实现。这里有两种常见的方法来完成这个需求&#xff1a; 方法1&#xff1a;使用annotate()和Count 假设你有一个模型Item&#xff0c;并且你想…...

Python实现prophet 理论及参数优化

文章目录 Prophet理论及模型参数介绍Python代码完整实现prophet 添加外部数据进行模型优化 之前初步学习prophet的时候&#xff0c;写过一篇简单实现&#xff0c;后期随着对该模型的深入研究&#xff0c;本次记录涉及到prophet 的公式以及参数调优&#xff0c;从公式可以更直观…...

Unit 1 深度强化学习简介

Deep RL Course ——Unit 1 Introduction 从理论和实践层面深入学习深度强化学习。学会使用知名的深度强化学习库&#xff0c;例如 Stable Baselines3、RL Baselines3 Zoo、Sample Factory 和 CleanRL。在独特的环境中训练智能体&#xff0c;比如 SnowballFight、Huggy the Do…...

UR 协作机器人「三剑客」:精密轻量担当(UR7e)、全能协作主力(UR12e)、重型任务专家(UR15)

UR协作机器人正以其卓越性能在现代制造业自动化中扮演重要角色。UR7e、UR12e和UR15通过创新技术和精准设计满足了不同行业的多样化需求。其中&#xff0c;UR15以其速度、精度及人工智能准备能力成为自动化领域的重要突破。UR7e和UR12e则在负载规格和市场定位上不断优化&#xf…...

精益数据分析(97/126):邮件营销与用户参与度的关键指标优化指南

精益数据分析&#xff08;97/126&#xff09;&#xff1a;邮件营销与用户参与度的关键指标优化指南 在数字化营销时代&#xff0c;邮件列表效度、用户参与度和网站性能等指标往往决定着创业公司的增长成败。今天&#xff0c;我们将深入解析邮件打开率、网站可用性、页面参与时…...

如何在网页里填写 PDF 表格?

有时候&#xff0c;你可能希望用户能在你的网站上填写 PDF 表单。然而&#xff0c;这件事并不简单&#xff0c;因为 PDF 并不是一种原生的网页格式。虽然浏览器可以显示 PDF 文件&#xff0c;但原生并不支持编辑或填写它们。更糟的是&#xff0c;如果你想收集表单数据&#xff…...

微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据

微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据 Power Query 具有大量专门帮助您清理和准备数据以供分析的功能。 您将了解如何简化复杂模型、更改数据类型、重命名对象和透视数据。 您还将了解如何分析列&#xff0c;以便知晓哪些列包含有价值的数据&#xff0c;…...