Socket编程

Linux Socket编程领域为了处理大量连接请求场景,需要使用非阻塞I/O和复用,​​select​​​、​​poll​​​、​​epoll​​​是Linux API提供的I/O复用方式,自从Linux2.6中加入了epoll之后,高性能服务器领域得到广泛的应用,Nignx就是使用​​epoll​​来实现I/O复用支持高并发。

对于“高性能”服务端而言,我们所关注的并不是语言的性能,而是缓存和语言支持异步非阻塞。

缓存

针对缓存要明白通信速度的快慢顺序

  • 内存>SSD>机械磁盘
  • 本机>网络
  • 进程内 > 进程间

缓存系统的目标是希望在进程内的命中率是最高的,那么此时缓存系统整体的效率也是最高的。

异步非阻塞

希望访问数据库、访问网络,访问一些比较慢的IO设备时,不要在等待上耗费大量时间。而是使用事件驱动的方式,当系统完成某项任务后再来通知我们。这样就可以将服务器CPU的空闲资源,用来服务客户端连接。

OpenResty

OpenResty是基于Ngnix和Lua的高性能web平台,内部集成精良的LUa库、第三方模块、依赖项。用于方便搭建能够处理高并发、扩展性极高的动态web应用、web服务、动态网关。可以使用Lua脚本调用Ngnix支持的C以及Lua模块,快速构建10K~1000K单机并发连接的高性能web应用系统。OpenResty的目标是让web服务直接运行在Nginx服务内部,利用Ngnix的非阻塞IO模型,对HTTP客户端请求和后端DB进行一致的高性能响应。

OpenResty的出现可以说是颠覆了高性能服务端的开发模式。OpenResty实际上是Nginx+LuaJIT的完美组合。

OpenResty搭建服务端_nginx

OpenResty工作方式

由于Nginx采用的是​​master-worker​​​模型,也就是一个​​master​​​主进程管理多个​​worker​​​进程,基本的事件处理都是放在​​worker​​​中,​​master​​​仅负责一些全剧初始化,以及对​​worker​​​的管理。在OpenResty中,每个​​worker​​​使用一个LuaVM,每个请求被分配到​​worker​​​时,将在这个​​LuaVM​​​中创建一个​​coroutine​​​协程。协程之间数据隔离,每个协程具有独立的全局变量​​_G​​。

Lua中的协程和多线程下的线程类似,都有自己的堆栈、局部变量、指令指针...,但是和其他协程程序共享全局变量等信息。线程和协程主要不同在于:多处理器的情况下,概念上来说多线程是同时运行多个线程,而协程是通过代码来完成协程的切换,任何时刻只有一个协程程序在运行。并且这个在运行的协程只有明确被要求挂起时才会被挂起。

根据实际测试,OpenResty性能接近于Nginx 性能之王c module,甚至超过。

OpenResty 架构

  • 负载均衡

LVS+HAProxy将流量转发给核心Nginx1和Nginx2,即实现了流量的负载均衡。

OpenResty搭建服务端_nginx_02

负载均衡

  • 单机闭环

所有想要的数据都能从本服务器直接获取,大多数时候无需通过网络或去其他服务器获取。

OpenResty搭建服务端_openresty_03

单机闭环

  • 分布式闭环

单机闭环会遇到2个主要问题

  1. 数据不一致
    例如没有主从架构导致不同服务器数据不一致
  2. 遇到存储瓶颈
    磁盘或内存遇到天花板

解决数据不一致比较好的办法是采用主从或分布式集中存储,而遇到存储瓶颈就需要进行按业务键进行分片,将数据分散到多台服务器。

OpenResty搭建服务端_openresty_04

分布式闭环

  • 接入网关

接入网关又叫接入层,即接收流量的入口,在入口处做如下事情:

OpenResty搭建服务端_数据_05

接入网关

OpenResty环境搭建

安装前准备,必须安装​​perl​​​、​​libpcre​​​、​​libssl​​库。

# 从系统路径中查看必备库是否已经安装
$ sudo ldconfig -v

# 安装必备库
$ sudo apt install libpcre3-dev libssl-dev perl make build-essential curl libreadline-dev libncurses5-dev

作者:JunChow520