3.分布式拓展

TPS:Transactions Per Second(每秒传输的事物处理个数)

一、Nginx反向代理负载均衡

单机存在容量问题,需要水平拓展至多机。

Nginx反向代理,可以将后端服务器集群,以一个统一的域名暴露出去,供用户来访问。

java 实现流量比例 简书 java亿级流量_java


java 实现流量比例 简书 java亿级流量_java_02

1.Nginx

  • 可以做静态web服务器
  • 可以做为动静分离服务器,将静态资源的请求直接处理,将动态的请求转发给相应后端服务,并以ajax的形式返回给前端,即
  • 做反向代理服务器

2.架构图迭代:

java 实现流量比例 简书 java亿级流量_java 实现流量比例 简书_03

java 实现流量比例 简书 java亿级流量_数据库_04

3.压缩网络建连的消耗

在默认情况下,nginx会使用http1.0 与后端服务器进行代理,而http1.0不支持长连接,因此需要更改为http1.1 且将connection设置为空(默认长连接,设置close为短连接)

应用与数据库通过Druid连接池维持长连接。

4.Nginx高性能的原因

(1)epoll多路复用

  1. java bio模型

java 实现流量比例 简书 java亿级流量_nginx_05


client发起socket.write首先写入缓冲区中,然后返回,但TCP/IP的缓冲区满的情况下,这个函数就阻塞在那里了。

  1. linux select模型

java 实现流量比例 简书 java亿级流量_java_06


变更触发轮训查找,有1024上线

  1. linux epoll模型

变更触发回调直接读取,理论上无限。

java 实现流量比例 简书 java亿级流量_nginx_07

java jdk中有个NIO模型,有select函数,在linux内核2.6以上时,会自动将select模型直接转成epoll模型。

(2)master worker

master为worker的父线程,可以对子线程的内存资源进行管理。
当接收到TCP/IP建立连接的请求时,worker门去抢占内存中的一块accpet区域的锁,谁抢到了谁就与改客户端建立连接,并负责后续的通讯。
reload操作可以平滑重启nginx的原因也是一样,并没有改变master,而是将worker换成了新的。

为啥没有多线程却能支持很多的并发呢?

为什么要有多线程呢?就是因为调用了一些IO阻塞的方法或者耗时的处理,会导致block住其他的操作。

因为存在阻塞所以使用多线程可以提高处理能力,但在nginx的worker进程中使用了epoll是不存在阻塞的,因此单进程即可处理高并发。

java 实现流量比例 简书 java亿级流量_java_08

(3)协程机制

  • 依附于线程的内存模型,切换开销小。
  • 遇到阻塞即归还控制权,代码同步
  • 无需加锁

Lua也是使用到了这个协程机制

二、分布式会话管理

会话管理:

  • 基于cookie传输sessionid:tomcat容器对session进行的实现,保存在了cookie中。

但在很多客户端,手机端禁止掉了cookie的使用,因此更流行下面的做法:

  • 基于token传输类似sessionid:java代码session实现。

但在迁移到分布式架构之后,会导致另一台机器上并没有登录的session信息。因此需要进行分布式的会话管理。

  • 基于cookie传输sessionid:tomcat容器对session进行的实现,迁移到redis
  • 基于token传输类似sessionid:java代码session实现。迁移到redis

Redis简介:

  • 集中式的缓存中间件
  • Nosql类型的key-value数据库
  • 内存缓存
  • 很适合分布式会话存储(无需开启redis持久化存储磁盘的功能,只需要使用其内存数据库,存放缓存即可)

具体操作:

  1. 引入包

    一旦引入包,填好redis地址,就自动进行session管理了。
  2. token是更加通用的做法

三、使用redis实现分布式会话存储