MoreRSS

site iconThetbw | 黑羽修改

游戏宅男,后端开发
请复制 RSS 到你的阅读器,或快速订阅到 :

Inoreader Feedly Follow Feedbin Local Reader

Thetbw | 黑羽的 RSS 预览

关于定时任务和一些其他异步任务的随想

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块钱,平时出门不用做电梯,还是比较方便的。公寓物业费挺高,相对的环境还算不错,所以说一楼的缺点主要就是这个,我的阳台旁边就是绿化,难免少不了虫子,尤其是晚上开灯;明天打算买一个纱网了,直接把阳台封起来,免得以后心惊胆战。

我又听见外边声音了,赶紧熄灯睡觉了


更新,是下面这玩意,今天到家发现已经死了
image.png

ChinaJoy游记

2025-08-05 21:51:06

之前也是久闻cj大名,这次还是第一次过来。

刚进去看到一些品牌在做一些类似关注抽奖的活动,刚开始觉得没必要,后面就是一发不可收拾,跟朋友光去排队抽奖去了,像是广场舞大妈排队领鸡蛋,这次回去也是拎了一大包乱七八糟的东西。

image.png

漫步者还挺可爱的包。还在他们家抽中了一个鼠标

image.png

属实抽象,他们家展台很大,看起来就很有钱的样子,还抽了包粉,口味一般。

图集

DSC07449.jpg

DSC07455.jpg

DSC07466.jpg

DSC07475.jpg

巫师

DSC07476.jpg

巫师

DSC07481.jpg

2077

DSC07503.jpg

akko

DSC07506.jpg

sony

DSC07518.jpg

DSC07525.jpg

DSC07535.jpg

三连

image.png

跟京东小姐姐的集邮

DSC07575.jpg

DSC07578.jpg

DSC07599.jpg

领克03

DSC07616.jpg

幻兽帕鲁

DSC07617.jpg

挺逗的手绘

DSC07625.jpg

“我是自愿干活的“

DSC07649.jpg

是兄弟就来砍我

DSC07669.jpg

DSC07674.jpg

DSC07689 1.jpg

DSC07730.jpg

DSC07744.jpg

image.png

外传

新增摄影画廊

2025-07-28 17:33:42

虽然博客也是一直有相册页面,奈何不是专业点的工具,上传图片大小都有限制,而且不支持exif相关信息,所以一直都没有展示,还是部署了个独立的画廊页面,你可以在导航栏看到地址。

4c511248802044a98a6dad544b581799.png

感觉整理的美观度还行。

除了基础的图片展示之外,由于这个项目还是比较的简单,没有版权相关信息展示,所以就用了腾讯云的数据万象的自动化流水线,在上传图片到 gallery 目录时,自动给图片加上版权水印,就像你在上图看到的一样。
不过这个水印也是有个问题,只支持绝对大小,没法限定最大大小,图片比较小时候水印可能就看着非常大,影响观感。

后面会把自己拍摄的一些东西逐步上传过去。
这个画廊项目的地址是PicImpact,之前也看到个比较好看的画廊项目,不过由于没有管理后台之类的,遂放弃,感兴趣的也可以看看,afilmory

今天天气不错

2025-07-20 12:51:21

DSC07232.jpg

DSC07247.jpg

DSC07248.jpg

DSC07255.jpg

DSC07260.jpg

微软账号被盗

2025-07-08 23:58:38

今天我下班之后,像是往常一样看会b站的视频,这时候,qq 收到一个邮件,我的微软账号正在进行安全信息替换;想到之前也收到过这种邮件,可能是那种撞库的,我没怎么在意,只是点了取消,这次我明确的看到的要替换的邮箱是个类似临时邮箱的东西,这明显是有人已经登录了我的账号的,赶紧就去看了看。

image.png

好在这种安全信息修改都不是即使生效的,需要等待一段时间,之前的安全信息都还是生效的,所以我才会收到这种通知信息。

我也是立马取消了这次的安全信息修改,然后开启了所有的账号安全选项,删除了密码登录,失效了之前登录的所有设备。


然后我开始复盘一下这次账号的问题。

image.png

攻击者的ip也没必要给他打码了吧,而且也换了多个ip地址

在今天下午的时候,我的账号出现了多次ip登录记录,最后一次登录,开始替换我的账号安全信息,然后就是这时候我收到了邮件提醒。

后面我在网上也在搜索相关关键词,毕竟不会没人无故盗你的账号。发现在我之前,也有好多人提到自己的手机经常收到登录允许提示。

这里说下微软的这个安全功能,就是你在电脑上登录时候,直接输入邮箱即可,然后手机上会弹出登录允许,这本来是一件很方便的功能,不用输入密码了,也可以避免你的密码泄露。但是如果别人知道了你的邮箱,不断地尝试登录,你又不小心点了允许,这是别人就可以登录你的账号了。所以一定要核对登录信息,不要误点了。

然后接着上面我找相关信息说起,有人提到了微软 Bing 积分,我突然一惊,原来我的账号早就被盗了,之前一直纳闷我的积分怎么突然没了,为此我还工单联系了客服。

image.png

上个月的时候,我的积分被兑换了14000

image.png

客服说无法退款

这里说下什么是微软积分,大概就是 Bing 和 Edge 的一个活动,你使用 Bing搜索可以获得积分,积分可以兑换礼品,上年我就兑换了一杯星巴克,后来也兑换了 50 京东E卡,这次门槛变高了,我也是攒了快一年,快可以兑换 100 块钱的礼品了,然后就是被盗我账号的人提前兑换了,礼品码估计也是被他已经使用了。


说到这些,Edge 浏览器上还存在一些我的保存的一些密码,我不怎么使用edge,这些都是之前什么时候从 Chrome 同步过去的,之前我还用火绒监控了Chrome 数据目录,防止其他程序读取 Chrome 数据,但是每次弹窗也是烦,有些程序读取快捷方式也是涉及到读取 Chrome 目录,这时候感觉 Mac 那种沙盒还挺好。


现在我已经把其他我的主要账号都检查了一下,没想到自己还能挨这一遭,借用我找相关信息看到的一句话,一朝被蛇咬十年怕井绳,现在我所有账号都开启了2FA ,希望大家都引以为戒,100 块钱是小事,其他信息被盗了就不好了;

之前看到一个科技博主 电丸科技AK 油管账号被盗了,被人投放了诈骗信息,账号还被油管官方封禁了,好在最后成功找回,吃饭的家伙丢了就不好了,更何况我们搞互联网的。

下一次就是检查一下我的浏览器插件,乱起八遭的开源项目也是别乱用,比如最近发生的 AList 事件。