shanchen
shanchen

hi

Spring Annotation: Scope

最近遇到一個Spring使用錯誤的情境,造成營運問題…… 這個錯誤事後想想很簡單,都覺得早可以避免。

背景知識可以看這篇,簡單說就是每個Request連上來,Controller不存在的話,Spring 會建一個Controller。過一陣子沒人用就GC掉,否則會共用。所以Controller必須是Stateless的。(而且要threadsafe)

Controller's life-cycle in Spring MVC
Thanks for contributing an answer to Stack Overflow! Please be sure to answer the question. Provide details and share…stackoverflow.com

錯誤的code示意

描述:Controller內有一個Autowired的Handler。呼叫 Autowired Handler.setdata(data)然後 Autowired Handler.handle()

對於每個Client 去使用controller,現在會用到同一個handler。A使用完setdata,B拿去process,結果就是錯誤。

目前想到四種作法

  1. 使用ProxyMode

參考 https://zhuanlan.zhihu.com/p/27971569, Value可以依自己狀況設定,有Session, Request等等context。

這樣設定後,Controller依然會共用。但每個request會使用到不同的handler。

2.使用Spring Context

上面提到Controller聲明Autowired handler後,Handler寫@Scope(“protype),這樣是行不通的。Controller中可以改成

(handler那邊也需要修改成讓Spring知道有這個bean)

3.Controller不共用

直接在Controller外面加上@Scope(“prototype”)

缺點就是每個client都一個controller也一個Handler,memory使用量高。Stateless的物件不需要這樣。

4.Handler 寫成Stateless

應是最好的做法,Controller和Handler都共用,效能最佳。

但改動的code比較多,要改太多業務邏輯的code,測試很耗時,需緊急修正的狀況下就不採用。

Handler內不應該有任何跟request的data有關的class variable,應該要做成handler.process(data),並且中間沒有任何暫存變數。而且handler裡面肥肥的,有email、cac

最後,找出解法不會花很久,使用任一解法,然後搭配一些instance log機制確認每次request都有不同handler(最後是先用第3種,這系統效能暫時沒問題)

但要撈出因為錯誤而造成的資料錯誤夠難,各種撈log、 sql語法的考驗,辛苦負責的同事惹….

CC BY-NC-ND 2.0 版权声明

喜欢我的文章吗?
别忘了给点支持与赞赏,让我知道创作的路上有你陪伴。

加载中…

发布评论