记录不寻常的采坑

采坑日志

这篇文章关于本人的采坑记录,常见的就不加了,相信也能百度的到。

Rsa加密解密

在获取rsa加密后拿到的秘钥(分为公钥和私钥)作为解密秘钥。在window中运行解密没有问题,但是在Linux服务器上解密就变成了带有乱码的数据,导致数据不对引发错误。
加密解密都是用RSA,秘钥也是对的。问题就出在这里

Cipher cipher = Cipher.getInstance("RSA");

这是不完全的RSA方式,应该将完整RSA的填充方式加上

Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");

解决!

线程池卡死问题

在一个用定时任务驱动的方法体中,有三四个网络请求与多个数据库更新方法。测试时发现服务器上跑完整个流程是十秒左右,但是数据量稍大的情况下又很紧急,就显得慢。于是我使用了线程池技术来驱动,刚开始的时候还好,后面发现有卡死的情况。
代码如下:

private static volatile ThreadPoolExecutor singleExecutor = null;
    private static Object ojb = new Object();

    public static synchronized ThreadPoolExecutor getInstanceThreadPool() {
        if (null == singleExecutor) {
            singleExecutor = new ThreadPoolExecutor(3, 10, 1, TimeUnit.SECONDS, new ArrayBlockingQueue<>(400));
            singleExecutor.allowCoreThreadTimeOut(true);
        }
        return singleExecutor;
    }
public List<String> getXXX(List<String> ids) {
	Thread thread = null;
    ThreadPoolExecutor executor = getInstanceThreadPool();
    List<Pair<Date, Thread>> activeThreads = new ArrayList<>();
    try{
	    for(String id:ids) {
		     thread = new Thread(() -> {
		     synchronized (ojb) {
	                    activeThreads.add(Pair.of(DateUtils.getDate(new Date(), "25s", 1), Thread.currentThread()));
	                }
		     // 逻辑xxxx
		     }
		     executor.execute(thread);
	     }
	     int blockTime = 0;
	        while (true) {
	            Threads.sleep(3000);
	            BlockingQueue<Runnable> queue = executor.getQueue();
	            int queueSize = CollectionUtils.size(queue);
	            logger.info("当前排队线程数 " + queueSize);
	            logger.info("当前活动线程数 " + executor.getActiveCount());
	            if (activeThreads.size() > 0) {
	                logger.info("thread size is " + activeThreads.size());
	                for (int i = activeThreads.size() - 1; i >= 0; i--) {
	                    Pair<Date, Thread> pair = activeThreads.get(i);
	                    if (null != pair && new Date().getTime() - pair.getKey().getTime() > 1000) {
	                        if (pair.getValue().isAlive()) {
	                            pair.getValue().stop();
	                        }
	                        activeThreads.remove(i);
	                        logger.info("stop the thread");
	                    }
	                }
	            }
	            if (queueSize == 0 && activeThreads.size() == 0) {
	                break;
	            }
	            if (queueSize > 0 && executor.getActiveCount() == 0 && activeThreads.size() == 0) {
	                blockTime ++;
	            } else {
	                blockTime = 0;
	            }
	            logger.info("block time is: " + blockTime);
	            if (blockTime > 100) {
	                for (Runnable runnable : queue) {
	                    executor.remove(runnable);
	                }
	                logger.info("thread over time");
	                break;
	            }
	        }
        } catch (Exception e) {
                logger.error("fk schedule error:", e);
            }
}

看到这里,发现有死循环检测。本以为是这里发生问题,但是有卡死退出检查:

即:if (blockTime > 100)

也有等待队列移除:

for (Runnable runnable : queue) {
executor.remove(runnable);
}

所以不在检测中。
我也想到资源竞争问题,但是由于时间问题,排查起来比较麻烦。
后来我发现这线程池是个单例方法~~ 好家伙,如果卡死的话不会像对象一样可以初始化。当机立断,直接改成了即用即建。
将如下:

// 将单例移除,把ThreadPoolExecutor executor = getInstanceThreadPool(); 改成如下
ThreadPoolExecutor executor = new ThreadPoolExecutor(3, 10, 1, TimeUnit.SECONDS, new ArrayBlockingQueue<>(200));
// 后增加如下代码
finally {
                executor.shutdownNow();
            }

MySQL 索引失效问题

在一次表数据关联分页查询的时候,发现查询耗时比较长。本以为是数据量的问题,然后看了下才两万多条数据,根据MySQL性能不可能慢,主要是执行sql没有任何异常。我是建了多个普通索引,后面排查是否sql有not in等关键字使索引失效,没有发现。用EXPLAIN 来解析sql 发现主表type 是All,性能巨差。查了很多次,问了AI,根据列出的可能发生问题列表进行排查。后来发现 表字段的字符集也会导致索引失效问题。
如下排查两张表的关联字段:
表中字段字符集
发现有一个为utf8bm4_bin 另一个为utf8bm4_general_ci,立即都改为utf8bm4_general_ci,然后发现快了数倍

MySQL8 数据库迁移并且数据与服务分离

在新的服务器上安装MySQL8 后发现磁盘比较少,经过商量后,决定用数据分离。
首先停止MySQL服务 service mysql stop
在MySQL的配置文件/etc/mysql/mysql.conf.d/mysqld.cnf 中配置datadir = /xxx/xxx/mysql
然后把mysql数据 从/var/lib/mysql复制到/xxx/xxx/mysql
cp -R /var/lib/mysql/* /xxx/xxx/mysql
后启动 service mysql start
发现启动报错:
在这里插入图片描述
无权限!!
我可是root用户,然后查了资料,博主都说是文件权限不够,但是发现拷贝过来的全部都是mysql用户组的目录与文件
各种更改权限与配置 发现毫无卵用
到这里已经花了一天半的时间了。。。
快绝望的时候 点开了一篇文章:

https://blog.csdn.net/weixin_41555271/article/details/125501219

救命稻草
发现里面有个文件是为mysql文件权限配置,Fxxk,只怪自己没有去官方参透。
执行以下指令:

vim /etc/apparmor.d/usr.sbin.mysqld
#将 Allow data dir access下的

/var/lib/mysql r,
/var/lib/mysql/** rwk,

#修改成

/xxx/xxx/mysql r,
/xxx/xxx/mysql/** rwk,
#重新启动mysql服务
/etc/init.d/apparmor restart

重启apparmor很重要!!
最后 我把全部步骤代码贴出来:

#停止mysql 服务
service mysql start
#创建新目录
mkdir -p /xxx/xxx/mysql
#拷贝所有数据到新目录
cp -R /var/lib/mysql/* /xxx/xxx/mysql
#调整目录所有者为用户mysql
chown -R mysql:mysql /xxx/xxx/mysql
#修改mysq配置文件

vim /etc/mysql/mysql.conf.d/mysqld.cnf
修改 datadir = /xxx/xxx/mysql

vim /etc/apparmor.d/usr.sbin.mysqld
#将 Allow data dir access下的

/var/lib/mysql r,
/var/lib/mysql/** rwk,

#修改成

/xxx/xxx/mysql r,
/xxx/xxx/mysql/** rwk,
#重新启动mysql服务
/etc/init.d/apparmor restart
service mysql start

批量修改mysql 表与列的字符集和排序规则

SELECT CONCAT('ALTER TABLE `', table_name, '` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;') AS sql_query
FROM information_schema.TABLES
WHERE table_schema = 'your_database_name'; -- 修改为你的数据库名

utf8mb4 与utf8mb4_general_ci可以改为你想要改成的字符集与排序规则
查询出来,复制生成的SQL并在数据库中执行它们。

vm虚拟机装其他服务 apt无效解决

今天自己在装MySQL8的时候遇到一个问题解决下:
在执行如下命令时:

sudo apt install mysql-server

结果等了很久,也没看到运行完毕。看到如下提示:
Media change: please insert the disc labeled
‘Ubuntu-Server 16.04.7 LTS Xenial Xerus - Release amd64 (20200810)’
in the drive ‘/media/cdrom/’ and press [Enter]

我一个劲的按 回车。没卵用
上网!
原来是:
导致这个原因因为 Ubuntu 的安装源没有配置对,找到 Ubuntu 的安装配置源 /etc/apt/sources.list (注意:是 sources 而不是 source)
把该配置文件中的cdrom注释掉
然后执行 sudo apt-get update
解决-- keep going

layer 弹窗关闭刷新表单

// 返回当前激活的Tab页面关联的iframe的Windows对象
function activeWindow() {
	var topWindow = $(window.parent.document);
	var currentId = $('.page-tabs-content', topWindow).find('.active').attr('data-id');
	if (!currentId) {
		return window.parent;
	}
    return $('.Eleboat_iframe[data-id="' + currentId + '"]', topWindow)[0].contentWindow;
}

// 刷新表单
var parentDoc = activeWindow();
parentDoc.$.table.refresh();

MySQL事务分布提交

使用spring-boot和MySQL + mybatis p,通常情况下直接在ServiceImpl层或Controller层加@Transactional注解就行,但是涉及大量更新和统计时,既要保证数据一致性也要保证统计的准确性,这个时候需要我们手动创建事务并提交,把更新与统计隔离开来。当然你也可以使用拆分代码的形式来做

// 1.注解
@Autowired
private TransactionTemplate  tranTemplate;


// 2.手动开启事务
DefaultTransactionDefinition defaultTransaction = new DefaultTransactionDefinition ();
TransactionStatus trans = tranTemplate.getTransactionManager().getTransaction(defaultTransaction);

// 3.手动提交事务
tranTemplate.getTransactionManager().commit(trans);

spring-boot 临时文件夹冲突

今天在部署测试环境的时候发现问题:

java.io.FileNotFoundException: D:\tomcat\temp\.ehcache-diskstore.lock (拒绝访问。)
这里显示是临时文件夹中的文件访问权限受限。
修改文件的权限为所有用户可读写
行不通!!!
于是另辟蹊径。
既然tmp文件没有访问权限,就自定义tmp路径
自定义tmp路径
在启动参数中增加:

-Djava.io.tmpdir=/xxx/xxxx/tmp

然后启动,不再报错 。
如果还是报错的话,双重保险:
在配置文件中增加:

spring.servlet.multipart.location=/xxx/xxx/tmp/

解决!!

持续更新中。。。。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值