nginx入門級詳解及跨域問題的解決

代理和反向代理的概念?

不知道有多少人跟我一樣,對代理和反向代理矇蔽的,今天就來給大家普及一下。

在很久以前小明去吃飯,往往就是走進一家飯店然後打開菜單,點着他最愛的紅燒肉,然後等着老闆上菜,吃完交錢溜了溜了。這個時候小明和飯店是一對一的關係。客戶和服務商之間完全透明化,小明知道這家餐館的名字,餐館也知道小明的名字。

後來有了第三方訂餐外賣平臺(代理),小明懶得動身前往飯店,小明打個電話或用APP,先選好某個飯店,再點好菜,外賣小哥會送上門來。

由於某個品牌的飯店口碑特別好,食客絡繹不絕涌入,第三方訂餐電話也不絕於耳,但是限於飯店接待能力有限,無法提供及時服務,很多食客等得不耐煩了,紛紛鎩羽而歸,飯店老總看着煮熟的鴨子飛走了,心疼不已。

痛定思痛,老總又成立了幾個連鎖飯店,形成一個集羣,對外提供統一標準的菜品服務,電話訂餐電話當食客涌入飯店總檯,總檯將食客用大巴運到各個連鎖店,這樣食客既不需要排隊,各連鎖店都能高速運轉起來,一舉兩得,老總樂開了花,併爲此種運作模式起名爲“反向代理”(Reverse Proxy)。

反向代理
在計算機世界裏,由於單個服務器的處理客戶端(用戶)請求能力有一個極限,當用戶的接入請求蜂擁而入時,會造成服務器忙不過來的局面,可以使用多個服務器來共同分擔成千上萬的用戶請求,這些服務器提供相同的服務,對於用戶來說,根本感覺不到任何差別

反向代理的實現
1)需要有一個負載均衡設備來分發用戶請求,將用戶請求分發到空閒的服務器上

2)服務器返回自己的服務到負載均衡設備

3)負載均衡將服務器的服務返回用戶

以上的潛臺詞是:用戶和負載均衡設備直接通信,也意味着用戶做服務器域名解析時,解析得到的IP其實是負載均衡的IP,而不是服務器的IP,這樣有一個好處是,當新加入/移走服務器時,僅僅需要修改負載均衡的服務器列表,而不會影響現有的服務。

談完反向代理服務,再來談談終端用戶常用的代理服務。

代理
1)用戶希望代理服務器幫助自己,和要訪問服務器通信,爲了實現此目標,需要以下工作:

a) 用戶IP報文的目的IP = 代理服務器IP
b) 用戶報文端口號 = 代理服務器監聽端口號
c) HTTP 消息裏的URL要提供服務器的鏈接

2)代理服務器可以根據c)裏的鏈接與服務器直接通信

3)服務器返回網頁

4)代理服務器打包3)中的網頁,返回用戶。

代理服務器應用場景
場景一

如果不採用代理,用戶的IP、端口號直接暴露在Internet(儘管地址轉換NAT),外部主機依然可以根據IP、端口號來開採主機安全漏洞,所以在企業網,一般都是採用代理服務器訪問互聯網。

那有同學會有疑問,那代理服務器就沒有安全漏洞嗎?
相比千千萬萬的用戶主機,代理服務器數量有限,修補安全漏洞更方便快捷。

場景二
在一個超大型局域網,德高望重的家長覺得小盆友們“幼稚”、“有時還有點單純”,外部的世界是洪水猛獸,爲了不讓小盆友們學壞,決定不讓小盆友們訪問一些網站,可小盆友們有強烈的逆反心理,儂越是不讓我看,我越是想看,於是小盆友們使用了代理服務器,這些代理服務器將禁止訪問的網頁打包好,然後再轉交給小盆友,僅此而已。

當然關鍵的關鍵是代理服務器不在禁止名單當中!


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解決跨域問題

1.什麼是跨域以及產生原因

  跨域是指a頁面想獲取b頁面資源,如果a、b頁面的協議、域名、端口、子域名不同,或是a頁面爲ip地址,b頁面爲域名地址,所進行的訪問行動都是跨域的,而瀏覽器爲了安全問題一般都限制了跨域訪問,也就是不允許跨域請求資源。

  跨域情況如下:

 

url說明是否跨域
http://www.cnblogs.com/a.js
http://www.a.com/b.js
不同域名
http://www.a.com/lab/a.js
http://www.a.com/script/b.js
同一域名下不同文件夾
http://www.a.com:8000/a.js
http://www.a.com/b.js
同一域名,不同端口
http://www.a.com/a.js
https://www.a.com/b.js
同一域名,不同協議
http://www.a.com/a.js
http://70.32.92.74/b.js
域名和域名對應ip
http://www.a.com/a.js
http://script.a.com/b.js
主域相同,子域不同是(cookie不可訪問)
http://www.a.com/a.js
http://a.com/b.js

2.跨域的常見解決方法

目前來講沒有不依靠服務器端來跨域請求資源的技術

  1.jsonp 需要目標服務器配合一個callback函數。

  2.window.name+iframe 需要目標服務器響應window.name。

  3.window.location.hash+iframe 同樣需要目標服務器作處理。

  4.html5的 postMessage+ifrme 這個也是需要目標服務器或者說是目標頁面寫一個postMessage,主要側重於前端通訊。

  5.CORS  需要服務器設置header :Access-Control-Allow-Origin。

  6.nginx反向代理 這個方法一般很少有人提及,但是他可以不用目標服務器配合,不過需要你搭建一箇中轉nginx服務器,用於轉發請求。

3.nginx解決跨域問題

我先來說說自己遇到的問題。我有一套項目用的是Angularjs+html,angularjs必須掛到服務下面,所以我啓動了一個nginx來掛載angularjs服務。然後在我的js裏面去訪問本地數據庫也就是http://localhost:8080的服務報出了跨域問題,

其實Nginx解決跨域問題的思路很簡單,既然兩個服務的端口號和域名不匹配,那麼我把他代理成端口號和域名一樣不就沒有跨域問題了,這個方法簡直就是絕妙了。只需要我們配置多個location就好。一般來說一個請求url過來,nginx會將它解析到某一個location來處理。這個解析的過程實際上根據location的配置基本可以分爲字符串匹配和正則表達式匹配這2種。對於location的組織方式,最簡單的就是直接將它們保存爲一個鏈表,解析url的時候一個一個遍歷即可找到相應location。

所以我們先配置第一個location,他是用來讀取我們的html和js的。

  location / {
            root   html\angulr;
            index  index.html;
        }

然後再配置我們的第二個location,第二個location說白了就是配置我們的ajax請求的URL,用來轉發到我們的真實請求。

location ^~/manage/ {
	    proxy_pass http://192.168.0.163:8080/manage/;
	}

來看一下js和匹配規則

$http.post('manage/get_my_data',angular.toJson($scope.queryContent)).success(function (largeLoad) {
    		 $scope.users=largeLoad.data.users;
    	
         });
這裏的話,發送一個請求,系統會根據manage這個字段進行匹配,然後找到nginx匹配的請求,轉發到我們真實的請求,這樣瀏覽器就認爲js和服務器在同一個域名同一個ip裏面,就不會出現跨域問題了。當然關於location還有很多匹配規則和正則匹配,這個後面再繼續深入理解。


當然在解決跨域問題的時候遇到了一些麻煩,和誤解。在這裏要多謝大佬的幫忙非常感謝54powerman


發佈了181 篇原創文章 · 獲贊 300 · 訪問量 69萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章