一、nginx高併發原理( 多進程+epoll實現高併發 )javascript
1. Nginx 在啓動後,會有一個 master 進程和多個相互獨立的 worker 進程。php
2. 每一個子進程只有一個線程,採用的 IO多路複用模型epoll,實現高併發。css
二、epoll能實現高併發原理html
1. epoll() 中內核則維護一個鏈表,epoll_wait 方法能夠獲取到鏈表長度,不爲0就知道文件描述符準備好了。vue
2. 在內核實現中 epoll 是根據每一個 sockfd 上面的與設備驅動程序創建起來的回調函數實現的。java
3. 某個 sockfd 上的事件發生時,與它對應的回調函數就會被調用,來把這個 sockfd 加入鏈表,其餘處於「空閒的」狀態的則不會。node
4. epoll上面鏈表中獲取文件描述,這裏使用內存映射(mmap)技術, 避免了複製大量文件描述符帶來的開銷linux
內存映射(mmap):內存映射文件,是由一個文件到一塊內存的映射,將沒必要再對文件執行I/O操做nginx
三、nginx和apache比較web
1)nginx相對於apache的優勢
1. 輕量級,一樣起web 服務,比apache 佔用更少的內存及資源
2. 抗併發,nginx 處理請求是異步非阻塞的,而apache 則是阻塞型的,在高併發下nginx 能保持低資源低消耗高性能
3. 高度模塊化的設計,編寫模塊相對簡單,社區活躍,各類高性能模塊出品迅速啊
2)apache 相對於nginx 的優勢
1. apache 更爲成熟,少 bug ,穩定性好
2. rewrite ,比nginx 的rewrite 強大
3. 模塊超多,基本想到的均可以找到
一、正向代理
1. 我訪問不了某網站,可是我能訪問一個代理服務器,這個代理服務器呢,他能訪問那個我不能訪問的網站
2. 因而我先連上代理服務器,告訴他我須要那個沒法訪問網站的內容,代理服務器去取回來,而後返回給我。
3. 客戶端必須設置正向代理服務器,固然前提是要知道正向代理服務器的IP地址,還有代理程序的端口。
4. 例如以前使用過這類軟件例如CCproxy,http://www.ccproxy.com/ 須要在瀏覽器中配置代理的地址。
正向代理做用:
1)訪問原來沒法訪問的資源,如google
2) 能夠作緩存,加速訪問資源
3)對客戶端訪問受權,上網進行認證
4)代理能夠記錄用戶訪問記錄(上網行爲管理),對外隱藏用戶信息
二、反向代理
1. 反向代理對用戶透明,客戶端無需任何配置便可訪問服務。
2. 實際運行方式是指以代理服務器來接受internet上的鏈接請求,而後將請求轉發給內部網絡上的服務器。
3. 並將從服務器上獲得的結果返回給internet上請求鏈接的客戶端,此時代理服務器對外就表現爲一個服務器。
三、反向代理使用場景
1)保證內網的安全,可使用反向代理提供WAF功能,阻止web攻擊
例:大型網站,一般將反向代理做爲公網訪問地址,Web服務器是內網
2)負載均衡,經過反向代理服務器來優化網站的負載
一、nginx配置文件註釋
#運行用戶 user nobody; #啓動進程,一般設置成和cpu的數量相等 worker_processes 1; #全局錯誤日誌及PID文件 #error_log logs/error.log; #error_log logs/error.log notice; #error_log logs/error.log info; #pid logs/nginx.pid; #工做模式及鏈接數上限 events { #epoll是多路複用IO(I/O Multiplexing)中的一種方式, #僅用於linux2.6以上內核,能夠大大提升nginx的性能 use epoll; #單個後臺worker process進程的最大併發連接數 worker_connections 1024; # 併發總數是 worker_processes 和 worker_connections 的乘積 # 即 max_clients = worker_processes * worker_connections # 在設置了反向代理的狀況下,max_clients = worker_processes * worker_connections / 4 爲何 # 爲何上面反向代理要除以4,應該說是一個經驗值 # 根據以上條件,正常狀況下的Nginx Server能夠應付的最大鏈接數爲:4 * 8000 = 32000 # worker_connections 值的設置跟物理內存大小有關 # 由於併發受IO約束,max_clients的值須小於系統能夠打開的最大文件數 # 而系統能夠打開的最大文件數和內存大小成正比,通常1GB內存的機器上能夠打開的文件數大約是10萬左右 # 咱們來看看360M內存的VPS能夠打開的文件句柄數是多少: # $ cat /proc/sys/fs/file-max # 輸出 34336 # 32000 < 34336,即併發鏈接總數小於系統能夠打開的文件句柄總數,這樣就在操做系統能夠承受的範圍以內 # 因此,worker_connections 的值需根據 worker_processes 進程數目和系統能夠打開的最大文件總數進行適當地進行設置 # 使得併發總數小於操做系統能夠打開的最大文件數目 # 其實質也就是根據主機的物理CPU和內存進行配置 # 固然,理論上的併發總數可能會和實際有所誤差,由於主機還有其餘的工做進程須要消耗系統資源。 # ulimit -SHn 65535 } http { #設定mime類型,類型由mime.type文件定義 include mime.types; default_type application/octet-stream; #設定日誌格式 log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; access_log logs/access.log main; #sendfile 指令指定 nginx 是否調用 sendfile 函數(zero copy 方式)來輸出文件, #對於普通應用,必須設爲 on, #若是用來進行下載等應用磁盤IO重負載應用,可設置爲 off, #以平衡磁盤與網絡I/O處理速度,下降系統的uptime. sendfile on; #tcp_nopush on; #鏈接超時時間 #keepalive_timeout 0; keepalive_timeout 65; tcp_nodelay on; #開啓gzip壓縮 gzip on; gzip_disable "MSIE [1-6]."; #設定請求緩衝 client_header_buffer_size 128k; large_client_header_buffers 4 128k; #設定虛擬主機配置 server { #偵聽80端口 listen 80; #定義使用 www.nginx.cn訪問 server_name www.nginx.cn; #定義服務器的默認網站根目錄位置 root html; #設定本虛擬主機的訪問日誌 access_log logs/nginx.access.log main; #默認請求 location / { #定義首頁索引文件的名稱 index index.php index.html index.htm; } # 定義錯誤提示頁面 error_page 500 502 503 504 /50x.html; location = /50x.html { } #靜態文件,nginx本身處理 location ~ ^/(images|javascript|js|css|flash|media|static)/ { #過時30天,靜態文件不怎麼更新,過時能夠設大一點, #若是頻繁更新,則能夠設置得小一點。 expires 30d; } #PHP 腳本請求所有轉發到 FastCGI處理. 使用FastCGI默認配置. location ~ .php$ { fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; } #禁止訪問 .htxxx 文件 location ~ /.ht { deny all; } } }
二、nginx配置舉例
user work; worker_processes 8; worker_rlimit_nofile 65535; error_log logs/error.log warn; #error_log logs/error.log notice; #error_log logs/error.log info; pid logs/nginx.pid; events { use epoll; worker_connections 65535; } # load modules compiled as Dynamic Shared Object (DSO) # #dso { # load ngx_http_fastcgi_module.so; # load ngx_http_rewrite_module.so; #} http { include mime.types; default_type application/octet-stream; server_names_hash_bucket_size 128; sendfile on; tcp_nopush on; tcp_nodelay on; fastcgi_connect_timeout 5; fastcgi_send_timeout 10; fastcgi_read_timeout 10; fastcgi_buffer_size 64k; fastcgi_buffers 4 64k; fastcgi_busy_buffers_size 128k; fastcgi_temp_file_write_size 128k; #keepalive_timeout 0; keepalive_timeout 60; keepalive_requests 1024; client_header_buffer_size 4k; large_client_header_buffers 4 32k; client_max_body_size 10m; client_body_buffer_size 512k; client_body_timeout 600; client_header_timeout 600; send_timeout 600; proxy_connect_timeout 1000ms; proxy_send_timeout 2000000ms; proxy_read_timeout 2000000ms; proxy_buffers 64 8k; proxy_busy_buffers_size 128k; proxy_temp_file_write_size 64k; proxy_redirect off; #proxy_next_upstream off ; gzip on; gzip_min_length 1k; gzip_buffers 4 16k; gzip_http_version 1.0; gzip_comp_level 2; gzip_types text/plain application/x-javascript text/css application/xml; gzip_vary on; add_header X-Frame-Options "ALLOW-FROM http://cloud.njsig.cn"; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Real-Port $remote_port; proxy_set_header Host $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" "$http_cookie" "$http_user_agent" ' '$request_time $remote_addr $server_addr $upstream_addr $host ' '"$http_x_forwarded_for" $upstream_response_time'; set_real_ip_from 10.0.0.0/8; real_ip_header X-Real-IP; #example # server { # listen 8000; # server_name www; # access_log logs/access.log main; # location / { # proxy_pass http://127.0.0.1:8001; # } # # # } include vhosts/*.conf; } #####
server { listen 80; server_name aaa.test.com bbb.test.com; access_log /home/work/nginx/logs/opwf_access.log main; location / { proxy_pass http://127.0.0.1:8001; } }
server { listen 80; server_name ccc.test.com; access_log /home/work/nginx/logs/nj1_access.log main; root /home/work/project/frontopwf/dist; location / { try_files $uri $uri/ @router; } location @router { rewrite ^.*$ /index.html last; } }
一、搭建實驗環境(使用docker部署兩臺nginx容器)
1)使用搭建第一臺nginx服務
[root@linux-node4 ~]# docker container run -d --name web01 -p 81:80 nginx 測試訪問:http://192.168.56.14:81/ root@c58a7f1fb89d:/# docker exec -it web01 bash root@c58a7f1fb89d:/# echo web01 > /usr/share/nginx/html/index.html
2)使用docker搭建第二臺nginx服務
[root@linux-node4 ~]# docker container run -d --name web02 -p 82:80 nginx 測試訪問:http://192.168.56.14:82/ root@a3440d30f27c:/# docker exec -it web02 bash root@a3440d30f27c:/# echo web02 > /usr/share/nginx/html/index.html
二、法1:默認輪訓(在真實主機中安裝nginx並配置負載均衡)
輪訓:每一個請求按時間順序逐一分配到不一樣的後端服務器,若是後端服務器down掉,能自動剔除。
[root@linux-node4 ~]# yum -y install nginx [root@linux-node4 ~]# vim /etc/nginx/nginx.conf #### 修改nginx.conf 默認是輪訓 ####
''' # 1. upstream是本身寫的,必定要放在server外面 upstream myservers { server 192.168.56.14:81; server 192.168.56.14:82; } # 2. server其實默認已經有一個,只須要修改location中配置,指定轉發代理便可 server { location / { proxy_pass http://myservers; } } ''' [root@linux-node4 nginx]# systemctl start nginx
三、負載均衡經常使用配置梳理
1、輪詢(默認) 每一個請求按時間順序逐一分配到不一樣的後端服務器,若是後端服務器down掉,能自動剔除。 upstream backserver { server 192.168.0.14; server 192.168.0.15; } 2、權重 weight 指定輪詢概率,weight和訪問比率成正比,用於後端服務器性能不均的狀況。 upstream backserver { server 192.168.0.14 weight=3; server 192.168.0.15 weight=7; } 3、ip_hash( IP綁定) 上述方式存在一個問題就是說,在負載均衡系統中,假如用戶在某臺服務器上登陸了,那麼該用戶第二次請求的時候,由於咱們是負載均衡系統,
每次請求都會從新定位到服務器集羣中的某一個,那麼已經登陸某一個服務器的用戶再從新定位到另外一個服務器,其登陸信息將會丟失,這樣顯然是不妥的。 咱們能夠採用ip_hash指令解決這個問題,若是客戶已經訪問了某個服務器,當用戶再次訪問時,會將該請求經過哈希算法,自動定位到該服務器。 每一個請求按訪問ip的hash結果分配,這樣每一個訪客固定訪問一個後端服務器,能夠解決session的問題。 upstream backserver { ip_hash; server 192.168.0.14:88; server 192.168.0.15:80; } 4、fair(第三方插件) 按後端服務器的響應時間來分配請求,響應時間短的優先分配。 upstream backserver { server server1; server server2; fair; } 5、url_hash(第三方插件) 按訪問url的hash結果來分配請求,使每一個url定向到同一個後端服務器,後端服務器爲緩存時比較有效。 upstream backserver { server squid1:3128; server squid2:3128; hash $request_uri; hash_method crc32; }