這道題比較偏運維,並非咱們開發的職能範圍。對於3年之內的開發算是超綱的面試題了,這種題目的回答最好說本身沒有權限操做服務器,或者說是組長負責,技術經理負責。強行回答會陷進面試官的坑裏前端
有興趣能夠看這篇文章:https://www.jb51.net/article/133246.htmjava
Springboot: mysql
我的對於springboot的理解是他對spring框架進行了模塊化,將spring和目前使用比較多的技術框架集成配置打包,省了使用者在開發時本身去配置集成。大大簡化了spring應用開發過程當中的搭建和開發。同時更好的解決了各個框架集成時依賴包的版本衝突以及引用的不穩定性。web
核心原理:面試
1> 基於SpringMVC無配置文件(純Java)徹底註解化+內置tomcat-embed-core實現SpringBoot框架,Main函數啓動。redis
2> SpringBoot核心快速整合第三方框架原理:Maven繼承依賴關係。算法
核心思想:開箱即用和約定優於配置spring
Springcloud:sql
springcloud雖然帶有‘cloud’,可是它並非雲計算解決方案,而是在springboot基礎上構建的,用於快速構建分佈式系統的通用模式的工具集數據庫
特色:
1.約定因爲配置
2.適用於各類環境。開發、部署在PC Server或各類雲環境都可
3.隱藏了組件的複雜性,並提供聲明式、無xml的配置方式
4.開箱即用,快速啓動。
5.輕量級的組件。Springcloud 整合的組件大多比較輕量。
6.組件豐富,功能齊全。springcloud爲微服務架構提供了很是完整的支持。例如配置管理、服務發現、斷路器、微服務
7.選型中立、豐富
8.靈活。springcloud的組成部分是解耦的,開發人員可按需靈活挑選技術選型
對比:
SpringBoot專一於快速方便的開發單個個體微服務。
SpringCloud是關注全局的微服務協調整理治理框架,它將SpringBoot開發的一個個單體微服務整合並管理起來,爲各個服務之間提供,配置管理、服務發現、斷路器、路由、微代理、事件總線、全局鎖、精選決策、分佈式會話等集成服務。
SpringBoot能夠離開SpringCloud獨立開發項目,可是SpringCloud離不開SpringBoot,屬於依賴關係。
SpringBoot專一於快速、方便的開發單個微服務個體,SpringCloud關注全局的服務治理框架。
現實中不大的項目使用springcloud只會徒增開發成本,因此在項目前期通常都是使用springboot,更有效率,快捷。
項目構建流程
項目立項
技術選型和項目框架搭建
需求分析
開發階段
UI界面設計
編碼開發
後端開發(整理完需求便可開始接口開發)
前端開發(依賴於UI界面設計和後端接口)
測試(完整的測試由測試==>修改==>迴歸測試組成)
功能測試
性能測試
上線
redis的使用場景不少,回答是不但須要答出在哪裏使用,最好要答出爲何這麼使用
1) 登陸,權限控制:session 數據的緩存
具體步驟:
用戶進行登陸時,提交的登陸表單,放入request;
服務器端校驗用戶名和密碼;
經過後將用戶信息存儲到Redis中,在數據庫中的key爲session_id;
服務器返回的response中的set-cookie字段包含該session_id,客戶端收到後將其值存入瀏覽器中;
客戶端以後的操做的request中都包含session_id,服務器收到後提取出並在Redis中拿到該session,完成業務操做;
使用Redis來實現session的共享和存儲,必需要保證session_id,不會被輕易獲取和破解,並設置合理的失效時間,對敏感操做必須再次校驗用戶。
2) 首頁列表等數據的緩存
這類數據量大,查詢條件比較複雜,性能消耗比較大。重複屢次請求會致使數據庫壓力過大,下降查詢效率,甚至宕機
3) 購物車/收藏等我的數據的緩存
這類數據的特色1是操做次數多,且更新快。redis能夠快速的寫入,移除和修改,很好的匹配這類數據的特性。
特色2是數據結構,其餘緩存的數據結構單一,沒有很好能符合這類數據的結構,redis的數據結構豐富,關鍵是它的hash數據類型很好的符合了這類數據結構的需求
好比,購物車場景,咱們首先須要兩個HASH來存儲,第一個HASH是用戶與購物車之間的關係,第二個HASH是購物車中的商品列表。
先經過userId獲取到shoppingCartId,而後再經過shoppingCartId就能夠獲取到用戶購物車的ProductIds。而後再經過ProductIds就能夠異步讀取用戶購物車的商品信息。
整體來講redis適用於一些實時性要求不高可是請求次數較多的數據。
Redis的特色(必須瞭解):
高併發(High Concurrency)是互聯網分佈式系統架構設計中必須考慮的因素之一,它一般是指,經過設計保證系統可以同時並行處理不少請求。
高併發相關經常使用的一些指標:
響應時間:系統對請求作出響應的時間。例如系統處理一個HTTP請求須要200ms,這個200ms就是系統的響應時間。
吞吐量:單位時間內處理的請求數量。
QPS:每秒響應請求數。在互聯網領域,這個指標和吞吐量區分的沒有這麼明顯。
併發用戶數:同時承載正常使用系統功能的用戶數量。例如一個即時通信系統,同時在線量必定程度上表明瞭系統的併發用戶數。
互聯網分佈式架構設計,提升系統併發能力的方式,方法論上主要有兩種:垂直擴展(Scale Up)與水平擴展(Scale Out)。
垂直擴展:提高單機處理能力。垂直擴展的方式又有兩種:
(1)加強單機硬件性能,例如:增長CPU核數如32核,升級更好的網卡如萬兆,升級更好的硬盤如SSD,擴充硬盤容量如2T,擴充系統內存如128G;
(2)提高單機架構性能,例如:使用Cache來減小IO次數,使用異步來增長單服務吞吐量,使用無鎖數據結構來減小響應時間;
無論是提高單機硬件性能,仍是提高單機架構性能,都有一個致命的不足:單機性能老是有極限的。因此互聯網分佈式架構設計高併發終極解決方案仍是水平擴展。
水平擴展:只要增長服務器數量,就能線性擴充系統性能。水平擴展對系統架構設計是有要求的,如何在架構各層進行可水平擴展的設計,以及互聯網公司架構各層常見的水平擴展實踐
咱們公司最先是一臺服務器2核8Gb,當用戶交互開始卡頓時升級到了4核16Gb,後面再次升級成了4核32GB。當用戶量上來後,開始使用集羣。
這裏就是先作垂直擴展,後作水平擴展
項目初期爲了快速迭代開發、推薦業務和成本看了,通常選用垂直擴展。當項目起來,用戶量上來盈利了,會選用水平擴展來支撐日益複雜的需求
1 定時短信、站內信的發送,涉及上萬用戶,若單線程的話耗時會很長,多線程能大大縮短髮送時間
2 定時操做列表記錄(記錄之間操做必須獨立)
3 導入大批量數據
線上bug通常分爲緊急和非緊急:
對於緊急的bug會當即組織測試和開發進行排查,如果代碼問題實時修復,修復後測試沒問題通知上線,上線後再測試和跟進
對於非緊急的bug會提交到bug管理工具(如禪道)上,統一時間進行排查和修復.修復測試沒問題在指定時間進行上線
因爲開發人員和測試人員有限,對於bug修復必須分狀況和優先級進行修復,畢竟開發和測試有其餘任務.
部署多少臺服務器根據項目實際狀況而定,通常用戶在10萬如下並不會使用到集羣,項目功能簡單也不會使用到分佈式服務.
公司項目初期爲了快速迭代開發通常一個應用便可,這時部署一臺服務器便可.從成本和效率上來講是最好的
項目中期的時候,隨着功能複雜起來,會對功能模塊進行拆分,這時部署會根據模塊服務數和用戶數來部署
目前咱們公司的服務器狀況:
商家數8000+,日活商家數1200+,用戶數90w+,日活2w+:
PC web端2臺服務器,H5 web端3臺服務器,後臺管理1臺服務器,核心服務(處理各類定時任務)部署了一臺服務器,上傳服務器2臺,短信服務器2臺,支付服務器2臺,圖片服務器採用的是阿里雲的OSS,數據庫採用的是阿里雲的RDS-mysql,緩存採用的是阿里雲的redis
服務器承受的壓力有不少因素:服務器的配置,應用的多少和性能都有關係,咱們公司的服務器配置是8和16G,這種配置服務器能承受併發能過2000以上
正常上線必須經過產品和測試,產品須要肯定需求中的功能是否已經實現,測試須要肯定現有功能是否已經沒有功能性問題,只有經過他們的驗收項目或者新需求才能上線.
RabbitMQ能承載多少高併發於服務器性能有關,測試4核8G的服務器上RabbitMQ的併發能破1000
這種題目只要說聽測試同窗說這個樣子,畢竟不是全部人都會進行性能測試的.
MySQL 5.0 版本開始支持存儲過程。
存儲過程(Stored Procedure)是一種在數據庫中存儲複雜程序,以便外部程序調用的一種數據庫對象。
存儲過程是爲了完成特定功能的SQL語句集,經編譯建立並保存在數據庫中,用戶可經過指定存儲過程的名字並給定參數(須要時)來調用執行。
存儲過程思想上很簡單,就是數據庫 SQL 語言層面的代碼封裝與重用。
存儲過程就是具備名字的一段代碼,用來完成一個特定的功能。
建立的存儲過程保存在數據庫的數據字典中。
優勢
存儲過程可封裝,並隱藏複雜的商業邏輯。
存儲過程能夠回傳值,並能夠接受參數。
存儲過程沒法使用 SELECT 指令來運行,由於它是子程序,與查看錶,數據表或用戶定義函數不一樣。
存儲過程能夠用在數據檢驗,強制實行商業邏輯等。
缺點
存儲過程,每每定製化於特定的數據庫上,由於支持的編程語言不一樣。當切換到其餘廠商的數據庫系統時,須要重寫原有的存儲過程。
存儲過程的性能調校與撰寫,受限於各類數據庫系統。
存儲過程總的來講比較雞肋:
1 受限於數據庫和編程語言,致使各個公司使用時有顧慮,以後的遷移和轉型成本會很大
2 編寫要求不像普通sql方便,沒有使用熟悉的編程語言開發效率高
目前我待過的幾個項目中均沒有使用到存儲過程
mysql優化:
目前用到過的:
1 實際開發中禁止使用’select *’
2 當知道結果只有一行數據時使用 LIMIT 1,這樣一來,MySQL數據庫引擎會在找到一條數據後中止搜索,而不是繼續日後查少下一條符合記錄的數據。
3 爲經常使用的搜索字段建索引
4永遠爲每張表設置一個ID作爲其主鍵,並且最好的是一個INT型的(推薦使用UNSIGNED),並設置上自動增長的AUTO_INCREMENT標誌。
5 like中’%‘在前面用不到索引,儘量將’%‘放在後面,進行有模糊查詢
6 mysql 不支持函數轉換,因此字段前面不能加函數,不然這將用不到索引
7 字段類型轉換致使不用索引,如字符串類型的不用引號,數字類型的用引號等,這有可能會用不到索引致使全表掃描
8 當數據量大的時候須要分庫分表
網上推薦的還有:
1 在Join表的時候使用至關類型的例,並將其索引:當兩個表中Join的字段是被建過索引時,MySQL內部會啓動爲你優化Join的SQL語句的機制
2 千萬不要 ORDER BY RAND(),這樣使用只會讓你的數據庫的性能呈指數級的降低
3 使用 ENUM 而不是 VARCHAR
4 or 的查詢儘可能用 union 代替(Innodb)
5 應儘可能避免在 where 子句中對字段進行 null 值判斷,不然將致使引擎放棄使用索引而進行全表掃描
6 應儘可能避免在 where 子句中使用 != 或 <> 操做符,不然將引擎放棄使用索引而進行全表掃描
7應儘可能避免在 where 子句中使用 or 來鏈接條件,若是一個字段有索引,一個字段沒有索引,將致使引擎放棄使用索引而進行全表掃描
8 in 和 not in 也要慎用,不然會致使全表掃描
固然要分析語句是否要優化必定得會使用Explain關鍵字,從 PROCEDURE ANALYSE() 取得建議
千、百萬級數據處理方法:
當數據達到千百萬級別是,查詢的效率是個很大的問題,這時寫完sql語句都應該使用explain來查看下語句的查詢信息,運行下語句看看使用的時間
當效率很低的時候就必須進行優化了:
1 從語句的性能進行優化 -- 以上的優化手段均可以用
2 從表結構進行優化,常見的有
A)對錶字段拆分,好比商品表,商品的名稱,主圖,規格等不變的字段放到基礎信息表中,商品的實時信息放到附屬表中;
B) 對大表進行按時間拆分表,好比用戶表,對指定時間內(60天)沒有登陸過的用戶放到一張用戶凍結表,其餘的放在用戶表,當凍結表中的用戶從新登陸後再移至用戶表中
3 從硬件上進行升級
前面兩種是減小語句的掃描量(查詢量),後面一種是提升掃描(查詢)的性能和效率
1. 選用適合的Oracle優化器
2、重建索引:alter index 索引名 rebuild 【online】
3、強制索引:給該語句加上hint後,強制其使用指定索引
JVM 中最大堆大小有三方面限制:
a.相關操做系統的數據模型(32-bt仍是64-bit)限制;
b.系統的可用虛擬內存限制;
c.系統的可用物理內存限制。
32位系統下,通常限制在1.5G~2G;64爲操做系統對內存無限制。
常見配置彙總
堆設置
-Xms:初始堆大小
-Xmx:最大堆大小
-Xmn:年輕代大小
-Xss:每一個線程的虛擬機棧大小
-XX:NewSize=n:設置年輕代大小
-XX:NewRatio=n:設置年輕代和年老代的比值。如:爲3,表示年輕代與年老代比值爲1:3,年輕代佔整個年輕代年老代和的1/4
-XX:SurvivorRatio=n:年輕代中Eden區與兩個Survivor區的比值。注意Survivor區有兩個。如:3,表示Eden:Survivor=3:2,一個Survivor區佔整個年輕代的1/5
-XX:MaxPermSize=n:設置持久代大小
-XX:MaxTenuringThreshold=n:設置垃圾最大年齡。若是設置爲0的話,則年輕代對象不通過Survivor區,直接進入年老代
收集器設置
-XX:+UseSerialGC:設置串行收集器
-XX:+UseParallelGC:設置並行收集器
-XX:ParallelGCThreads=20:配置並行收集器的線程數,即:同時多少個線程一塊兒進行垃圾回收。此值最好配置與處理器數目相等
-XX:+UseParallelOldGC:配置年老代垃圾收集方式爲並行收集
-XX:+UseParalledlOldGC:設置並行年老代收集器
-XX:+UseConcMarkSweepGC:設置併發收集器
-XX:MaxGCPauseMillis=100:設置每次年輕代垃圾回收的最長時間,若是沒法知足此時間,JVM會自動調全年輕代大小,以知足此值。
-XX:+UseAdaptiveSizePolicy:設置此選項後,並行收集器會自動選擇年輕代區大小和相應的Survivor區比例,以達到目標系統規定的最低相應時間或者收集頻率等,此值建議使用並行收集器時,一直打開。
-XX:+DisableExplicitGC,這個參數做用是禁止代碼中顯示調用GC
垃圾回收統計信息
-XX:+PrintGC
-XX:+PrintGCDetails
-XX:+PrintGCTimeStamps
-Xloggc:filename
-XX:GCTimeRatio=n:設置垃圾回收時間佔程序運行時間的百分比。公式爲1/(1+n)
-XX:+PrintGCApplicationConcurrentTime:打印每次垃圾回收前,程序未中斷的執行時間
-XX:+PrintGCApplicationStoppedTime:打印垃圾回收期間程序暫停的時間。
-XX:PrintHeapAtGC:打印GC先後的詳細堆棧信息
-Xloggc:filename:與上面幾個配合使用,把相關日誌信息記錄到文件以便分析。
併發收集器設置
-XX:+CMSIncrementalMode:設置爲增量模式。適用於單CPU狀況。
-XX:+UseParNewGC:設置年輕代爲並行收集。可與CMS收集同時使用。JDK5.0以上,JVM會根據系統配置自行設置,因此無需再設置此值。
-XX:CMSFullGCsBeforeCompaction:因爲併發收集器不對內存空間進行壓縮、整理,因此運行一段時間之後會產生「碎片」,使得運行效率下降。此值設置運行多少次GC之後對內存空間進行壓縮、整理。
-XX:+UseCMSCompactAtFullCollection:打開對年老代的壓縮。可能會影響性能,可是能夠消除碎片
調優總結
年輕代大小選擇
響應時間優先的應用:儘量設大,直到接近系統的最低響應時間限制(根據實際狀況選擇)。在此種狀況下,年輕代收集發生的頻率也是最小的。同時,減小到達年老代的對象。
吞吐量優先的應用:儘量的設置大,可能到達Gbit的程度。由於對響應時間沒有要求,垃圾收集能夠並行進行,通常適合8CPU以上的應用。
年老代大小選擇
響應時間優先的應用:年老代使用併發收集器,因此其大小須要當心設置,通常要考慮併發會話率和會話持續時間等一些參數。若是堆設置小了,能夠會形成內存碎片、高回收頻率以及應用暫停而使用傳統的標記清除方式;若是堆大了,則須要較長的收集時間。最優化的方案,通常須要參考如下數據得到:
併發垃圾收集信息
持久代併發收集次數
傳統GC信息
花在年輕代和年老代回收上的時間比例
減小年輕代和年老代花費的時間,通常會提升應用的效率
吞吐量優先的應用:通常吞吐量優先的應用都有一個很大的年輕代和一個較小的年老代。緣由是,這樣能夠儘量回收掉大部分短時間對象,減小中期的對象,而年老代盡存放長期存活對象。
較小堆引發的碎片問題
由於年老代的併發收集器使用標記、清除算法,因此不會對堆進行壓縮。當收集器回收時,他會把相鄰的空間進行合併,這樣能夠分配給較大的對象。可是,當堆空間較小時,運行一段時間之後,就會出現「碎片」,若是併發收集器找不到足夠的空間,那麼併發收集器將會中止,而後使用傳統的標記、清除方式進行回收。若是出現「碎片」,可能須要進行以下配置:
-XX:+UseCMSCompactAtFullCollection:使用併發收集器時,開啓對年老代的壓縮。
-XX:CMSFullGCsBeforeCompaction=0:上面配置開啓的狀況下,這裏設置多少次Full GC後,對年老代進行壓縮
經典案例:
java -Xmx3550m -Xms3550m -Xmn2g -Xss128k
-Xmx3550m:設置JVM最大可用內存爲3550M。
-Xms3550m:設置JVM促使內存爲3550m。此值能夠設置與-Xmx相同,以免每次垃圾回收完成後JVM從新分配內存。
-Xmn2g:設置年輕代大小爲2G。整個JVM內存大小=年輕代大小 + 年老代大小 + 持久代大小。持久代通常固定大小爲64m,因此增大年輕代後,將會減少年老代大小。此值對系統性能影響較大,Sun官方推薦配置爲整個堆的3/8。
-Xss128k:設置每一個線程的虛擬機棧大小。JDK5.0之後每一個線程棧大小爲1M,之前每一個線程棧大小爲256K。更具應用的線程所需內存大小進行調整。在相同物理內存下,減少這個值能生成更多的線程。可是操做系統對一個進程內的線程數仍是有限制的,不能無限生成,經驗值在3000~5000左右。
java -Xmx3550m -Xms3550m -Xss128k -XX:NewRatio=4 -XX:SurvivorRatio=4 -XX:MaxPermSize=16m -XX:MaxTenuringThreshold=0
-XX:NewRatio=4:設置年輕代(包括Eden和兩個Survivor區)與年老代的比值(除去持久代)。設置爲4,則年輕代與年老代所佔比值爲1:4,年輕代佔整個堆棧的1/5
-XX:SurvivorRatio=4:設置年輕代中Eden區與Survivor區的大小比值。設置爲4,則兩個Survivor區與一個Eden區的比值爲2:4,一個Survivor區佔整個年輕代的1/6
-XX:MaxPermSize=16m:設置持久代大小爲16m。
-XX:MaxTenuringThreshold=0:設置垃圾最大年齡。若是設置爲0的話,則年輕代對象不通過Survivor區,直接進入年老代。對於年老代比較多的應用,能夠提升效率。若是將此值設置爲一個較大值,則年輕代對象會在Survivor區進行屢次複製,這樣能夠增長對象再年輕代的存活時間,增長在年輕代即被回收的概論。
何謂自旋鎖?它是爲實現保護共享資源而提出一種鎖機制。
其實,自旋鎖與互斥鎖比較相似,它們都是爲了解決對某項資源的互斥使用。不管是互斥鎖,仍是自旋鎖,在任什麼時候刻,最多隻能有一個保持者,也就說,在任什麼時候刻最多隻能有一個執行單元得到鎖。可是二者在調度機制上略有不一樣。對於互斥鎖,若是資源已經被佔用,資源申請者只能進入睡眠狀態。可是自旋鎖不會引發調用者睡眠,若是自旋鎖已經被別的執行單元保持,調用者就一直循環在那裏看是否該自旋鎖的保持者已經釋放了鎖,"自旋"一詞就是所以而得名。
自旋鎖是一種比較低級的保護數據結構或代碼片斷的原始方式,這種鎖可能存在兩個問題:
死鎖。試圖遞歸地得到自旋鎖必然會引發死鎖:遞歸程序的持有實例在第二個實例循環,以試圖得到相同自旋鎖時,不會釋放此自旋鎖。在遞歸程序中使用自旋鎖應遵照下列策略:遞歸程序決不能在持有自旋鎖時調用它本身,也決不能在遞歸調用時試圖得到相同的自旋鎖。此外若是一個進程已經將資源鎖定,那麼,即便其它申請這個資源的進程不停地瘋狂「自旋」,也沒法得到資源,從而進入死循環。
過多佔用cpu資源。若是不加限制,因爲申請者一直在循環等待,所以自旋鎖在鎖定的時候,若是不成功,不會睡眠,會持續的嘗試,單cpu的時候自旋鎖會讓其它process動不了. 所以,通常自旋鎖實現會有一個參數限定最多持續嘗試次數. 超出後, 自旋鎖放棄當前time slice. 等下一次機會。
分佈式鎖是控制分佈式系統之間同步訪問共享資源的一種方式。在分佈式系統中,經常須要協調他們的動做。若是不一樣的系統或是同一個系統的不一樣主機之間共享了一個或一組資源,那麼訪問這些資源的時候,每每須要互斥來防止彼此干擾來保證一致性,在這種狀況下,便須要使用到分佈式鎖。
目前通常會使用redis來實現分佈式鎖,核心代碼:
單點登陸(Single Sign On),簡稱爲 SSO。是在多個應用系統中,用戶只須要登陸一次就能夠訪問全部相互信任的應用系統。
有一個獨立的認證中心,只有認證中心才能接受用戶的用戶名和密碼等信息進行認證,其餘系統不提供登陸入口,只接受認證中心的間接受權。間接受權經過令牌實現,當用戶提供的用戶名和密碼經過認證中心認證後,認證中心會建立受權令牌,在接下來的跳轉過程當中,受權令牌做爲參數發送給各個子系統,子系統拿到令牌即獲得了受權,而後建立局部會話
特色: 一處登陸,到處穿梭
1 請求的耗時
2 請求的個數
3 查詢的個數
4 查詢的耗時
5 代碼運行的耗時
6 代碼的性能
7 代碼的耦合性
8 代碼的可讀性
總之:優化必定得從如下幾個方面考慮
性能:如代碼的耗時,請求響應速度,請求的個數,查詢的個數,查詢的耗時
可維護性:如代碼的耦合性,可讀性,可維護性
常見的方式:
1 圖形驗證碼,這經常使用於短信接口的防禦
2 限定請求次數,常見於秒殺,搶購等功能中
3 流程條件限制,如知足必定條件,註冊用戶,獲取權限等
4 ip地址限定,java中通常寫攔截器對統一ip進行判斷,同一ip指定時間內只能訪問指定次數
5 服務器接口驗證:常見於一些須要付費的接口,這類接口須要內部的token或祕鑰才能請求
髒讀就是指當一個事務正在訪問數據,而且對數據進行了修改,而這種修改尚未提交到數據庫中,這時,另一個事務也訪問這個數據,而後使用了這個數據。由於這個數據是尚未提交的數據,那麼另一個事務讀到的這個數據是髒數據(Dirty Data),依據髒數據所作的操做多是不正確的。
擴展:不可重複讀是指在一個事務內,屢次讀同一數據。在這個事務尚未結束時,另一個事務也訪問該同一數據。那麼,在第一個事務中的兩次讀數據之間,因爲第二個事務的修改,那麼第一個事務兩次讀到的數據多是不同的。這樣就發生了在一個事務內兩次讀到的數據是不同的,所以稱爲是不可重複讀
髒數據在涉及到歷史數據,資金等重要數據幾乎是致命的。
好比:在秒殺系統中,髒數據的產生可能會致使庫存不足,商家就會虧損;在資金系統中,如有髒數據會致使整個系通通帳錯誤。
上線的項目查看bug通常是經過日誌系統。因此項目中必須有詳細日誌記錄,在更新數據先後,重要操做節點都應該有詳細的日誌記錄。
項目中異常的處理無非是兩種方式:
1 try catch 抓取異常
2 throw 拋出異常
方式簡單,可是注意的細節卻很多:
1. 能經過預檢查方式規避的RuntimeException不該該經過catch方式處理,如IndexOutofBoundsException(角標越位異常),NullPointException(空指針異常)
2. 異常不能用來作流程控制或條件控制:異常的效率遠低於比較判斷方式
3. try catch時不能一股腦的吧代碼全包含進去,這隻會增長問題定位的難度,使得代碼沒法根據不一樣的異常作出處理,同時也是不負責任的表現
4. 捕捉異常的目的是處理他,若不處理就應該將異常拋給他的調用者。在展現給用戶以前必須處理掉
5. try catch中如有事務代碼,在catch完後必定注意是否須要rollback事務
6. finally代碼塊中對資源對象、流對象進行關閉時如有異常也要作try catch處理
7. 捕獲異常與拋出的異常類型要徹底匹配,或者捕獲的異常是拋出異常的父類
8. finally代碼塊中不能有return:當有return時就不會執行try catch中的return
目前線上的日誌使用的是log4j,測試時會記錄debug級別的信息,上線時記錄info級別的信息。通常更新數據庫數據先後須要打日誌,敏感操做節點也須要打日誌.這些日誌都會寫到日誌文件中保存起來,通常的日誌文件保存7到15天.
跟蹤線上問題:
1 先肯定問題是在哪一個頁面或者哪一個功能中,而後查看功能對應的日誌文件,看看是否有Error信息或者Exception信息
2 若沒有異常信息說明極可能是代碼邏輯的問題,查看功能日誌點看看日誌狀況,通常是能定位問題點
3 若從日誌中定位不出來只能是覆盤功能代碼
日誌的存儲:
單服務器上日誌通常存在指定的目錄下,可在日誌配置中定義
分佈式/集羣:能夠存在各類服務器上,也可使用日誌服務器統一管理日誌文件
測試的職責是找出項目應用中存在的問題,及時提交給開發修復.在上線前將問題儘量的找出處理掉.如今不少開發以爲測試和他們是對立面,常常和測試針鋒相對,推脫問題.其實測試和開發都是爲了將項目功能儘量的完善,交付給用戶使用,這是他們的共同目的.
和測試的交互應該注重客觀事實,根據測試提交的問題排查是什麼緣由形成的,而後有問題的解決掉,沒問題的反饋給測試從新測試.重點是和測試多溝通,瞭解彼此的想法,不能形成誤解,影響工做.
至少我如今公司開發和測試很和諧,天天測試工做時遇到須要緊急需立刻解決的問題會立刻和開發溝通,是否真正有問題由開發排查後反饋解決.非緊急的問題會提交到禪道上,由開發本身去看和解決本身的問題.測試天天定點看禪道的bug解決率,並提醒開發前去解決bug
問題的反饋: 測試測試出來或者用戶反饋過來
問題的肯定: 開發拿到問題後如今測試服中重現問題,沒法重現的經過查看日誌,覆盤代碼來定位問題
問題的解決: 通常小問題會在主幹上修復並測試上線,大問題會開分支專門修復問題測試沒問題後合併再測試上線
通知: 問題解決上線後通知相關的部門和人員修復結果(作到事事有結果)
java項目部署目前通常部署在tomcat上,springboot出現後直接將項目打成jar包進運行。
部署前須要對環境進行確認:確認項目應用所需的環境是否正確,如系統環境,java版本,數據庫版本,系統的硬件配置
對項目的配置文件進行確認:有些項目的配置文件在測試時須要修改,這時上線的時候須要改回去,若是沒有check,可能會使用測試配置上線,這樣就好致使上線出現問題
對數據庫表字段進行確認:防止由於新增的表或字段未添加或名稱有出入致使上線後報錯
對上線時間的確認和通知
上線時對之前線上的代碼進行備份:確保上線失敗時能夠回退
上線後:必須對所上線的功能進行再次測試,防止有問題
1 未作分佈式鎖時常常會出現併發和重複請求的數據:添加分佈式鎖
2 秒殺搶購被用戶摸到接口,使用工具重複提交搶購:使用攔截器對同一ip同一接口進行請求間隔限制
3 一個用戶多地登陸致使數據異常:限制用戶只能一地登陸
4 數據庫被清空:好在數據庫數據每小時都有作備份,吧備份數據導回線上數據庫,但仍是損失了備份點以後的數據
5 系統達到瓶頸:升級硬件配置,使用集羣
目前我碰到的有兩種實現方式:
1 用戶購買一件商品就生成一條訂單記錄,商品的庫存減一
2 在商品發佈時生成庫存量個token,每次用戶購買商品就獲取一個token,同時生成一條訂單記錄,token使用完後失效
第一種須要注意重複提交和併發問題
第二種適用於商品庫存量不大的應用
微信和支付寶支付接口的對接都有相應的流程,他們都提供了詳細的對接demo.這兩種支付方式以及快錢支付方式的對接都基本一致.
原理:
用戶發起支付請求,應用服務端將支付的金額,支付的緣由以及應用生成的惟一商戶訂單號使用支付接口方提供的加簽方式進行加簽後,生產預支付記錄,同事調用支付接口進行支付.支付提交後有兩種獲取回執相應的方式:同步和異步.同步是用戶點擊支付完成,由服務端像支付接口方服務器發起查詢,對查詢結果進行校驗操做.異步是支付接口方接受到支付打款後向咱們應用指定接口發生支付成功的請求,咱們對請求進行解析校驗操做.不管異步仍是同步都會返回咱們生成的惟一商戶訂單號做爲回執.操做成功後,根據商戶訂單進行更新記錄
安全性: 這幾種支付方式在提交支付是都會有加簽步,當對應支付完成會有他們服務器回調咱們接口.這時咱們對他們的請求參數用指定的密鑰和解籤方式進行解籤,對解簽結果進行校驗.
對購物車裏的商品加鎖,只有拿到鎖的一方纔能進行下單處理,另外一方沒法下單操做.
如今咱們處理的方法:
1加密,通常是對稱加密的方法.
2 信息使用特殊字符替換,如手機號:在服務端將手機號中間幾位使用*替換掉