說實話,之前做完第一次技術周小結之后,由于時間,個人拖延等問題,一直沒有堅持下去寫。上周又想到了這個事情,回想了一下自己當時為什么要做這個周小結,感覺自己當初的出發點就是每周都能接觸,了解,學到很多新的,或者之前知道但不太了解的東西,平時稍微做點記錄,然后每周周末的時候再花一點時間整理一下,就感覺這周比較有成就感。但是,沒堅持下去。
最近在工作中,發現每天都會接觸很多不太了解的東西,之前都是記在筆記本上,但是感覺很龐雜,而且也都只是當時自己的隨筆,不是很系統,而且感覺一直放在筆記本里也不太好。所以,我又想起了自己之前的這個周小結,回顧之前的做法,現在愈發感覺要堅持下去了!
好了,廢話不多說,直接上內容。
目錄:
1.高并發設計的幾點思路(High Concurrence Architecture Design)
2.高性能的優化(High Performance Optimizing)
3.郵件系統的架構和相關協議
4.分布式系統初探
5.Spring 異常處理辦法
6.認識的一些 "新的伙伴"
1.高并發設計的幾點思路
對于高并發設計的切入點,看了很多文章,總結了一些目前主流的一些做法,其中主要包括對服務器端
,數據庫
,緩存
,靜態資源
的設計。
- 服務器端
- 引入負載均衡,比如利用nginx充當負載均衡器,使用阿里云SLB服務
- 對資源進行監控
- 采用分布式的架構,緩解單機訪問壓力,提高并發量
- 數據庫
- 主從分離
- 建立數據庫集群
- 建立分布式的數據庫架構
- 表優化、索引優化
- 緩存
- 利用redis,memcached,mongodb等NOSQL數據庫,同時要做到主從分離,集群部署
參考文章:
大話程序猿眼里的高并發
大話程序猿眼里的高并發架構
2.高性能的優化
我自己對于高性能的簡單理解就是,服務器的響應速度很快。(這里可能理解的過于簡單,如果有什么問題,希望大家能給我指出來,我也要再學習下)。
那么該怎么做呢?
- 代碼優化
- JVM調優
- 數據庫優化,包括sql語句,連接池,采用NOSQL數據庫,讀寫分離,水平和垂直分庫分表
- 利用緩存,比如本地緩存HashMap,Ehcache,緩存服務Redis/Tair/Memcache
- 架構上的調優,比如負載均衡,分布式系統
- 采用異步請求機制
- 度量、監控系統 提供間接幫助來優化系統。
仔細對比一下1和2的總結,可以看到有很多重合的解決辦法,所以說,其實高并發也屬于高性能的一個指標。
參考文章:
美團點評-常見性能優化策略的總結
3.郵件系統的架構和相關協議
郵件系統涉及的參與者:
- 用戶代理
- 郵件服務器
涉及的協議
- POP3
Post Office Protocol 3 它是規定個人計算機如何連接到互聯網上的郵件服務器進行收發郵件的協議。它是因特網電子郵件的第一個離線協議標準,POP3協議允許用戶從服務器上把郵件存儲到本地主機(即自己的計算機)上,同時根據客戶端的操作刪除或保存在郵件服務器上的郵件,而POP3服務器則是遵循POP3協議的接收郵件服務器,用來接收電子郵件的。 - SMTP
Simple Mail Transfer Protocol 是一種提供可靠且有效電子郵件傳輸的協議。SMTP是建立在FTP文件傳輸服務上的一種郵件服務,主要用于傳輸系統之間的郵件信息并提供與來信有關的通知。 - IMAP
Internet Mail Access Protocol(交互式郵件存取協議)IMAP是斯坦福大學在1986年開發的研發的一種郵件獲取協議。它的主要作用是郵件客戶端(例如MS Outlook Express)可以通過這種協議從郵件服務器上獲取郵件的信息,下載郵件等。當前的權威定義是RFC3501。IMAP協議運行在TCP/IP協議之上,使用的端口是143。它與POP3協議的主要區別是用戶可以不用把所有的郵件全部下載,可以通過客戶端直接對服務器上的郵件進行操作。
其特點是:
1.用戶可以維護自己在服務器上的郵件目錄;可以直接抓取郵件的特定部分
2.IMAP它只下載郵件的主題,并不是把所有的郵件內容都下載下來,而是你郵箱當中還保留著郵件的副本,沒有把你原郵箱中的郵件刪除。
4.分布式系統初探
1.分布式系統的特點:
-
可擴展性
企業級應用需求經常隨時間而不斷變化,企業級應用平臺必須要能適應需求的變化,即具有可擴展性。
-
性能制約:內部網絡通訊開銷
所以分布式系統每個節點一般不采用高性能的服務器,而是性能相對一般的普通PC服務器。提升分布式系統的整體性能是要通過橫向擴展(增加更多的服務器),而不是縱向擴展(提升每個節點的服務器性能)。
廉價高效
-
能夠企業應用服務層面的彈性擴展
應用服務層面的彈性擴展是相對計算資源層面的彈性擴展而言的。一般公有云服務(IaaS)廠商都會提供計算資源層面的彈性擴展,比如可以很方便地增加或刪除虛擬主機、提升或降低虛擬主機的性能配置等等。但是企業客戶真正需要的是應用服務層面的彈性擴展,即隨著業務量的漲落,后臺應用服務的實例能動態變化,這是IaaS廠商還做不到的。比如,某移動互聯網短視頻分享應用,在晚間11點到凌晨1點是訪問高峰,同時在線人數高達幾十萬,這時后臺應用服務要擴張到數千個實例才能應付這么高并發的訪問請求;過了高峰時段,后臺應用服務可以收縮到幾十個實例。有了分布式系統,就可以很方便地調度應用服務實例,從幾十個到幾百個甚至上千個,真正實現應用服務的彈性擴展。
2.設計理念:
分布式系統對服務器硬件要求很低
分布式系統強調橫向可擴展性
分布式系統不允許單點失效
分布式系統盡可能減少節點間通訊開銷(Hadoop MapReduce)
-
分布式系統應用服務最好做成無狀態的(Redis/Memcache)
把應用服務設計成無狀態的,讓程序把需要保存的數據都保存在專門的存儲上,這樣應用服務程序可以任意重啟而不丟失數據,方便分布式系統在服務器宕機后恢復應用服務。
參考文章:
分布式系統的特點以及設計理念
5.Spring 異常處理辦法
1.局部異常處理:
- Annotation:@ExceptionHandler
2.全局異常處理:
- web.xml and Application.xml Configuration
- @ControllerAdvice
- SimpleMappingExceptionResolver
- Interface:HandlerExceptionResolver
2.1 Web.xml and Application.xml Configuration
In Web.xml:
<error-page>
<error-code>404</error-code>
<location>/404</location>
</error-page>
<error-page>
<error-code>500</error-code>
<location>/500</location>
</error-page>
<!-- 未捕獲的錯誤,同樣可指定其它異常類,或自定義異常類 -->
<error-page>
<exception-type>java.lang.Exception</exception-type>
<location>/uncaughtException</location>
</error-page>
In Application.xml:
<!-- 錯誤路徑和錯誤頁面,注意指定viewResolver -->
<mvc:view-controller path="/404" view-name="404"/>
<mvc:view-controller path="/500" view-name="500"/>
<mvc:view-controller path="/uncaughtException" view-name="uncaughtException"/>
2.2 @ControllerAdvice
從注解名字上來看,其負責對所有的Controller進行增強,具體增強的邏輯在其方法中實現。那么對于異常處理,其實就是對Controller的一種增強邏輯,具體做法如下:
@ControllerAdvice
public class ControllerAdvice {
@ExceptionHandler(NullPointerException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ResponseBody
public String handleIOException(NullPointerException ex) {
return ClassUtils.getShortName(ex.getClass()) + ex.getMessage();
}
}
首先類ControllerAdvice
有一個類注解@ControllerAdvice
表示該類是對所有的Controller的增強,具體的增強邏輯在其方法handleIOException
中實現,同時在該方法上有一個最開始提到過的注解@ExceptionHandler
,表示該方法要對相應的異常進行捕獲,然后處理。
同時,注解@ResponseStatus
經常和@ExceptionHandler
共同使用,表示要返回的status。
2.3 Class: SimpleMappingExceptionResolver
該類SimpleMappingExceptionResolvers
是Spring MVC提供的一個異常處理實現類。其常見用法如下:
基于傳統xml配置的:
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<!-- 默認錯誤頁面,就是不在exceptionMappings指定范圍內 -->
<property name="defaultErrorView" value="uncaughtException" />
<property name="exceptionMappings">
<props>
<!-- 異常類名,可以是全路徑,錯誤頁面或Controller路徑! -->
<prop key="NullPointerException">NullPointerException</prop>
<prop key="java.io.IOException">IOException</prop>
</props>
</property>
</bean>
基于 Hard Code的:
@Configuration
@EnableWebMvc
@ComponentScan(basePackages = {"com.balbala.mvc.web"})
public class WebMVCConfig extends WebMvcConfigurerAdapter{
@Bean
public SimpleMappingExceptionResolver simpleMappingExceptionResolver()
{
SimpleMappingExceptionResolver b = new SimpleMappingExceptionResolver();
Properties mappings = new Properties();
mappings.put("org.springframework.web.servlet.PageNotFound", "page-404");
mappings.put("org.springframework.dao.DataAccessException", "data-access");
mappings.put("org.springframework.transaction.TransactionException", "transaction-Failure");
b.setExceptionMappings(mappings);
return b;
}
}
從上邊的使用上可以窺探到,該類內部是封裝了一個Map對象,該對象存儲、維護著異常類型與view之間的對應關系,Spring會拋出異常之后,會根據該類的Map對象維護的映射關系來選擇返回的View。
2.4 Interface: HandlerExceptionResolver
用法如下:
public class CustomHandlerExceptionResolver implements HandlerExceptionResolver{
@Override
public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) {
Map<String, Object> model = new HashMap<String, Object>();
model.put("e", e);
//這里可根據不同異常引起類做不同處理方式,本例做不同返回頁面。
String viewName = ClassUtils.getShortName(e.getClass());
return new ModelAndView(viewName, model);
}
}
實現該接口,并將其實現類注冊為一個Bean放入到Spring IOC中,接著出現異常就會走這個實現方法。
參考文章:
Spring-MVC開發之全局異常捕獲全面解讀
Exception Handling in Spring MVC
[Spring Exception Demo](spring-mvc-exception demo:https://spring.io/blog/2013/11/01/exception-handling-in-spring-mvc)
認識的一些 "新的伙伴"
1.Mysql Route: lightweight middleware
2.敏捷項目開發工具:redMine,gitlab,Jira,MantisHub