工程結構(參考阿里巴巴Java開發手冊)
應用分層
推薦
圖中默認上層依賴於下層,箭頭關係表示可直接依賴,如:開放接口層能夠依賴於Web層,也能夠直接依賴於Service層,依此類推:
開放接口層 :可直接封裝Service方法暴露成RPC接口;經過Web封裝成http接口;進行網關安全控制、流量控制等。
終端顯示層 :各個端的模板渲染並執行顯示的層。當前主要是velocity渲染,JS渲染,JSP渲染,移動端展現等。
Web層 :主要是對訪問控制進行轉發,各種基本參數校驗,或者不復用的業務簡單處理等。
Service層 :相對具體的業務邏輯服務層。
Manager層 :通用業務處理層,它有以下特徵:
1) 對第三方平臺封裝的層,預處理返回結果及轉化異常信息。
2) 對Service層通用能力的下沉,如緩存方案、中間件通用處理。
3) 與DAO層交互,對多個DAO的組合複用。
DAO層 :數據訪問層,與底層MySQL、Oracle、Hbase等進行數據交互。
外部接口或第三方平臺 :包括其它部門RPC開放接口,基礎平臺,其它公司的HTTP接口。
參考
分層異常處理規約
在DAO層,產生的異常類型有不少,沒法用細粒度的異常進行catch,使用catch(Exception e)方式,並throw new DAOException(e),不須要打印日誌,由於日誌在Manager/Service層必定須要捕獲並打印到日誌文件中去,若是同臺服務器再打日誌,浪費性能和存儲。
在Service層出現異常時,必須記錄出錯日誌到磁盤,儘量帶上參數信息,至關於保護案發現場。若是Manager層與Service同機部署,日誌方式與DAO層處理一致,若是是單獨部署,則採用與Service一致的處理方式。
Web層毫不應該繼續往上拋異常,由於已經處於頂層,若是意識到這個異常將致使頁面沒法正常渲染,那麼就應該直接跳轉到友好錯誤頁面,加上用戶容易理解的錯誤提示信息。
開放接口層要將異常處理成錯誤碼和錯誤信息方式返回。
經驗:能夠有通用的異常處理filter,轉換各類異常到合適的錯誤信息
分層領域模型規約
DO(Data Object):此對象與數據庫表結構一一對應,經過DAO層向上傳輸數據源對象。
DTO(Data Transfer Object):數據傳輸對象,Service或Manager向外傳輸的對象。
BO(Business Object):業務對象,由Service層輸出的封裝業務邏輯的對象。
AO(Application Object):應用對象,在Web層與Service層之間抽象的複用對象模型,極爲貼近展現層,複用度不高。
VO(View Object):顯示層對象,一般是Web向模板渲染引擎層傳輸的對象。
Query:數據查詢對象,各層接收上層的查詢請求。注意超過2個參數的查詢封裝,禁止使用Map類來傳輸。
二方庫依賴
二方庫,即公司內部的依賴庫,通常指公司內部的其餘項目發佈的jar包
強制
定義GAV聽從如下規則
1)GroupID格式 :com.{公司/BU }.業務線 [.子業務線],最多4級。
說明:{公司/BU} 例如:alibaba/taobao/tmall/aliexpress等BU一級;子業務線可選。
正例:com.taobao.jstorm 或 com.alibaba.dubbo.register
2)ArtifactID格式 :產品線名-模塊名。語義不重複不遺漏,先到中央倉庫去查證一下。
正例:dubbo-client / fastjson-api / jstorm-tool
3)Version :詳細規定參考下方。
二方庫版本號命名方式:主版本號.次版本號.修訂號
1)主版本號:產品方向改變,或者大規模API不兼容,或者架構不兼容升級。
2)次版本號:保持相對兼容性,增長主要功能特性,影響範圍極小的API不兼容修改。
3)修訂號:保持徹底兼容性,修復BUG、新增次要功能特性等。
說明:注意起始版本號必須爲:1.0.0,而不是0.0.1,正式發佈的類庫必須先去中央倉庫進行查證,使版本號有延續性,正式版本號不容許覆蓋升級 。如當前版本:1.3.3,那麼下一個合理的版本號:1.3.4 或 1.4.0 或 2.0.0
經驗:若是版本號容許升級的話,對於使用者來講會奇怪,他依賴的版本號沒變,可是邏輯或者接口變了,致使了意料以外的bug或問題。
線上應用不要依賴SNAPSHOT版本(安全包除外)。
說明:不依賴SNAPSHOT版本是保證應用發佈的冪等性 。另外,也能夠加快編譯時的打包構建。
經驗:保證冪等性,即一次和屢次處理(對於HTTP來講就是請求)某一個資源對於資源自己應該具備一樣的結果。
經驗:SNAPSHOT版本號不變,但代碼可能會更新。
同一個SNAPSHOT版本的依賴能夠屢次發佈(deploy)到倉庫中,也就是說同一個SNAPSHOT版本的依賴能夠在倉庫中存在多份,每一份都是代碼在某一個特定時間的快照,這也是SNAPSHOT的含義。SNAPSHOT不是一個特定的版本,而是一系列的版本的集合,其中HEAD老是指向最新的快照,對外界可見的通常也是最新版,這種給人的假象是新的覆蓋了老的,從而使得使用SNAPSHOT依賴的客戶端老是經過從新構建(有時候須要-U強制更新)就能夠拿到最新的代碼。
所以和RELEASE版本相比,使用者必須明白其中的區別,避免SNAPSHOT版本更新後致使沒必要要的問題。
二方庫的新增或升級,保持除功能點以外的其它jar包仲裁結果不變。若是有改變,必須明確評估和驗證。
說明:在升級時,進行dependency:resolve先後信息比對,若是仲裁結果徹底不一致,那麼經過dependency:tree命令,找出差別點,進行<exclude>排除jar包。
經驗:maven仲裁機制(依賴解決)一般採用短路徑優先原則。
一、在工程的依賴樹上,深度越淺,越被有限選擇。
二、若兩個依賴包處於依賴樹上的同一層,則誰在前選擇誰。
二方庫裏能夠定義枚舉類型,參數可使用枚舉類型,可是接口返回值不容許使用枚舉類型或者包含枚舉類型的POJO對象。
依賴於一個二方庫羣時,必須定義一個統一的版本變量,避免版本號不一致。
說明:依賴springframework-core,-context,-beans,它們都是同一個版本,能夠定義一個變量來保存版本:${spring.version},定義依賴的時候,引用該版本。
禁止在子項目的pom依賴中出現相同的GroupId,相同的ArtifactId,可是不一樣的Version。
說明:在本地調試時會使用各子項目指定的版本號,可是合併成一個war,只能有一個版本號出如今最後的lib目錄中。可能出現線下調試是正確的,發佈到線上卻出故障的問題。
推薦
底層基礎技術框架、核心數據管理平臺、或近硬件端系統謹慎引入第三方實現。
全部pom文件中的依賴聲明放在<dependencies>語句塊中,全部版本仲裁放在<dependencyManagement>語句塊中。
說明:<dependencyManagement>裏只是聲明版本,並不實現引入,所以子項目須要顯式的聲明依賴,version和scope都讀取自父pom。而<dependencies>全部聲明在主pom的<dependencies>裏的依賴都會自動引入,並默認被全部的子項目繼承。
經驗:
dependencies即便在子項目中不寫該依賴項,那麼子項目仍然會從父項目中繼承該依賴項(所有繼承)
dependencyManagement裏只是聲明依賴,並不實現引入,所以子項目須要顯示的聲明須要用的依賴。若是不在子項目中聲明依賴,是不會從父項目中繼承下來的;只有在子項目中寫了該依賴項,而且沒有指定具體版本,纔會從父項目中繼承該項,而且version和scope都讀取自父pom;另外若是子項目中指定了版本號,那麼會使用子項目中指定的jar版本。
二方庫不要有配置項,最低限度不要再增長配置項。
參考
爲避免應用二方庫的依賴衝突問題,二方庫發佈者應當遵循如下原則:
1)精簡可控原則。移除一切沒必要要的API和依賴,只包含 Service API、必要的領域模型對象、Utils類、常量、枚舉等。若是依賴其它二方庫,儘可能是provided引入,讓二方庫使用者去依賴具體版本號;無log具體實現,只依賴日誌框架。
2)穩定可追溯原則。每一個版本的變化應該被記錄,二方庫由誰維護,源碼在哪裏,都須要能方便查到。除非用戶主動升級版本,不然公共二方庫的行爲不該該發生變化。
服務器
推薦
高併發服務器建議調小TCP協議的time_wait超時時間。
說明:操做系統默認240秒後,纔會關閉處於time_wait狀態的鏈接,在高併發訪問下,服務器端會由於處於time_wait的鏈接數太多,可能沒法創建新的鏈接,因此須要在服務器上調小此等待值。
正例:在linux服務器上請經過變動/etc/sysctl.conf文件去修改該缺省值(秒):net.ipv4.tcp_fin_timeout = 30
調大服務器所支持的最大文件句柄數(File Descriptor,簡寫爲fd)。
說明:主流操做系統的設計是將TCP/UDP鏈接採用與文件同樣的方式去管理,即一個鏈接對應於一個fd。主流的linux服務器默認所支持最大fd數量爲1024,當併發鏈接數很大時很容易由於fd不足而出現「open too many files」錯誤,致使新的鏈接沒法創建。建議將linux服務器所支持的最大句柄數調高數倍(與服務器的內存數量相關)。
給JVM環境參數設置-XX:+HeapDumpOnOutOfMemoryError參數,讓JVM碰到OOM場景時輸出dump信息。
說明:OOM的發生是有機率的,甚至相隔數月纔出現一例,出錯時的堆內信息對解決問題很是有幫助。
在線上生產環境,JVM的Xms和Xmx設置同樣大小的內存容量,避免在GC 後調整堆大小帶來的壓力。
參考
服務器內部重定向使用forward;外部重定向地址使用URL拼裝工具類來生成,不然會帶來URL維護不一致的問題和潛在的安全風險。
歡迎關注本站公眾號,獲取更多信息