记录一次接入xxl-job的踩坑记录

最近记录了一些java中常踩的坑、设计思路和小知识点,大家可以看看
详细记录一次接入xxl-job的踩坑路径
30s快速解决循环依赖
idea中一个小小的操作竟能解决如此多的问题
docker中的服务接入xxljob需要注意的一点
关于一次fullgc的告警分析
mysql中的int类型竟变成了它?
jpa中的字段总是自己莫名更新?
获取不到类上的注解?空指针?
学会这招,再也不怕依赖冲突!
redis的热点key还能这么处理?
领导让我设计一个任务系统
当服务重启时,大部分人没考虑这点
参数还能这么优雅校验?
文件上传报错,全局异常处理!
常见的点赞功能如何实现,如何防止刷赞

1. 接入企业公用邮箱的邮箱告警改造

因为xxl-job是自带邮箱告警的,但是我需要的场景是,使用企业内部邮箱,发件人是企业公用账户,由于一些文档的缺失,导致这块接起来也废了点劲,主要需要改造下EmailJobAlarm这个类。
原本发送邮件的部分是这样的,这种适用于我已经有了发件人的邮箱账号和密码,是可以直接使用无需改造的。

MimeMessage mimeMessage = XxlJobAdminConfig.getAdminConfig().getMailSender().createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true);
helper.setFrom(XxlJobAdminConfig.getAdminConfig().getEmailFrom(), personal);
helper.setTo(email);
helper.setSubject(title);
helper.setText(content, true);
XxlJobAdminConfig.getAdminConfig().getMailSender().send(mimeMessage);

但是对于公用账户而言,密码是动态的,所以需要去动态获取设置,改造为

JavaMailSenderImpl mailSender = XxlJobAdminConfig.getAdminConfig().getMailSender();
mailSender.setPassword(getMailPassword(mailSender.getUsername(), token));
MimeMessage mimeMessage = mailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true, StandardCharsets.UTF_8.name());
helper.setFrom(XxlJobAdminConfig.getAdminConfig().getEmailFrom());
helper.setTo(email);
helper.setSubject(title);
helper.setText(content, true);
mailSender.send(mimeMessage);

主要就是将XxlJobAdminConfig中的mailSender的实现类换为JavaMailSenderImpl,这样我们就可以给他动态设置password,然后再自己写个根据token获取密码的http接口即可。

最后,因为很多企业邮箱是缺少证书的,而xxl-job中默认是开启了邮箱安全验证的,这个时候就会报类似

Caused by: javax.net.ssl.SSLHandshakeException:                 
  sun.security.validator.ValidatorException: PKIX path building failed: 
  sun.security.provider.certpath.SunCertPathBuilderException:  
    unable to find valid certification path to requested target 

网上很多办法是虚拟一个证书之类的,但是没必要,我是直接把xxl-job的邮箱安全验证关掉的。
把他们注释掉就好了

#spring.mail.properties.mail.smtp.auth=true
#spring.mail.properties.mail.smtp.starttls.enable=true
#spring.mail.properties.mail.smtp.starttls.required=true
#spring.mail.properties.mail.smtp.socketFactory.class=javax.net.ssl.SSLSocketFactory

2. 关于xxl-job接入eureka的坑

客户端接入eureka教程很简单,大家自己去搜,我这里列一下我踩的坑

  1. 关于pom依赖的导致的注册失败
    我一开始引入的依赖是idea自动引入的
<!-- eureka -->
<dependency>
	<groupId>org.springframework.cloud</groupId>
	<artifactId>spring-cloud-netflix-eureka-client</artifactId>
	<version>2.2.2.RELEASE</version>
</dependency>

要改成这样

<!-- eureka -->
<dependency>
	<groupId>org.springframework.cloud</groupId>
	<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

首先是引入的包发生了变化,只有下面这个才会自动注册(原因还在分析)
其次是版本号去掉,eureka要和springboot版本号匹配(有些是不兼容的)
但是直接在这里写版本号不利于统一管理,idea也会报错,所以groupId一致的最好交由父项目统一管理

<dependencyManagement>
		<dependencies>
			<dependency>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-starter-parent</artifactId>
				<version>${spring-boot.version}</version>
				<type>pom</type>
				<scope>import</scope>
			</dependency>
			<dependency>
				<groupId>org.springframework.cloud</groupId>
				<artifactId>spring-cloud-dependencies</artifactId>
				<version>2021.0.3</version>
				<type>pom</type>
				<scope>import</scope>
			</dependency>
		</dependencies>
	</dependencyManagement>

这里统一管理了org.springframework.bootorg.springframework.cloud两种依赖的版本,其中org.springframework.cloud是我后来加的,因为eureka用的是它。
但是springCloud和springBoot也是有兼容关系的!
兼容关系如下(大家复制以json格式打开)

{
    
    "git":{
    
    "branch":"ab69b84e03e0cd44f38dab35bc3ae1cdcc35416e","commit":{
    
    "id":"ab69b84","time":"2022-08-23T15:02:55Z"}},"build":{
    
    "version":"0.0.1-SNAPSHOT","artifact":"start-site","versions":{
    
    "spring-boot":"2.7.3","initializr":"0.13.0-SNAPSHOT"},"name":"start.spring.io website","time":"2022-08-23T15:04:28.319Z","group":"io.spring.start"},"bom-ranges":{
    
    "codecentric-spring-boot-admin":{
    
    "2.4.3":"Spring Boot >=2.3.0.M1 and <2.5.0-M1","2.5.6":"Spring Boot >=2.5.0.M1 and <2.6.0-M1","2.6.8":"Spring Boot >=2.6.0.M1 and <2.7.0-M1","2.7.4":"Spring Boot >=2.7.0.M1 and <3.0.0-M1","3.0.0-M4":"Spring Boot >=3.0.0-M1 and <3.1.0-M1"},"solace-spring-boot":{
    
    "1.1.0":"Spring Boot >=2.3.0.M1 and <2.6.0-M1","1.2.1":"Spring Boot >=2.6.0.M1 and <2.7.0-M1"},"solace-spring-cloud":{
    
    "1.1.1":"Spring Boot >=2.3.0.M1 and <2.4.0-M1","2.1.0":"Spring Boot >=2.4.0.M1 and <2.6.0-M1","2.3.0":"Spring Boot >=2.6.0.M1 and <2.7.0-M1"},"spring-cloud":{
    
    "Hoxton.SR12":"Spring Boot >=2.2.0.RELEASE and <2.4.0.M1","2020.0.6":"Spring Boot >=2.4.0.M1 and <2.6.0-M1","2021.0.0-M1":"Spring Boot >=2.6.0-M1 and <2.6.0-M3","2021.0.0-M3":"Spring Boot >=2.6.0-M3 and <2.6.0-RC1","2021.0.0-RC1":"Spring Boot >=2.6.0-RC1 and <2.6.1","2021.0.3":"Spring Boot >=2.6.1 and <3.0.0-M1","2022.0.0-M1":"Spring Boot >=3.0.0-M1 and <3.0.0-M2","2022.0.0-M2":"Spring Boot >=3.0.0-M2 and <3.0.0-M3","2022.0.0-M3":"Spring Boot >=3.0.0-M3 and <3.0.0-M4","2022.0.0-M4":"Spring Boot >=3.0.0-M4 and <3.1.0-M1"},"spring-cloud-azure":{
    
    "4.3.0":"Spring Boot >=2.5.0.M1 and <3.0.0-M1"},"spring-cloud-gcp":{
    
    "2.0.11":"Spring Boot >=2.4.0-M1 and <2.6.0-M1","3.3.0":"Spring Boot >=2.6.0-M1 and <2.7.0-M1"},"spring-cloud-services":{
    
    "2.3.0.RELEASE":"Spring Boot >=2.3.0.RELEASE and <2.4.0-M1","2.4.1":"Spring Boot >=2.4.0-M1 and <2.5.0-M1","3.3.0":"Spring Boot >=2.5.0-M1 and <2.6.0-M1","3.4.0":"Spring Boot >=2.6.0-M1 and <2.7.0-M1","3.5.0":"Spring Boot >=2.7.0-M1 and <3.0.0-M1"},"spring-geode":{
    
    "1.3.12.RELEASE":"Spring Boot >=2.3.0.M1 and <2.4.0-M1","1.4.13":"Spring Boot >=2.4.0-M1 and <2.5.0-M1","1.5.14":"Spring Boot >=2.5.0-M1 and <2.6.0-M1","1.6.10":"Spring Boot >=2.6.0-M1 and <2.7.0-M1","1.7.2":"Spring Boot >=2.7.0-M1 and <3.0.0-M1","2.0.0-M4":"Spring Boot >=3.0.0-M1 and <3.1.0-M1"},"spring-shell":{
    
    "2.1.1":"Spring Boot >=2.7.0 and <3.0.0-M1"},"vaadin":{
    
    "14.8.16":"Spring Boot >=2.1.0.RELEASE and <2.6.0-M1","23.1.7":"Spring Boot >=2.6.0-M1 and <2.8.0-M1"},"wavefront":{
    
    "2.0.2":"Spring Boot >=2.1.0.RELEASE and <2.4.0-M1","2.1.1":"Spring Boot >=2.4.0-M1 and <2.5.0-M1","2.2.2":"Spring Boot >=2.5.0-M1 and <2.7.0-M1","2.3.0":"Spring Boot >=2.7.0-M1 and <3.0.0-M1"}},"dependency-ranges":{
    
    "native":{
    
    "0.9.0":"Spring Boot >=2.4.3 and <2.4.4","0.9.1":"Spring Boot >=2.4.4 and <2.4.5","0.9.2":"Spring Boot >=2.4.5 and <2.5.0-M1","0.10.0":"Spring Boot >=2.5.0-M1 and <2.5.2","0.10.1":"Spring Boot >=2.5.2 and <2.5.3","0.10.2":"Spring Boot >=2.5.3 and <2.5.4","0.10.3":"Spring Boot >=2.5.4 and <2.5.5","0.10.4":"Spring Boot >=2.5.5 and <2.5.6","0.10.5":"Spring Boot >=2.5.6 and <2.5.9","0.10.6":"Spring Boot >=2.5.9 and <2.6.0-M1","0.11.0-M1":"Spring Boot >=2.6.0-M1 and <2.6.0-RC1","0.11.0-M2":"Spring Boot >=2.6.0-RC1 and <2.6.0","0.11.0-RC1":"Spring Boot >=2.6.0 and <2.6.1","0.11.0":"Spring Boot >=2.6.1 and <2.6.2","0.11.1":"Spring Boot >=2.6.2 and <2.6.3","0.11.2":"Spring Boot >=2.6.3 and <2.6.4","0.11.3":"Spring Boot >=2.6.4 and <2.6.6","0.11.5":"Spring Boot >=2.6.6 and <2.7.0-M1","0.12.0":"Spring Boot >=2.7.0-M1 and <2.7.1","0.12.1":"Spring Boot >=2.7.1 and <3.0.0-M1"},"okta":{
    
    "1.4.0":"Spring Boot >=2.2.0.RELEASE and <2.4.0-M1","1.5.1":"Spring Boot >=2.4.0-M1 and <2.4.1","2.0.1":"Spring Boot >=2.4.1 and <2.5.0-M1","2.1.6":"Spring Boot >=2.5.0-M1 and <3.0.0-M1"},"mybatis":{
    
    "2.1.4":"Spring Boot >=2.1.0.RELEASE and <2.5.0-M1","2.2.2":"Spring Boot >=2.5.0-M1"},"camel":{
    
    "3.5.0":"Spring Boot >=2.3.0.M1 and <2.4.0-M1","3.10.0":"Spring Boot >=2.4.0.M1 and <2.5.0-M1","3.13.0":"Spring Boot >=2.5.0.M1 and <2.6.0-M1","3.17.0":"Spring Boot >=2.6.0.M1 and <2.7.0-M1","3.18.1":"Spring Boot >=2.7.0.M1 and <3.0.0-M1"},"picocli":{
    
    "4.6.3":"Spring Boot >=2.4.0.RELEASE and <3.0.0-M1"},"open-service-broker":{
    
    "3.2.0":"Spring Boot >=2.3.0.M1 and <2.4.0-M1","3.3.1":"Spring Boot >=2.4.0-M1 and <2.5.0-M1","3.4.1":"Spring Boot >=2.5.0-M1 and <2.6.0-M1","3.5.0":"Spring Boot >=2.6.0-M1 and <2.7.0-M1"}}}

然后这里是springCloud的版本
最后因为xxl-job的springBoot版本是2.6.7,所以选出了2021.0.3这个版本的springCloud。
启动,注册成功。
所以总结一下,就是首先eureka引入的依赖要正确,其次它的版本不能与springBoot冲突,不然就会报各种错,服务都起不来。

2021-12-22 18:06:42.658 ERROR 12172 — [nfoReplicator-0] c.n.d.s.t.d.RedirectingEurekaHttpClient : Request execution error. endpoint=DefaultEndpoint{ serviceUrl='http://localhost:8761/eureka/}at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49) [spring-boot-devtools-2.2.5.RELEASE.jar:2.2.5.RELEASE]
Caused by: java.net.ConnectException: Connection refused: connect at java.net.DualStackPlainSocketImpl.waitForConnect(Native Method) ~[na:1.8.0_41]

3. 关于xxl-job注册到容器中

这个其实不算坑了,算是一个需要注意的点吧,就是服务注册到实体机和容器中的一个小区别。
就是注册的host和port最好是获取容器对外暴漏的host与port,相应的也要根据部署环境的不同,写不同的配置文件,这个因为每个人的场景可能都不一样,所以不细说了。

4. 关于调度器无法访问容器中的执行器的坑

调度器和执行器都注册成功以后,发现调度器无法访问执行器了,奇怪,明明本地试的时候还可以。
一开始报错Full authentication is required to access this resource,一查,应该是spring安全策略的问题,可是如果这样的话本地按理说也会有这个报错,所以感觉不是这个问题。
但还是试了试把报错的url加入到了安全白名单,然后试了一下发现404了。
所以判断应该不是安全策略的问题,应该是访问路径出了问题。
最后发现试执行器注册的信息有误,正确的注册信息应该是

@Bean
    public XxlJobSpringExecutor assetsXxlJobExecutor() {
    
    
        log.info(">>>>>>>>>>> xxl-job config init.");
        XxlJobSpringExecutor xxlJobSpringExecutor = new XxlJobSpringExecutor();
        xxlJobSpringExecutor.setAdminAddresses(adminAddresses);
        xxlJobSpringExecutor.setAppname(appname);
        xxlJobSpringExecutor.setAccessToken(accessToken);
        xxlJobSpringExecutor.setLogPath(logPath);
        // xxlJobSpringExecutor.setIp(ip);
        xxlJobSpringExecutor.setPort(innerPort);
        xxlJobSpringExecutor.setAddress("http://{ip_port}/".replace("{ip_port}", IpUtil.getIpPort(ip, externalPort)));
        return xxlJobSpringExecutor;
    }

这里的innerPort是容器内部端口,也就是执行器启动的时候要使用的端口,一般会在容器部署的时候分配一个端口。
这里的externalPort是容器对外暴漏的端口,也就是容器真正起来以后,容器内部端口所分配到的对外暴露端口。

这里的内部端口就类似于 8081 8080之类的,每个容器中都有一套,但一个实体机上会有多个容器,所以这个端口其实不是真实的。
对外暴露的端口可能就是31239之类的,其实容器所在实体机上的真正端口,也就是对外暴露的端口,用做执行器注册与调度通信,它与容器内部端口是有映射关系的。

然后这里注册的setAddress是用于 “执行器注册” 和 “调度中心请求并触发任务”,这点xxl-job官方文档中也有写,setPort传进去是单独用做执行器启动的。
这样设置以后,执行器和调度器就可以正常通信了。

猜你喜欢

转载自blog.csdn.net/qq_31363843/article/details/126520184
今日推荐