2025-08-31 15:19:33
最近公司定时任务越来越多,新的需求也在增加,新写了代码就要上线,上线重新部署的时候,如果这时候有其他定时任务或者异步逻辑在处理,这个处理就会被中断,而中断自然就会影响到业务。
之前我是加了个页面监控当前正在运行的任务,在每次部署的时候,看看现在有没有其他业务在运行,如果有的话,就等一会这个任务结束再部署。
不过最近也是有一些任务耗时特别长,可能你需要等它一天,如果这时候重新部署打断了这个任务,就会影响到业务,出现比如用户的扣款日没有扣款,导致一些订单违约之类的,总之让用户感知到肯定是不好的。
所以,如果重新部署后恢复执行呢,一个是定时任务的代码也要经过适配,需要确认不会出现重复执行的情况,也就是代码也要有幂等的设计;然后就是多余的系统消耗,之前已经执行了10小时了,快执行完了,你这一打断,又需要重新来了;还有就是最重要的,可能会忘记,自己不经意间打断了正在进行的任务,后面用户投诉过来才想起了,就不好了。
还有就是代码幂等适配这个问题,这种约定俗成的规则在编程语言中也很常见,不过在这里我不太喜欢这种设计,他更多是一种君子协议,万一有人没有遵守,或者说忘了什么的,到时候逻辑就会有问题,既然是写 Java 的,相比 JS,Java 这种强类型要的不就是编译期间确认问题吗,所有我更倾向于定义一个接口之类,强制要求实现一些方法,来实现逻辑的中断和恢复。
所有就有了接下来的想法,能不能设计一套可以中断然后重新恢复的底层框架,让上层应用可以在此之上写业务逻辑,这些逻辑就可以支持随时中断,在后面条件允许的情况下恢复执行。
既然是中断,就需要知道在哪里中断,然后保存上下文,下次从这里恢复。
这里就不得不说下 Java 的 InterruptedException
,写 Java 的肯定知道 Threa.sleep(100L)
这种线程休眠必须要捕获这个异常,因为当前线程运行时可能会被其他线程触发中断,必须要处理中断逻辑。什么时候会触发这个中断呢,比如当你调用线程池的 shutdownNow
方法时,当前线程池运行的线程都会被标记为中断,对于此时线程逻辑来说,就应该考虑退出了。
通常,当你运行一个异步任务,任务里涉及到循环或者 IO 这种耗时的工作,都可以考虑适当判断中断,来让系统关闭时及时退出。例如:
for (int i = 0; i < 100000; i++) { //业务逻辑 if (Thread.currentThread().isInterrupted()) { // 线程已经被中断,这时候需要清理环境,及时退出 break; }}
如果没有这种判断的话,当你 kill 这个进程的话,可能就要卡很久,这时候虽然可以强制杀死,但如果数据损坏呢,所以考虑这种情况可以让代码更加健壮。
再说回之前的问题,我一开始想到的有个 Task 接口如下。
interface Task{ void run(Context context);}
context
为任务上下文,业务可以把当前执行情况保存到上下文中,如果中途发生了中断,下次恢复执行可以传入相同的上下文,实现任务继续。但是想了想还是太乱。
后面想到了 Kolin,Kolin 的协程可以在指定代码触发中断,然后切换其他协程,后面也可以恢复回来,也是保存了上下文,不过这个就是更底层的保存,我想我如何可以用同样的代码,精准的知道在字节码什么位置中断任务,然后把任务的堆栈之类信息序列化保存,后面需要时再恢复对应堆栈,继续执行,不就可以完美解决了,而且还是几乎业务无感的,只需要在一些位置打上标记即可。
不过这种方法需要修改字节码,还是颇有难度,我又去看了看有没有 Java 的其他协程框架,看到一个很有意思的,不是协程框架,叫 RxJava
RxJava
可以实现java的流式计算,像是下面这种,
Flowable.range(1, 10) .flatMap(v -> Flowable.just(v) .subscribeOn(Schedulers.computation()) .map(w -> w * w) ) .blockingSubscribe(System.out::println);
AtomicInteger count = new AtomicInteger();Observable.range(1, 10) .doOnNext(ignored -> count.incrementAndGet()) .ignoreElements() .andThen(Single.just(count.get())) .subscribe(System.out::println);
import io.reactivex.rxjava3.schedulers.Schedulers;Flowable.fromCallable(() -> { Thread.sleep(1000); // imitate expensive computation return "Done";}) .subscribeOn(Schedulers.io()) .observeOn(Schedulers.single()) .subscribe(System.out::println, Throwable::printStackTrace);Thread.sleep(2000); // <--- wait for the flow to finish
RxJava 让代码以一个个消费者的形式异步流式执行,可以实现例如上面这些例子,可以让执行代码块在后台执行,然后回到主线程获取结果,这在一些 UI 场景例如安卓可能会有点用;
感觉和我想实现的想法差不多,复杂的逻辑通过这种方式可以拆分成很多子逻辑,他们以 Lambda 块,也就是匿名类的方式编写,也不需要修改字节码,他们本省就是独立的;同过响应式流的方式传递运行数据,也就是上一个代码的执行结果,通过流的参数向下传递,这时候我在框架这边,就可以截胡了,把相应数据进行保存,同时也可以标记当前执行到流的哪一步了,即使是循环这种场景(参考上面的 range
例子),我甚至可以判断当前循环到哪里,这时候就可以在任务需要中断的时候,保存这些信息,然后在系统恢复的时候,拿着之前保存的信息,判断执行流的位置,之前已经执行的就跳过,跳到上次中断的地方,继续执行。
对于数据库相关操作,可以强制使用事务来保证多次执行的可靠性,同时可以设置相关回滚的逻辑。
这种想法会对逻辑影响蛮大,之前的业务代码就需要重写。不过我想单独写一个库封装这种操作,对于使用这种方式的任务就是支持中断的,同时之前老写法的类就是不支持中断的。我觉得现在任务还是有挺多这种场景。
现在还是停留在想法这一阶段,我记得安卓也是专门有后台任务这个概念的,系统有资源的时候才会执行,可能以各种情况暂停执行,后面也可以去看看安卓的这个设计是什么东西。
2025-08-17 22:41:47
就在刚才,我正在晾衣服,直接一个虫呼我脸上,也不知道什么虫,感觉像是蝙蝠;我赶紧衣服一扔进屋关上了阳台门,那个虫感觉是看到了光还是什么,撞了两下门,吓死我了;刚才他还在唧唧叫,感觉是挤在门缝里一样,我拉上了门帘,劝它断了这个念想,衣服也不敢凉了,明天重新洗一下吧,白天虫子一般不怎么出没。
我这个人还是比较胆小的,之前房子里也是进了一个什么蛾子,我拿个扫把在那赶,最后也不知道它跑到那里去了,我只能心惊胆战的睡下去,最近也没见那个蛾子,感觉它不太可能飞出去,就怕哪天我收拾家里时突然掉下来一个虫子尸体,之前蟑螂就是的,一天心情都不好了。
我住的这个是在公寓一楼,价格相比3楼以上,一个月便宜了600块钱,平时出门不用做电梯,还是比较方便的。公寓物业费挺高,相对的环境还算不错,所以说一楼的缺点主要就是这个,我的阳台旁边就是绿化,难免少不了虫子,尤其是晚上开灯;明天打算买一个纱网了,直接把阳台封起来,免得以后心惊胆战。
我又听见外边声音了,赶紧熄灯睡觉了
更新,是下面这玩意,今天到家发现已经死了
2025-08-05 21:51:06
之前也是久闻cj大名,这次还是第一次过来。
刚进去看到一些品牌在做一些类似关注抽奖的活动,刚开始觉得没必要,后面就是一发不可收拾,跟朋友光去排队抽奖去了,像是广场舞大妈排队领鸡蛋,这次回去也是拎了一大包乱七八糟的东西。
漫步者还挺可爱的包。还在他们家抽中了一个鼠标
属实抽象,他们家展台很大,看起来就很有钱的样子,还抽了包粉,口味一般。
巫师
巫师
2077
akko
sony
三连
跟京东小姐姐的集邮
领克03
幻兽帕鲁
挺逗的手绘
“我是自愿干活的“
是兄弟就来砍我
众
外传
2025-07-28 17:33:42
虽然博客也是一直有相册页面,奈何不是专业点的工具,上传图片大小都有限制,而且不支持exif相关信息,所以一直都没有展示,还是部署了个独立的画廊页面,你可以在导航栏看到地址。
感觉整理的美观度还行。
除了基础的图片展示之外,由于这个项目还是比较的简单,没有版权相关信息展示,所以就用了腾讯云的数据万象的自动化流水线,在上传图片到 gallery 目录时,自动给图片加上版权水印,就像你在上图看到的一样。
不过这个水印也是有个问题,只支持绝对大小,没法限定最大大小,图片比较小时候水印可能就看着非常大,影响观感。
后面会把自己拍摄的一些东西逐步上传过去。
这个画廊项目的地址是PicImpact,之前也看到个比较好看的画廊项目,不过由于没有管理后台之类的,遂放弃,感兴趣的也可以看看,afilmory。
2025-07-08 23:58:38
今天我下班之后,像是往常一样看会b站的视频,这时候,qq 收到一个邮件,我的微软账号正在进行安全信息替换;想到之前也收到过这种邮件,可能是那种撞库的,我没怎么在意,只是点了取消,这次我明确的看到的要替换的邮箱是个类似临时邮箱的东西,这明显是有人已经登录了我的账号的,赶紧就去看了看。
好在这种安全信息修改都不是即使生效的,需要等待一段时间,之前的安全信息都还是生效的,所以我才会收到这种通知信息。
我也是立马取消了这次的安全信息修改,然后开启了所有的账号安全选项,删除了密码登录,失效了之前登录的所有设备。
然后我开始复盘一下这次账号的问题。
攻击者的ip也没必要给他打码了吧,而且也换了多个ip地址
在今天下午的时候,我的账号出现了多次ip登录记录,最后一次登录,开始替换我的账号安全信息,然后就是这时候我收到了邮件提醒。
后面我在网上也在搜索相关关键词,毕竟不会没人无故盗你的账号。发现在我之前,也有好多人提到自己的手机经常收到登录允许提示。
这里说下微软的这个安全功能,就是你在电脑上登录时候,直接输入邮箱即可,然后手机上会弹出登录允许,这本来是一件很方便的功能,不用输入密码了,也可以避免你的密码泄露。但是如果别人知道了你的邮箱,不断地尝试登录,你又不小心点了允许,这是别人就可以登录你的账号了。所以一定要核对登录信息,不要误点了。
然后接着上面我找相关信息说起,有人提到了微软 Bing 积分,我突然一惊,原来我的账号早就被盗了,之前一直纳闷我的积分怎么突然没了,为此我还工单联系了客服。
上个月的时候,我的积分被兑换了14000
客服说无法退款
这里说下什么是微软积分,大概就是 Bing 和 Edge 的一个活动,你使用 Bing搜索可以获得积分,积分可以兑换礼品,上年我就兑换了一杯星巴克,后来也兑换了 50 京东E卡,这次门槛变高了,我也是攒了快一年,快可以兑换 100 块钱的礼品了,然后就是被盗我账号的人提前兑换了,礼品码估计也是被他已经使用了。
说到这些,Edge 浏览器上还存在一些我的保存的一些密码,我不怎么使用edge,这些都是之前什么时候从 Chrome 同步过去的,之前我还用火绒监控了Chrome 数据目录,防止其他程序读取 Chrome 数据,但是每次弹窗也是烦,有些程序读取快捷方式也是涉及到读取 Chrome 目录,这时候感觉 Mac 那种沙盒还挺好。
现在我已经把其他我的主要账号都检查了一下,没想到自己还能挨这一遭,借用我找相关信息看到的一句话,一朝被蛇咬十年怕井绳,现在我所有账号都开启了2FA ,希望大家都引以为戒,100 块钱是小事,其他信息被盗了就不好了;
之前看到一个科技博主 电丸科技AK 油管账号被盗了,被人投放了诈骗信息,账号还被油管官方封禁了,好在最后成功找回,吃饭的家伙丢了就不好了,更何况我们搞互联网的。
下一次就是检查一下我的浏览器插件,乱起八遭的开源项目也是别乱用,比如最近发生的 AList 事件。