基於Springboot 用nginx做反向代理實現動靜結合 給tomcat的集羣做負載均衡和Session共享

本文內容和需要用到的兩個Springboot程序我放到了github上, 可以直接下載, 另外需要用的nginx的配置文件也放入了github中, 可以直接下載

一.基本原理

前置副本:什麼是nginx呢

在我的理解來說:
nginx就是一個HTTP服務器, 或者說的更具體他常被用作一個靜態資源服務器, 可以解析請求然後返回對應的靜態文件, 比如html, css, 圖片視頻什麼的, 但是不能處理動態請求, 比如jsp之類的, 就類似於apache, 要處理動態請求得藉助像php這樣的腳本語言;

那麼爲什麼要用nginx呢, 因爲他能實現非常高效的反向代理和負載均衡, 性能非常好;

1.反向代理:

就是我訪問nginx的服務器, 比如我要訪問天貓網站的搜索頁面, 但是我不訪問tmall.com(假設這是一個tomcat服務器), 而是去訪問xyz.com(假設這是一個nginx服務器), 但在這個nginx服務器上並沒有完整的搜索頁面, 他就會把請求轉發給tomcat, 然後獲得response之後發給客戶, 對於客戶而言看似就是從nginx服務器上獲取了頁面, 但其實nginx上是沒有頁面的, 他是反向代理了tomcat;

1.2正向代理:

既然有反向代理自然有正向代理啦, 比如我要訪問tudou.com, 但是我使用了正向代理, 比如vpn, 那麼我輸入tudou.com這個網址訪問, 其實我們訪問的是另外一個服務器, 而不是土豆的服務器, 然後再由那個服務器去訪問tudou.com並把獲得的頁面返回給客戶端, 在用戶看來似乎就是直接訪問了tudou.com;

2.動靜結合

其實在nginx服務器上也並不是什麼都沒有, 上面會存有一些靜態資源, 比如我要訪問天貓網站的搜索界面, 其中搜索內容是變化的, 是動態的, 要去向tomcat去request, 但是有一些內容是靜態的, 比如footer.html這樣的頁眉頁腳, 還有一些圖片視頻啥的, 是可以直接放在nginx上的, 那麼這些內容就不需要向tomcat去請求了, 這樣就非常大程度上減小了tomcat的壓力, 實現動靜結合;

3.負載均衡

在nginx的配置中配置反向代理後, 可以配置反向代理到多個服務器, 對每個服務器設置對應的weight權重, 就可以簡單的配置負載均衡了;

4.Session共享

比如我現在有兩個tomcat服務器做了按負載均衡, 然後我第一次連接練到了A服務器, 並且登錄了, 然後這時候突然被我的流量被分到了B服務器上, 但是此時我在B服務器上還沒有登錄, 所以我要重新登錄, 這樣就很不方便, 所以需要做多個負載均衡的服務器上的Session共享;



二.代碼實現

前置副本:準備兩個完全一樣的Springboot程序並且配置到不同端口模擬多服務器(我配置到了8081和8082端口)

這裏兩個Springboot程序我放到了github上, 可以直接下載
說一下這裏面我做了什麼:
首先我寫了兩個簡單的springboot項目, 分別配置到了8081和8082端口, 然後實現了這樣的功能, 當你訪問127.0.0.1/hello的時候, 會看到一個妹子照片, 此時在session中寫入一個user變量, 然後在訪問127.0.0.1/who的時候會顯示出來session中的user的值, 並清空session中的user變量, 所以刷新who頁面之後就看不到session中user的內容了;
然後在tomcat的控制檯中, 可以看到當前訪問了什麼樣的url;

最終我希望實現什麼樣的結果呢:
當我配置好了反向代理, 負載均衡, 動靜結合, session共享之後;
我應該能看到: 我訪問127.0.0.1:9090/hello這是nginx的服務器端口, 然後我能進入到8081或者8082服務器的hello頁面, 並且設置session, 再進入who頁面, 查看到session, 刷新後session清楚, 顯示nothing; 同時當我們查看tomcat的控制檯輸出的時候, 可以看到8081和8082的服務器都有流量訪問, 而且是在nginx負載均衡的情況下, 各自有概率地訪問, 而且看到靜態資源比如說圖片並沒有走tomcat獲取, 而是走nginx獲取

這裏在沒有配置session共享之前, 會查看到進入hello頁面後設置了session, 但是進入who頁面不一定能看到session中user的內容, 因爲此時可能訪問的是還沒有設置過session的另一個服務器;

1.配置反向代理

我使用的是mac系統, 關於nginx安裝配置的內容可以看我這篇博客mac下安裝配置nginx
首先找到nginx.conf這個文件, 這是對nginx做配置的配置文件, 找到這一段, 改成:

        location / {
            proxy_pass http://127.0.0.1:8081;
            root   html;
            index  index.html index.htm;
    }

這裏的意思是把所有的流量全部通過proxy代理到http://127.0.0.1:8081這個本地的8081端口;
這裏就實現了反向代理;

2.動靜結合

在這裏我們希望靜態資源使用nginx獲取, 而動態資源從tomcat獲取, 在nginx.conf文件中, 在上面的配置信息的下方, 加上一段:

        location / {
            proxy_pass http://tomcat80818082;
            root   html;
            index  index.html index.htm;
        }

        location ~\.(css|js|jpg)$ {
        	root /your_ocation/nginx/nginxtest2/src/main/resources/static;
	    }

注意, 這一段root /your_ocation/nginx/nginxtest2/src/main/resources/static;要改成你自己的靜態資源放置的位置, 可以進入我前面提供的springboot項目文件, 任選一個進入其中的nginxtest2/src/main/resources/static這個目錄下獲取真實路徑複製進來即可;

3.負載均衡

我之前已經準備好了兩個tomcat的服務器, 分別在8081和8082端口, 所以我現在要做這兩個服務器的負載均衡, 首先創建一個upstream, 在nginx.conf大概這樣操作:

    #keepalive_timeout  0;
    keepalive_timeout  65;

    #gzip  on;

    upstream tomcat80818082{
    server  127.0.0.1:8081  weight=1;
    server  127.0.0.1:8082 weight=2;
    }

    server {
        listen       9090;
        server_name  localhost;

新建一個upstream, 注意名字不能有下劃線, 然後在其中配置服務器的weight表示負載均衡是按照權重來做的;

然後把第一步中反向代理的服務器地址改爲:

        location / {
            proxy_pass http://tomcat80818082;
            root   html;
            index  index.html index.htm;
        }

講道理到這裏爲止, 已經配置完了反向代理, 動靜結合和負載均衡, 已經可以看到的效果是, 訪問localhost的9090端口的hello頁面, 得到的8081或者8082端口的服務器的頁面內容, 發現tomcat控制檯中顯示加載的圖片沒有從tomcat走, 刷新幾次hello頁面發現, 基本上8081和8082的流量是1:2的;

4.Session共享

現在要做Session的共享, 問題在於, 做完前一步, 我們希望可以看到先進入hello頁面設置了session, 然後進入who界面可以看到session中的user的值, 但是實際上有的時候, 可能hello訪問的是8081服務器但是who頁面就訪問到了8082服務器, 但是此時在8082服務器中還沒有設置session中的user, 所以看到的是nothing;
爲了解決這個問題我們需要做Session共享;(這一部分我已經放在我前面提供的項目文件裏了)

首先要在maven中導入兩個包, 用於session共享

<dependency>  
        <groupId>org.springframework.boot</groupId>  
        <artifactId>spring-boot-starter-redis</artifactId>  
</dependency>  
<dependency>  
        <groupId>org.springframework.session</groupId>  
        <artifactId>spring-session-data-redis</artifactId>  
</dependency> 

然後要配置一個RedisSessionConfig來配置redis的session



@Configuration  
@EnableRedisHttpSession  
public class RedisSessionConfig {  
}

然後在spring的propoties中配置redis的相關配置

spring.redis.host=localhost  
spring.redis.port=6379

這樣就能實現把Session存儲到redis裏
到這裏就實現了session共享, 可以看到最終效果了~

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章