【学习】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;

三、负载均衡;

四、分布式缓存;

五、数据库读写分离或数据切分(垂直或水平);

六、服务分布式部署。

相关文章
相关标签/搜索