写在开始

其实这个事情我咕咕咕了好久了。这次主要处理两个问题

第一个是之前做的自动转换格式的那个东西有点小问题, 那就是如果有大量的图片同时加载会直接把服务器内存和cpu卡爆掉, 毕竟我开始的时候就是很简单的来了一个就转码一个, 也不排队, 一起都丢进里面转码, 导致了这个问题。

另一个就是我好久之前就写完了然后一直没推上的功能, 增强版的定期备份, 之前我用的是周更的方式备份, 感觉这样子频率可能有点低, 所以我就换了一种方式实现了两天一更。

简单写一下实现方式

第一个问题

解决掉第一个问题其实思路挺简单, 想办法加一个类似锁或者生产者消费者模型就可以处理, 就是让多余的请求在那里等着计算就行。

但是这里有个问题, 我整个项目还是用的异步的, 最好不要玩同步, 所以如果要实现, 那么我要在我的Controller里面使用await来等待是最好的, 而且整体用自带的异步系统是最好的, 然后我就发现了这个支持异步等待的东西SemaphoreSlim

这个类就是常见的信号量那种东西, 但是这个类里面的WaitAsync()方法是支持await的, 所以整体思路就很明了了, 用这个信号量来限制一下并发就可以了, 反正都是用await等着, 至少不会卡爆服务器。

在这里简单介绍一下这个类, 这个类初始化的时候添加一个参数, 应当是信号量的最大值, 达到这个数值之后WaitAsync()方法是会在那里异步等待的

SemaphoreSlim semaphore = new SemaphoreSlim (1); 

这样子就限制了并发量为1, 接下来就在函数调用的开始调用await semaphore.WaitAsync();就可以实现在这里异步等待了。

调用完成之后记得要保证释放出来这个信号量, 使用semaphore.Release();就可以释放出来这个信号量了, 如果有必要可能需要用try/catch来把执行流程中的异常捕获掉来保证至少这个方法能在最后被成功调用, 用个finally就可以了。

第二个问题

这个算是日常操作了。

原本我直接用定时器周更的, 加个定时器的最小Tick, 然后在Controller里面计数就好了, 没啥好说的,更好的解决方式就是直接用这个定时器库里面自带的Cron来实现, 更简单。

优化完成后

主要还是优化第一个问题了, 这样子优化完毕之后清空转码的缓存然后测试下面这个文章。

这个文章是我之前炸服的那个, 优化完成之后打开CPU虽然还是满的(转码图片还不满的?), 但是内存不会一直往上加了, 大概占用了600M的内存之后就不增加了。

你可能会问我为啥不用ASP.NET Core 3.0之后加的GCHeapHardLimit参数手动调整内存上限, 或者不使用ServerGC来解决内存问题。 实际上我也测试过那个, 要么感觉服务假死, 要么没用。 还是优化代码来得实际

写在最后

至少把之前咕咕咕的问题解决了一下, 虽然Gravatar还是用的老的那套, 但是那套感觉问题不大, 毕竟图片小。 吃CPU和内存的量也小。 至少现在看来不会因为打开个文章炸服了, 还是很舒服的。

Last modification:March 10th, 2020 at 02:44 pm