记录不寻常的采坑

采坑日志

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

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,然后发现快了数倍

持续更新中。。。。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值