2019年7月

Maven

概念

Maven是一个项目管理工具,它包含了一个项目对象模型 (Project Object Model),一组标准集合,一个项目生命周期(Project Lifecycle),一个依赖管理系统(Dependency Management System),和用来运行定义在生命周期阶段(phase)中插件(plugin)目标(goal)的逻辑。

特性

  • 遵循最佳实践的简单项目设置 - 在几秒钟内启动新项目或模块
  • 所有项目的一致使用 - 意味着新开发人员进入项目的时间不会增加
  • 高级依赖管理,包括自动更新,依赖关闭(也称为传递依赖)
  • 能够轻松地同时处理多个项目
  • 一个庞大且不断增长的库和元数据库,可以立即使用,并与最大的开源项目安排实时可用的最新版本
  • 可扩展,能够轻松编写 Java或脚本语言的插件
  • 只需很少或不需要额外配置即可即时访问新功能
  • 用于在Maven之外进行依赖关系管理和部署的Ant任务
  • 基于模型的构建:Maven能够根据项目的元数据将任意数量的项目构建到预定义的输出类型(如JAR,WAR或分发)中,而无需在大多数情况下执行任何脚本编写。
  • 项目信息的连贯性站点:使用与构建过程相同的元数据,Maven能够生成包含您需要添加的任何文档的网站或PDF,并添加有关项目开发状态的标准报告。在“项目信息”和“项目报告”子菜单下,可以在本网站左侧导航栏的底部看到此信息的示例。
  • 发布管理和发布发布:没有太多额外配置,Maven将与您的源代码控制系统(如Subversion或Git)集成,并根据特定标记管理项目的发布。它还可以将其发布到分发位置以供其他项目使用。Maven能够发布单个输出,例如JAR,包含其他依赖关系和文档的存档,或者作为源分发。
  • 依赖管理:Maven鼓励使用JAR和其他依赖项的中央存储库。Maven附带了一种机制,您的项目客户可以使用该机制从中央JAR存储库下载构建项目所需的任何JAR,就像Perl的CPAN一样。这允许Maven的用户跨项目重用JAR并鼓励项目之间的通信,以确保处理向后兼容性问题。

安装配置

下载安装

下载页面:点我去下载maven
下载解压即可,在安装 Maven 之前,需确保安装JDK,可通过 java -version 命令查看
环境变量配置:
1) MVN_HOME = maven的bin目录所在路径(不包含/bin)
2) 添加环境变量,设置 Path 添加 %MVN_HOME%/bin
3)在控制台执行mvn -v 查看版本信息,以确认安装就绪

配置文件

settings.xml它是用来设置Maven参数的配置文件,可设置本地仓库、远程仓库,代理信息,镜像服务,认证信息等配置。

settings.xml是Maven的全局配置文件,

pom.xml文件是所在项目的局部配置文件,

/home/user/.m2/settings.xml 是用户的配置文件

配置优先级从高到低:pom.xml> user settings > global settings
如果这些文件同时存在,在应用配置时,会合并它们的内容,如果有重复的配置,优先级高的配置会覆盖优先级低的

本地仓库的路径

<localRepository>/home/maven/repository</localRepository>

镜像加速

  <mirrors>
    <mirror>
      <id>alimaven</id>
      <name>aliyun maven</name>
      <url>http://maven.aliyun.com/nexus/content/groups/public/</url>
      <mirrorOf>central</mirrorOf>        
    </mirror>
  </mirrors>

Maven生命周期

Maven的生命周期就是对所有的构建过程进行抽象和统一。包含了项目的清理、初始化、编译、测试、打包、集成测试、验证、部署和站点生成等几乎所有的构建步骤。Maven的生命周期是抽象的,即生命周期不做任何实际的工作,实际任务由插件完成,类似于设计模式中的模板方法。

Maven有三套相互独立的生命周期,分别是clean、default和site。每个生命周期包含一些阶段(phase),阶段是有顺序的,后面的阶段依赖于前面的阶段。

default生命周期:构建项目,重要的phase如下。

1)validate:验证工程是否正确,所有需要的资源是否可用。
2)compile:编译项目的源代码。
3)test:使用合适的单元测试框架来测试已编译的源代码。这些测试不需要已打包和布署。
4)package:把已编译的代码打包成可发布的格式,比如jar。
5)integration-test:如有需要,将包处理和发布到一个能够进行集成测试的环境。
6)verify:运行所有检查,验证包是否有效且达到质量标准。
7)install:把包安装到maven本地仓库,可以被其他工程作为依赖来使用。
8)deploy:在集成或者发布环境下执行,将最终版本的包拷贝到远程的repository,使得其他的开发者或者工程可以共享。

使用场景

String

String 数据结构是简单的key-value类型,value其实不仅是String,也可以是数字,或者包含某种特定的数据格式,如可序列化对象,Java对象,Json,xml等。

除了可对字符串进行get/set操作,还可以追加字符串,获取字符串长度,设置过期时间,如果是数字还可以执行自增/自减操作。

典型场景如:首页统计数据,用户对象,系统配置元数据,点赞数,浏览数,粉丝数。

Hash

hash 是一个string类型的field和value的映射表,hash特别适合用于存储对象。每个 hash 可以存储键值对40多亿。

redis提供了丰富的命令可对hash数据进行增删改查,批量添加获取。

典型场景如:hash数据结构特别适合保存一组相关类的数据,如一个对象信息,一组特定的业务数据,比如我们可能有多个第三方服务商,如短信,这个时候我们缓存阿里云的短信配置信息和腾讯的短信配置信息。

List

List 类型是一个链表结构的集合,其主要功能有push、pop、获取元素等。更详细的说,List类型是一个双端链表 的结构,我们可以通过相关操作进行集合的头部或者尾部添加删除 元素,list的设计非常简单精巧,即可以做为栈,又可以作为队列。

使用list数据结构我们可以轻松构建出以下数据结构类型

  • 后进先出(LIFO) lpush + lpop = Stack(栈)
  • 先进先出(FIFO) lpush + rpop = Queue(队列)
  • lpush + brpop = Message Queue(消息队列,阻塞弹出)

应用场景:秒杀抢单,生产者/消费者模式

Set

set是 String 类型的无序集合。集合成员是唯一的,这就意味着集合中不能出现重复的数据。

set对外提供的功能与list类似是一个列表的功能,特殊之处在于set是可以自动排重的,当你需要存储一个列表数据,又不希望出现重复数据时,set是一个很好的选择,并且set提供了判断某个成员是否在一个set集合内的重要接口,这个也是list所不能提供的。

应用场景:存储手机号,粉丝关注的集合数据,主要是存储某个相关的业务数据且无序不重复的。

Sorted Set

sorted set的使用场景与set类似,区别是set不是自动有序的,而sorted set可以通过用户额外提供一个优先级(score)的参数来为成员排序,并且是插入有序的,即自动排序。当你需要一个有序的并且不重复的集合列表,那么可以选择sorted set数据结构

应用场景: 学生对象排序,设置分数插入到集合里,可以实现自动根据分数排序。

ActiveMQ消息中间件详细介绍和使用总结

概念

ActiveMQ 是由 Apache 出品的一款开源消息中间件,旨在为应用程序提供高效、可扩展、稳定、安全的企业级消息通信。 它的设计目标是提供标准的、面向消息的、多语言的应用集成消息通信中间件。ActiveMQ 实现了 JMS 1.1 并提供了很多附加的特性,比如 JMX 管理、主从管理、消息组通信、消息优先级、延迟接收消息、虚拟接收者、消息持久化、消息队列监控等等。

特性

  • 支持Java,C,C ++,C#,Ruby,Perl,Python,PHP等各种跨语言客户端和协议
  • 适用于Java,C,C ++,C#的高性能客户端的OpenWire
  • Stomp支持,以便客户端可以轻松地用C,Ruby,Perl,Python,PHP,ActionScript / Flash,Smalltalk编

写,以便与ActiveMQ以及任何其他流行的Message Broker交谈

  • AMQP v1.0支持
  • MQTT v3.1支持允许在物联网环境中进行连接。
  • 完全支持JMS客户端和Message Broker中的企业集成模式
  • 支持许多高级功能,如消息组,虚拟目标,通配符和复合目标
  • 完全支持JMS 1.1和J2EE 1.4,支持瞬态,持久,事务和XA消息传递
  • Spring支持,以便ActiveMQ可以轻松嵌入到Spring应用程序中,并使用Spring的XML配置机制进行配置
    在流行的J2EE服务器中进行测试,例如TomEE,Geronimo,JBoss,GlassFish和WebLogic

包括用于入站和出站消息传递的JCA 1.5资源适配器,以便ActiveMQ可以在任何符合J2EE 1.4的服务器中自动部署

  • 支持可插拔传输协议,如in-VM,TCP,SSL,NIO,UDP,多播,JGroups和JXTA传输
  • 使用JDBC和高性能日志支持非常快速的持久性
  • 专为高性能群集,客户端 - 服务器,基于对等的通信而设计
  • REST API,为消息传递提供技术无关和基于语言的中性Web API
  • Ajax支持使用纯DHTML对Web浏览器的Web流支持,允许Web浏览器成为消息传递结构的一部分
    CXF和Axis支持,以便可以轻松地将ActiveMQ放入这些Web服务堆栈中,以提供可靠的消息传递

可用作内存中的JMS提供程序,非常适合单元测试JMS

运行原理

首先需要创建连接工厂(ConnectionFactory ),用于连接ActiveMQ的服务端,其中ConnectionFactory 又有两个子类分别是队列连接工厂(QueueConnectionFactory)和主题连接工厂(TopicConnectionFactory),在我们发送消息的时候具体使用哪个连接工厂是由消息发送的目的地(Destination)来决定的,Destination是消息生产者的消息发送目标或者说消息消费者的消息来源。对于消息生产者来说,它的Destination是某个队列(Queue)或某个主题(Topic),对于消息消费者来说,它的Destination也是某个队列或主题(即消息来源)
然后在确定了使用哪种连接工厂后,就通过该连接工厂创建出连接对象(Connection),该连接对象是对TCP/IP socket的包装。连接对象可以产生多个会话(session),通过会话来发送消息(Message),这就是我们发送和接受的消息。

基本组件

ActiveMQ 使用时包含的基本组件各与 JMS 是相同的:

  1. Broker,消息代理,表示消息队列服务器实体,接受客户端连接,提供消息通信的核心服务。
  2. Producer,消息生产者,业务的发起方,负责生产消息并传输给 Broker 。
  3. Consumer,消息消费者,业务的处理方,负责从 Broker 获取消息并进行业务逻辑处理。
  4. Topic,主题,发布订阅模式下的消息统一汇集地,不同生产者向 Topic 发送消息,由 Broker 分发到不同的订阅者,实现消息的广播。
  5. Queue,队列,点对点模式下特定生产者向特定队列发送消息,消费者订阅特定队列接收消息并进行业务逻辑处理。
  6. Message,消息体,根据不同通信协议定义的固定格式进行编码的数据包,来封装业务 数据,实现消息的传输。

消息存储

JMS 规范中消息的分发方式有两种:非持久化和持久化。对于非持久化消息 JMS 实现者须保证尽最大努力分发消息,但消息不会持久化存储;而持久化方式分发的消息则必须进行持久化存储。非持久化消息常用于发送通知或实时数据,当你比较看重系统性能并且即使丢失一些消息并不影响业务正常运作时可选择非持久化消息。持久化消息被发送到消息服务器后如果当前消息的消费者并没有运行则该消息继续存在,只有等到消息被处理并被消息消费者确认之后,消息才会从消息服务器中删除。

对以上这两种方式 ActiveMQ 都支持,并且还支持通过缓存在内存中的中间状态消息的方式来恢复消息。概括起来看 ActiveMQ 的消息存储有三种:存储到内存、存储到文件、存储到数据库。具体使用上 ActiveMQ 提供了一个插件式的消息存储机制,类似于消息的多点传播,主要实现了如下几种:

  • AMQ,是 ActiveMQ 5.0及以前版本默认的消息存储方式,它是一个基于文件的、支持事务的消息存储解决方案。 在此方案下消息本身以日志的形式实现持久化,存放在 Data Log 里。并且还对日志里的消息做了引用索引,方便快速取回消息。
  • KahaDB,也是一种基于文件并具有支持事务的消息存储方式,从5.3开始推荐使用 KahaDB 存储消息,它提供了比 AMQ 消息存储更好的可扩展性和可恢复性。
  • JDBC,基于 JDBC 方式将消息存储在数据库中,将消息存到数据库相对来说比较慢,所以 ActiveMQ 建议结合 journal 来存储,它使用了快速的缓存写入技术,大大提高了性能。
  • 内存存储,是指将所有要持久化的消息放到内存中,因为这里没有动态的缓存,所以需要注意设置消息服务器的 JVM 和内存大小。
  • LevelDB,5.6版本之后推出了 LevelDB 的持久化引擎,它使用了自定义的索引代替常用的 BTree 索引,其持久化性能高于 KahaDB,虽然默认的持久化方式还是 KahaDB,但是 LevelDB 将是趋势。在5.9版本还提供了基于 LevelDB 和 Zookeeper 的数据复制方式,作为 Master-Slave 方式的首选数据复制方案。

安装启动

ActiveMQ支持多系统平台下的安装实用,要使用ActiveMQ,请先下载最新版本,点击我下载

Windows安装启动

  1. 1. 解压ActiveMQ安装包
    2. 进入到解压文件夹路径:E:\devsoft\apache-activemq-5.15.8\bin\win64
    3. 点击activemq.bat启动,如果想要后台启动可以先安装服务InstallService.bat 再启动服务

    Linux安装启动

  2.    1. 解压ActiveMQ安装包
       2.  进入解压文件夹路径:/home/yancheng/dev-soft/apache-activemq-5.9.1/bin
       3.  命令行启动: ./activemq start    命令行停止: ./activemq stop
管理控制台监控页面地址:http://localhost:8161/    账号密码 默认amdin=admin

broker-url=tcp://localhost:61616

Springboot集成

如何使用Springbooot集成

点击查看集成框架

Mysql事务级别详细介绍总结

概念定义

事务(Transaction)是指一个对数据库进行一系列操作集合的统称,它是数据库执行的逻辑单元。在一个逻辑单元中可以有多个CRUD执行操作。

事务特性

事务具有四种特性,一般简称ACID特性

  • 原子性(Atomicity):事务作为一个整体被执行,包含在其中的对数据库的操作要么全部被执行,要么都不执行
  • 一致性(Consistency):事务应确保数据库的状态从一个一致状态转变为另一个一致状态。一致状态的含义是数据库中的数据应满足完整性约束
  • 隔离性(Isolation):多个事务并发执行时,一个事务的执行不应影响其他事务的执行
  • 持久性(Durability):已被提交的事务对数据库的修改应该永久保存在数据库

事务作用

为什么要使用事务?由于我们的业务逻辑都是由很多数据组成,每组数据的正确性依赖于其他数据的正确性,完整性,如A向B转账,如果A扣款成功,B一定要收到钱,反之B收到钱,A必须扣款,如果扣款失败,A既不扣款,B也不收款,如扣款成功,A必须扣款,B必须收款。这种业务逻辑的正确执行才能满足我们的实际需求,但是如何去保证这一逻辑的正确执行呢? 这时候就需要用到数据库事务,使用事务可以保证我们的业务逻辑正常执行,数据得到正确性,完整性,安全性。如果没有事物的话数据的完整性一致性等无法保障,我们就无法编写正确的业务逻辑。

事务原理

事务使用

  • 编程式事务:就是直接在代码里手动开启事务,手动提交,手动回滚。优点就是可以灵活控制,缺点就是太麻烦了,太多重复的代码了。
  • 声明式事务:就是使用SpringAop配置事务,这种方式大大的简化了编码。需要注意的是切入点表达式一定要写正确。
  • 注解事务:直接在Service层的方法上面加上@Transactional注解

事务回滚

在多个crud执行中,由于数据的不正确或者异常的导致,我们对数据库提交的数据需要做撤回操作,可以利用数据库事务回滚机制来解决脏数据插入到数据库。使用事务回滚,数据库会将数据恢复到原来之前的样子,确保事务的一致性,原子性。

Spring默认情况下会对运行期例外(RunTimeException)进行事务回滚。这个例外是unchecked

如果遇到checked意外就不回滚。

如何改变默认规则:

  1. 让checked例外也回滚:在整个方法前加上 @Transactional(rollbackFor=Exception.class)
  2. 让unchecked例外不回滚: @Transactional(notRollbackFor=RunTimeException.class)
  3. 不需要事务管理的(只查询的)方法:@Transactional(readOnly=true) 或者不加注解
  4. 如果不添加rollbackFor等属性,Spring碰到Unchecked Exceptions都会回滚,不仅是RuntimeException,也包括Error

注意:

如果异常被try{}catch{}了,事务就不回滚了,如果想让事务回滚必须再往外抛

try{}catch{throw Exception}

为什么事务回滚默认指是针对未检查异常?

  Checked Exception异常,这也是在编程中使用最多的Exception,所有继承自Exception并且不是RuntimeException的异常都是checked Exception,下图中的IOException和ClassNotFoundException。JAVA 语言规定必须对checked Exception作处理,编译器会对此作检查,要么在方法体中声明抛出checked Exception,要么使用catch语句捕获checked Exception进行处理,不然不能通过编译。Spring鼓励你手动去处理处理这种异常,确保不会因此出现问题。

事务回滚总结:

  1. 要想事务起作用,必须是主方法名上有@Transactional注解,方法体内不能用try catch;如果用try catch,则catch中必须用throw new Exception();
  2. @Transactional注解应该只被应用到public方法上,不要用在protected、private等方法上,即使用了也将被忽略,不起作用。这是由Spring AOP决定的
  3. 只有来自外部的方法调用才会被AOP代理捕捉,类内部方法调用类内部的其他方法,子方法并会不引起事务行为,即使被调用的方法上使用有@Transactional注解。

关于第三点:

在一个Service内部,事务方法之间的嵌套调用,普通方法和事务方法之间的嵌套调用,都不会开启新的事务。其背后原因是因为事务的实现机制是spring通过代理实现的,spring采用动态代理机制来实现事务控制,而动态代理最终都是要调用原始对象的,而原始对象在去调用方法时,是不会再触发代理了。

当然解决办法有两种:

  1. 把这两个方法分开到不同的类中;
  2. 使用代理对象调用当前类的方法

ServiceA proxy =(ServiceA)AopContext.currentProxy();
proxy.b();


事务隔离级别

四种事务级别:

  1. 读未提交(read uncommitted ):别人改数据的事务尚未提交,我在我的事务中也能读到。
  2. 读已提交(read committed):别人改数据的事务已经提交,我在我的事务中才能读到。
  3. 可重复读(repeatable read):别人改数据的事务已经提交,我在我的事务中也不去读。
  4. 串行提交(serializable:):事务串行化执行,后面的事务等待前面的事务执行完才能去接着执行。

总结:这 4 种隔离级别,并行性能依次降低,安全性依次提高。

avatar

修改事务级别

查询当前数据库的事务隔离级别:SELECT @@tx_isolation

mysql内置四种事务:

read uncommitted

read committed

repeatable read

serializable

设置当前会话
set session transaction isolation LEVEL read uncommitted

设置全局
set global transaction isolation LEVEL read uncommitted

事务传播机制

在当前含有事务方法内部调用其他的方法(无论该方法是否含有事务),这就属于Spring事务传播机制的知识点范畴了。Spring事务基于Spring AOP

传播行为官方含义简单理解
PROPAGATION_REQUIRED表示当前方法必须在一个事务中运行。如果一个现有事务正在进行中,该方法将在那个事务中运行,否则就要开始一个新事务有事务就用已有的,没有就重新开启一个
PROPAGATION_SUPPORTS表示当前方法不需要事务性上下文,但是如果有一个事务已经在运行的话,它也可以在这个事务里运行有事务就用已有的,没有也不会重新开启
PROPAGATION_MANDATORY表示该方法必须运行在一个事务中。如果当前没有事务正在发生,将抛出一个异常必须要有事务,没事务抛异常
PROPAGATION_REQUIRES_NEW表示当前方法必须在它自己的事务里运行。一个新的事务将被启动,而且如果有一个现有事务在运行的话,则将在这个方法运行期间被挂起开启新事务,若当前已有事务,挂起当前事务
PROPAGATION_NOT_SUPPORTED表示该方法不应该在一个事务中运行。如果一个现有事务正在进行中,它将在该方法的运行期间被挂起不需要事务,若当前已有事务,挂起当前事务
PROPAGATION_NEVER表示当前的方法不应该在一个事务中运行。如果一个事务正在进行,则会抛出一个异常不需要事务,若当前已有事务,抛出异常
PROPAGATION_NESTED表示如果当前正有一个事务在进行中,则该方法应当运行在一个嵌套式事务中。被嵌套的事务可以独立于封装事务进行提交或回滚。如果封装事务不存在,行为就像PROPAGATION_REQUIRES一样嵌套事务,如果外部事务回滚,则嵌套事务也会回滚!!!外部事务提交的时候,嵌套它才会被提交。嵌套事务回滚不会影响外部事务。

Spring的@Transactional默认是PROPAGATION_REQUIRED。

事务嵌套

事务与锁

  1. 共享锁(S锁)

用于只读操作(SELECT),锁定共享的资源。共享锁不会阻止其他用户读,但是阻止其他的用户写和修改。

  1. 更新锁(U锁)

用于可更新的资源中。防止当多个会话在读取、锁定以及随后可能进行的资源更新时发生常见形式的死锁。

  1. 独占锁(X锁,也叫排他锁)

一次只能有一个独占锁用在一个资源上,并且阻止其他所有的锁包括共享缩。写是独占锁,可以有效的防止“脏读”。

Read Uncommited 如果一个事务已经开始写数据,则另外一个数据则不允许同时进行写操作,但允许其他事务读此行数据。该隔离级别可以通过“排他写锁”实现。

Read Committed 读取数据的事务允许其他事务继续访问该行数据,但是未提交的写事务将会禁止其他事务访问该行。可以通过“瞬间共享读锁”和“排他写锁”实现。

Repeatable Read 读取数据的事务将会禁止写事务(但允许读事务),写事务则禁止任何其他事务。可以通过“共享读锁”和“排他写锁”实现。

Serializable 读加共享锁,写加排他锁,读写互斥。

Ngxin使用教程总结

概念介绍

Nginx是一款自由的、开源的、高性能的HTTP服务器和反向代理服务器;同时也是一个IMAP、POP3、SMTP代理服务器;Nginx可以作为一个HTTP服务器进行网站的发布处理,另外Nginx可以作为反向代理进行负载均衡的实现。

功能作用

HTTP代理和Web服务器功能

  • 能够以较低的内存占用率处理10,000多个并发连接(每10k非活动HTTP保持活动连接约2.5 MB )
  • 处理静态文件,索引文件和自动索引
  • 具有缓存的反向代理
  • 使用带内健康检查进行负载平衡
  • TLS / SSL与SNI和OCSP装订支持,通过OpenSSL的。
  • FastCGI,SCGI,uWSGI支持缓存
  • 自2018年3月以来的gRPC支持,版本1.13.10。
  • 基于名称和IP地址的虚拟服务器
  • IPv6兼容
  • WebSockets,HTTP / 1.1升级(101交换协议),HTTP / 2协议支持
  • URL重写和重定向

邮件代理功能

  • TLS / SSL支持
  • STARTTLS支持
  • SMTP,POP3和IMAP 代理
  • 使用外部HTTP服务器进行身份验证[30]

结构特性

模块化设计

核心模块(core modules): 核心模块分为标准模块和可选模块,标准模块就是只要你编译了Nginx就必须会编译的模块,不可选择;可选模块就是编译的时候可以选择用或者不用。

邮件模块(Mail modules): Nginx不光是一个web服务器,还是一个后端代理服务器,且可以为邮件相关的服务进行代理,所以如果需要此功能就可以装载邮件模块即可。

第三方模块(3rd party modules): Nginx还支持许多第三方模块,这些第三方模块我们在编译时要手动指明加载方式进行加载。

高可靠性

Nginx采用一个主进程(master)和N个工作进程(worker)的工作模式,而worker进程才是真正复制相应用户请求的进程。配置了缓存时还会有缓存加载器进程(cache loader)和缓存管理器进程(cache manager)等。所有进程均是仅含有一个线程,并主要通过“共享内存”的机制实现进程间通信。主进程以root用户身份运行,而worker、cache loader和cache manager均应以非特权用户身份运行。

支持热部署

由于Nginx使用主进程和工作进程的机制,使得Nginx支持热部署,这个热部署包括不停止服务更新配置文件、更新日志文件、以及更新服务器程序版本;有人也称这位平滑升级。

低内存消耗

Nginx对于内存的消耗是非常小的,特别是对于非活动连接,官方数据在持久连接模式下10000个非活动连接只需要占用2.5M内存。Nginx对于非活动连接是指,当我们开启持久连接功能时,用户连接不再发送数据后就会立即转为非活动连接,直到持久连接超时时间到达,即销毁。

高扩展性

Nginx 的设计极具扩展性,它完全是由多个不同功能、不同层次、不同类型且耦合度极低的模块组成。 因此,当对某一个模块修复 Bug 或进行升级时,可以专注于模块自身,无须在意其他。而且在HTTP模块中,还设计了 HTTP过滤器模块 : 一个正常的HTTP模块在处理完请求后,会有一串HTTP过滤器模块对请求的结果进行再处理。这样,当我们开发一个新的HTTP模块时, 不但可以使用诸如HTTP核心模块、events 模块、log 模块等不同层次或者不同类型的模块, 还可以原封不动地复用大量已有的HTTP过滤器模块。这种低耦合度的优秀设计,造就了Nginx庞大的第三方模块,当然,公开的第三方模块也如官方发布的模块一样容易使用。Nginx的模块都是嵌入到二进制文件中执行的,无论官方发布的模块还是第三方模块都是如此。这使得第三方模块一样具备极其优秀的性能,充分利用 Nginx 的高并发特性,因此,许多高流量的网站都倾向于开发符合自己业务特性的定制模块。

架构模式

kjJijS.md.png

kjJkng.md.png

从上图可以看出Ningx启动一个主进程Master和多个工作进程worker,工作进程以非特权用户运行。

Master进程的主要工作如下

1)读取并验正配置信息;

2)创建、绑定及关闭套接字;

3)启动、终止及维护worker进程的个数;

4)无须中止服务而更新程序;

5)控制非中断式程序升级,启用新的二进制程序并在需要时回滚至老版本;

6)重新打开日志文件,实现日志滚动;

7)编译嵌入式perl脚本;

Worker进程主要工作如下

1)接收、传入并处理来自客户端的连接,可以是http或者是https协议;

2)提供反向代理功能,根据不同的协议提供给后端真正的应用程序服务器处理请求,如http协议,说明nginx可以自己处理静态请求,也可以代理到后端的web服务器处理静态请求;基于fastcgi协议把用户的动态请求代理到后端的php-fpm服务器;同时还可以根据memcache协议把用户请求提交给后端的memcached服务器进行缓存。Nginx支持的后端存储还有很多,比如mongofs协议,与mongofs这样的分布式存储进行交互,当然这需要装载第三方模块。

3)每个worker进程内部组合了多个模块,如http的核心模块、http协议的负载均衡模块、http的反向代理模块、fastcgi模块等等;事实上worker用到什么模块就会自动装载进来的,用户请求就是在这里模块之间流动。

4)另外面向客户端请求时,每一个worker进程是如何响应客户端的呢?上图也有说明,nginx支持各种客户端连接处理方法,特定方法的有效性取决于所使用的平台上。在支持的几种方法中,nginx通常会自动选择最有效的方法根据其平台。然而,如果需要的话,一个连接处理方法,可以明确地使用use指令指定连接处理方法,前提是此方法必须编译进Nginx。支持的方式(事件驱动模型)有: 如FreeBSD系统支持的kqueue、Linux2.6+支持的epoll、Solaris系统支持的/dev/poll等机制实现进程复用,因此一个进程可以处理N个请求。

5)与本地磁盘进行交互时,Nginx支持高级I/O机制、支持sendfile、sendfilev、sendfile64(sendfile是一种当用户请求一个文件时进程发起系统调用内核到硬盘加载文件可以直接响应给用户;不需在回应给用户空间进程而进程再通过内核TCP/IP协议栈发送给用户节约了时间;sendfile64支持大文件);支持文件AIO(使用AIO必须开启DIRECTIO);支持MMAP等机制。

6)一般反向代理时,Nginx支持直接在本地缓存的机制,当启用缓存功能后,为了能够管理缓存中的缓存对象,需要经常对缓存进行装载和清理等工作。这就需要两个助类的进程来管理,一个叫cache loader、一个叫cache manager。Cache loader进程主要工作是检查缓存存储中的缓存对象,使用缓存元数据建立内存数据库;而Cache manager进程主要工作是缓存的失效时间及过期检验等。

安装使用

nginx支持windows和Linux安装部署使用,下载nginx最新版,请点击查看

windows点击 nginx/Windows-1.15.9 下载已经编译好的版本,可直接使用。

Linux使用系统的源安装或者下载源码,自行编译安装即可。

常用命令

启动nginx服务

service nginx start

或者 在nginx目录下执行 ./nginx

或者以指定配置文件启动 nginx -c /home/nginx.conf

重新载入配置文件

nginx -s reload

nginx在加载期间仍然可以不间断提供服务,不保证所有的参数及时生效,必要时重启nginx

优雅停止nginx服务

nginx -s quit

有连接时会等连接请求完成再杀死worker进程

查看nginx版本和编译参数信息

nginx -V

重新打开日志文件

nginx -s reopen

适合切割日志文件

测试配置文件语法是否正确

nginx -t

查看nginx进程信息

ps -ef |grep nginx

常用参数

在nginx.conf配置文件中有非常多的配置参数,哪些参数是什么意思,具体要注意什么,如何设置合理的阀值,如何配置一份需要的配置文件呢?

由于nginx配置参数非常之多,我们单独开设一篇文章讲解,请点击查看

虚拟主机

虚拟主机,也叫“网站空间”,就是把一台运行在互联网上的物理服务器划分成多个虚拟服务器。有时候我们需要在一个服务器上部署多个web应用程序,如博客,论坛,个人网站等,这些程序对外提供访问,如何在保证共用一个80端口的情况实现不同域名的访问,或者多端口下只是启动一个web服务器访问,这就需要用到web服务器中的虚拟主机功能。nginx的虚拟主机使用server大括号表示,并且可以支持三种方式:

  1. 基于域名的虚拟主机
server {
    listen  80;  # web浏览器默认80端口,在浏览器上不需要输入端口号  http://host 
    server_name www.520code.net;  # 设置你的访问域名

    location / {
        root html/www;
        index index.html;
     }
   }
  1. 基于IP地址的虚拟主机
server {
    listen  80;  # 访问你的网站 http://192.168.1.2  
    server_name 192.168.1.2; # 设置本机的ip地址

    location / {
        root html/www
        index index.html;
      }
    }
  1. 基于端口的虚拟主机
server {
    listen  8080;  # 需要在浏览器输入端口号 http://host:8080  访问你的网站
    server_name www.520code.net;

    location / {
        root html/www;
        index index.html;
      }
    }

静态网站

nginx默认支持静态资源文件,且无需任何复杂配置,即可完成,通常你只需要告诉 nginx你的请求路径和静态资源路径,

在nginx中使用location表示定位请求路径,使用 root 和 alias 表示静态资源路径,它们二者在表现形式有以下区别:

  1. 作用范围不同

root:可以出现在server、http和location中

alias: 只能出现在location中

  1. 后缀带正斜杠 /

root:可有可无

alias:强制必须带 /

  1. 请求路径变化

root:会带上location后面 http://host/location+root/资源文件名

alis:是别名路径,不会带上location http://host/alias/资源文件名

server {
    listen  80;  
    server_name www.520code.net;

    location /bbs {
        root html/www;
        index index.html;
      }
      
    location /blog {
        alias /usr/www/;
        index index.html;
      }
    }

反向代理

反向代理(Reverse Proxy)方式是指以代理服务器来接受internet上的连接请求,然后将请求转发给其他网络上的服务器,并将从服务器上得到的结果返回给internet上请求连接的客户端,此时代理服务器对外就表现为一个服务器。反向代理的好处就是屏蔽了连接的透明性,带来的好处就是可以控制权限访问,可以智能分配请求压力,可以减少客户端正向代理配置的繁琐,可以实现跨多台服务器的访问,可以跨域访问,可以记录请求日志,这些对于客户端都是不可知的。

kv22yF.jpg


# 使用 proxy_pass  代理一个网站
server {
    listen  80;  
    server_name www.oneinlet.com;

  location / {
    proxy_pass http://www.520code.net;
      }
   }

# 使用 upstream+proxy_pass 配置多个代理服务器,既可以实现反向代理还可以配置负载均衡

http{

    upstream backend {
        server www..520code.net;
        server www..oneinlet.com;
   }

   server {
      listen  80;  
      server_name www.oneinlet.com;

      location / {
           proxy_pass  http://backend;
        }
    }
}

location语法

location指令的作用是根据用户请求URI来执行不同的应用,location会根据用户请求网站URL进行匹配定位到某个location区块。 如果匹配成功将会处理location块的规则。

语法规则

location  =     /uri
   ┬      ┬       ┬
   │      │       │
   │      │       │
   │      │       │
   │      │       │
   │      │       └─────────────── 前缀|正则
   │      └──────────────────── 可选的修饰符(用于匹配模式及优先级)
   └───────────────────────── 必须关键字

修饰符说明

从上到下,第一个优先级最高

=      |   location = /uri              表示精准匹配
^~     |   location ^~ /uri             表示以某个常规字符串开头,不是正则匹配
~      |   location ~ pattern           表示区分大小写的正则匹配
~*     |   location ~* pattern          表示不区分大小写的正则匹配
/uri   |   location /uri                表示匹配以/uri开头的地址
@      |   location @err                表示用于定义一个Location块,只能被nginx内部配置指令所访问
/      |   locatioon /                  表示通用匹配, 如果没有其它匹配,任何请求都会匹配到 

1、 = ,精确匹配,表示严格相等

location = /static {
  default_type text/html;
  return 200 "hello world";
}

# http://localhost/static   [成功]
# http://localhost/Static   [失败]

2、 ^~ ,匹配以URI开头

location ^~ /static {
  default_type text/html;
  return 200 "hello world";
}


# http://localhost/static/1.txt    [成功]
# http://localhost/public/1.txt    [失败]

3、 ~ ,对大小写敏感, 使用正则 注意:某些操作系统对大小写敏感是不生效的,比如windows操作系统

location ~ ^/static$ {
  default_type text/html;
  return 200 "hello world";
}

# http://localhost/static         [成功]
# http://localhost/static?v=1     [成功] 忽略查询字符串
# http://localhost/STATic         [失败]
# http://localhost/static/        [失败] 多了斜杠

4、 ~* ,与~相反,忽略大小写敏感, 使用正则

location ~* ^/static$ {
  default_type text/html;
  return 200 "hello world";
}

# http://localhost/static         [成功]
# http://localhost/static?v=1     [成功] 忽略查询字符串
# http://localhost/STATic         [成功]
# http://localhost/static/        [失败] 多了斜杠

5、 /uri ,匹配以/uri开头的地址

location  /static {
  default_type text/html;
  return 200 "hello world";
}

# http://localhost/static              [成功]
# http://localhost/STATIC?v=1          [成功]
# http://localhost/static/1            [成功]
# http://localhost/static/1.txt        [成功]

6、 @ 用于定义一个 Location 块,且该块不能被外部 Client 所访问,只能被nginx内部配置指令所访问,比如 try_files or error_page

location  / {
  root   /root/;
  error_page 404 @err;
}
location  @err {
  # 规则
  default_type text/html;
  return 200 "err";
}

# 如果 http://localhost/1.txt 404,将会跳转到@err并输出err

修饰符优先级

  1. 先判断精准匹配,如果匹配,立即返回结果并结束解析过程
  2. 然后,判断普通命中没如果有多个命中,记录最长的匹配结果
  3. 再然后判断正则表达式的解析过程,按配置里的正则表达式顺序为准,由上到下开始匹配,一旦匹配成功立即返回结果并结束解析过程。

注意:

  • 普通匹配与顺序无关,因为按照匹配的长短来取匹配结果。
  • 正则匹配与顺序有关,因为是从上往下匹配。(首先匹配,取其之。结束解析过程)

SSL配置

nginx 针对https提供ssl/tls配置功能的支持。

 server {
 
    server_name www.oneinelt.com;        
    listen 443 ssl;   # 指定监听443端口  https专有默认的端口
    ssl_certificate E:/nginx/nginx-1.13.11/cert/daluu.pem;   # 申请的证书
    ssl_certificate_key E:/nginx/nginx-1.13.11/cert/daluu.key;    # 申请的证书密钥
    ssl_session_timeout 5m; 
    ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_prefer_server_ciphers on;
    
        location / {
         proxy_pass http://127.0.0.1:8080;
          }   
}

缓存机制

通过设置缓存,可以加速网站请求的访问,减少服务器压力和代理请求,设置合理的缓存为我们节约大量资源,处理更多的任务。启用缓存后,nginx会将响应保存在磁盘缓存中,并使用它们响应客户端,而无需每次都代理对相同内容的请求。官网文档资料查询详细的配置说明,英文请点击我 中文资料请点击我

启用缓存

http {
    # proxy_cache_path 缓存文件路径   keys_zone 缓存项目的元数据的共享内存区域的名称和大小
    proxy_cache_path /data/nginx/cache keys_zone=one:10m;

    server {
        # 使用缓存名称 one
        proxy_cache one;
        location / {
            proxy_pass http://localhost:8000;
        }
    }
}

指定缓存请求

Nginx使用缓存key作为密钥,如果请求具有与缓存响应相同的密钥,则NGINX将缓存的响应发送给客户端。缓存密钥就是指请求主机,地址,请求参数等等,还可以设置http请求方法是GET,POST,PUT,包括缓存触发次数。

    
 location   / { 
           
  proxy_cache content;                      #设置keys_zone后的缓存名称 

  proxy_pass http://192.168.56.1:8080/;     #反向代理地址

  proxy_cache_key "$host$request_uri$cookie_user";  #通过key来hash,定义KEY的值,即是缓存命中的key

  proxy_cache_methods GET HEAD POST;        #设置需要缓存的http请求方法  

  proxy_cache_min_uses 5;      #设置具有请求相同key密钥的最低缓存触发次数,即是访问某个请求多少次触发缓存

    }

限制或绕过缓存

默认情况下,响应将无限期地保留在缓存中。 只有缓存超过最大配置大小,然后按照最后一次请求的时间长度,它们才被删除。要限制缓存响应与特定状态代码被认为有效的时间,请使用 proxy_cache_valid 指令。

    
 location   / { 
           
  proxy_cache_valid 200 302 10m;  # 设置需要缓存的http状态码 和  缓存的时间   d天数 h小时 m分钟  s秒
  proxy_cache_valid 404      1m;  # 可以设置多个proxy_cache_valid 指令  以区分缓存时间
  proxy_cache_valid any 5m;       # 设置缓存所有状态码,请使用 any 关键字
  proxy_cache_bypass $ cookie_nocache  $ arg_nocache $ arg_comment; # 如果参数不为空且不为0,则不会缓存,会将请求转发
  proxy_no_cache $http_pragma $http_authorization; #设置不缓存响应的条件
  proxy_ignore_headers   Cache-Control Set-Cookie;# 设置不缓存的header项
    }

负载均衡缓存

跨多个应用程序实例的负载平衡是一种常用技术,用于优化资源利用率,最大化吞吐量,减少延迟并确保容错配置

官网文档资料查询详细的配置说明, 请点击我

下面介绍Nginx负载均衡七种策略,有些是需要下载第三方模块编译安装的。

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

注意:

  • 在nginx版本1.3.1之前,不能在ip_hash中使用权重(weight)。
  • ip_hash不能与backup同时使用。
  • 此策略适合有状态服务,比如session。
  • 当有服务器需要剔除,必须手动down掉。

4、least_conn

  把请求转发给连接数较少的后端服务器。轮询算法是把请求平均的转发给各个后端,使它们的负载大致相同;但是,有些请求占用的时间很长,会导致其所在的后端负载较高。这种情况下,least_conn这种方式就可以达到更好的负载均衡效果。

#动态服务器组
    upstream dynamic_zuoyu {
        least_conn;    #把请求转发给连接数较少的后端服务器
        server localhost:8080   weight=2;
        server localhost:8081;
        server localhost:8082 backup;
        server localhost:8083   max_fails=3 fail_timeout=20s;
    }

  注意:

  • 此负载均衡策略适合请求处理时间长短不一造成服务器过载的情况。

5、fair(第三方)

按后端服务器的响应时间来分配请求,响应时间短的优先分配。

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

6、url_hash(第三方)

按访问url的hash结果来分配请求,使每个url定向到同一个后端服务器,后端服务器为缓存时比较有效。

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

在需要使用负载均衡的server中增加

proxy_pass http://backserver/; 
upstream backserver{ 
ip_hash; 
server 127.0.0.1:9090 down; (down 表示单前的server暂时不参与负载) 
server 127.0.0.1:8080 weight=2; (weight 默认为1.weight越大,负载的权重就越大) 
server 127.0.0.1:6060; 
server 127.0.0.1:7070 backup; (其它所有的非backup机器down或者忙的时候,请求backup机器) 
} 

max_fails :允许请求失败的次数默认为1.当超过最大次数时,返回proxy_next_upstream 模块定义的错误

fail_timeout:max_fails次失败后,暂停的时间

7、Sticky

Sticky工作原理 :

Sticky是nginx的一个模块,它是基于cookie的一种nginx的负载均衡解决方案,通过分发和识别cookie,来使同一个客户端的请求落在同一台服务器上,默认标识名为route
1.客户端首次发起访问请求,nginx接收后,发现请求头没有cookie,则以轮询方式将请求分发给后端服务器。
2.后端服务器处理完请求,将响应数据返回给nginx。
3.此时nginx生成带route的cookie,返回给客户端。route的值与后端服务器对应,可能是明文,也可能是md5、Hash值
4.客户端接收请求,并保存带route的cookie。
5.当客户端下一次发送请求时,会带上route,nginx根据接收到的cookie中的route值,转发给对应的后端服务器。

http {
#OK include vhost/xxx.conf;
upstream shop_server{
sticky;
#Sticky是nginx的一个模块,它是基于cookie的一种nginx的负载均衡解决方案,通过分发和识别cookie,来使同一个客户端的请求落在同一台服务器上
# server 192.168.1.23; 
server 192.168.1.24;
# server 192.168.1.25;
keepalive 32;
}

性能调优

....