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

OpenAI API 工程化落地:稳定可控的生产级接入指南

1. 这不是“调用一个接口”那么简单&#xff1a;一个真实从业者眼中的 OpenAI API 入门真相 我带过十几支从零起步的业务团队落地 AI 功能&#xff0c;见过太多人把 OpenAI API 当成“复制粘贴几行代码就能上线的魔法按钮”。结果呢&#xff1f;第一天跑通 gpt-3.5-turbo 返回…...

Adobe-GenP终极指南:如何免费激活Adobe全家桶的完整教程

Adobe-GenP终极指南&#xff1a;如何免费激活Adobe全家桶的完整教程 【免费下载链接】Adobe-GenP Adobe CC 2019/2020/2021/2022/2023 GenP Universal Patch 3.0 项目地址: https://gitcode.com/gh_mirrors/ad/Adobe-GenP Adobe-GenP是一款专门针对Adobe Creative Cloud…...

Diablo Edit2:暗黑破坏神2角色编辑器完整指南 - 5分钟打造完美角色

Diablo Edit2&#xff1a;暗黑破坏神2角色编辑器完整指南 - 5分钟打造完美角色 【免费下载链接】diablo_edit Diablo II Character editor. 项目地址: https://gitcode.com/gh_mirrors/di/diablo_edit 你是否曾在暗黑破坏神2中因为技能点分配错误而懊悔&#xff1f;是否…...

AI药物研发工程化实践:从数据管理到模型部署的全流程解析

1. 项目概述&#xff1a;从“Harness”看AI药物研发的工程化实践最近在GitHub上看到一个名为“AIDD-Projects/harness”的项目&#xff0c;这个名字起得很有意思——“Harness”&#xff0c;直译是“马具、挽具”&#xff0c;引申为“驾驭、利用”。在AI药物研发这个充满挑战的…...

Windows Cleaner:你的C盘空间还能抢救一下吗?

Windows Cleaner&#xff1a;你的C盘空间还能抢救一下吗&#xff1f; 【免费下载链接】WindowsCleaner Windows Cleaner——专治C盘爆红及各种不服&#xff01; 项目地址: https://gitcode.com/gh_mirrors/wi/WindowsCleaner 当Windows系统右下角弹出那个令人焦虑的红色…...

DaVinci系统ARM+DSP双核内存优化实战

1. DaVinci系统内存架构深度解析在嵌入式多媒体处理领域&#xff0c;TI的DaVinci平台凭借其独特的ARMDSP双核架构&#xff0c;成为视频编解码应用的经典选择。这种架构的核心挑战在于如何高效管理ARM与DSP之间的共享内存资源。让我们先拆解这个系统的内存组成&#xff1a;物理上…...

开源情绪感知交互空间:从传感器到氛围生成的软硬件实现

1. 项目概述&#xff1a;一个开源的情绪感知与交互空间最近在GitHub上看到一个挺有意思的项目&#xff0c;叫“open-vibe-island”。光看名字&#xff0c;你可能会有点摸不着头脑&#xff0c;这“开放氛围岛”到底是个啥&#xff1f;简单来说&#xff0c;这是一个开源的情绪感知…...

llmware开源框架:企业级AI应用开发的RAG全流程解决方案

1. 项目概述&#xff1a;一个为构建企业级AI应用而生的开源框架如果你正在尝试将大语言模型&#xff08;LLM&#xff09;集成到你的业务系统中&#xff0c;无论是想做一个智能客服、一个文档分析工具&#xff0c;还是一个内部知识问答机器人&#xff0c;你大概率会遇到一系列令…...

AI Agent技能库实战:153个专业提示词赋能SEO与CRO工作流

1. 项目概述&#xff1a;一个为AI Agent打造的“技能武器库”如果你和我一样&#xff0c;每天都在和Claude Code、Cursor这类AI编程助手打交道&#xff0c;那你肯定也遇到过这样的时刻&#xff1a;想让AI帮你写一篇高质量的SEO文章&#xff0c;或者优化一个着陆页的转化率&…...

智能字典生成器:从规则引擎到安全测试的自动化密码构造

1. 项目概述与核心价值最近在GitHub上看到一个挺有意思的项目&#xff0c;叫“dictator”。光看名字&#xff0c;你可能会联想到一些不太好的东西&#xff0c;但在技术圈里&#xff0c;这个名字其实挺直白的——它就是一个“字典生成器”。不过&#xff0c;别小看它&#xff0c…...