• NetCore踩坑记3、还是EFCore吃内存的问题,有时候最简单的方法便是最好的方法


    距离上一次分享已经过去了三个月;情况并没有预想中的乐观。

    上篇:https://www.cnblogs.com/for-example/p/12955788.html

    1、出现了什么状况

    还是上一次分享的问题,EFCore多租户模式吃内存。

    按照上一次我们分享的处理方式,我们进行了以下处理

    1. 增大MemoryCache实例的[空间?]最大值(使用新的MemoryCache实例替换掉原本的实现)
    2. 减小每个Model在MemoryCache中的[空间?]占用
    3. 设置缓存存活时间
    4. 配置缓存刷新时间

    情况并没有得到好转,它依旧吃掉了很多内存,因为即使经过了这样的处理,对于我们来说,也没有任何的帮助,设置缓存存活时间,配置缓存的刷新时间确实是能有效的利用缓存,但在所有客户蜂拥而至的时候,依旧是每个客户都需要为其缓存Model,如果客户是错峰而来,这样确实有用,但每个客户都是三餐高频访问,总不能让人不吃饭吧。

    2、我们如何设计解决方案

    • 回想起我们的应用还在单体的时候,一个DBHelp,不去缓存Model,手写sql直达DB,从未遇到过内存的问题
    • EFCore是因为需要缓存映射关系(Model)才吃掉很多内存。

    EFCore有错吗?它没有。缓存映射关系,就是合理的设计方案,因为确实是在映射上存在差异。

    我们能不能把差异点变更呢?这使我们找到了解决的灵感,我们可以通过一些处理,让原本存在的映射差异前移或者后移。

    3、我们如何解决

    1. 我们取消了Model的缓存,让所有租户使用同一Model
    2. 我们在ToTable的时候使用占位符取代表名差异部位
    3. 我们向EFCore的上下文添加了拦截器(EFCore3x重新回归),在拦截器内截获将要执行的sql,替换掉表名里的占位符

    通过以上方式,我们对EFCore屏蔽了租户差异,截获其执行的sql之后还原了租户差异,替换表名的过程是实时进行的,是简单的字符串Replace,虽然会消耗一点算力,但相比刷新缓存消耗的算力和内存,所付出的代价几乎微乎其微。

    4、变更后的成效

    内存和CPU都降下来了,现在我们每个服务的内存控制在180Mb左右,调用最密集的服务,内存消耗在600Mb左右(并不是EF吃掉的)

    总结

    预留占位符,然后替换占位符,这是最简单的方式,然而却也是最有效的方式,有时候最简单的方法便最好的办法。

  • 相关阅读:
    OSPF 开放最短路径优先协议
    RIP 路由算法
    原创 记一个上门洗车服务范围的需求实现
    转载 一位资深程序员大牛给予Java学习者的学习路线建议
    原创 解决异步调用实时跳转
    FIFO队列 ADT接口 数组实现
    FIFO队列 ADT接口 链表实现
    约瑟夫问题 链表实现
    合并-查找接口实现
    快速查找 快速合并 加权快速合并 路径等分加权快速合并 算法
  • 原文地址:https://www.cnblogs.com/for-example/p/13589143.html
Copyright © 2020-2023  润新知