使用命令 nginx -vhtml
一個在本身機器上(192.168.1.120),一個在測試服務器(192.168.8.110)上。服務端口均爲1008。java
調用rest服務時向一張表nginx_test中寫入數據。nginx
訪問url:web
/nginxTest/insert(接口添加到不用作驗證的接口列表)redis
192.168.1.120服務上實例向數據庫表寫入字段666spring
192.168.8.110服務上實例向數據庫寫入字段8.110sql
#user nobody; worker_processes 1; #error_log logs/error.log; #error_log logs/error.log notice; #error_log logs/error.log info; #pid logs/nginx.pid; events { worker_connections 1024; } http { include mime.types; default_type application/x-www-form-urlencoded; #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; error_log logs/access.log info; sendfile on; #tcp_nopush on; #keepalive_timeout 0; keepalive_timeout 65; #gzip on; upstream tomcats { server 192.168.1.120:1008 weight=1; server 192.168.8.110:1008 weight=2; } server { listen 80; location / { proxy_pass http://tomcats; } } }
SET FOREIGN_KEY_CHECKS=0; -- ---------------------------- -- Table structure for nginx_test -- ---------------------------- DROP TABLE IF EXISTS `nginx_test`; CREATE TABLE `nginx_test` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `ip` varchar(20) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=28 DEFAULT CHARSET=utf8;
package com.richfit.ruiche.nginxTest.controller; import javax.servlet.http.HttpServletRequest; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import com.richfit.ruiche.nginxTest.service.NginxTestService; @RestController @RequestMapping(value = "/nginxTest") public class NginxTestController { private static final String ip = "666"; // private static final String ip = "8.110"; @Autowired private NginxTestService nginxTestService; @RequestMapping(value = "/insert") public void insert(HttpServletRequest request) throws NoSuchMethodException, SecurityException{ nginxTestService.insert(ip); } }
package com.richfit.ruiche.nginxTest.service; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import com.richfit.ruiche.nginxTest.mapper.NginxTestMapper; @Service public class NginxTestService { @Autowired private NginxTestMapper nginxTestMapper; public void insert(String ip){ nginxTestMapper.insert(ip); } }
package com.richfit.ruiche.nginxTest.mapper; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @Mapper public interface NginxTestMapper { void insert(@Param(value="ip")String ip); }
<?xml version = "1.0" encoding = "UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD com.example.Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace = "com.richfit.ruiche.nginxTest.mapper.NginxTestMapper"> <insert id="insert" parameterType="string"> <![CDATA[ INSERT INTO nginx_test ( ip ) VALUES ( #{ip} ) ]]> </insert> </mapper>
配置文件爲nginx.conf,位置以下數據庫
直接訪問nginx服務器的地址(由於nginx配置的是80端口,因此這裏沒寫):apache
http://localhost/nginxTest/insertwindows
配置文件的關鍵部分寫成以下這樣:
upstream tomcats { server 192.168.1.120:1008; server 192.168.8.110:1008; } server { listen 80; location / { proxy_pass http://tomcats; } }
那麼默認就是按輪詢的方式進行的,先服務器1,再服務器2,再服務器1,依次輪詢。。。
關閉192.168.1.120服務器(即本機),那麼發現服務都轉發到了192.168.8.110了。可見nginx很強大。
upstream tomcats { server 192.168.1.120:1008 weight=1; server 192.168.8.110:1008 weight=2; } server { listen 80; location / { proxy_pass http://tomcats; } }
如上weight就是權重。如上配置的話,就會訪問1次192.168.1.120,而後訪問2次192.168.8.110,而後訪問1次192.168.1.120,而後訪問2次192.168.8.110。。。
實際中訪問的是server,
可是server只是個代理,將請求轉發給了服務器組。具體的訪問策略,則根據nginx的規則本身選擇。
一、輪詢
輪詢即Round Robin,根據Nginx配置文件中的順序,依次把客戶端的Web請求分發到不一樣的後端服務器上。若是後端服務器down掉,能自動剔除。
二、最少鏈接 least_conn;
Web請求會被轉發到鏈接數最少的服務器上。
三、IP地址哈希 ip_hash;
每一個請求按訪問ip的hash結果分配,這樣每一個訪客固定訪問一個後端服務器,能夠解決session的問題。
四、基於權重 weight
指定輪詢概率,weight和訪問比率成正比,用於後端服務器性能不均的狀況。
upstream tomcats { server 192.168.1.120:1008 weight=1; server 192.168.8.110:1008 weight=2; } server { listen 80; location / { proxy_pass http://tomcats; } }
proxy_pass http://tomcats:表示將全部請求轉發到tomcats服務器組中配置的某一臺服務器上。tomcats是服務器組的名稱。
upstream模塊:配置反向代理服務器組,Nginx會根據配置,將請求分發給組裏的某一臺服務器。tomcats是服務器組的名稱。
upstream模塊下的server指令:配置處理請求的服務器IP或域名,端口可選,不配置默認使用80端口。
可用性提升:運行多個服務實例,好比兩個,因爲機器故障一個down時,服務整體仍可用。
性能提升:提升併發訪問數量。
我係統中沒有使用session。
我在系統中使用的不是session,而是在token中夾帶了不少信息。如何判斷用戶是否掉線了呢?
用戶首次登陸成功時,用redis或者guava緩存新增LoginMap<Long userId,DataTime loginTime>。
有個定時任務定時掃描LoginMap,若上次訪問時間loginTime超過設置時間(好比1個小時),則將該key-value踢出LoginMap。
後面每次訪問根據userId先查看LoginMap是否存在值,若存在直接可進入系統並刷新 loginTime;若不存在則須要從新登陸。
使用redis或者guava存儲LoginMap<Long userId,DataTime loginTime>都可。
此時使用guava不能夠了。由於guava是跟隨服務實例的,不是全局的,確定會形成混亂。
此時使用redis便可,無論幾個服務實例,都使用redis存儲LoginMap<Long userId,DataTime loginTime>。由於redis是全局的,全部服務實例共享redis,跟單機其實是同樣的。
實現負載均衡經常使用的Web服務器軟件有Nginx、HAProxy、LVS、Apache。