日常问题处理积累[JAVA]

Q1:java 项目分别部署在两台服务器中, private volatile boolean retryLock = false;

这行代码中的 volatile 关键字,还有效么,两台服务器中起的线程还能实时访问到retryLock 这个变量的值么?

解答:

在Java中,volatile关键字用于保证变量的可见性和禁止指令重排序。它可以确保多个线程对该变量的读写操作都能实时访问到最新的值。
如果两台服务器是独立的,即每台服务器都有自己的JVM进程和内存空间,那么volatile关键字将无法保证两台服务器中的线程能够实时访问到retryLock变量的最新值。因为每台服务器都有自己的内存空间,对于一个服务器中的线程来说,它只能访问到自己内存空间中的变量副本,无法直接访问另一台服务器的内存空间。

Q2:@AutoConfigureBefore和@AutoConfigureAfter 的区别

解答:

1.@AutoConfigureAfter,对于这个注解

//说明
// C将会在A之后加载
@AutoConfigureAfter(A.class)
public class C{
}

则是先加载A 后加载 C,

1.那如果 A 加载装配失败,C还能正常被加载装配么?
2.如果A在项目启动的时候没有自动装配,C 还能被自动装配么?
结论 :即使A类装配失败,C类仍然可以被正常装配。
@AutoConfigureAfter注解指定了C类在A类之后进行自动装配。这意味着即使A类装配失败,Spring Boot仍然会尝试装配C类。

但是需要注意的是,尽管C类可以被正常装配,但它依赖于A类的装配结果。如果A类装配失败,可能会导致C类在运行时出现错误或异常。因此,在使用@AutoConfigureAfter注解时,仍然需要确保A类能够成功装配,并且满足C类的自动装配条件

2.@AutoConfigureBefore

// 说明
// C 将会在 A 之前加载
@AutoConfigureBefore(A.class)
public class C {
}

正好最近在将项目整合 shardingjdbc 数据源,可以看下他的源码

@AutoConfigureBefore({DataSourceAutoConfiguration.class})
public class ShardingSphereAutoConfiguration implements EnvironmentAware {
    private String schemaName;
    private final SpringBootPropertiesConfiguration props;
    private final Map<String, DataSource> dataSourceMap = new LinkedHashMap();
    ...........

这里有两个配置 ShardingSphereAutoConfiguration 和DataSourceAutoConfiguration
在项目的配置文件中,我将 spring.datasource.url 等等注释了,统一使用了shardingjdbc 的数据源配置

像这样
#spring.datasource.url = jdbc:mysql://127.0.0.1:3306/lb_location?useUnicode=true&characterEncoding=utf-8&useSSL=false&allowMultiQueries=true&useAffectedRows=true&tinyInt1isBit=false
#spring.datasource.username = lb_location
#spring.datasource.password = 123456
#spring.datasource.driver-class-name = com.mysql.jdbc.Driver

spring.shardingsphere.datasource.master.url=jdbc:mysql://127.0.0.1:3306/lb_location?useUnicode=true&characterEncoding=utf-8&useSSL=false&allowMultiQueries=true&useAffectedRows=true&tinyInt1isBit=false
spring.shardingsphere.datasource.master.type=com.alibaba.druid.pool.DruidDataSource
spring.shardingsphere.datasource.master.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.master.username=lb_location
spring.shardingsphere.datasource.master.password=123456
spring.shardingsphere.datasource.master.initial-size=5

然后启动项目,报错了

 Unsatisfied dependency expressed through bean property 'sqlSessionFactory'; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'sqlSessionFactory' defined in class path resource [com/baomidou/mybatisplus/autoconfigure/MybatisPlusAutoConfiguration.class]: Unsatisfied dependency expressed through method 'sqlSessionFactory' parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dynamicDataSourceConfig': Injection of resource dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'shardingSphereDataSource' defined in class path resource 
 [org/apache/shardingsphere/spring/boot/ShardingSphereAutoConfiguration.class]: Initialization of bean failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.boot.autoconfigure.jdbc.DataSourceInitializerInvoker': Invocation of init method failed; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'dataSource': Requested bean is currently in creation: Is there an unresolvable circular reference?

这里应该明显的看出shardingSphereDataSource 数据源配置失败,
,点进最后的错误里面跳到了DataSourceAutoConfiguration 的源码里面
显示该数据源配置错误,
后来我就直接在启动类中添加了这行代码试试

@SpringBootApplication(exclude={
        DataSourceAutoConfiguration.class} )

发现项目启动成功了,sharding的数据源也能正常依赖spring管理,并且拿到
现在总结下上面的两个问题
那么即使A类装配失败,C类仍然可以被正常装配。
@AutoConfigureBefore注解指定了C类在A类之前进行自动装配。这意味着即使A类装配失败,Spring Boot仍然会尝试装配C类。
但是需要注意的是,尽管C类可以被正常装配,但它依赖于A类的装配结果。如果A类装配失败,可能会导致C类在运行时出现错误或异常。因此,在使用@AutoConfigureBefore注解时,仍然需要确保A类能够成功装配,并且满足C类的自动装配条件。

项上述例子中A 装配失败的原因应该是Error creating bean with name ‘sqlSessionFactory’ defined in class path resource 这个原因导致的项目启动错误
,sqlSessionFactory(是MyBatis的核心接口之一,用于创建SqlSession对象。SqlSession是与数据库交互的主要对象,可以执行SQL语句、提交事务等操作。SqlSessionFactory负责创建和管理SqlSession对象,包括配置数据源、事务管理等。) 这个类在mybatis 中又是必要的

所以说@AutoConfigureXXX 只是规定了springboot 的作用是指定配置类加载的顺序,而不是bean的加载顺序(需要控制bean 的加载顺序 可以使用可以用@ConditionalOnMissingBean注解);

xxljob 自动注册不了的几种情况

先以这份配置文件为例子

# xxl-job
xxl:
  job:
    admin:
      addresses: http://127.0.0.1:19011/xxl-job-admin/ #xxl-job的地址,如果有多个地址,用逗号分隔开
    executor:
      appname: xxl-test  #执行器AppName
      ip:   #执行器IP [选填]:默认为空表示自动获取IP,多网卡时可手动设置指定IP,该IP不会绑定Host仅作为通讯时用;地址信息用于 "执行器注册""调度中心请求并触发任务";
      port: -1 # 执行器端口号 [选填]:小于等于0则自动获取;默认端口为9999,单机部署多个执行器时,注意要配置不同执行器端口;
      logpath: /local/xxl-job/logs/  #执行器运行日志文件存储磁盘路径
      logretentiondays: -1 #执行器日志文件保存天数 [选填] : 过期日志自动清理, 限制值大于等于3时生效; 否则,-1, 关闭自动清理功能;
    accessToken: default   #执行器通讯TOKEN [选填]:非空时启用

1.xxl job服务部署失败
这个可以访问下部署xxljob 的地址 默认的密码和用户分别是admin 123456
http://127.0.0.1:19011/xxl-job-admin/ 如果访问不成功说明服务部署的有问题
2. 执行器为在页面手动添加
executor:
appname: xxl-test #执行器AppName
这里的执行器名称是 xxl-test

在这里插入图片描述
在页面必须要添加这个执行器,这里执行器的ip可以不填(前提你要确认你的机器不是单网卡的机器)
3. 端口号设置的问题
port: -1 # 执行器端口号 [选填]:小于等于0则自动获取;默认端口为9999,单机部署多个执行器时,注意要配置不同执行器端口;

如果一台服务器部署了多个服务,每一个服务都用了xxljob 这个中间件,你的port 就需要手动指定区分下,
前两天在部署的时候,就是因为一个机器部署了两个服务,都用了同一个xxljob,但是端口都用了默认的9999,导致两个服务的执行器都不能注册到xxljob 的服务里面.

4.token问题
accessToken: default #执行器通讯TOKEN [选填]:非空时启用
这个token的设置必须要和你xxljob 服务的配置文件的token 一致我这里的token是default
那么你的部署的xxljob服务的token也必须是 default
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值