【學習】021 Nginx

nginx入門

什麼是nginx?

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

反向代理服務器

 Nginx、lvs、F5(硬件)、haproxyjava

nginx應用場景

一、http服務器。Nginx是一個http服務能夠獨立提供http服務。能夠作網頁靜態服務器。linux

二、虛擬主機。能夠實如今一臺服務器虛擬出多個網站。例如我的網站使用的虛擬主機。nginx

三、反向代理,負載均衡。當網站的訪問量達到必定程度後,單臺服務器不能知足用戶的請求時,須要用多臺服務器集羣可使用nginx作反向代理。而且多臺服務器能夠平均分擔負載,不會由於某臺服務器負載高宕機而某臺服務器閒置的狀況。c++

Windows環境下安裝Nginx

解壓:nginx-windowsweb

雙擊: nginx.exeredis

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

演示下 nginx作靜態服務器spring

windows經常使用命令

nginx.exe -s stop  #中止

nginx優缺點

佔內存小,能夠實現高併發鏈接、處理響應快。數據庫

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

nginx配置簡單

能夠不暴露真實服務器IP地址

nginx.conf 介紹

nginx.conf文件的結構

nginx的配置由特定的標識符(指令符)分爲多個不一樣的模塊。 
指令符分爲簡單指令塊指令

  • 簡單指令格式:[name parameters;]
  • 塊指令格式:和簡單指令格式有同樣的結構,但其結束標識符不是分號,而是大括號{},塊指令內部能夠包含simple directives 和block directives, 能夠稱塊指令爲上下文(e.g. events, http, server, location)

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

配置靜態訪問

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;
        } 
}  

nginx實現反向代理

什麼是反向代理?

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

啓動一個Tomcat 127.0.0.1:8080

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

Host文件新增

127.0.0.1 8080.hongmoshui.com
127.0.0.1 8081.hongmoshui.com

nginx.conf 配置

配置信息:

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

nginx實現負載均衡

什麼是負載均衡

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

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

負載均衡策略

一、輪詢(默認)
每一個請求按時間順序逐一分配到不一樣的後端服務器,若是後端服務器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; 
} 

4、fair(第三方)
按後端服務器的響應時間來分配請求,響應時間短的優先分配。 

upstream backserver { 
  server server1; 
  server server2; 
  fair; 
} 

五、url_hash(第三方)
按訪問url的hash結果來分配請求,使每一個url定向到同一個後端服務器,後端服務器爲緩存時比較有效。 

upstream backserver { 
  server squid1:3128; 
  server squid2:3128; 
  hash $request_uri; 
  hash_method crc32; 
} 

配置代碼

upstream backserver { 
     server 127.0.0.1:8080; 
     server 127.0.0.1:8081; 
    } 

    server {
        listen       80;
        server_name  www.hongmoshui.com;
        location / {
            proxy_pass  http://backserver;
            index  index.html index.htm;
        }
    }

宕機輪訓配置規則

    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;
            }
        
         }

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;
        }
    }

nginx配置防盜鏈

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

nginx配置DDOS

限制請求次數

設置Nginx、Nginx Plus的鏈接請求在一個真實用戶請求的合理範圍內。好比,若是你以爲一個正經常使用戶每兩秒能夠請求一次登陸頁面,你就能夠設置Nginx每兩秒鐘接收一個客戶端IP的請求(大約等同於每分鐘個請求)。

limit_req_zone $binary_remote_addr zone=one:10m rate=2r/s;
server {
...
location /login.html {
limit_req zone=one;
...
}
}

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

限制請求速度

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

漏桶算法能夠很好地限制容量池的大小,從而防止流量暴增。若是針對uri+ip做爲監測的key,就能夠實現定向的設定指定ip對指定uri容量大小,超出的請求作隊列處理(隊列處理要引入消息機制)或者丟棄處理。這也是v2ex對流量攔截的算法,針對uri+ip作流量監測。 

linux操做nginx

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

 

linux安裝

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

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

安裝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++

安裝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

安裝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

安裝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

啓動nginx

$ /usr/local/nginx/sbin/nginx

檢查是否啓動成功:

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

經常使用命令

重啓:

$ /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

啓動Nginx + Keepalived高可用

什麼是Keepalived

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

 

上圖是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地址等。

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

安裝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

keepalived安裝成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

到此咱們安裝完畢!

keepalived 經常使用命令

service keepalived start

service keepalived stop

配置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配置負載均衡

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

集羣狀況下Session共享解決方案

集羣狀況下session會產生什麼緣由?

什麼是會話機制

Session存放在哪裏

Session共享解決方案

nginx或者haproxy作的負載均衡)

用Nginx 作的負載均衡能夠添加ip_hash這個配置,

用haproxy作的負載均衡能夠用 balance source這個配置。

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

利用數據庫同步session

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

 

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

使用Session集羣存放Redis

建立一個springboot項目

引入maven依賴

<project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.hongmoshui.www</groupId>
    <artifactId>redis</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.3.RELEASE</version>
    </parent>
    <dependencies>
        <!--spring boot 與redis應用基本環境配置 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <!--spring session 與redis應用基本環境配置,須要開啓redis後纔可使用,否則啓動Spring boot會報錯 -->
        <dependency>
            <groupId>org.springframework.session</groupId>
            <artifactId>spring-session-data-redis</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>


</project>

建立SessionConfig

package com.hongmoshui.session;
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;

    @Value("${redis.password:123456}")
    String Password;

    @Bean
    public JedisConnectionFactory connectionFactory()
    {
        JedisConnectionFactory connection = new JedisConnectionFactory();
        connection.setPort(Port);
        connection.setHostName(HostName);
        connection.setPassword(Password);
        return connection;
    }
}

初始化Session

package com.hongmoshui.session;
import org.springframework.session.web.context.AbstractHttpSessionApplicationInitializer;

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

控制器層代碼

package com.hongmoshui.controller;

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:8080}")
    private String PORT;

    public static void main(String[] args)
    {
        SpringApplication.run(SessionController.class, args);
    }

    @RequestMapping("/index")
    public String index()
    {
        return "index:" + PORT;
    }

    /**
     * 往session存放值
     * @param request
     * @param sessionKey
     * @param sessionValue
     * @author 墨水
     */
    @RequestMapping("/setSession")
    public String setSession(HttpServletRequest request, String sessionKey, String sessionValue)
    {
        HttpSession session = request.getSession(true);
        session.setAttribute(sessionKey, sessionValue);
        return "success,port:" + PORT;
    }

    /**
     * 從Session獲取值
     * @param request
     * @param sessionKey
     * @author 墨水
     */
    @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;
    }

}

啓動代碼

package com.hongmoshui;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class StartApp
{
    public static void main(String[] args)
    {
        SpringApplication.run(StartApp.class, args);
    }
}

高併發解決方案

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

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

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

系統環境 -》 JVM調優

頁面優化 -》 減小頁面鏈接數、頁面尺寸瘦身

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

二、CDN;

三、負載均衡;

四、分佈式緩存;

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

六、服務分佈式部署。

相關文章
相關標籤/搜索