第二部分 網絡編程和併發(34題)
1. 簡述 OSI 七層協議。
互聯網協議按照功能不同分爲tcp/ip四層或tcp/ip五層或osi七層。
物理層:主要是基於電器特性發送高低電壓(電信號),高電壓對應數字1,低電壓對應數字0。
數據鏈路層:定義了電信號的分組方式。
網絡層:引入一套新的地址用來區分不同的廣播域/子網,這套地址即網絡地址。
傳輸層:建立端口到端口的通信。
會話層:建立、管理、終止進程之間的會話。
表示層:對上層數據或信息進行變換以保證一個主機應用層信息可以被另一個主機的應用程序理解。
應用層:爲操作系統或網絡應用程序提供訪問網絡服務的接口。
2. 什麼是C/S和B/S架構?
C/S架構是第一種比較早的軟件架構,主要用於局域網內。
它可以分爲客戶機和服務器兩層:
第一層: 在客戶機系統上結合了界面顯示與業務邏輯;
第二層: 通過網絡結合了數據庫服務器。
B/S架構的全稱爲Browser/Server,即瀏覽器/服務器結構。
Browser指的是Web瀏覽器,極少數事務邏輯在前端實現,但主要事務邏輯在服務器端實現。
B/S架構的系統無須特別安裝,只要有Web瀏覽器即可。
B/S架構的分層:
B/S架構有三層,分別爲:
第一層表現層:主要完成用戶和後臺的交互及最終查詢結果的輸出功能。
第二層邏輯層:主要是利用服務器完成客戶端的應用邏輯功能。
第三層數據層:主要是接受客戶端請求後獨立進行各種運算。
3. 簡述 三次握手、四次揮手的流程。
建立雙工通信,確保雙方都能收到對方的信息,所以需要3次握手。
第1次握手:建立連接時,客戶端發送syn包(syn=x)到服務器,並進入同步已發送狀態,等待服務器確認;SYN:同步序列編號。
第2次握手:服務器收到syn包,必須確認客戶的SYN(ack=x+1),同時自己也發送一個SYN包(syn=y),即SYN+ACK包,此時服務器進入同步已接受狀態。
第3次握手:客戶端收到服務器的SYN+ACK包,向服務器發送確認包ACK(ack=y+1),此包發送完畢,客戶端和服務器進入ESTABLISHED(TCP連接成功)狀態,完成三次握手。
全雙工關閉需要客戶端和服務器發送和接受都關閉,但是關閉連接時,當Server端收到FIN報文時,很可能並不會立即關閉SOCKET,只能先回復一個ACK報文,所以需要4次揮手
第1次揮手:客戶端進程發出連接釋放報文,並且停止發送數據。此時,客戶端進入FIN-WAIT-1(終止等待1)狀態。
第2次揮手:服務器收到連接釋放報文,發出確認報文。服務端就進入了CLOSE-WAIT(關閉等待)狀態。TCP服務器通知高層的應用進程,客戶端向服務器的方向就釋放了,這時候處於半關閉狀態,即客戶端已經沒有數據要發送了,但是服務器若發送數據,客戶端依然要接受。這個狀態還要持續一段時間,也就是整個CLOSE-WAIT狀態持續的時間。
客戶端收到服務器的確認請求後,此時,客戶端就進入FIN-WAIT-2(終止等待2)狀態,等待服務器發送連接釋放報文(在這之前還需要接受服務器發送的最後的數據)。
第3次揮手:服務器將最後的數據發送完畢後,就向客戶端發送連接釋放報文,FIN=1,ack=u+1,由於在半關閉狀態,服務器很可能又發送了一些數據,假定此時的序列號爲seq=w,此時,服務器就進入了LAST-ACK(最後確認)狀態,等待客戶端的確認。
第4次揮手:客戶端收到服務器的連接釋放報文後,必須發出確認,ACK=1,ack=w+1,而自己的序列號是seq=u+1,此時,客戶端就進入了TIME-WAIT(時間等待)狀態。注意此時TCP連接還沒有釋放,必須經過2MSL(最長報文段壽命)的時間後,當客戶端撤銷相應的TCB後,才進入CLOSED狀態。
服務器只要收到了客戶端發出的確認,立即進入CLOSED狀態。同樣,撤銷TCB後,就結束了這次的TCP連接。可以看到,服務器結束TCP連接的時間要比客戶端早一些。
4. 什麼是arp協議?
ARP協議,全稱“Address Resolution Protocol”,中文名是地址解析協議,使用ARP協議可實現通過IP地址獲得對應主機的物理地址(MAC地址)。
在TCP/IP的網絡環境下,每個聯網的主機都會被分配一個32位的IP地址,這種互聯網地址是在網際範圍標識主機的一種邏輯地址。
爲了讓報文在物理網路上傳輸,還必須要知道對方目的主機的物理地址(MAC)才行,這樣就存在把IP地址變換成物理地址的地址轉換的問題,需要有一個服務或功能將IP地址轉換爲相應的物理地址(MAC地址),這個服務或者功能就是ARP協議。
所謂的“地址解析”,就是主機在發送幀之前將目標IP地址轉換成目標MAC地址的過程。
ARP協議的基本功能就是通過目標設備的IP地址,查詢目標設備的MAC地址,以保證主機間相互通信的順利進行。
ARP 協議和DNS有點相像之處,不同點是:DNS是在域名和IP之間的解析,另外,ARP協議不需要配置服務,而DNS要配置服務才行。
ARP協議要求通信的主機雙方必須在同一個物理網段(即局域網環境)!
5. TCP和UDP的區別?
- TCP(Transmission ControlProtocol,傳輸控制協議)提供的是面向連接,可靠的字節流服務。
客戶和服務器交換數據前,必須現在雙方之間建立一個TCP連接,之後才能傳輸數據。
並提供超時重發、丟棄重複數據,檢驗數據,流量控制等功能,保證數據能完整地從一端傳到另一端。
簡單說就是必須要建立連接後才能傳輸數據,確保傳輸完整性,類比現實當中的打電話。
- UDP(User Data Protocol,用戶數據報協議)是一個簡單的面向數據報的運輸層協議。
不可靠傳輸,”報頭”部分一共只有8個字節,總長度不超過65,535字節,正好放進一個IP數據包。
它不提供可靠性,只是把應用程序傳給IP層的數據報發送出去,但是不能保證它們能到達目的地。
由於UDP在傳輸數據報前不用再客戶和服務器之間建立一個連接,且沒有超時重發等機制,所以傳輸速度很快。
簡單說就是單向把程序中的信息發送了,但也不知道對方收到沒有,類比現實當中的寄信。
6. 什麼是局域網和廣域網?
- 局域網
局域網,LAN(Local Area Network)是指在某一區域內(如一個學校、工廠和機關內)由多臺計算機互聯成的計算機組。一般是方圓幾千米以內。將各種計算機,外部設備和數據庫等互相聯接起來組成的計算機通信網。它可以通過數據通信網或專用數據電路,與遠方的局域網、數據庫或處理中心相連接,構成一個較大範圍的信息處理系統。
局域網可以實現文件管理、應用軟件共享、打印機共享、工作組內的日程安排、電子郵件和傳真通信服務等功能。局域網嚴格意義上是封閉型的,可以由辦公室內的兩臺計算機組成,也可以由一個公司內的上千臺計算機組成。
- 廣域網
廣域網,WAN(Wide Area Network)也稱遠程網。通常跨接很大的物理範圍,所覆蓋的範圍從幾十公里到幾千公里,它能連接多個城市或國家,或橫跨幾個洲並能提供遠距離通信,形成國際性的遠程網絡。
廣域網的通信子網主要使用分組交換技術。廣域網的通信子網可以利用公用分組交換網、衛星通信網和無線分組交換網,它將分佈在不同地區的局域網或計算機系統互連起來,達到資源共享的目的。如因特網(Internet)是世界範圍內最大的廣域網。
廣域網是由許多交換機組成的,交換機之間採用點到點線路連接,幾乎所有的點到點通信方式都可以用來建立廣域網,包括租用線路、光纖、微波、衛星信道。而廣域網交換機實際上就是一臺計算機,有處理器和輸入/輸出設備進行數據包的收發處理。
7. 爲何基於tcp協議的通信比基於udp協議的通信更可靠?
tcp協議一定是先建好雙向鏈接,發一個數據包要得到確認纔算發送完成,沒有收到就一直給你重發;udp協議沒有鏈接存在,udp直接丟數據,不管你有沒有收到。
TCP的可靠保證,是它的三次握手雙向機制,這一機制保證校驗了數據,保證了他的可靠性。而UDP就沒有了,udp信息發出後,不驗證是否到達對方,所以不可靠。
不過UDP的速度是TCP比不了的,而且UDP的反應速度更快,QQ就是用UDP協議傳輸的,HTTP是用TCP協議傳輸的。
8. 什麼是socket?簡述基於tcp協議的套接字通信流程。
Socket通常也稱作"套接字",用於描述IP地址和端口,是一個通信鏈的句柄,可以用來實現不同虛擬機或不同計算機之間的通信。
在Internet上的主機一般運行了多個服務軟件,同時提供幾種服務。每種服務都打開一個Socket,並綁定到一個端口上,不同的端口對應於不同的服務。
基於tcp 協議的套接字通信流程:
- 服務器先用 socket 函數來建立一個套接字,用這個套接字完成通信的監聽。
- 用 bind 函數來綁定一個端口號和 IP 地址。因爲本地計算機可能有多個端口和 IP,每一個 IP 和端口有多個組合。需要指定一個 IP 和端口進行監聽。
- 服務器調用 listen 函數,使服務器的這個端口和 IP 處於監聽狀態,等待客戶機的連接。
- 客戶機用 socket 函數建立一個套接字,設定遠程 IP 和端口。
- 客戶機調用 connect 函數連接遠程計算機指定的端口。
- 服務器用 accept 函數來接受遠程計算機的連接,建立起與客戶機之間的通信。
- 建立連接以後,客戶機用 write 函數向 socket 中寫入數據。也可以用 read 函數讀取服務器發送來的數據。
- 服務器用 read 函數讀取客戶機發送來的數據,也可以用 write 函數來發送數據。
- 完成通信以後,用 close 函數關閉 socket 連接。
9. 什麼是粘包? socket 中造成粘包的原因是什麼? 哪些情況會發生粘包現象?
粘包:在接收數據時,一次性多接收了其它請求發送來的數據(即多包接收)。
如,對方第一次發送hello,第二次發送world,在接收時,應該收兩次,一次是hello,一次是world,但事實上是一次收到helloworld,一次收到空,這種現象叫粘包。
原因:粘包問題主要還是因爲接收方不知道消息之間的界限,不知道一次性提取多少字節的數據所造成的。
什麼情況會發生:
1、發送端需要等緩衝區滿才發送出去,造成粘包(發送數據時間間隔很短,數據很小,會合到一起,產生粘包)
2、接收方不及時接收緩衝區的包,造成多個包接收(客戶端發送了一段數據,服務端只收了一小部分,服務端下次再收的時候還是從緩衝區拿上次遺留的數據,產生粘包)
解決方案:
發送之前告訴對方自己要發送的字節長度,這樣對方可以根據長度判斷什麼時候終止接受。
10. IO多路複用的作用?
阻塞IO
舉個簡單的例子,我們要買網絡編程一本書,來到書店問老闆,老闆的回覆是等待一下,他去找書,這個時候我們就只能靜靜的等,直到老闆找到這本書。
非阻塞IO
還是上面的例子,我們要買網絡編程這本書,來到書店問老闆,老闆的回覆是他去找書,這個時候情況就不同了,我們出去買一根雪糕,回來之後再問老闆找到了沒有 ,如果老闆回覆沒有找到,我們再出去買包辣條再回來,直到老闆回覆找到了。
阻塞IO存在的問題是,當數據沒有到來時,程序會一直阻塞,什麼事情也做不了。非阻塞IO雖然會及時返回一個結果,但是需要不停地輪詢IO請求的狀態。
IO多路複用
假設你跟這個書店老闆很熟了,我們問完有沒有網絡編程這本書之後,書店老闆去找找,你說,找到之後放我家門口收件箱裏吧,在這個收件箱裏有我們所有請求的信息,只需要監聽這個收件箱就可以了。
I/O多路複用是用於提升效率,單個進程可以同時監聽多個網絡連接IO。
舉例:通過一種機制,可以監視多個文件描述符,一旦描述符就緒(讀就緒和寫就緒),能通知程序進行相應的讀寫操作,I/O多路複用避免阻塞在io上,原本爲多進程或多線程來接收多個連接的消息變爲單進程或單線程保存多個socket的狀態後輪詢處理。
11. 什麼是防火牆,作用是什麼?
防火牆的基本概念
古時候,人們常在寓所之間砌起一道磚牆,一旦火災發生,它能夠防止火勢蔓延到別的寓所。
現在,如果一個網絡接到了Internet上面,它的用戶就可以訪問外部世界並與之通信。但同時,外部世界也同樣可以訪問該網絡並與之交互。
爲安全起見,可以在該網絡和Internet之間插入一箇中介系統,豎起一道安全屏障。
這道屏障的作用是阻斷來自外部通過網絡對本網絡的威脅和入侵,提供扼守本網絡的安全和審計的唯一關卡,它的作用與古時候的防火磚牆有類似之處,因此我們把這個屏障就叫做“防火牆”。
在電腦中,防火牆是一種裝置,它是由軟件或硬件設備組合而成,通常處於企業的內部局域網與Internet之間,限制Internet用戶對內部網絡的訪問以及管理內部用戶訪問外界的權限。
換言之,防火牆是一個位於被認爲是安全和可信的內部網絡與一個被認爲是不那麼安全和可信的外部網絡(通常是Internet)之間的一個封鎖工具。
防火牆是一種被動的技術,因爲它假設了網絡邊界的存在,它對內部的非法訪問難以有效地控制。因此防火牆只適合於相對獨立的網絡,例如企業內部的局域網絡等。
作用:
- 過濾不安全服務
基於這個準則,防火牆應封鎖所有信息流,然後對希望提供的安全服務逐項開放,對不安全的服務或可能有安全隱患的服務一律扼殺在萌芽之中。
這是一種非常有效實用的方法,可以造成一種十分安全的環境,因爲只有經過仔細挑選的服務才能允許用戶使用。
- 過濾非法用戶和訪問特殊站點
基於這個準則,防火牆應先允許所有的用戶和站點對內部網絡的訪問,然後網絡管理員按照IP地址對未授權的用戶或不信任的站點進行逐項屏蔽。
這種方法構成了一種更爲靈活的應用環境,網絡管理員可以針對不同的服務面向不同的用戶開放,也就是能自由地設置各個用戶的不同訪問權限。
12. select、poll、epoll 模型的區別?
select
優點:單進程下支持高併發,可以跨平臺
缺點:
多次從內核到應用,應用到內核的數組拷貝;
每次內核都會重置填寫的數據
最大支持1024客戶端,原因在於fd_set定義使用了FD_SETSIZE,大小爲1024;
POLL模型:
POLL的原理與select相同,比select改進的地方:
1,請求和返回分離,避免每次都要重設數組
2,可以突破1024限制,poll是由打開文件的上限決定,可以使用ulimit命令查看上限
3,不能跨平臺
EPOLL:
不管是select,還是poll,都需要遍歷數組輪詢,而且select僅支持1024個客戶端,在大量併發,少量活躍的情況下效率較低,也就滋生了epoll模型。
1,可以突破1024限制,不跨平臺
2,無須遍歷整個文件描述符集,只需遍歷被內核IO事件異步喚醒,而加入ready隊列的文件描述符。
3,除了select/poll的IO事件水平觸發(level triggered)外,還提供邊沿觸發(edge Triggered),可以緩存IO狀態,減少epoll_wait調用,提高效率
13. 簡述 進程、線程、協程的區別 以及應用場景?
1.進程是計算器最小資源分配單位 .
2.線程是CPU調度的最小單位 .
3.進程切換需要的資源很最大,效率很低 .
4.線程切換需要的資源一般,效率一般(當然了在不考慮GIL的情況下) .
5.協程切換任務資源很小,效率高(協程本身並不存在,是程序員通過控制IO操作完成) .
6.多進程、多線程根據cpu核數不一樣可能是並行的,但是協程是在一個線程中所以是併發.
進程:
一個運行的程序(代碼)就是一個進程,沒有運行的代碼叫程序,進程是系統資源分配的最小單位,進程擁有自己獨立的內存空間,所以進程間數據不共享,開銷大。
線程:
調度執行的最小單位,也叫執行路徑,不能獨立存在,依賴進程存在一個進程至少有一個線程,叫主線程,而多個線程共享內存(數據共享,共享全局變量),從而極大地提高了程序的運行效率。
協程:
是一種用戶態的輕量級線程,協程的調度完全由用戶控制。
協程擁有自己的寄存器上下文和棧。
協程調度切換時,將寄存器上下文和棧保存到其他地方,在切回來的時候,恢復先前保存的寄存器上下文和棧,直接操作棧則基本沒有內核切換的開銷,
可以不加鎖的訪問全局變量,所以上下文的切換非常快。
14. GIL鎖是什麼?
在CPython中,全局解釋器鎖(global interpreter lock,GIL)是一個互斥鎖,它防止多個本機線程同時執行Python字節碼。
這個鎖是必要的,主要是因爲CPython的內存管理不是線程安全的。
然而,由於GIL存在,其他特徵已經發展成依賴於它所實施的保證。
首先需要明確的一點是GIL並不是Python的特性,它是在實現Python解析器(CPython)時所引入的一個概念。
就好比C++是一套語言(語法)標準,但是可以用不同的編譯器來編譯成可執行代碼。
有名的編譯器例如GCC,INTEL C++,Visual C++等。
Python也一樣,同樣一段代碼可以通過CPython,PyPy,Psyco等不同的Python執行環境來執行。
像其中的JPython就沒有GIL。
然而因爲CPython是大部分環境下默認的Python執行環境,所以在很多人的概念裏CPython就是Python,也就想當然的把GIL歸結爲Python語言的缺陷。
所以這裏要先明確一點:GIL並不是Python的特性,Python完全可以不依賴於GIL。
每次執行python程序,都會產生一個獨立的進程。在一個python的進程內,不僅有該進程的主線程和由該主線程開啓的其他線程,還有解釋器開啓的垃圾回收等解釋器級別的線程。
總之,所有線程都運行在這一個進程內,所有數據都是共享的,這其中,代碼作爲一種數據也是被所有線程共享的(主進程的所有代碼以及Cpython解釋器的所有代碼)。
所有線程的任務,都需要將任務的代碼當做參數傳給解釋器的代碼去執行,即所有的線程要想運行自己的任務,首先要能夠訪問到解釋器的代碼。
解釋器的代碼是所有線程共享的,所以垃圾回收線程也可能訪問到解釋器的代碼而去執行,這就導致了一個問題:對於同一個數據100,可能線程1執行x=100的同時,而垃圾回收執行的是回收100的操作,解決這種問題沒有什麼高明的方法,就是加鎖處理,如下圖的GIL,保證python解釋器同一時間只能執行一個任務的代碼。
鎖的目的是爲了保護共享的數據,同一時間只能有一個線程來修改共享的數據。
然後,我們可以得出結論:保護不同的數據就應該加不同的鎖。
GIL 是解釋器級別的,當然保護的就是解釋器級別的數據,比如垃圾回收的數據。
有了GIL的存在,同一時刻同一個進程中只有一個線程被執行。
15. Python中如何使用線程池和進程池?
ProcessPoolExecutor類是一個Executor子類,它使用進程池異步執行調用。
ProcessPoolExecutor使用多處理模塊,這允許它繞過全局解釋器鎖,但也意味着只能執行和返回可選擇的對象。
import os
import time
import random
from concurrent.futures import ProcessPoolExecutor
def task(n):
print("n =", n, "on", os.getpid(), "is running.")
time.sleep(random.randint(1, 3))
return n ** 2
if __name__ == '__main__':
executor = ProcessPoolExecutor(max_workers=3)
futures = []
for i in range(10):
future = executor.submit(task, i)
futures.append(future)
executor.shutdown(True)
for future in futures:
print(future.result())
ThreadPoolExecutor是一個Executor子類,它使用線程池異步執行調用。
import time
import random
import threading
from concurrent.futures import ThreadPoolExecutor
def task(n):
print("n =", n, "on", threading.currentThread().getName(), "is running.")
time.sleep(random.randint(1, 3))
return n ** 2
if __name__ == '__main__':
executor = ThreadPoolExecutor(max_workers=3)
futures = []
for i in range(10):
future = executor.submit(task, i)
futures.append(future)
executor.shutdown(True)
for future in futures:
print(future.result())
16. threading.local的作用?
threading.local()這個方法的特點用來保存一個全局變量,但是這個全局變量只有在當前線程才能訪問,如果在開發多線程應用的時候 需要每個線程保存一個單獨的數據供當前線程操作,可以考慮使用這個方法,簡單有效。
舉例:每個子線程使用全局對象a,但每個線程定義的屬性a.xx是該線程獨有的,Python提供了 threading.local 類,將這個類實例化得到一個全局對象,但是不同的線程使用這個對象存儲的數據其它線程不可見(本質上就是不同的線程使用這個對象時爲其創建一個獨立的字典)。
17. 進程之間如何進行通信?
-
管道:速度慢,容量有限,只有父子進程能通訊
-
FIFO:任何進程間都能通訊,但速度慢
-
消息隊列:容量受到系統限制,且要注意第一次讀的時候,要考慮上一次沒有讀完數據的問題
-
信號量:不能傳遞複雜消息,只能用來同步
-
共享內存區:能夠很容易控制容量,速度快,但要保持同步,比如一個進程在寫的時候,另一個進程要注意讀寫的問題,相當於線程中的線程安全
18. 什麼是併發和並行?
- 併發(Concurrent)
在操作系統中,是指一個時間段中有幾個程序都處於已啓動運行到運行完畢之間,且這幾個程序都是在同一個處理機上運行。
- 並行
並行(Parallel),當系統有一個以上CPU時,當一個CPU執行一個進程時,另一個CPU可以執行另一個進程,兩個進程互不搶佔CPU資源,可以同時進行,這種方式我們稱之爲並行(Parallel)。
19. 進程鎖和線程鎖的作用?
線程鎖:
多線程可以同時運行多個任務但是當多個線程同時訪問共享數據時,可能導致數據不同步,甚至錯誤! so,不使用線程鎖, 可能導致錯誤
進程鎖:
也是爲了控制同一操作系統中多個進程訪問一個共享資源,只是因爲程序的獨立性,各個進程是無法控制其他進程對資源的訪問的,但是可以使用本地系統的信號量控制(操作系統基本知識)。
20. 解釋什麼是異步非阻塞?
同步和異步是針對應用程序和內核的交互而言的,同步指的是用戶進程觸發 IO 操作並等待或者輪詢的去查看IO 操作是否就緒,而異步是指用戶進程觸發IO 操作以後便開始做自己的事情,而當IO 操作已經完成的時候會得到IO 完成的通知。
同步異步是針對調用者來說的,調用者發起一個請求後,一直乾等被調用者的反饋就是同步,不必等去做別的事就是異步。
阻塞和非阻塞是針對於進程在訪問數據的時候,根據IO操作的就緒狀態來採取的不同方式,說白了是一種讀取或者寫入操作方法的實現方式,阻塞方式下讀取或者寫入函數將一直等待,而非阻塞方式下,讀取或者寫入方法會立即返回一個狀態值。
阻塞非阻塞是針對被調用者來說的,被調用者收到一個請求後,做完請求任務後纔給出反饋就是阻塞,收到請求直接給出反饋再去做任務就是非阻塞。
21. 路由器和交換機的區別?
工作層次不同:
交換機主要工作在數據鏈路層(第二層)
路由器工作在網絡層(第三層)。
轉發依據不同:
交換機轉發所依據的對象時:MAC地址。(物理地址)
路由轉發所依據的對象是:IP地址。(網絡地址)
主要功能不同:
交換機主要用於組建局域網
路由主要功能是將由交換機組好的局域網相互連接起來,或者接入Internet。
交換機能做的,路由都能做。
交換機不能分割廣播域,路由可以。
路由還可以提供防火牆的功能。
路由配置比交換機複雜。
22. 什麼是域名解析?
域名解析是將域名轉換爲其對應的IP地址的任務。
在使用Internet的應用程序中輸入域名時,應用程序將發出命令讓操作系統將域名轉換爲其IP地址,然後連接到該IP地址以執行它嘗試執行的任何操作。
23. 如何修改本地hosts文件?
Windows操作胸膛hosts文件路徑:C:\Windows\System32\drivers\etc
Linux及其他類Unix操作系統hosts文件路徑:/etc
以管理員或超級用戶的身份打開並編輯。
24. 生產者消費者模型應用場景及優勢?
產生數據的模塊,就形象地稱爲生產者;而處理數據的模塊,就稱爲消費者。
在生產者與消費者之間在加個緩衝區,我們形象的稱之爲倉庫,生產者負責往倉庫了進商品,而消費者負責從倉庫裏拿商品,這就構成了生產者消費者模型。
結構圖如下:
生產者消費者模型的優點:
1、解耦
假設生產者和消費者分別是兩個類。
如果讓生產者直接調用消費者的某個方法,那麼生產者對於消費者就會產生依賴(也就是耦合)。
將來如果消費者的代碼發生變化, 可能會影響到生產者。而如果兩者都依賴於某個緩衝區,兩者之間不直接依賴,耦合也就相應降低了。
2、支持併發
由於生產者與消費者是兩個獨立的併發體,他們之間是用緩衝區作爲橋樑連接,生產者只需要往緩衝區裏丟數據,
就可以繼續生產下一個數據,而消費者只需要從緩衝區了拿數據即可,這樣就不會因爲彼此的處理速度而發生阻塞。
3、支持忙閒不均
緩衝區還有另一個好處。如果製造數據的速度時快時慢,緩衝區的好處就體現出來了。
當數據製造快的時候,消費者來不及處理,未處理的數據可以暫時存在緩衝區中。 等生產者的製造速度慢下來,消費者再慢慢處理掉。
應用場景:
使用多線程,在做爬蟲的時候,生產者用着產生url鏈接,消費者用於獲取url數據,在隊列的幫助下可以使用多線程加快爬蟲速度。
25. 什麼是cdn?
CDN全稱是Content Delivery Network,即內容分發網絡,比如我們客戶端向服務器請求一個數據,當這個數據很大,請求頻繁,而且服務器距離客戶端很遠,這樣很浪費資源,浪費大量的帶寬,嚴重時候還會造成網絡阻塞,而且這樣響應時間非常慢。
CDN主要由負載均衡,和高速緩存服務器組成。其中分爲中心部分和邊緣部分。中心部分就是負責全局負載均衡,當客戶端發送請求,首先會訪問中心CDN,經過全局負載均衡,根據用戶請求的ip 地址,一定的算法,然後算出距離用戶最近,用戶接入量最少得CDN緩存服務器,這樣是不是相當於走了捷徑。
因爲cdn是介於客戶端和請求服務器之間的一個緩存服務器,有一點點像redis緩存。當然第一次請求的時候,cdn沒有緩存的話,cdn也會請求一次服務器,然後根據服務器返回的數據一方面留給自己緩存作爲備用,另一方面也返回給客戶端,好像現在像騰訊網,阿里雲都有提供cdn服務器。而且域名配置服務器時候,就可以配到cdn。
26. LVS是什麼及作用?
一.LVS是什麼?
LVS的英文全稱是Linux Virtual Server,即Linux虛擬服務器。它是我們國家的章文嵩博士的一個開源項目。在linux內存2.6中,它已經成爲內核的一部分,在此之前的內核版本則需要重新編譯內核。
二.LVS能幹什麼?
LVS主要用於多服務器的負載均衡。它工作在網絡層,可以實現高性能,高可用的服務器集羣技術。它廉價,可把許多低性能的服務器組合在一起形成一個超級服務器。它易用,配置非常簡單,且有多種負載均衡的方法。它穩定可靠,即使在集羣的服務器中某臺服務器無法正常工作,也不影響整體效果。另外可擴展性也非常好。
27. Nginx是什麼及作用?
nginx是一個高性能的HTTP和反向代理服務器,其特點是佔用內存少,併發能力強.
作爲 Web 服務器:相比 Apache,Nginx 使用更少的資源,支持更多的併發連接,體現更高的效率,這點使 Nginx 尤其受到虛擬主機提供商的歡迎。能夠支持高達 50,000 個併發連接數的響應,感謝 Nginx 爲我們選擇了 epoll and kqueue 作爲開發模型.
作爲負載均衡服務器:Nginx 既可以在內部直接支持 Rails 和 PHP,也可以支持作爲 HTTP代理服務器 對外進行服務。Nginx 用 C 編寫, 不論是系統資源開銷還是 CPU 使用效率都比 Perlbal 要好的多。
作爲郵件代理服務器: Nginx 同時也是一個非常優秀的郵件代理服務器(最早開發這個產品的目的之一也是作爲郵件代理服務器),Last.fm 描述了成功並且美妙的使用經驗。
Nginx 安裝非常的簡單,配置文件 非常簡潔(還能夠支持perl語法),Bugs非常少的服務器: Nginx 啓動特別容易,並且幾乎可以做到7*24不間斷運行,即使運行數個月也不需要重新啓動。你還能夠在不間斷服務的情況下進行軟件版本的升級。
28. keepalived是什麼及作用?
Keepalived是Linux下一個輕量級別的高可用解決方案。
Keepalived起初是爲LVS設計的,專門用來監控集羣系統中各個服務節點的狀態,它根據TCP/IP參考模型的第三、第四層、第五層交換機制檢測每個服務節點的狀態,如果某個服務器節點出現異常,或者工作出現故障,Keepalived將檢測到,並將出現的故障的服務器節點從集羣系統中剔除,這些工作全部是自動完成的,不需要人工干涉,需要人工完成的只是修復出現故障的服務節點。
29. haproxy是什麼以及作用?
HAProxy 是一款提供高可用性、負載均衡以及基於TCP(第四層)和HTTP(第七層)應用的代理軟件,支持虛擬主機,它是免費、快速並且可靠的一種解決方案。
HAProxy特別適用於那些負載特大的web站點,這些站點通常又需要會話保持或七層處理。
HAProxy運行在時下的硬件上,完全可以支持數以萬計的 併發連接。
並且它的運行模式使得它可以很簡單安全的整合進您當前的架構中, 同時可以保護你的web服務器不被暴露到網絡上。
作用: 高可用性,負載平衡和用於TCP和基於http的應用程序的代理
30. 什麼是負載均衡?
負載均衡(Load Balance),意思是將負載(工作任務,訪問請求)進行平衡、分攤到多個操作單元(服務器,組件)上進行執行。是解決高性能,單點故障(高可用),擴展性(水平伸縮)的終極解決方案。
31. 什麼是rpc及應用場景?
RPC(Remote Procedure Call,即遠程過程調用)是建立在Socket之上的,在一臺機器上運行的主程序,可以調用另一臺機器上準備好的子程序,就像LPC(本地過程調用)。
也就是說兩臺服務器A,B,一個應用部署在A服務器上,想要調用B服務器上應用提供的函數/方法,由於不在一個內存空間,不能直接調用,需要通過網絡來表達調用的語義和傳達調用的數據。
對於RPC架構來說,應用越底層,代碼越複雜、靈活性越高、效率越高;應用越上層,抽象封裝的越好、代碼越簡單、效率越差。
在網絡通信中,不管是TCP 還是UDP,我們都要在傳輸層上設計自己的應用層協議,使得前後端的數據可以相互通信傳輸一個可以識別的內容。
後來,人們期望能夠更方便一點地讓前後端進行交互,於是提出了RPC,就像調用函數一樣來讓前後端來進行通信,屏蔽掉複雜的應用層協議。
32. 簡述 asynio模塊的作用和應用場景。
asyncio是Python 3.4版本引入的標準庫,直接內置了對異步IO的支持。
asyncio的編程模型就是一個消息循環,我們從asyncio模塊中直接獲取一個EventLoop的引用,然後把需要執行的協程扔到EventLoop中執行,就實現了異步IO。
33. 簡述 gevent模塊的作用和應用場景。
當一個greenlet遇到IO操作時,比如訪問網絡,就自動切換到其他的greenlet,等到IO操作完成,再在適當的時候切換回來繼續執行。
由於IO操作非常耗時,經常使程序處於等待狀態,有了gevent爲我們自動切換協程,就保證總有greenlet在運行,而不是等待IO。
由於切換是在IO操作時自動完成,所以gevent需要修改Python自帶的一些標準庫,這一過程在啓動時通過monkey patch完成:
34. twisted框架的使用和應用?
Twisted 是用 Python 實現的基於事件驅動的網絡引擎框架,提供了允許阻塞行爲但不會阻塞代碼執行的方法,比較適合異步的程序。
事件驅動編程是一種編程範式,這裏程序的執行流由外部事件來決定。它的特點是包含一個事件循環,當外部事件發生時使用回調機制來觸發相應的處理。另外兩種常見的編程範式是(單線程)同步以及多線程編程。
讓我們用例子來比較和對比一下單線程、多線程以及事件驅動編程模型。
下圖展示了隨着時間的推移,這三種模式下程序所做的工作。
這個程序有3個任務需要完成,每個任務都在等待I/O操作時阻塞自身。阻塞在I/O操作上所花費的時間已經用灰色框標示出來了。
在單線程同步模型中,任務按照順序執行。如果某個任務因爲I/O而阻塞,其他所有的任務都必須等待,直到它完成之後它們才能依次執行。這種明確的執行順序和串行化處理的行爲是很容易推斷得出的。如果任務之間並沒有互相依賴的關係,但仍然需要互相等待的話這就使得程序不必要的降低了運行速度。
在多線程版本中,這3個任務分別在獨立的線程中執行。這些線程由操作系統來管理,在多處理器系統上可以並行處理,或者在單處理器系統上交錯執行。這使得當某個線程阻塞在某個資源的同時其他線程得以繼續執行。與完成類似功能的同步程序相比,這種方式更有效率,但程序員必須寫代碼來保護共享資源,防止其被多個線程同時訪問。多線程程序更加難以推斷,因爲這類程序不得不通過線程同步機制如鎖、可重入函數、線程局部存儲或者其他機制來處理線程安全問題,如果實現不當就會導致出現微妙且令人痛不欲生的bug。
在事件驅動版本的程序中,3個任務交錯執行,但仍然在一個單獨的線程控制中。當處理I/O或者其他昂貴的操作時,註冊一個回調到事件循環中,然後當I/O操作完成時繼續執行。回調描述了該如何處理某個事件。事件循環輪詢所有的事件,當事件到來時將它們分配給等待處理事件的回調函數。這種方式讓程序儘可能的得以執行而不需要用到額外的線程。事件驅動型程序比多線程程序更容易推斷出行爲,因爲程序員不需要關心線程安全問題。