天天看點

網際網路公司開發常見面試問題

本地(帶圖形環境):jvisualvm 連接配接遠端jvm

線上(無圖形環境):看總記憶體用top,看詳細資訊用jmap dump出來分析

get一般用于擷取/查詢 資源資訊,而post一般用于更新 資源資訊。

查詢字元串(名稱/值對)是在 get 請求的 url 中發送的:

1

<code>/test/demo_form.asp?name1=value1&amp;name2=value2</code>

post 方法

請注意,查詢字元串(名稱/值對)是在 post 請求的 http 消息主體中發送的:

2

3

<code>post /test/demo_form.asp http/</code><code>1.1</code>

<code>host: w3schools.com</code>

<code>name1=value1&amp;name2=value2</code>

  

omm主要三類: 

permgen oom , 由于加載的類太多,或者反射的類太多

heap oom, 因為一些無用對象沒有及時釋放造成的,檢查代碼加上 heap dump 去分析吧

stack overflow ,由于調用層數,或者遞歸深度太大造成的

常見的錯誤提示:

4

5

<code>tomcat:java.lang.outofmemoryerror: permgen space</code>

<code>tomcat:java.lang.outofmemoryerror: java heap space</code>

<code>weblogic:root cause of servletexception java.lang.outofmemoryerror</code>

<code>resin:java.lang.outofmemoryerror</code>

<code>java:java.lang.</code>

導緻outofmemoryerror異常的常見原因有以下幾種:

記憶體中加載的資料量過于龐大,如一次從資料庫取出過多資料;

集合類中有對對象的引用,使用完後未清空,使得jvm不能回收;

代碼中存在死循環或循環産生過多重複的對象實體;

使用的第三方軟體中的bug;

啟動參數記憶體值設定的過小;

解決方法:

1.應用伺服器提示錯誤的解決:

把啟動參數記憶體值設定足夠大。

2.java代碼導緻錯誤的解決:

重點排查以下幾點:

1)檢查代碼中是否有死循環或遞歸調用。

2)檢查是否有大循環重複産生新對象實體。

3)檢查對資料庫查詢中,是否有一次獲得全部資料的查詢。一般來說,如果一次取十萬條記錄到記憶體,就可能引起記憶體溢出。這個問題比較隐蔽,在上線前,資料庫中資料較少,不容易出問題,上線後,資料庫中資料多了,一次查詢就有可能引起記憶體溢出。是以對于資料庫查詢盡量采用分頁的方式查詢。

4 )檢查list、map等集合對象是否有使用完後,未清除的問題。list、map等集合對象會始終存有對對象的引用,使得這些對象不能被gc回收。

6

7

8

9

10

11

12

<code>tomcat中java.lang.outofmemoryerror: java heap space異常處理</code>

<code>一、heap size</code>

<code>jvm堆的設定是指java程式運作過程中jvm可以調配使用的記憶體空間的設定.jvm在啟動的時候會自動設定heap size的值,</code>

<code>其初始空間(即-xms)是實體記憶體的</code><code>1</code><code>/</code><code>64</code><code>,最大空間(-xmx)是實體記憶體的</code><code>1</code><code>/</code><code>4</code><code>。可以利用jvm提供的-xmn -xms -xmx等選項可</code>

<code>進行設定。heap size 的大小是young generation 和tenured generaion 之和。</code>

<code>提示:在jvm中如果</code><code>98</code><code>%的時間是用于gc且可用的heap size 不足</code><code>2</code><code>%的時候将抛出此異常資訊。</code>

<code>提示:heap size 最大不要超過可用實體記憶體的</code><code>80</code><code>%,一般的要将-xms和-xmx選項設定為相同,而-xmn為</code><code>1</code><code>/</code><code>4</code><code>的-xmx值。</code>

<code>二、解決方法:手動設定heap size</code>

<code>修改tomcat_home/bin/catalina.sh</code>

<code>在“echo </code><code>"using catalina_base: $catalina_base"</code><code>”上面加入以下行:</code>

<code>java_opts=</code><code>"-server -xms800m -xmx800m -xx:maxnewsize=256m"</code>

13

<code>tomcat中java.lang.outofmemoryerror: permgen space異常處理</code>

<code>一、permgen space</code>

<code>permgen space的全稱是permanent generation space,是指記憶體的永久儲存區域,</code>

<code>這塊記憶體主要是被jvm存放class和meta資訊的,class在被loader時就會被放到permgen space中,</code>

<code>它和存放類執行個體(instance)的heap區域不同,gc(garbage collection)不會在主程式運作期對</code>

<code>permgen space進行清理,是以如果你的應用中有很多class的話,就很可能出現permgen space錯誤,</code>

<code>這種錯誤常見在web伺服器對jsp進行pre compile的時候。如果你的web app下都用了大量的第三方jar, 其大小</code>

<code>超過了jvm預設的大小(4m)那麼就會産生此錯誤資訊了。</code>

<code>解決方法: 手動設定maxpermsize大小</code>

<code>java_opts="-server -xx:permsize=64m -xx:maxpermsize=128m</code>

<code>建議:将相同的第三方jar檔案移置到tomcat/shared/lib目錄下,這樣可以達到減少jar 文檔重複占用記憶體的目的。</code>

 

14

15

<code>weblogic中java.lang.outofmemoryerror異常處理</code>

<code>錯誤提示:</code>

<code>"root cause of ervletexception java.lang.outofmemoryerror"</code>

<code>解決辦法:</code>

<code>調整bea/weblogic/common中commenv中參數</code>

<code>   :sun</code>

<code>  </code><code>if</code> <code>"%production_mode%"</code> <code>== </code><code>"true"</code> <code>goto</code> <code>sun_prod_mode</code>

<code>  set java_vm=-client</code>

<code>  set mem_args=-xms256m -xmx512m -xx:maxpermsize=256m</code>

<code>  set java_options=%java_options% -xverify:none</code>

<code>  </code><code>goto</code> <code>continue</code>

<code>  :sun_prod_mode</code>

<code>  set java_vm=-server</code>

sql 的連接配接(join)語句将資料庫中的兩個或多個表組合起來.

由"連接配接"生成的集合, 可以被儲存為表, 或者當成表來使用. join 語句的含義是把兩張表的屬性通過它們的值組合在一起. 基于 ansi 标準的 sql 列出了五種 join 方式: 内連接配接(inner), 全外連接配接(full outer), 左外連接配接(left outer), 右外連接配接(right outer)和交叉連接配接(cross). 在特定的情況下, 一張表(基本表, 視圖, 或連接配接表)可以和自身進行連接配接, 成為自連接配接(self-join).

内連接配接(inner join),外連接配接(outer join),

内連接配接又包括等值連接配接,非等值連接配接,自連接配接;而外連接配接又分為左連接配接和右連接配接。其中預設的是内連接配接的等值連接配接。

外連接配接的三種情況大概就是取a、b的并集,或者a或者b的完全集。交叉連接配接是把表a和表b的資料進行一個n*m的組合,即笛卡爾積。交叉連接配接産生的資料集較大,影響性能,尤其是表很大的時候。

消息 1字頭:

一類型的狀态碼,代表請求已被接受,需要繼續處理。這類響應是臨時響應,隻包含狀态行和某些可選的響應頭資訊,并以空行結束。由于 http/1.0 協定中沒有定義任何 1xx 狀态碼,是以除非在某些試驗條件下,伺服器禁止向此類用戶端發送 1xx 響應。

成功 2字頭:

這一類型的狀态碼,代表請求已成功被伺服器接收、了解、并接受。

重定向 3字頭:

這類狀态碼代表需要用戶端采取進一步的操作才能完成請求。通常,這些狀态碼用來重定向,後續的請求位址(重定向目标)在本次響應的 location 域中指明。

當且僅當後續的請求所使用的方法是 get 或者 head 時,使用者浏覽器才可以在沒有使用者介入的情況下自動送出所需要的後續請求。用戶端應當自動監測無限循環重定向(例如:a-&gt;a,或者a-&gt;b-&gt;c-&gt;a),因為這會導緻伺服器和用戶端大量不必要的資源消耗。按照 http/1.0 版規範的建議,浏覽器不應自動通路超過5次的重定向。

請求錯誤 4字頭:

這類的狀态碼代表了用戶端看起來可能發生了錯誤,妨礙了伺服器的處理。除非響應的是一個 head 請求,否則伺服器就應該傳回一個解釋目前錯誤狀況的實體,以及這是臨時的還是永久性的狀況。這些狀态碼适用于任何請求方法。浏覽器應當向使用者顯示任何包含在此類錯誤響應中的實體内容。

如果錯誤發生時用戶端正在傳送資料,那麼使用tcp的伺服器實作應當仔細確定在關閉用戶端與伺服器之間的連接配接之前,用戶端已經收到了包含錯誤資訊的資料包。如果用戶端在收到錯誤資訊後繼續向伺服器發送資料,伺服器的tcp棧将向用戶端發送一個重置資料包,以清除該用戶端所有還未識别的輸入緩沖,以免這些資料被伺服器上的應用程式讀取并幹擾後者。

伺服器錯誤 5字頭:

這類狀态碼代表了伺服器在處理請求的過程中有錯誤或者異常狀态發生,也有可能是伺服器意識到以目前的軟硬體資源無法完成對請求的處理。除非這是一個head 請求,否則伺服器應當包含一個解釋目前錯誤狀态以及這個狀況是臨時的還是永久的解釋資訊實體。浏覽器應當向使用者展示任何在目前響應中被包含的實體。

線程池的關鍵點是:

1、盡量減少線程切換和管理的開支; 

2、最大化利用cpu。

對于1,要求線程數盡量少,這樣可以減少線程切換和管理的開支;

對于2,要求盡量多的線程,以保證cpu資源最大化的利用。

是以對于任務耗時短的情況,要求線程盡量少,如果線程太多,有可能出現線程切換和管理的時間,大于任務執行的時間,那效率就低了;

對于耗時長的任務,要分是cpu任務,還是io等類型的任務。如果是cpu類型的任務,線程數不宜太多;但是如果是io類型的任務,線程多一些更好,可以更充分利用cpu。

是以:

高并發,低耗時的情況:建議少線程,隻要滿足并發即可;例如并發100,線程池可能設定為10就可以

低并發,高耗時的情況:建議多線程,保證有空閑線程,接受新的任務;例如并發10,線程池可能就要設定為20;

高并發高耗時:

1要分析任務類型,

2增加排隊,

3加大線程數

java nio :同步非阻塞,jvm實作模式為一個請求一個線程,即用戶端發送的連接配接請求都會注冊到多路複用器上,多路複用器輪詢到連接配接有i/o請求時才啟動一個線程進行處理。

java aio :異步非阻塞,用戶端的i/o請求都是由os先完成了再通知伺服器應用去啟動線程進行處理,

nio方式适用于連接配接數目多且連接配接比較短(輕操作)的架構,比如聊天伺服器,并發局限于應用中,jdk1.4開始支援。

aio方式使用于連接配接數目多且連接配接比較長(重操作)的架構,比如http伺服器等,充分調用os參與并發操作,jdk7開始支援

簡而言之在 linux 下 nio 是 jvm内部進行事件的輪訓後捕獲(可以通過參數打開 nio epoll 來提高新能) ,而 aio 則是使用 epoll 由作業系統來觸發事件.

如果把核心比作快遞,nio就是你要自己時不時到官網查下快遞是否已經到了你所在城市,然後自己去取快遞;aio就是快遞員送貨上門了。

前台頁面:靜态化頁面資源

分層設計:使用多層緩存

資料庫優化,讀寫分離:配置多台讀庫

使用nosql和搜尋引擎:為特定的檢索服務配置專門的索引或者搜尋引擎,減輕資料庫壓力

伺服器叢集改善并發處理能力:配置多台伺服器叢集,通過負載均衡,将來自使用者浏覽器的通路請求分發到應用伺服器叢集中的任何一台伺服器上。

反向代理和cdn加速網站響應:可以讓使用者從距離自己最近的伺服器獲得請求的資源,盡早傳回資料給使用者,一方面加快使用者通路速度,另一方面也減輕後端伺服器的負載壓力。

業務拆分:使用消息隊列分發請求

使用 max() 函數:

<code>select</code> <code>* </code><code>from</code> <code>table</code> <code>where</code> <code>table_row </code><code>in</code> <code>(</code><code>select</code> <code>max</code><code>(table_row) </code><code>from</code> <code>table</code><code>)</code>

如果支援行号,可以使用order by,mysql不支援:

<code>select</code> <code>* </code><code>from</code> <code>table</code> <code>where</code> <code>rownum=1</code>

<code>order</code> <code>by</code> <code>table_row </code><code>desc</code><code>;</code>

使用not exists:

<code>select</code> <code>* </code><code>from</code> <code>table</code> <code>t1 </code><code>where</code> <code>not</code> <code>exists</code>

<code>(</code><code>select</code> <code>1 </code><code>from</code> <code>table</code> <code>where</code> <code>table_row &gt; t1.table_row)</code>

連接配接mysql庫,主鍵添加索引情況下查詢,max()函數方法耗時1.513s,

not exists 方法耗時98.655s,資料量877550。

序列化是幹什麼的?

簡單說就是為了儲存在記憶體中的各種對象的狀态(也就是執行個體變量,不是方法),并且可以把儲存的對象狀态再讀出來。雖然你可以用你自己的各種各樣的方法來儲存object states,但是java給你提供一種應該比你自己好的儲存對象狀态的機制,那就是序列化。

什麼情況下需要序列化

a)當你想把的記憶體中的對象狀态儲存到一個檔案中或者資料庫中時候;

b)當你想用套接字在網絡上傳送對象的時候;

c)當你想通過rmi傳輸對象的時候;

ioc(di):其實這個spring架構核心的概念沒有這麼複雜,更不像有些書上描述的那樣晦澀。java程式員都知道:java程式中的每個業務邏輯至少需要兩個或以上的對象來協作完成,通常,每個對象在使用他的合作對象時,自己均要使用像new object() 這樣的文法來完成合作對象的申請工作。你會發現:對象間的耦合度高了。而ioc的思想是:spring容器來實作這些互相依賴對象的建立、協調工作。對象隻需要關系業務邏輯本身就可以了。從這方面來說,對象如何得到他的協作對象的責任被反轉了(ioc、di)。

這是我對spring的ioc的體會。di其實就是ioc的另外一種說法。di是由martin fowler在2004年初的一篇論文中首次提出的。他總結:控制的什麼被反轉了?就是:獲得依賴對象的方式反轉了。

如果對這一核心概念還不了解:這裡引用一個叫bromon的blog上找到的淺顯易懂的答案:

ioc與di

  首先想說說ioc(inversion of control,控制倒轉)。這是spring的核心,貫穿始終。所謂ioc,對于spring架構來說,就是由spring來負責控制對象的生命周期和對象間的關系。這是什麼意思呢,舉個簡單的例子,我們是如何找女朋友的?常見的情況是,我們到處去看哪裡有長得漂亮身材又好的mm,然後打聽她們的興趣愛好、qq号、電話号、ip号、iq号………,想辦法認識她們,投其所好送其所要,然後嘿嘿……這個過程是複雜深奧的,我們必須自己設計和面對每個環節。傳統的程式開發也是如此,在一個對象中,如果要使用另外的對象,就必須得到它(自己new一個,或者從jndi中查詢一個),使用完之後還要将對象銷毀(比如connection等),對象始終會和其他的接口或類藕合起來。

  那麼ioc是如何做的呢?有點像通過婚介找女朋友,在我和女朋友之間引入了一個第三者:婚姻介紹所。婚介管理了很多男男女女的資料,我可以向婚介提出一個清單,告訴它我想找個什麼樣的女朋友,比如長得像李嘉欣,身材像林熙雷,唱歌像周傑倫,速度像卡洛斯,技術像齊達内之類的,然後婚介就會按照我們的要求,提供一個mm,我們隻需要去和她談戀愛、結婚就行了。簡單明了,如果婚介給我們的人選不符合要求,我們就會抛出異常。整個過程不再由我自己控制,而是有婚介這樣一個類似容器的機構來控制。spring所倡導的開發方式就是如此,所有的類都會在spring容器中登記,告訴spring你是個什麼東西,你需要什麼東西,然後spring會在系統運作到适當的時候,把你要的東西主動給你,同時也把你交給其他需要你的東西。所有的類的建立、銷毀都由 spring來控制,也就是說控制對象生存周期的不再是引用它的對象,而是spring。對于某個具體的對象而言,以前是它控制其他對象,現在是所有對象都被spring控制,是以這叫控制反轉。如果你還不明白的話,我決定放棄。

ioc的一個重點是在系統運作中,動态的向某個對象提供它所需要的其他對象。這一點是通過di(dependency injection,依賴注入)來實作的。比如對象a需要操作資料庫,以前我們總是要在a中自己編寫代碼來獲得一個connection對象,有了 spring我們就隻需要告訴spring,a中需要一個connection,至于這個connection怎麼構造,何時構造,a不需要知道。在系統運作時,spring會在适當的時候制造一個connection,然後像打針一樣,注射到a當中,這樣就完成了對各個對象之間關系的控制。a需要依賴 connection才能正常運作,而這個connection是由spring注入到a中的,依賴注入的名字就這麼來的。那麼di是如何實作的呢? java 1.3之後一個重要特征是反射(reflection),它允許程式在運作的時候動态的生成對象、執行對象的方法、改變對象的屬性,spring就是通過反射來實作注入的。

在應用開發中,以應用開發人員的身份設計元件時,往往需要引用和調用其他元件的服務,這種依賴關系如果固化在元件設計中,就會造成依賴關系的僵化和維護難度的增加,這個時候,如果使用ioc容器,把資源擷取的方向反轉,讓ioc容器主動管理這些依賴關系,将這些依賴關系注入到元件中,那麼會讓這些依賴關系的适配和管理更加靈活。

面向切面程式設計,aop适合于那些具有橫切邏輯的應用:如性能監測,通路控制,事務管理、緩存、對象池管理以及日志記錄。aop将這些分散在各個業務邏輯中的代碼通過橫向切割的方式抽取到一個獨立的子產品中。aop 實作的關鍵就在于 aop 架構自動建立的 aop 代理,aop 代理則可分為靜态代理和動态代理兩大類,其中靜态代理是指使用 aop 架構提供的指令進行編譯,進而在編譯階段就可生成 aop 代理類,是以也稱為編譯時增強;而動态代理則在運作時借助于 jdk 動态代理、cglib 等在記憶體中“臨時”生成 aop 動态代理類,是以也被稱為運作時增強。 

代理對象的方法 = 增強處理 + 被代理對象的方法 

spring aop 則采用運作時生成 aop 代理類,是以無需使用特定編譯器進行處理。由于 spring aop 需要在每次運作時生成 aop 代理,是以性能略差一些。

aop使用場景 

aop用來封裝橫切關注點,具體可以在下面的場景中使用 

authentication 權限 

caching 緩存 

context passing 内容傳遞 

error handling 錯誤處理 

lazy loading 懶加載 

debugging  調試 

logging, tracing, profiling and monitoring 記錄跟蹤 優化 校準 

performance optimization 性能優化 

persistence  持久化 

resource pooling 資源池 

synchronization 同步 

transactions 事務

可以。

jsonp(json with padding)是一個非官方的協定,它允許在伺服器端內建script tags傳回至用戶端,通過javascript callback的形式實作跨域通路(這僅僅是jsonp簡單的實作形式)。

由于同源政策的限制,xmlhttprequest隻允許請求目前源(域名、協定、端口)的資源,為了實作跨域請求,可以通過script标簽實作跨域請求,然後在服務端輸出json資料并執行回調函數,進而解決了跨域的資料請求。

内部跳轉的時候實際上是通過伺服器端将請求轉發到另外的頁面或者servlet中,這個時候跳轉到的目标頁面或者servlet可以擷取到請求對象,也可以擷取到請求中的屬性和參數。而外部跳轉的時候實際上是第一次請求後,伺服器端向用戶端發送了一個指令,讓用戶端再次請求了一次伺服器端,這個時候伺服器第二次拿到的request對象已經不是第一次請求的request對象了,是以無法擷取到第一次請求裡的參數和屬性。 

内部跳轉的url位址欄不會發生變化,外部跳轉url則會發生變化。 

内部跳轉無法跳轉到工程以外的jsp或者servlet,外部跳轉則可以。 

内部跳轉實作的方法:

request.getrequestdispatcher("xxx.jsp或者servlet").forward(request, response), 

而外部跳轉實作的方法:

response.sendredirect("xxx.jsp或者servlet")。

為什麼在連接配接資料庫時要使用連接配接池

連接配接池技術盡可能多地重用了消耗記憶體地資源,大大節省了記憶體,提高了伺服器地服務效率,能夠支援更多的客戶服務。通過使用連接配接池,将大大提高程式運作效率,同時,我們可以通過其自身的管理機制來監視資料庫連接配接的數量、使用情況等。

資料庫連接配接池的基本原理

資料庫連接配接池的基本思想就是為資料庫連接配接 建立一個“緩沖池”。預先在緩沖池中放入一定數量的連接配接,當需要建立資料庫連接配接時,隻需從“緩沖池”中取出一個,使用完畢之後再放回去。我們可以通過設定 連接配接池最大連接配接數來防止系統無盡的與資料庫連接配接。更為重要的是我們可以通過連接配接池的管理機制監視資料庫的連接配接的數量和使用情況,為系統開發和測試及性能調 整提供依據。

資料庫連接配接池的工作原理

連接配接池的工作原理主要由三部分組成,分别為連接配接池的建立、連接配接池中連接配接的使用管理、連接配接池的關閉。

第一、連接配接池的建立。一般在系統初始化時,連接配接池會根據系統配置建立,并在池中建立了幾個連接配接對象,以便使用時能從連接配接池中擷取。連接配接池中的連接配接不能随意建立和關閉,這樣避免了連接配接随意建立和關閉造成的系統開銷。java中提供了很多容器類可以友善的建構連接配接池,例如vector、stack等。

第二、連接配接池的管理。連接配接池管理政策是連接配接池機制的核心,連接配接池内連接配接的配置設定和釋放對系統的性能有很大的影響。其管理政策是:

當客戶請求資料庫連接配接時,首先檢視連接配接池中是否有空閑連接配接,如果存在空閑連接配接,則将連接配接配置設定給客戶使用;如果沒有空閑連接配接,則檢視目前所開的連接配接數是否已經達到最大連接配接數,如果沒達到就重新建立一個連接配接給請求的客戶;如果達到就按設定的最大等待時間進行等待,如果超出最大等待時間,則抛出異常給客戶。

當客戶釋放資料庫連接配接時,先判斷該連接配接的引用次數是否超過了規定值,如果超過就從連接配接池中删除該連接配接,否則保留為其他客戶服務。

該政策保證了資料庫連接配接的有效複用,避免頻繁的建立、釋放連接配接所帶來的系統資源開銷。

第三、連接配接池的關閉。當應用程式退出時,關閉連接配接池中所有的連接配接,釋放連接配接池相關的資源,該過程正好與建立相反。

連接配接池關鍵問題分析

  1、并發問題

  為了使連接配接管理服務具有最大的通用性,必須考慮多線程環境,即并發問題。這個問題相對比較好解決,因為java語言自身提供了對并發管理的支 持,使用synchronized關鍵字即可確定線程是同步的。使用方法為直接在類方法前面加上synchronized關鍵字,如:

  public synchronized connection getconnection()

  2、多資料庫伺服器和多使用者

  對于大型的企業級應用,常常需要同時連接配接不同的資料庫(如連接配接oracle和sybase)。如何連接配接不同的資料庫呢?我們采用的政策是:設計 一個符合單例模式的連接配接池管理類,在連接配接池管理類的唯一執行個體被建立時讀取一個資源檔案,其中資源檔案中存放着多個資料庫的url位址()?使用者名()?密 碼()等資訊。如 tx.url=172.21.15.123:5000/tx_it,tx.user=yang,tx.password=yang321。根據資源檔案提 供的資訊,建立多個連接配接池類的執行個體,每一個執行個體都是一個特定資料庫的連接配接池。連接配接池管理類執行個體為每個連接配接池執行個體取一個名字,通過不同的名字來管理不同的連 接池。

  對于同一個資料庫有多個使用者使用不同的名稱和密碼通路的情況,也可以通過資源檔案處理,即在資源檔案中設定多個具有相同url位址,但具有不同使用者名和密碼的資料庫連接配接資訊。

  3、事務處理

  我們知道,事務具有原子性,此時要求對資料庫的操作符合“all-all-nothing”原則,即對于一組sql語句要麼全做,要麼全不做。

  在java語言中,connection類本身提供了對事務的支援,可以通過設定connection的autocommit屬性為 false,然後顯式的調用commit或rollback方法來實作。但要高效的進行connection複用,就必須提供相應的事務支援機制。可采用 每一個事務獨占一個連接配接來實作,這種方法可以大大降低事務管理的複雜性。

  4、連接配接池的配置設定與釋放

  連接配接池的配置設定與釋放,對系統的性能有很大的影響。合理的配置設定與釋放,可以提高連接配接的複用度,進而降低建立新連接配接的開銷,同時還可以加快使用者的通路速度。

  對于連接配接的管理可使用空閑池。即把已經建立但尚未配置設定出去的連接配接按建立時間存放到一個空閑池中。每當使用者請求一個連接配接時,系統首先檢查空閑池内 有沒有空閑連接配接。如果有就把建立時間最長(通過容器的順序存放實作)的那個連接配接配置設定給他(實際是先做連接配接是否有效的判斷,如果可用就配置設定給使用者,如不可用 就把這個連接配接從空閑池删掉,重新檢測空閑池是否還有連接配接);如果沒有則檢查目前所開連接配接池是否達到連接配接池所允許的最大連接配接數(maxconn),如果沒有 達到,就建立一個連接配接,如果已經達到,就等待一定的時間(timeout)。如果在等待的時間内有連接配接被釋放出來就可以把這個連接配接配置設定給等待的使用者,如果 等待時間超過預定時間timeout,則傳回空值(null)。系統對已經配置設定出去正在使用的連接配接隻做計數,當使用完後再返還給空閑池。對于空閑連接配接的狀 态,可開辟專門的線程定時檢測,這樣會花費一定的系統開銷,但可以保證較快的響應速度。也可采取不開辟專門線程,隻是在配置設定前檢測的方法。

  5、連接配接池的配置與維護

  連接配接池中到底應該放置多少連接配接,才能使系統的性能最佳?系統可采取設定最小連接配接數(minconn)和最大連接配接數(maxconn)來控制連接配接 池中的連接配接。最小連接配接數是系統啟動時連接配接池所建立的連接配接數。如果建立過多,則系統啟動就慢,但建立後系統的響應速度會很快;如果建立過少,則系統啟動的很 快,響應起來卻慢。這樣,可以在開發時,設定較小的最小連接配接數,開發起來會快,而在系統實際使用時設定較大的,因為這樣對通路客戶來說速度會快些。最大連 接數是連接配接池中允許連接配接的最大數目,具體設定多少,要看系統的通路量,可通過反複測試,找到最佳點。

  如何確定連接配接池中的最小連接配接數呢?有動态和靜态兩種政策。動态即每隔一定時間就對連接配接池進行檢測,如果發現連接配接數量小于最小連接配接數,則補充相應數量的新連接配接,以保證連接配接池的正常運轉。靜态是發現空閑連接配接不夠時再去檢查。

tomcat:應用也算非常廣泛的web伺服器,支援部分j2ee,免費,出自apache基金組織 

jboss:開源的應用伺服器,比較受人喜愛,免費(文檔要收費) 

weblogic:應該說算是業界第一的app server,全部支援j2ee1.4, 對于開發者,有免費使用一年的許可證。

apache:全球應用最廣泛的http伺服器,免費,出自apache基金組織 

tomcat不支援ejb,隻能做jsp和servlet的container,隻能做web伺服器。

jboss是實作了ejb容器,同時内嵌tomcat,處理靜态頁面jboss的速度要比較快,可以作應用伺服器。

jboss和weblogic、websphere都含有jsp和servlet容器,也就可以做web容器。

jboss和weblogic、websphere也都包含ejb容器,是完整的j2ee應用伺服器 。

https是一種基于ssl/tls的http協定,所有的http資料都是在ssl/tls協定封裝之上傳輸的。

https協定在http協定的基礎上,添加了ssl/tls握手以及資料加密傳輸,也屬于應用層協定。

——&gt;http協定運作在tcp之上,所有傳輸的内容都是明文,用戶端和伺服器端都無法驗證對方的身份。

——&gt;https是運作在ssl/tls之上的http協定,ssl/tls運作在tcp之上。所有傳輸的内容都經過加密,加密采用對稱加密,但對稱加密的密鑰用伺服器方的證書進行了非對稱加密。

這個問題比較寬泛,以下幾個方面可以考慮:

優化sql查詢和索引;

配置緩存,memcached,redis;

主從複制做讀寫分離;

使用mysql自帶分區表;

資料庫切分,包括垂直切分和水準切分。

總之分區分表成本較高,應該是最後才考慮的措施。

更多的可以參考知乎的這個問題:

<a href="https://www.zhihu.com/question/19719997" target="_blank">mysql 對于千萬級的大表要怎麼優化?</a>

大表資料的處理應該在系統設計之初就考慮到,未雨綢缪。

可以使用一些第三方工具将日志統一彙總到一個檔案中,

比如這篇文章:

<a href="http://blog.jobbole.com/96823/" target="_blank">logstash實踐: 分布式系統的日志監控</a>

另外參考:

<a href="http://www.infoq.com/cn/news/2015/09/bookkeeper-twitter" target="_blank">twitter是如何建構高性能分布式日志的</a>

負載均衡的原理牽扯到作業系統底層,簡單了解。

負載均衡有硬體和軟體兩種。

硬體層的比較牛逼,将4-7層負載均衡功能做到一個硬體裡面,如f5。

目前主流的軟體負載均衡分為四層和七層

lvs屬于四層負載均衡,工作在tcp/ip協定棧上,通過修改網絡包的ip位址和端口來轉發, 由于效率比七層高,一般放在架構的前端。

七層的負載均衡有nginx, haproxy, apache等, 工作在應用層,是以可以将http請求等應用資料發送到具體的應用伺服器,如将圖檔請求轉發到特定的伺服器上,總之可以做到更智能的負載均衡,這些功能在四層負載均衡上不好實作,一般放在架構的後面位置,布置在應用伺服器前面。

網絡由下往上分為實體層、資料鍊路層、網絡層、傳輸層、會話層、表示層和應用層。

我們知道ip協定對應于網絡層,tcp協定對應于傳輸層,而http協定對應于應用層,

三者從本質上來說沒有可比性,

socket則是對tcp/ip協定的封裝和應用(程式員層面上)。也可以說,tpc/ip協定是傳輸層協定,主要解決資料如何在網絡中傳輸,

而http是應用層協定,主要解決如何包裝資料。

關于tcp/ip和http協定的關系,網絡有一段比較容易了解的介紹:

“我們在傳輸資料時,可以隻使用(傳輸層)tcp/ip協定,但是那樣的話,如果沒有應用層,便無法識别資料内容。

如果想要使傳輸的資料有意義,則必須使用到應用層協定。

應用層協定有很多,比如http、ftp、telnet等,也可以自己定義應用層協定。

web使用http協定作應用層協定,以封裝http文本資訊,然後使用tcp/ip做傳輸層協定将它發到網絡上。”

而我們平時說的最多的socket是什麼呢,實際上socket是對tcp/ip協定的封裝,socket本身并不是協定,而是一個調用接口(api)。

通過socket,我們才能使用tcp/ip協定。實際上,socket跟tcp/ip協定沒有必然的聯系。

socket程式設計接口在設計的時候,就希望也能适應其他的網絡協定。

是以說,socket的出現隻是使得程式員更友善地使用tcp/ip協定棧而已,是對tcp/ip協定的抽象,

進而形成了我們知道的一些最基本的函數接口,比如create、listen、connect、accept、send、read和write等等。

網絡有一段關于socket和tcp/ip協定關系的說法比較容易了解:

“tcp/ip隻是一個協定棧,就像作業系統的運作機制一樣,必須要具體實作,同時還要提供對外的操作接口。

這個就像作業系統會提供标準的程式設計接口,比如win32程式設計接口一樣,

tcp/ip也要提供可供程式員做網絡開發所用的接口,這就是socket程式設計接口。”

ip協定的應用和程式設計接口的知識,也就是剛才說了很多的http和socket。

http是轎車,提供了封裝或者顯示資料的具體形式;socket是發動機,提供了網絡通信的能力。

實際上,傳輸層的tcp是基于網絡層的ip協定的,而應用層的http協定又是基于傳輸層的tcp協定的,而socket本身不算是協定,就像上面所說,它隻是提供了一個針對tcp或者udp程式設計的接口。

1.浏覽器将自己支援的一套加密規則發送給網站。

2.網站從中選出一組加密算法與hash算法,并将自己的身份資訊以證書的形式發回給浏覽器。證書裡面包含了網站位址,加密公鑰,以及證書的頒發機構等資訊。

3.獲得網站證書之後浏覽器要做以下工作:

a) 驗證證書的合法性(頒發證書的機構是否合法,證書中包含的網站位址是否與正在通路的位址一緻等),如果證書受信任,則浏覽器欄裡面會顯示一個小鎖頭,否則會給出證書不受信的提示。

b) 如果證書受信任,或者是使用者接受了不受信的證書,浏覽器會生成一串随機數的密碼,并用證書中提供的公鑰加密。

c) 使用約定好的hash計算握手消息,并使用生成的随機數對消息進行加密,最後将之前生成的所有資訊發送給網站。

4.網站接收浏覽器發來的資料之後要做以下的操作:

a) 使用自己的私鑰将資訊解密取出密碼,使用密碼解密浏覽器發來的握手消息,并驗證hash是否與浏覽器發來的一緻。

b) 使用密碼加密一段握手消息,發送給浏覽器。

5.浏覽器解密并計算握手消息的hash,如果與服務端發來的hash一緻,

此時握手過程結束,之後所有的通信資料将由之前浏覽器生成的随機密碼并利用對稱加密算法進行加密。

這裡浏覽器與網站互相發送加密的握手消息并驗證,目的是為了保證雙方都獲得了一緻的密碼,并且可以正常的加密解密資料,為後續真正資料的傳輸做一次測試。

其中非對稱加密算法用于在握手過程中加密生成的密碼,對稱加密算法用于對真正傳輸的資料進行加密,而hash算法用于驗證資料的完整性。

由于浏覽器生成的密碼是整個資料加密的關鍵,是以在傳輸的時候使用了非對稱加密算法對其加密。

非對稱加密算法會生成公鑰和私鑰,公鑰隻能用于加密資料,是以可以随意傳輸,而網站的私鑰用于對資料進行解密,是以網站都會非常小心的保管自己的私鑰,防止洩漏。

tls握手過程中如果有任何錯誤,都會使加密連接配接斷開,進而阻止了隐私資訊的傳輸。