什么是Nginx?
Nginx 是一款是由俄罗斯的程序设计师Igor Sysoev所开发高性能的Web和反向代理服务器,也是一个IMAP / POP3 / SMTP代理服务器。
在高连接并发的情况下,Nginx的是Apache的服务器不错的替代品
安装配置
下载
启动
假设nginx在d:/nginx目录下,那么就需要通过如下命令启动:
1 | cmd |
关闭方式也是与之对应的
1 | nginx -s stop |
打开访问地址,就可以看到如图所示的效果
1 | http://127.0.0.1 |
关闭方式,亦可以用任务管理器关闭
注: nginx启动之后,在任务管理里有两个nginx进程,这个是正常的,一个是1个守护进程 1个工作进程,得手动分别关闭。
启动失败
启动失败的常见问题一般是端口被占用,可以使用taskkill 杀死占用的进程,或者将 Nginx 端口修改
打开nginx目录下的conf/nginx.conf文件,然后找到listen 80,修改为9090,关闭nginx再启动,就可以通过如下地址访问了:
1 | http://127.0.0.1:9090/ |
注: 也可以通如下命令进行重启
1 | nginx -s reload |
多Tomcat
在解释为什么要提供多个Tomcat之前,首先解释一下为什么要额外提供Tomcat。
Nginx是一个web服务器,很快速,但是不能作为Servlet 容器独立运行,所以通常的工作方式是Nginx配合Tomcat来协同工作。 这就是为什么要单独提供Tomcat,以方便配合Nginx进行工作。
那么为什么要提供多个Tomcat呢?因为在后续的 「负载均衡」,「session共享」 教程里需要多个Tomcat来配合演示。 右上角有两个Tomcat,下载后运行其中的startup.bat就可以启动,端口号分别是8111和8222
访问
下载tomcat_8111.zip,解压并运行其中bin目录下的startup.bat
启动之后访问地址:
1 | http://127.0.0.1:8111/ |
会自动跳转到
1 | http://127.0.0.1:8111/login.jsp |
反向代理
概念
先说正向代理,比如要访问youtube,但是不能直接访问,只能先找个翻墙软件,通过翻墙软件才能访问youtube. 翻墙软件就叫做正向代理。
所谓的反向代理,指的是用户要访问youtube,但是youtube悄悄地把这个请求交给bilibili来做,那么bilibili就是反向代理了。
在当前教程指的就是访问nginx,但是nginx把请求交给tomcat来做。
尝试
- 启动 8111 端口的 tomcat
- 修改 nginx.conf ,主要30 - 42行
1 | location / { |
- 重启nginx并访问
1 | 重启 |
意义
既然直接通过127.0.0.1:8111/login.jsp 可以访问,那么干嘛要通过127.0.0.1/login.jsp 去反向代理到tomcat呢? 为什么不直接使用tomcat呢?
因为nginx在处理静态文件的吞吐量上面比tomcat好很多,通常他们俩配合,不会把所有的请求都如本例所示的交给tomcat, 而是把静态请求交给nginx,动态请求,如 jsp ,servlet , ssm,struts等请求交给tomcat. 从而达到动静分离的效果
动静分离
概念
所谓的动静分离就是指图片,css, js之类的都交给nginx来处理,nginx处理不了的,比如jsp 就交给tomcat来处理
好处是nginx处理静态内容的吞吐量很高,比tomcat高多了,这样无形中提升了性能。
修改nginx.conf
在locaction下面添加一个新的location:
1 | location ~\.(css|js|png)$ { |
这表示所有的css js png访问都由nginx来做,访问的地址是:
1 | D:/tomcat/tomcat_8111/webapps/ROOT |
这里要注意,填写本地地址的时候,要用正斜杠 / 不要用反斜杠 \
效果
访问地址
1 | http://127.0.0.1/login.jsp |
观察tomcat 输出日志,发现只访问了 jsp,是因为 nginx 负责了其他的
负载均衡
概念
负载均衡的概念就是当访问量很大的时候,一个 Tomcat 吃不消了,这时候就准备多个 Tomcat,由Nginx按照权重来对请求进行分配,从而缓解单独一个Tomcat受到的压力
尝试
启动两个Tomcat
修改 nginx.conf
首先增加一个upstream ,用来指向这两个tomcat
1 | upstream tomcat_8111_8222{ |
然后修改location,反向代理到上述配置
1 | location / { |
weight表示权重,值越大,被分配到的几率越大。 最大多少呢?我也不知道。。。反正10以内都可以用吧
重启nginx并访问
使用命令 nginx -s reload 重启,然后使劲访问
此时就可以观察到对jsp的访问,被分配到了不同的 Tomcat上
Session共享
通过「负载均衡」的介绍,我们可以把请求分发到不同的 Tomcat 来缓解服务器的压力,但是这里存在一个问题: 当同一个用户第一次访问tomcat_8111 并且登录成功, 而第二次访问却被分配到了tomcat_8222, 这里并没有记录他的登陆状态,那么就会呈现未登录状态了,严重伤害了用户体验。
办法一(ip_hash)
通过ip地址标记用户,如果多次请求都是从同一个ip来的,那么就都分配到同一个tomcat.
这样就不会出现「负载均衡 session问题」了。 处理手段也很简单,在upstream最后加上ip_hash即可。
不过这种方案并不完美,当如下几种情况发生时就有问题:
- 大量请求来之某个局域网,那么相当于就没有负载均衡
- 如果tomcat_8111 挂了,那么此时nginx只能把请求交给tomcat_8222,但是这里却没有记录session,用户体验依然受影响
办法二(redis+tomcat-sessoin-manager)
然第一种解决办法有问题,那么就采用第二种解决办法:用Redis来存取session.
Redis是什么呢?说简单点就是个独立的Hashmap,用来存放键值对的。
这样当tomcat1需要保存session值的时候,就可以把它放在Redis上,需要取的时候,也从Redis上取。
那么考虑这个情景:
- 用户提交账号密码的行为被分配在了tomcat8111上,登陆信息被存放在redis里。
- 当用户第二次访问的时候,被分配到了tomcat8222上
- 那么此时tomcat8222就会从redis去获取相关信息,一看有对应信息,那么就会呈现登陆状态。
这样就规避了「解决办法一: ip_hash」里会出现的两种问题了。
方法二操作
接下来进行具体操作,分几个步骤
- 启动redis
- 给两个tomcat使用jar包
- 配置两个tomcat
- 重启两个tomcat
- 测试
启动redis
下载redis,解压后运行redis-server.exe程序
给两个tomcat使用jar包
Tomcat需要链接 redis,所以需要专门的jar包,这些包都放在了tomcat-redis.zip里。 一共有3个jar包:
1 | jedis-2.5.2.jar, |
下载解压后,放在tomat8111的lib目录下。注:不要放在webapp里面去了哦
下载解压后,放在tomat8222的lib目录下。注:不要放在webapp里面去了哦
###配置两个tomcat
然后修改tomcat/conf/context.xml ,增加下面这些东西
1 | <Valve className="com.orangefunction.tomcat.redissessions.RedisSessionHandlerValve" /> |
重启两个Tomcat
重启 Tomcat
测试
Redis session共享机制和nginx其实无关,是发生在nginx之后的事情,所以直接访问login.jsp。
然后登陆,并观察到已登陆状态
http://127.0.0.1:8111/login.jsp
然后直接访问tomcat8222
http://127.0.0.1:8222/login.jsp
虽然没有在tomcat8222上登陆,但是可以观察到已经呈现为登陆状态了