這是我參與更文挑戰的第30天,活動詳情查看:更文挑戰linux
應用分層
- 默認上層依賴下層,箭頭關係表示直接依賴(好比開放接口能夠依賴於Web層,也能夠直接依賴於Service層)
- 開放接口層: 能夠直接封裝Service方法暴露成RPC接口; 經過Web封裝成接口; 進行網關安全控制,流量控制等
- 終端顯示層: 各個端的模板渲染並執行顯示的層. 當前主要是velocity渲染,JS渲染,JSP渲染,移動端展現等
- Web層: 主要對訪問控制進行轉發,各種基本參數校驗,或者不復用業務的簡單處理等
- Service層: 相對具體的業務邏輯服務層
- Manager層: 通用業務處理層,具備如下特徵:
- 對第三方平臺封裝的層,預處理返回結果及轉化異常信息
- 對Service層通用能力下沉,好比緩存方案,中間件通用處理
- 與DAO層交互,對多個DAO的組合複用
- DAO層: 數據訪問層,與底層MySQL,Oracle,HBase等進行數據交互
- 外部接口或第三方平臺: 包括其它部門的RPC開放接口,基礎平臺,其它企業的HTTP接口
![在這裏插入圖片描述](http://static.javashuo.com/static/loading.gif)
- 分層異常處理規約:
- DAO層:
- 產生的異常類型有不少,沒法用細粒度的異常進行catch
- 使用catch(Exception e) 方式,並throw new DAOException(e)
- 不須要打印日誌,由於日誌在Manager或者Service層必定須要捕獲並打印到日誌文件中去,若是同臺服務器再打印日誌,會浪費性能和存儲
- Service層:
- 出現異常時,必須記錄出錯日誌到磁盤,儘量帶上參數信息,至關於保護案發現場
- Manager層:
- 若是Manager層與Service同機部署,日誌方式與DAO層處理一致
- 若是是單獨部署,採用與Service一致的處理方式
- Web層:
- Web層絕對不容許繼續往上拋異常,由於已經處於頂層
- 若是意識到這個異常將致使頁面沒法正常渲染,應該直接跳轉到友好錯誤頁面,加上用戶容易理解的錯誤提示信息
- 開放接口層:
- 分層領域模型規約:
- DO: Data Object, 此對象與數據庫表結構一一對應,經過DAO層向上傳輸數據源對象
- DTO: Data Transfer Object, 數據傳輸對象 ,Service或者Manager向外傳輸的對象
- BO: Business, 業務對象,由Service層輸出的封裝業務邏輯對象
- AO: Application Object, 應用對象,在Web層與Service層之間抽象的複用對象模型,極爲貼近展現層,複用度不高
- VO: View Object, 顯示層對象,一般是Web向模板渲染引擎層傳輸的對象
- Query: 數據查詢對象,各層接收上層的查詢請求. 注意超過2個參數的查詢封裝,禁止使用Map類來傳輸
二方庫依賴規約
- 定義GAV遵循如下規則:
- GroupID格式: com.[公司/BU].業務線[.子業務線]
- 最多4級
- 子業務線可選
- com.taobao.jstorm, com.alibaba.dubbo.register
- ArtifactID格式: 產品線-模塊名
- 語義不重複不遺漏
- 先到中央倉庫查證一下
- dubbo-client, fastjson-api
- Version: 主版本號.次版本號.修訂號
- 主版本號: 產品方向更改,或者大規模的API不兼容,或者架構不兼容升級
- 次版本號: 保持相對兼容性,增長主要功能特性,影響範圍極小的API不兼容修改
- 修訂號: 保持徹底兼容性,修復BUG,新增次要功能特性
- 注意起始版本號爲: 1.0.0,而不是 0.0.1.
- 正式發佈的類庫必須先去中央倉庫進行查證,使版本號有延續性,正式版本號不容許覆蓋升級
- 線上應用不要依賴SNAPSHOT版本,除了安全包之外
- 不依賴SNAPSHOT版本是保證應用發佈的冪等性
- 同時也能夠加快編譯時的打包構建
- 二方庫的新增或升級,保持除功能點以外的其它jar包不變
- 若是有改變,必須明確評估和驗證,建議進行dependency:resolve先後信息比對
- 若是仲裁結果徹底不一致,那麼經過dependency:tree命令,找出差別點,進行 < excludes > 排除jar包
- 二方庫能夠定義枚舉類型,參數可使用枚舉類型,可是接口返回值不容許使用枚舉類型或者包含枚舉類型的POJO對象
- 依賴於一個二方庫羣時,必須定義一個統一的版本變量,避免版本號不一致
- 依賴springframework-core, -context, -beans. 都是同一個版本號,能夠定義一個變量來保存版本
- ${spring.version}, 定義依賴的時候,引用該版本
- 禁止在子項目的pom依賴中出現相同的GroupId, 相同的ArtifactId, 可是不一樣的Version
- 在本地調試時會使用各子項目指定的版本號,可是合併成一個war, 只能有一個版本號出如今lib目錄中
- 可能出現線下調試是正確的,發佈到線上去出現故障問題
- 因此pom文件中的依賴聲明放在 < dependencies > 語句塊中,全部版本號仲裁放在 < dependencyManagement > 語句塊中
- < dependencyManagement > 裏只是聲明版本,並不實現引入
- 須要子項目顯式的聲明依賴 ,version和scope都讀取自父pom
- < dependencies > 全部聲明在主pom的 < dependencies > 裏的依賴都會自動導入,並默認被全部的子項目繼承
- 二方庫不要有配置項,最低限度不要再增長配置項
- 爲了不應用二方庫的依賴衝突問題,二方庫發佈者應當遵循如下原則:
- 精簡可控原則:
- 移除一切沒必要要的API和依賴,只包含Service API, 必要的領域模型對象, Utils類, 常量, 枚舉等
- 若是依賴其它二方庫,儘可能是provided引入,讓二方庫使用者去依賴具體的版本號
- 無log的具體實現,只依賴日誌框架
- 穩定可追溯原則:
- 每一個版本的變化應該被記錄,二方庫維護信息,源碼位置,都須要可以方便查到
- 除非用戶主動升級版本,不然公共二方庫的行爲不該該發生變化
服務器規約
- 高併發的服務器要調小TCP協議的time_wait時間
- 操做系統默認240秒後,纔會關閉處於time_wait狀態的鏈接
- 在高併發訪問下,服務器端會由於處於time_wait的鏈接數太多,可能沒法創建新的鏈接
- 因此須要在服務器上調小此等待值
- 在linux服務器上經過變動 /etc/sysctl.conf文件去修改該缺省值(s)
net.ipv4.tcp_fin_timeout = 30
複製代碼
- 調大服務器所支持的最大文件句柄數(fd, File Descriptor)
- 主流操做系統的設計是將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維護不一致問題和潛在的安全風險