學習記錄-5.30
同步在我的博客可以來看看
http://www.zhihuigou.top/
### Golang為什么比別的語言跟擅長并發:
首先是因為Goroutine,算是go的一個最大的特色
是輕量級的線程,創建一個goroutine的開銷非常小,大約幾KB,且調度開銷很低
并且goroutine的調度,并不依賴操作系統的線程調度器,而是使用了GMP模型
其次就是channel,也是go的特色
channel
通信機制:channel 算是鎖的一個升級,可以避免顯示鎖的使用,channel可以傳遞數據,用于異步通信,降低并發編程的難度
提到了GMP模型講一下
G:groutine
- goroutine是go語言中的輕量級線程,每個goroutine都有自己的棧和執行狀態
- Goroutine的棧空間是動態擴展的,初始棧的空間很小幾kb,可以根據需要自動增長和縮小
M:Machine
- 每一個M對應一個內核線程,M是執行G的實體
- 每個M綁定一個操作系統線程,負責執行G的代碼
P:Processor
- 管理G隊列,每一個P維護一個運行隊列,保存待執行的G
- P是G調度的核心單位,M需要從P獲取G才能執行
- P一般與CPU核心數相同,可以在runtime.MAXPROCS(n)來設置P的數量
調度過程大致是:
G的創建與調度:
- 當創建一個新的G時,它會被放入到某個P的本地隊列
- M從P的本地隊列中獲取G進行執行,如果P的本地隊列為空,嘗試從全局隊列或者其他P的隊列中竊取
M和P的綁定
- M在運行時需要綁定一個P,才能從P的隊列中獲取g
- 所有P都被占用,有額外的M需要執行,那么這些M會阻塞等待,直到某個P可用
P的數量控制
- P的數量決定了可以同時并行執行G的最大數量
- 通過runtime包中的GOMAXPROCS()來設置
調度的公平性和搶占式調度
- 實現搶占式調度,可以在長時間運行的G中插入檢查點,確保其他G也能獲得執行機會
- 通過搶占機制防止某個G長時間占用CPU,提高系統的公平性和響應性
工作竊取
- 如果本地P為空則嘗試從全局隊列或者其他本地隊列中獲取G
- 這樣可以提高負載均衡,減少因局部隊列空閑造成的資源浪費
### 如何檢測golang的內存泄漏
使用runtime包提供的一些對內存使用情況進行查看的方法
初步判斷內存是否泄露
使用pprof工具進行分析 go tool pprof
使用pprof.WriteHeapProfile函數生成內存快照
然后使用 go tool pprof來進行分析
常見內存泄漏原因:
未關閉goroutine
未關閉文件或網絡連接
緩存和數據結構:不必要的數據保存在全局變量或長生命周期的結構
內存泄漏是指程序運行過程中,已經不再需要使用的內存無法被釋放,從而造成內存資源的良妃.內存泄漏會使得應用程序的內存使用量不斷增加,最后可能導致系統內存耗盡,應用崩潰或者性能下降
得物-Golang-記一次線上服務的內存泄露排查_golang 解決線上問題-CSDN博客
### select和channel關鍵字
select和channel是處理并發編程的兩個重要工具
channels
是go語言提供的一種通信機制,用于在go之間傳遞數據,無需使用鎖
類型:有緩沖的,無緩沖的
select
用于在多個channel中進行選擇,類似于多路復用器
select會阻塞,直到其中一個case可以繼續執行
default
select
語句使得在多個channel上進行非阻塞和超時控制變得容易。
### 關于Mysql的性能優化:
首先就是在資金充足的情況下,沖高性能服務器
在建表的時候:選擇最合適的字段屬性
盡量把字段設置為NOT NULL 這樣查詢的時候數據庫不用比較NULL值
使用連接代替子查詢
- MySQL以前是join幾張表幾個for循環嵌套,
- 8.0做了優化將一張表存入內存減少循環嵌套
- 子查詢結果會在內存臨時創建表存儲,浪費資源
索引時使用最左前綴規則 (聯合索引進行查詢)
模糊查詢不能利用索引
不要過多創建索引
- 過多的索引會占用空間,且每次crud都會重建索引
索引長度盡量短
索引更新不能太頻繁
避免使用select * 用什么查什么就好
合適的情況下,使用的合適的索引
數據量少的時候,全表掃描的速度比索引的速度快
開啟慢查詢日志
grpc是基于http幾
http2,HTTP2提供了一些關鍵特性
多路復用:
- 支持單個TCP連接上同時發送多個請求和響應,減少連接的開銷和延遲
流量控制
- 提供了更細粒度的流量控制,允許客戶端和服務器控制數據流的速率和優先級,這對于高吞吐量和低延遲的通信非常的重要
頭部壓縮
- http/2使用HPACK壓縮算法對HTTP頭部進行壓縮,減少了請求和響應的大小,提高了傳輸效率
服務器推送
- 可以在服務器請求之前發送資源
### 介紹一下http1.0/http1.1/http2/http3
1.0
- 單個請求響應模型
- 無狀態
- 基本的緩存控制
- 缺乏持久連接
1.1
- 持久連接
- 管道化
- 更好的緩存控制
- 分塊傳輸編碼
- 帶寬優化和內容協商
有隊頭阻塞問題
多請求復用單連接效果有限
2
- 二進制分幀
- 多路復用
- 頭部壓縮
- 服務器推送
3
- 基于QUIC協議
- 減少連接建立時間
- 消除隊頭阻塞
- 更快的握手過程
- 改進丟包的處理
HTTP/1.0:簡單的單請求-響應模型,適合早期Web應用。
HTTP/1.1:引入持久連接和更好的緩存機制,但仍存在隊頭阻塞問題。
HTTP/2:二進制分幀、多路復用和頭部壓縮顯著提升性能。
HTTP/3:基于QUIC協議,通過UDP實現更快速和可靠的連接,進一步優化傳輸性能
### 訪問網頁全過程:
用戶輸入url
DNS 解析:
- 瀏覽器緩存
- 操作系統緩存
- 本地hosts文件
- 遞歸DNS查詢
TCP連接建立
三次握手
發送HTTP請求
服務器處理請求
請求解析
生成響應
服務器發送響應
- 分片發送
- 數據包處理
瀏覽器接收和渲染
數據包處理細節
-
ip數據包處理
-
TCP數據包處理
-
數據包重組
TLS和SSL
如果是加密的三次握手之后要加上:
- 客戶端發送client Hello消息,包含支持加密算法和TLS版本
- 服務器回應severHello消息,選擇加密算法和TLS版本,并發送服務器證書
- 客戶端驗證證書,發送Pre-Master Secret,雙方生成會話密鑰
- 雙方使用會話密鑰進行加密通信
### 常用的docker命令:
docker version
docker pull
docker exec -it bin/bash
docker-compose up
docker-compose down
docker-compose logs
docker-compose ps
docker ps
docker network ls
docker images
docker pull
docker push
docker build -t
docker rmi
docker run
docker start
restart stop rm logs
容器和鏡像的關系,容器是鏡像的一個實例
容器異常排查異常原因:
docker logs
dockers ps -a
進入容器進行查看
檢查docker事件
docker events --since “1h”
顯示過去一小時內的dockers事件日志
k8s管理docker
Docker 負責容器的創建、運行和管理,是容器化應用的基礎。
Kubernetes 負責容器的編排和集群管理,提供了自動化部署、擴展和管理的功能。
k8s的基本概念
Master Node
-
Master Node
:位于圖的上方中央,用于管理和協調整個 Kubernetes 集群。它包含以下組件:
- API Server:處理所有的 API 請求。
- Scheduler:負責將 Pod 分配到適當的 Node。
- Controller Manager:管理控制循環,確保集群處于期望狀態。
- etcd:存儲集群的所有數據。
Node
-
Node
:實際運行應用程序的工作節點。圖中展示了三個 Node(Node 1、Node 2、Node N),每個 Node 上運行以下組件:
- kubelet:管理該 Node 上的 Pod 和容器。
- kube-proxy:處理 Pod 網絡規則。
- 容器運行時(如 Docker 或 containerd):實際運行容器。
Pod
- Pod:Kubernetes 中的最小部署單元,每個 Node 上可以運行多個 Pod。圖中展示了每個 Node 上運行的 Pod。
Namespace
- Namespace:用于邏輯上隔離和組織資源的機制。圖中展示了一個包含所有 Node 和 Pod 的虛線框表示的 Namespace。
Controller
- Controller(如 Deployment、StatefulSet 等):通過自動化的控制循環管理 Pod 的生命周期。圖中用箭頭和文字標示在 Master Node 下方。
HPA (Horizontal Pod Autoscaler)
- HPA:根據負載自動調整 Pod 的副本數,圖中在中央用箭頭和文字標示。
Service
- Service:定義了一組 Pod 的邏輯集合,并提供穩定的訪問方式。圖中在右側用箭頭和文字標示。
### tcp擁塞控制
TCP擁塞控制是TCP協議中的一個重要功能,用于在網絡擁塞時調整數據傳輸的速率,以避免網絡擁塞進一步加劇或導致丟包。TCP擁塞控制主要通過四個算法來實現:
- 慢啟動(Slow Start):TCP連接剛建立時,發送方會將擁塞窗口(Congestion Window)初始化為一個較小的值,然后隨著時間的推移,擁塞窗口逐漸增加,指數增長,直到達到一個閾值(慢啟動閾值)。
- 擁塞避免(Congestion Avoidance):一旦擁塞窗口的大小達到了慢啟動閾值,TCP發送方就會進入擁塞避免階段。在這個階段,擁塞窗口的增長速率變為線性增長,而不再是指數增長,以避免過快地向網絡注入數據。
- 快重傳(Fast Retransmit):當發送方連續收到三個重復的確認(ACK)時,它會認為有一個數據包丟失,并立即重傳該數據包,而不必等待超時發生。
- 快恢復(Fast Recovery):在快重傳之后,TCP連接進入快恢復狀態,擁塞窗口的大小會減半,然后采用擁塞避免的方式逐漸增加。
這些算法共同作用,使得TCP連接可以根據網絡擁塞情況動態調整發送速率,從而維持網絡的穩定性和公平性。
### 進程線程協程三者
進程(Process)、線程(Thread)和協程(Coroutine)是計算機中用于實現并發執行的重要概念,它們分別在不同的層次和場景下提供了并發執行的機制。
- 進程(Process):
- 進程是操作系統進行資源分配和調度的基本單位,每個進程有自己獨立的地址空間和系統資源,包括內存、文件句柄、CPU時間等。
- 進程之間通常是獨立的,彼此隔離,不能直接訪問對方的資源,通信需要通過進程間通信(IPC)機制來實現,比如管道、消息隊列、共享內存等。
- 創建和銷毀進程的開銷相對較大,因為需要為每個進程分配獨立的地址空間和系統資源。
- 線程(Thread):
- 線程是進程內的一個獨立執行單元,多個線程共享相同的地址空間和系統資源,包括內存、文件句柄等。
- 線程之間可以通過共享內存等方式進行通信,但需要考慮同步和互斥問題,以避免數據競爭和資源爭用。
- 創建和銷毀線程的開銷相對較小,因為它們共享所屬進程的資源。
- 協程(Coroutine):
- 協程是一種輕量級的線程,它可以在同一個線程中實現并發執行,通過協作式調度實現多個任務之間的切換。
- 不同于線程的搶占式調度,協程是通過程序員主動讓出執行權給其他協程來實現的,因此不需要進行顯式的同步和互斥操作。
- 協程通常用于高效的異步編程,可以有效地利用單個線程的資源,實現大規模并發,提高系統的響應速度和性能。
在實際應用中,開發者需要根據具體的需求和場景選擇合適的并發模型。通常情況下,進程適用于需要隔離和安全性較高的場景,線程適用于需要共享資源和較小開銷的場景,而協程適用于需要高效利用單個線程資源和實現大規模并發的場景。
三者區別:
進程(Process)、線程(Thread)和協程(Coroutine)都是用于并發執行的概念,它們之間有一些關鍵區別:
-
并發模型:
- 進程:進程是操作系統進行資源分配和調度的基本單位,每個進程有自己獨立的地址空間和系統資源。進程之間通常通過進程間通信(IPC)進行通信。
- 線程:線程是進程內的一個獨立執行單元,多個線程共享相同的地址空間和系統資源。線程之間可以通過共享內存等方式進行通信,但需要考慮同步和互斥問題。
- 協程:協程是一種輕量級的線程,它可以在同一個線程中實現并發執行。不同于線程的搶占式調度,協程是通過協作式調度實現的,即協程主動讓出執行權給其他協程。
-
資源消耗:
- 進程:每個進程有自己獨立的地址空間和系統資源,創建和銷毀進程的開銷較大。
- 線程:線程共享所屬進程的資源,包括內存、文件句柄等,創建和銷毀線程的開銷相對較小。
- 協程:協程是在同一個線程內部執行,因此創建和銷毀協程的開銷很小。
-
并發性和并行性:
- 進程:不同進程之間是獨立的,可以在多核處理器上實現真正的并行執行。
- 線程:線程是進程內的執行單元,在單核處理器上通過線程切換實現并發執行,在多核處理器上也可以實現并行執行。
- 協程:協程在同一個線程內部執行,不能利用多核處理器實現真正的并行執行,但通過協作式調度可以實現并發執行。
-
通信機制:
- 進程:進程之間通信通常通過進程間通信(IPC)機制,如管道、消息隊列、共享內存等。
- 線程:線程之間可以通過共享內存等方式進行通信,但需要考慮同步和互斥問題。
- 協程:協程之間通常通過消息傳遞或共享數據進行通信,但由于是在同一個線程內部執行,通常不需要考慮同步和互斥問題。
總的來說,進程、線程和協程都是用于實現并發執行的機制,但它們的設計思想和適用場景有所不同,開發者需要根據具體的需求和場景選擇合適的并發模型。