Nginx實現高可用

Nginx Windows Linux HTML Tomcat 設計師 中央處理器 IT技術資源共享 2019-07-01

一、課程目標

Nginx介紹

Ningx應用場景

Windows環境下安裝Nginx

Windows環境下實現反向代理

Windows環境下實現負載均衡

Nginx實現網關接口跨域解決方案

Nginx實現防盜鏈

Nginx防止DDOS

Linux環境下安裝Nginx

Linux環境下實現反向代理

Linux環境下nginx+keepalived實現高可用

Linux環境下Session共享解決方案

高併發解決方案

一、nginx入門

1.1什麼是nginx?

nginx是一款高性能的http 服務器/反向代理服務器及電子郵件(IMAP/POP3)代理服務器。由俄羅斯的程序設計師Igor Sysoev所開發,官方測試nginx能夠支支撐5萬併發鏈接,並且cpu、內存等資源消耗卻非常低,運行非常穩定,所以現在很多知名的公司都在使用nginx。

1.2 nginx應用場景

1、http服務器。Nginx是一個http服務可以獨立提供http服務。可以做網頁靜態服務器。

2、虛擬主機。可以實現在一臺服務器虛擬出多個網站。例如個人網站使用的虛擬主機。

3、反向代理,負載均衡。當網站的訪問量達到一定程度後,單臺服務器不能滿足用戶的請求時,需要用多臺服務器集群可以使用nginx做反向代理。並且多臺服務器可以平均分擔負載,不會因為某臺服務器負載高宕機而某臺服務器閒置的情況。

Nginx實現高可用

1.3 Windows環境下安裝Nginx

解壓:nginx-windows

雙擊: nginx.exe

Nginx實現高可用

能看到nginx歡迎界面說明,nginx安裝成功

演示下 nginx做靜態服務器

1.3.1 windows常用命令

nginx.exe -s stop –停止

1.4 nginx優缺點

佔內存小,可以實現高併發連接、處理響應快。

可以實現http服務器、虛擬主機、反向代理、負載均衡。

nginx配置簡單

可以不暴露真實服務器IP地址

1.4 nginx.conf 介紹

1.4.1 nginx.conf文件的結構

nginx的配置由特定的標識符(指令符)分為多個不同的模塊。

指令符分為簡單指令和塊指令。

簡單指令格式:[name parameters;]

塊指令格式:和簡單指令格式有一樣的結構,但其結束標識符不是分號,而是大括號{},塊指令內部可以包含simple directives 和block directives, 可以稱塊指令為上下文(e.g. events, http, server, location)

conf文件中,所有不屬於塊指令的簡單指令都屬於main上下文的,http塊指令屬於main上下文,server塊指令http上下文。

1.4.2 配置靜態訪問

Web server很重要一部分工作就是提供靜態頁面的訪問,例如images, html page。nginx可以通過不同的配置,根據request請求,從本地的目錄提供不同的文件返回給客戶端。

打開安裝目錄下的nginx.conf文件,默認配置文件已經在http指令塊中創建了一個空的server塊,在nginx-1.8.0中的http塊中已經創建了一個默認的server塊。內容如下:

server {
listen 80;
server_name localhost;
location / {
root html;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}

1.4 nginx實現反向代理

1.4.1什麼是反向代理?

反向代理(Reverse Proxy)方式是指以代理服務器來接受internet上的連接請求,然後將請求轉發給內部網絡上的服務器,並將從服務器上得到的結果返回給internet上請求連接的客戶端,此時代理服務器對外就表現為一個反向代理服務器。

啟動一個Tomcat 127.0.0.1:8080

使用nginx反向代理 8080.itmayiedu.com 直接跳轉到127.0.0.1:8080

1.4.1Host文件新增

127.0.0.1 8080.itmayiedu.com
127.0.0.1 b8081.itmayiedu.com

1.4.2 nginx.conf 配置

配置信息:

 server {
listen 80;
server_name 8080.itmayiedu.com;
location / {
proxy_pass http://127.0.0.1:8080;
index index.html index.htm;
}
}
server {
listen 80;
server_name b8081.itmayiedu.com;
location / {
proxy_pass http://127.0.0.1:8081;
index index.html index.htm;
}
}

1.5 nginx實現負載均衡

1.5.1什麼是負載均衡

負載均衡 建立在現有網絡結構之上,它提供了一種廉價有效透明的方法擴展網絡設備和服務器的帶寬、增加吞吐量、加強網絡數據處理能力、提高網絡的靈活性和可用性。

負載均衡,英文名稱為Load Balance,其意思就是分攤到多個操作單元上進行執行,例如Web服務器、FTP服務器、企業關鍵應用服務器和其它關鍵任務服務器等,從而共同完成工作任務。

Nginx實現高可用

1.5.3負載均衡策略

1、輪詢(默認)
每個請求按時間順序逐一分配到不同的後端服務器,如果後端服務器down掉,能自動剔除。
upstream backserver {
server 192.168.0.14;
server 192.168.0.15;
}
2、指定權重
指定輪詢機率,weight和訪問比率成正比,用於後端服務器性能不均的情況。
upstream backserver {
server 192.168.0.14 weight=10;
server 192.168.0.15 weight=10;
}
3、IP綁定 ip_hash
每個請求按訪問ip的hash結果分配,這樣每個訪客固定訪問一個後端服務器,可以解決session的問題。
upstream backserver {
ip_hash;
server 192.168.0.14:88;
server 192.168.0.15:80;
}

1.5.4配置代碼

upstream backserver { 
server 127.0.0.1:8080;
server 127.0.0.1:8081;
}
server {
listen 80;
server_name www.itmayiedu.com;
location / {
proxy_pass http://backserver;
index index.html index.htm;
}
}

1.5.4宕機輪訓配置規則


server {
listen 80;
server_name www.itmayiedu.com;
location / {
proxy_pass http://backserver;
index index.html index.htm;
proxy_connect_timeout 1;
proxy_send_timeout 1;
proxy_read_timeout 1;
}

}

1.6 nginx解決網站跨域問題

server {
listen 80;
server_name www.itmayiedu.com;
location /A {
proxy_pass http://a.a.com:81/A;
index index.html index.htm;
}
location /B {
proxy_pass http://b.b.com:81/B;
index index.html index.htm;
}
}

1.7 nginx配置防盜鏈

location ~ .*\.(jpg|jpeg|JPG|png|gif|icon)$ {
valid_referers blocked http://www.itmayiedu.com www.itmayiedu.com;
if ($invalid_referer) {
return 403;
}
}

1.7 nginx配置DDOS

1.7.1限制請求速度

設置Nginx、Nginx Plus的連接請求在一個真實用戶請求的合理範圍內。比如,如果你覺得一個正常用戶每兩秒可以請求一次登錄頁面,你就可以設置Nginx每兩秒鐘接收一個客戶端IP的請求(大約等同於每分鐘30個請求)。

limit_req_zone $binary_remote_addr zone=one:10m rate=30r/m;

server {

...

location /login.html {

limit_req zone=one;

...

}

}

limit_req_zone命令設置了一個叫one的共享內存區來存儲請求狀態的特定鍵值,在上面的例子中是客戶端IP($binary_remote_addr)。location塊中的limit_req通過引用one共享內存區來實現限制訪問/login.html的目的。

1.7.1限制請求速度

設置Nginx、Nginx Plus的連接數在一個真實用戶請求的合理範圍內。比如,你可以設置每個客戶端IP連接/store不可以超過10個。

三、linux操作nginx

Nginx是一款輕量級的網頁服務器、反向代理服務器。相較於Apache、lighttpd具有佔有內存少,穩定性高等優勢。它最常的用途是提供反向代理服務。

3.1 linux安裝

在Centos下,yum源不提供nginx的安裝,可以通過切換yum源的方法獲取安裝。也可以通過直接下載安裝包的方法,以下命令均需root權限執行:

首先安裝必要的庫(nginx 中gzip模塊需要 zlib 庫,rewrite模塊需要 pcre 庫,ssl 功能需要openssl庫)。選定/usr/local為安裝目錄,以下具體版本號根據實際改變。

3.1.1.安裝PCRE庫

$ cd /usr/local/
$ wget ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/pcre-8.36.tar.gz
$ tar -zxvf pcre-8.36.tar.gz
$ cd pcre-8.36
$ ./configure
$ make
$ make install

./configure報錯

configure: error: You need a C++ compiler for C++ support.

解決辦法

yum install -y gcc gcc-c++

3.1.2.安裝zlib庫

$ cd /usr/local/ 
$ wget http://zlib.net/zlib-1.2.8.tar.gz
$ tar -zxvf zlib-1.2.8.tar.gz
$ cd zlib-1.2.8
$ ./configure
$ make
$ make install

3.1.3.安裝ssl

$ cd /usr/local/
$ wget http://www.openssl.org/source/openssl-1.0.1j.tar.gz
$ tar -zxvf openssl-1.0.1j.tar.gz
$ ./config
$ make
$ make install

3.1.4.安裝nginx

$ cd /usr/local/
$ wget http://nginx.org/download/nginx-1.8.0.tar.gz
$ tar -zxvf nginx-1.8.0.tar.gz
$ cd nginx-1.8.0
$ ./configure --prefix=/usr/local/nginx
$ make
$ make install

安裝常見錯誤:

Nginx啟動提示找不到libpcre.so.1解決方法

如果是32位系統

[root@lee ~]# ln -s /usr/local/lib/libpcre.so.1 /lib

如果是64位系統

[root@lee ~]# ln -s /usr/local/lib/libpcre.so.1 /lib64

然後在啟動nginx就OK了

[root@lee ~]# /usr/local/webserver/nginx/sbin/nginx

3.2 啟動nginx

$ /usr/local/nginx/sbin/nginx

檢查是否啟動成功:

打開瀏覽器訪問此機器的 IP,如果瀏覽器出現 Welcome to nginx! 則表示 Nginx 已經安裝並運行成功。

3.2.1常用命令

重啟:

$ /usr/local/nginx/sbin/nginx 啟動命令

重啟:

$ /usr/local/nginx/sbin/nginx –s reload

停止:

$ /usr/local/nginx/sbin/nginx –s stop

測試配置文件是否正常:

$ /usr/local/nginx/sbin/nginx –t

強制關閉:

$ pkill nginx

3.2 啟動Nginx + Keepalived高可用

什麼是Keepalived

Keepalived是一個免費開源的,用C編寫的類似於layer3, 4 & 7交換機制軟件,具備我們平時說的第3層、第4層和第7層交換機的功能。主要提供loadbalancing(負載均衡)和 high-availability(高可用)功能,負載均衡實現需要依賴Linux的虛擬服務內核模塊(ipvs),而高可用是通過VRRP協議實現多臺機器之間的故障轉移服務。

Nginx實現高可用

上圖是Keepalived的功能體系結構,大致分兩層:用戶空間(user space)和內核空間(kernel space)。

內核空間:主要包括IPVS(IP虛擬服務器,用於實現網絡服務的負載均衡)和NETLINK(提供高級路由及其他相關的網絡功能)兩個部份。

用戶空間:

WatchDog:負載監控checkers和VRRP進程的狀況

VRRP Stack:負載負載均衡器之間的失敗切換FailOver,如果只用一個負載均稀器,則VRRP不是必須的。

Checkers:負責真實服務器的健康檢查healthchecking,是keepalived最主要的功能。換言之,可以沒有VRRP Stack,但健康檢查healthchecking是一定要有的。

IPVS wrapper:用戶發送設定的規則到內核ipvs代碼

Netlink Reflector:用來設定vrrp的vip地址等。

Netlink Reflector:用來設定vrrp的vip地址等。

Keepalived的所有功能是配置keepalived.conf文件來實現的。

3.2.1安裝keepalived

下載keepalived地址:http://www.keepalived.org/download.html

解壓安裝:

tar -zxvf keepalived-1.2.18.tar.gz -C /usr/local/

yum install -y openssl openssl-devel(需要安裝一個軟件包)

cd keepalived-1.2.18/ && ./configure --prefix=/usr/local/keepalived

make && make install

3.2.2keepalived安裝成Linux系統服務

將keepalived安裝成Linux系統服務,因為沒有使用keepalived的默認安裝路徑(默認路徑:/usr/local),安裝完成之後,需要做一些修改工作:

首先創建文件夾,將keepalived配置文件進行復制:

mkdir /etc/keepalived

cp /usr/local/keepalived/etc/keepalived/keepalived.conf /etc/keepalived/

然後複製keepalived腳本文件:

cp /usr/local/keepalived/etc/rc.d/init.d/keepalived /etc/init.d/

cp /usr/local/keepalived/etc/sysconfig/keepalived /etc/sysconfig/

ln -s /usr/local/sbin/keepalived /usr/sbin/

ln -s /usr/local/keepalived/sbin/keepalived /sbin/

可以設置開機啟動:chkconfig keepalived on,到此我們安裝完畢!

3.2.3keepalived 常用命令

service keepalived start

service keepalived stop

3.2.3 配置nginx主備自動重啟

第三步:對配置文件進行修改:vim /etc/keepalived/keepalived.conf

keepalived.conf配置文件說明:

(一)Master

! Configuration File for keepalived
global_defs {
router_id bhz005 ##標識節點的字符串,通常為hostname
}
##keepalived 會定時執行腳本並且對腳本的執行結果進行分析,動態調整vrrp_instance的優先級。這裡的權重weight 是與下面的優先級priority有關,如果執行了一次檢查腳本成功,則權重會-20,也就是由100 - 20 變成了80,Master 的優先級為80 就低於了Backup的優先級90,那麼會進行自動的主備切換。
如果腳本執行結果為0並且weight配置的值大於0,則優先級會相應增加。
如果腳本執行結果不為0 並且weight配置的值小於0,則優先級會相應減少。
vrrp_script chk_nginx {
script "/etc/keepalived/nginx_check.sh" ##執行腳本位置
interval 2 ##檢測時間間隔
weight -20 ## 如果條件成立則權重減20(-20)
}
##定義虛擬路由 VI_1為自定義標識。
vrrp_instance VI_1 {
state MASTER ## 主節點為MASTER,備份節點為BACKUP
## 綁定虛擬IP的網絡接口(網卡),與本機IP地址所在的網絡接口相同(我這裡是eth6)
interface eth6
virtual_router_id 172 ## 虛擬路由ID號
mcast_src_ip 192.168.1.172 ## 本機ip地址
priority 100 ##優先級配置(0-254的值)
Nopreempt ##
advert_int 1 ## 組播信息發送間隔,倆個節點必須配置一致,默認1s
authentication {
auth_type PASS
auth_pass bhz ## 真實生產環境下對密碼進行匹配
}
track_script {
chk_nginx
}
virtual_ipaddress {
192.168.1.170 ## 虛擬ip(vip),可以指定多個
}
}

(二)Backup

! Configuration File for keepalived

global_defs {

router_id bhz006

}

vrrp_script chk_nginx {

script "/etc/keepalived/nginx_check.sh"

interval 2

weight -20

}

vrrp_instance VI_1 {

state BACKUP

interface eth7

virtual_router_id 173

mcast_src_ip 192.168.1.173

priority 90 ##優先級配置

advert_int 1

authentication {

auth_type PASS

auth_pass bhz

}

track_script {

chk_nginx

}

virtual_ipaddress {

192.168.1.170

}

}

(三)nginx_check.sh 腳本:

#!/bin/bash
A=`ps -C nginx –no-header |wc -l`
if [ $A -eq 0 ];then
/usr/local/nginx/sbin/nginx
sleep 2
if [ `ps -C nginx --no-header |wc -l` -eq 0 ];then
killall keepalived
fi
fi

(四)我們需要把master的keepalived配置文件 copy到master機器(172)的 /etc/keepalived/ 文件夾下,在把backup的keepalived配置文件copy到backup機器(173)的 /etc/keepalived/ 文件夾下,最後把nginx_check.sh腳本分別copy到兩臺機器的 /etc/keepalived/文件夾下。

(五)nginx_check.sh腳本授權。賦予可執行權限:chmod +x /etc/keepalived/nginx_check.sh

(六)啟動2臺機器的nginx之後。我們啟動兩臺機器的keepalived

/usr/local/nginx/sbin/nginx

service keepalived start

ps -ef | grep nginx

ps -ef | grep keepalived

可以進行測試,首先看一下倆臺機器的ip a 命令下 都會出現一個虛擬ip,我們可以停掉 一個機器的keepalived,然後測試,命令:service keepalived stop。結果發現當前停掉的機器已經不可用,keepalived會自動切換到另一臺機器上。

Nginx實現高可用

(七)我們可以測試在nginx出現問題的情況下,實現切換,這個時候我們只需要把nginx的配置文件進行修改,讓其變得不可用,然後強殺掉nginx進程即可,發現也會實現自動切換服務器節點。

 **3.2.3 nginx配置負載均衡**

創建一個springboot項目 實現負載均衡

四、集群情況下Session共享解決方案

4.1 集群情況下session會產生什麼原因?

4.2 什麼是會話機制

4.3 Session存放在哪裡

4.4 Session共享解決方案

4.4.1 nginx或者haproxy做的負載均衡)

用Nginx 做的負載均衡可以添加ip_hash這個配置,

用haproxy做的負載均衡可以用 balance source這個配置。

從而使同一個ip的請求發到同一臺服務器。

4.4.2 利用數據庫同步session

4.4.3利用cookie同步session數據原理圖如下

Nginx實現高可用

缺點:安全性差、http請求都需要帶參數增加了帶寬消耗

4.4.4使用Session集群存放Redis

創建一個springboot項目

4.4.1引入maven依賴

	<!--spring boot 與redis應用基本環境配置 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-redis</artifactId>
</dependency>
<!--spring session 與redis應用基本環境配置,需要開啟redis後才可以使用,不然啟動Spring boot會報錯 -->
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
</dependency>

4.4.2創建SessionConfig

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;
//這個類用配置redis服務器的連接
//maxInactiveIntervalInSeconds為SpringSession的過期時間(單位:秒)
@EnableRedisHttpSession(maxInactiveIntervalInSeconds = 1800)
public class SessionConfig {
// 冒號後的值為沒有配置文件時,制動裝載的默認值
@Value("${redis.hostname:localhost}")
String HostName;
@Value("${redis.port:6379}")
int Port;
@Bean
public JedisConnectionFactory connectionFactory() {
JedisConnectionFactory connection = new JedisConnectionFactory();
connection.setPort(Port);
connection.setHostName(HostName);
return connection;
}
}

4.4.3初始化Session

//初始化Session配置
public class SessionInitializer extends AbstractHttpSessionApplicationInitializer{
public SessionInitializer() {
super(SessionConfig.class);
}
}

4.4.4 控制器層代碼

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class SessionController {
@Value("${server.port}")
private String PORT;
public static void main(String[] args) {
SpringApplication.run(SessionController.class, args);
}
@RequestMapping("/index")
public String index() {
return "index:" + PORT;
}
/**
*
* @methodDesc: 功能描述:(往session存放值)
*/
@RequestMapping("/setSession")
public String setSession(HttpServletRequest request, String sessionKey, String sessionValue) {
HttpSession session = request.getSession(true);
session.setAttribute(sessionKey, sessionValue);
return "success,port:" + PORT;
}
/**
*
* @methodDesc: 功能描述:(從Session獲取值)
*/
@RequestMapping("/getSession")
public String getSession(HttpServletRequest request, String sessionKey) {
HttpSession session =null;
try {
session = request.getSession(false);
} catch (Exception e) {
e.printStackTrace();
}
String value=null;
if(session!=null){
value = (String) session.getAttribute(sessionKey);
}
return "sessionValue:" + value + ",port:" + PORT;
}
}

五、高併發解決方案

六、業務數據庫 -》 數據水平分割(分區分表分庫)、讀寫分離

七、業務應用 -》 邏輯代碼優化(算法優化)、公共數據緩存

八、應用服務器 -》 反向靜態代理、配置優化、負載均衡(apache分發,多tomcat實例)

九、系統環境 -》 JVM調優

十、頁面優化 -》 減少頁面連接數、頁面尺寸瘦身

十一、1、動態資源和靜態資源分離;

十二、2、CDN;

十三、3、負載均衡;

十四、4、分佈式緩存;

十五、5、數據庫讀寫分離或數據切分(垂直或水平);

十六、6、服務分佈式部署。

相關推薦

推薦中...