本文內容和需要用到的兩個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共享, 可以看到最終效果了~