4.7. 中间件¶
4.7.1. Web Server¶
Nginx¶
- 
- Nginx 通过异步非阻塞的事件处理机制实现高并发。Apache 每个请求独占一个线程,非常消耗系统资源。 
- 事件驱动适合于IO密集型服务(Nginx),多进程或线程适合于CPU密集型服务(Apache),所以Nginx适合做反向代理,而非web服务器使用。 
 
- 
- nginx只适合静态和反向代理,不适合处理动态请求。 
 
OpenResty¶
- 
- 通过 Lua 模块可以在Nginx上进行开发。 
 
Tengine¶
Apache Httpd¶
Tomcat¶
架构原理¶
- 《JBoss vs. Tomcat: Choosing A Java Application Server》 - Tomcat 是轻量级的 Serverlet 容器,没有实现全部 JEE 特性(比如持久化和事务处理),但可以通过其他组件代替,比如Spring。 
- Jboss 实现全部了JEE特性,软件开源免费、文档收费。 
 
调优方案¶
- 
- 启动NIO模式(或者APR);调整线程池;禁用AJP连接器(Nginx+tomcat的架构,不需要AJP); 
 
- 
- AJP 协议(8009端口)用于降低和前端Server(如Apache,而且需要支持AJP协议)的连接数(前端),通过长连接提高性能。 
- 并发高时,AJP协议优于HTTP协议。 
 
Jetty¶
- 
- 架构比较:Jetty的架构比Tomcat的更为简单。 
- 性能比较:Jetty和Tomcat性能方面差异不大,Jetty默认采用NIO结束在处理I/O请求上更占优势,Tomcat默认采用BIO处理I/O请求,Tomcat适合处理少数非常繁忙的链接,处理静态资源时性能较差。 
- 其他方面:Jetty的应用更加快速,修改简单,对新的Servlet规范的支持较好;Tomcat 对JEE和Servlet 支持更加全面。 
 
4.7.2. 缓存¶
本地缓存¶
- 
- 堆内、堆外、磁盘三级缓存。 
- 可按照缓存空间容量进行设置。 
- 按照时间、次数等过期策略。 
 
- 
- 简单轻量、无堆外、磁盘缓存。 
 
4.7.3. 客户端缓存¶
- 
- 主要是利用 Cache-Control 参数。 
 
4.7.4. 服务端缓存¶
Web缓存¶
Memcached¶
- 
- 采用多路复用技术提高并发性。 
- slab分配算法: memcached给Slab分配内存空间,默认是1MB。分配给Slab之后 把slab的切分成大小相同的chunk,Chunk是用于缓存记录的内存空间,Chunk 的大小默认按照1.25倍的速度递增。好处是不会频繁申请内存,提高IO效率,坏处是会有一定的内存浪费。 
 
- 《memcache 中 add 、 set 、replace 的区别》 - 区别在于当key存在还是不存在时,返回值是true和false的。 
 
Redis¶
- 
- 使用 ziplist 存储链表,ziplist是一种压缩链表,它的好处是更能节省内存空间,因为它所存储的内容都是在连续的内存区域当中的。 
- 使用 skiplist(跳跃表)来存储有序集合对象、查找上先从高Level查起、时间复杂度和红黑树相当,实现容易,无锁、并发性好。 
 
- 
- RDB方式:定期备份快照,常用于灾难恢复。优点:通过fork出的进程进行备份,不影响主进程、RDB 在恢复大数据集时的速度比 AOF 的恢复速度要快。缺点:会丢数据。 
- AOF方式:保存操作日志方式。优点:恢复时数据丢失少,缺点:文件大,回复慢。 
- 也可以两者结合使用。 
 
架构¶
回收策略¶
Tair¶
- 特点:可以配置备份节点数目,通过异步同步到备份节点 
- 一致性Hash算法。 
- 架构:和Hadoop 的设计思想类似,有Configserver,DataServer,Configserver 通过心跳来检测,Configserver也有主备关系。 
几种存储引擎:
- MDB,完全内存性,可以用来存储Session等数据。 
- Rdb(类似于Redis),轻量化,去除了aof之类的操作,支持Restfull操作 
- LDB(LevelDB存储引擎),持久化存储,LDB 作为rdb的持久化,google实现,比较高效,理论基础是LSM(Log-Structured-Merge Tree)算法,现在内存中修改数据,达到一定量时(和内存汇总的旧数据一同写入磁盘)再写入磁盘,存储更加高效,县比喻Hash算法。 
- Tair采用共享内存来存储数据,如果服务挂掉(非服务器),重启服务之后,数据亦然还在。 
4.7.5. 消息队列¶
- 《消息队列-推/拉模式学习 & ActiveMQ及JMS学习》 - RabbitMQ 消费者默认是推模式(也支持拉模式)。 
- Kafka 默认是拉模式。 
- Push方式:优点是可以尽可能快地将消息发送给消费者,缺点是如果消费者处理能力跟不上,消费者的缓冲区可能会溢出。 
- Pull方式:优点是消费端可以按处理能力进行拉去,缺点是会增加消息延迟。 
 
消息总线¶
消息总线相当于在消息队列之上做了一层封装,统一入口,统一管控、简化接入成本。
消息的顺序¶
RabbitMQ¶
支持事务,推拉模式都是支持、适合需要可靠性消息传输的场景。
RocketMQ¶
Java实现,推拉模式都是支持,吞吐量逊于Kafka。可以保证消息顺序。
ActiveMQ¶
纯Java实现,兼容JMS,可以内嵌于Java应用中。
Kafka¶
高吞吐量、采用拉模式。适合高IO场景,比如日志同步。
Redis 消息推送¶
生产者、消费者模式完全是客户端行为,list 和 拉模式实现,阻塞等待采用 blpop 指令。
ZeroMQ¶
TODO
4.7.6. 定时调度¶
单机定时调度¶
- 
- fork 进程 + sleep 轮询 
 
- 
- 定时调度在 QuartzSchedulerThread 代码中,while()无限循环,每次循环取出时间将到的trigger,触发对应的job,直到调度器线程被关闭。 
 
分布式定时调度¶
- 
- opencron、LTS、XXL-JOB、Elastic-Job、Uncode-Schedule、Antares 
 
- 
- Quartz集群中,独立的Quartz节点并不与另一其的节点或是管理节点通信,而是通过相同的数据库表来感知到另一Quartz应用的 
 
4.7.7. RPC¶
- 
- 核心角色:Server: 暴露服务的服务提供方、Client: 调用远程服务的服务消费方、Registry: 服务注册与发现的注册中心。 
 
Dubbo¶
** SPI ** TODO
Thrift¶
- 
- 支持多语言,通过中间语言定义接口。 
 
gRPC¶
服务端可以认证加密,在外网环境下,可以保证数据安全。
4.7.8. 数据库中间件¶
4.7.9. 日志系统¶
日志搜集¶
4.7.10. 配置中心¶
- 
- Spring Boot 和 Spring Cloud 
- 支持推、拉模式更新配置 
- 支持多种语言 
 
servlet 3.0 异步特性可用于配置中心的客户端
4.7.11. API 网关¶
主要职责:请求转发、安全认证、协议转换、容灾。