時間過得飛快,距離上次升級改進GWA2吉娃兔🐇已經又三個月過去了。GWA2吉娃兔🐇升级模板引擎子系统( https://ufqi.com/blog/gwa2-updt-template-engine/ )。這期間,GWA2一直在進行細微改進升級,這次記錄的是改進較大的一個地方,對内置Built-in的緩存模塊進行了再次優化。其中的細節和思考值得分享,備忘於此。
GWA2吉娃兔🐇自相應體系創建以來,花了大量的時間和精力持續不斷地推進創建“更好的下一個版本”。關於緩存相關的改進,有記錄可以見于“GWA2-Java built-in cache with connection pool design/带连接池的缓存流程设计( https://ufqi.com/blog/gwa2-ja... )”、“-GWA2 更新缓存调用built-in cache方法( https://ufqi.com/blog/gwa2-built-in-cache/ )”。
圖1. GWA2吉娃兔内置緩存機制
這些努力都是希望基於GWA2的應用系統跑得快些,再快些!待到進行到某種極緻的狀態時,往往面臨的是某種權衡和取捨。比如緩存功能,如果訪問速度更快,則預期的緩存時間越長,更新頻次越低。而對於某些改動,又需要立即更新,這就需要做出某種平衡和不同優先級的考慮。有些系統可以允許緩存一定時間再將改動提到到前端系統,有些系統則對實時性要求較高,不允許有片刻的緩存。
這樣總體考慮,大致是三種情況:1)全部用緩存,數據更新及時性次級考慮,2)全部不用緩存數據即時更新,系統效能次級考慮,3)部分查詢用緩存,平衡系統效能和數據及時性。
gMIS吉密斯 ( https://ufqi.com/dev/gmis/ ) 作爲 GWA2吉娃兔的一個應用實例,就是使用3)方式,部分查詢使用緩存,另外一部分完全不使用緩存,這樣在系統效能和數據及時性之間做tradeoff. 比如gMIS管理所訪問的當前數據表不使用緩存,數據及時性得到保證,而一些公共菜單、權限檢查等則使用了緩存,更新無法立即生效,需等待一個緩存失效的周期。
有沒有一種機制將這種實時性區分開來(第4種情況:全部使用緩存而又能保證數據的及時性, 既….又….?)?儅允許緩存時,使用默認的緩存機制,將數據緩存起來,以此來提升系統響應速度;儅需要實時性時,則立即進行相關數據的更新。經過一番探索,我們采用事件驅動機制,增加了對這些設想的工程實現。其大致思路時,儅用戶發起對系統的寫入、更新操作時,在更新系統對象狀態時,即刻觸發對緩存的更新,從而實現了按需更新想要緩存的目標,讓緩存數據與系統對象真實狀態保持高度一致性、同步性。這些改進包括如下兩個地方。
1. 改進頂級類 inc/WebApp,rmBy 方法的實現
改造之前,inc/WebApp.rmBy 的操作只支持針對數據庫接口的刪除操作。這次改進之後,inc/WebApp.rmBy 將支持形如 “cache:keyString” 的參數定義,儅接收到這樣的參數時,觸發對相應的緩存的刪除。
緩存刪除操作通過 inc/Cachea 接管后效用相應的緩存驅動,進而實現對緩存的刪除、更新操作。也即,通過改進 inc/WebApp.rmBy , 調用 inc/WebApp.writeObject , 通過寫入一個沒有緩存值的對象來發起對當前緩存的更新。這一流程中數據的流轉大致如下。
…. –> mod/ObjectInstance.setBy(execBy) –> inc/WebApp.rmBy
–> inc/WebApp.writeObject –> inc/Cachea.rm
–> inc/Memcached.rm –> …
圖2. GWA2 緩存刪除操作
相應地,不但可以在 inc/WebApp 中通過 rmBy(“cache:keyString”) 的形式調用針對緩存的清理,也可以在任何繼承或實現了 inc/WebApp 的類中調用該方法,實現對緩存的更精準的控制。比如通過圖2. 實現了對單條數據記錄字段級的更新時同步更新緩存的操作,如果針對一個具有多條數據集的操作,該如何同步進行緩存更新操作?
顯然地,需要在控制器中,顯示地調用 mod/ObjectInstance.rmBy(“cache:keyString”) 的方法來清空所涉及到的緩存對象。這是超出内置緩存的範疇,需要具體問題具體分析進行,尤其是每個cache的key不同時,如果有多條cache需求更新,還需要多次調用 rmBy(“cache:anotherKeyString”) .
2. 優化更新操作時觸發緩存操作
在此之前,按圖1.的標志,内置緩存只在數據對象讀取時發生作用,也即在 inc/WebApp.getBy/execBy 時生效,對於寫入、更新操作 inc/WebApp.setBy/execBy 時,無需調用相應的緩存功能模塊,因爲寫入數據無需進行緩存。
帶上開篇提到的問題,儅我們需要在寫入、更新操作時進行緩存更新時,采用事件驅動模式進行相應操作時,需要在寫入、更新操作 inc/WebApp.setBy/execBy 考慮一下緩存。只不過這時候考慮緩存,不是寫入緩存,而是也同步“更新緩存”。具體的改進包括如下兩項。
2.1. 改進 inc/WebApp.setBy
inc/WebApp.setBy 此前的方法中,支持第三個參數 HashMap args 形式,其主要功能是考慮需要寫入非數據庫時的需求。比如寫入緩存系統,寫入文件系統等,儅有這些發生時,需求被進一步地前傳給 inc/writeObject .
接著這個可擴展的機制,我們可以在寫入數據庫時,也通過 args 帶入需要更新的緩存keyString, 儅完成了相應的寫入數據庫的操作時,相應地發起對緩存的更新操作。其流程與圖2.描述相同。
2.2. 改進 inc/WebApp.execBy
inc/WebApp.execBy 的情況稍微複雜一些。在目前的設計中,inc/WebApp.execBy 是為了滿足一些特定的SQL查詢語句,儅我們無法通過 getBy/setBy 實現目標SQL查詢時,execBy 就被排上用場。他甚至可以替代 getBy/setBy ( 在某些GWA2的新手,或者簡單應用中,開發者甚至只用這一種方法即可完成與數據庫的全部讀寫操作 ) ,因而需要考慮 execBy 的讀取和寫入兩種情況。
儅 execBy 執行讀取操作時,其第三個參數 HashMap args 本身就帶有 cache keyString 的參數,意在用於儅讀取成功時,通過這個cache keyString 將查詢結果緩存起來,下次再有類似查詢時,優先主動使用緩存數據。這也是 圖1. 我們的内置緩存的運行機制。
現在我們需要更多地考慮一層,儅 execBy 執行寫入、更新操作時,儅完成相應的操作后,需要進一步地考察 args 中的 cache keyString 參數,如果給定了相應的cache keyString,則我們認爲這是需要同步觸發更新緩存的操作,於是就進一步地呼叫 inc/WebApp.rm(“cache:keyString”) , 同步完成對緩存的更新。
只是,這裏如果是通過 execBy 發起對非數據庫的操作呢? 比如,通過 execBy 發起對 緩存系統,文件系統的操作呢? 目前還沒有這方面的需求,不過的確是需要再考慮的事情。@todo .
-GWA2 吉娃兔 是”通用网络应用架构( General Web Application Architeture, https://ufqi.com/dev/gwa2/ )”,基于 -GWA2 可以轻便构建各种网络应用程序,
包括复杂的在线购物商城、在线医疗、在线教育、 旅游交易平台、社群或者社交网站和新闻资讯网站等,
也包括各种企事业单位网上门户,在线交互及服务作业系统等.
还可以包括为NativeApp做服务器端支持, 甚至是WebApp的全部.
-GWA2 是为数不多的支持跨开发语言的应用框架,目前支持 -Java, -PHP, -Perl, -Aspx and -Python .
-GWA2 is a “General Web Application Architecture” and based on -GWA2 developers can easily build a variety of network applications,
including complex online shopping malls, online medical services, online teaching, travel trading platforms, community or social networking sites and news information sites, etc.
Also the applications include various online portals of enterprises and institutions, online interaction and service operations systems.
Moreover it contains server-side support for NativeApp, or even all of the WebApp.
-GWA2 is one of the web frameworks which provide cross-language support for -Java, -PHP, -Perl, -Aspx and -Python at present.
-GWA2 is E.A.S.Y
**Easy Along, Swift Yield
**轻松启动, 快速产出.
GWA2吉娃兔 基於事件驅動的緩存處理機制已經在 有福工坊UfqiWork ( https://ufqi.com/work/ )上得到部署應用。
有福工坊UfqiWork 是一个在线服务交易平台。
有福工坊提供在线分类服务信息,致力于在线撮合服务交易的买方和卖方,并为买方、卖方提供“行准”服务,居间担保服务交易。行准服务的提供方为居间交易的第三方。有福工坊的服务交易平台为整个服务交易流程的第四方。
**[-R/B2SU
http://ufqi.com/blog/gwa2-upd...](https://ufqi.com/naturedns/se...**