java 核心
2024-06-28 15:39:54 9 举报
AI智能生成
学习整理
作者其他创作
大纲/内容
数据存储
mysql
存储引擎
InnoDb
行锁,支持事务,支持MVVC,读写并发性能好,综合性能高
MyIsam
表级别锁,插入与查询速度较快,更新速度慢,不支持事务。一般适合做报表类
Memory
数据存放内存,读写速度快,数据库重启崩溃会丢失数据,适合做临时表
CSV
数据存放CSV文件,不支持索引,适用于导入数据之类场景
索引
数据结构(排序)
二叉树
左小右大
优点:结构简单 缺点:树深度不够平衡
平衡树
子树深度差值不能超过1
优点:解决二叉树问题 缺点:数据量大树太深,IO次数过多,innerDB加载page 16KB,空间浪费问题
B 树
节点拥有子树数量叫度
页分裂/合并 保持树的平衡
频繁修改索引值,无序的值会导致页频繁分裂,合并
B+树(innoDb)
B树加强版
只有在叶子节点上存储数据
叶子节点之间是双向指针
索引类型
Hash索引
innoDb不能使用哈希索引,特殊引擎可以使用Memory
通过hashCode映射查找数据,效率快,但存在hashCode碰撞问题
无序索引,比较等操作都不支持
BTree索引
索引存储
myisam
*.myi(索引文件)
通过*.myi文件找到地址,在*.MYD查找到相应的数据
*.myd(数据文件)
innodb
*.idb 数据跟索引
叶子节点存储的数据(聚集索引)
叶子节点存储的是主键索引值(非聚集索引)
使用原则
1.where 条件,order,join ,group 字段上建立索引
2.个数不宜过多
3.离散度低的字段不宜建立索引 如性别
4.经常需要更新的字段
5.无序的值不宜建立索引
6.复合索引 离散度高的建立在前
7.过长的字段,使用前缀索引(字段长度截断)
日志
binlog(Server端 记录DML,DDL语句)
作用:主从复制,数据恢复
提交事务时候追加写
模式
Statement(记录SQL语句)
优点:日志量少,IO少,性能好
缺点:不同版本SQL语句不兼容问题,master与slave执行相同函数不同结果问题
Row(记录修改前后值)
优点:没有兼容性问题,无BUG
缺点:日志量大,性能差
Mixed(Statement与Row的混合)
redolog
作用:服务异常崩溃,数据恢复
redolog效率高,顺序IO,安装目录lb_logfile
大小固定,默认48M,追加写,写满触发刷脏
undolog
作用:事务日志,回滚事务,保证原子性
buffer pool
内存缓冲区 提升读写性能 inner_buffer_pool
内存淘汰LRU算法
热数据区
冷数据区(新访问数据进入)
change_buffer(非唯一性索引数据操作)
执行流程
1.缓冲操作到change_buffer
2.数据在buffer_pool中直接更新
3.数据不在内存,下次加载到内存 直接merge
log_buffer(redolog缓冲区)
innodb_flush_log_at_trx_commit参数
0 事务提交后 每1秒将数据刷到磁盘
1 事务提交立即刷新磁盘
2 事务提交 写入操作os系统缓冲区,os操作系统每隔1s刷到磁盘
执行顺序
更新
1.从buffpool查找数据,未查到从磁盘查找,加载到server执行器
2.更新Server执行器数据
3.记录undolog 更新前原数据
4.记录redolog 更新后数据
5. 更新buffpool 原数据更改成更新后数据
6.Server 层记录binlog
7.提交事务 , 刷脏
事务
特性
原子性A
隔离性I
持久性D
一致性C
MVVC
脏读(未提交读)
innoDb快照读
幻读(已提交读,add)
innoDb加行锁
不可重复读(已提交读,update/delete)
innoDb快照读
隔离级别
RU(未提交读)
脏读问题
幻读问题
不可重复读问题
RC(提交读)
幻读问题
不可重复读问题
高并发推荐,不加行锁
RR(可重复读)
幻读问题(innodb通过行锁解决幻读问题)
系统默认,并发小,强一致性推荐
SZ(串行化)
解决任何问题,效率差
如何选择隔离级别
锁(锁定主键)
记录锁
=查询,命中记录
间隙锁
=查询,未命中记录
临间锁
区间查询, ( ] 左开右闭
死锁
发生条件
1.互斥
2.不可剥夺
3.持有并等待
如何解决
1.顺序访问
2.数据排序
3.申请足够级别的锁
4.避免没有where条件更新
5.事务拆分,大事务拆小
6.少用范围查询
问题排查
执行计划(Explain)
id(查询序号)
序号值(1,2,3)
先大后小(3-2-1)
序号值(1,1,1)
从上往下
select_type(查询类型)
SIMPLE
简单查询
PRIMARY
包含子查询的主查询
SUBQUERY
子查询
DERIVED
临时表
UNION
联合查询
table(查询的表)
partitions(分区)
type
const
主键索引/唯一索引查询
system
系统表查询
eq_ref
关联查询 匹配主键索引/唯一索引
ref
匹配索引 最左匹配原则
range
匹配索引 范围查询
index
索引全部扫描 返回所有索引
All
全表扫描
possible_keys(可能用到的索引)
key(实际用到的索引)
key_len(索引长度)
ref(索引比较的列)
rows(预估扫描行数)
filter(按表条件刷选行的百分比)
extra
using index
使用覆盖索引
using where
存储引擎拿到多余数据 需要过滤
using filesort
索引不能排序 需要额外排序
using temporary
索引使用临时表
慢sql
开启慢SQL日志(/etc/my.cnf)
slow_query_log
是否启用慢sql查询日志 默认0 0-否 1-是
slow_query_log_file
指定慢sql日志位置以及文件名称
long_query_time
慢sql执行阈值 默认10 单位s
log_ouput
慢sql 输出目标 默认是file 即输出到文件
log_timestamps
输出文件显示时区 默认UTC 建议更改成SYSTEM
log_queries_not_using_indexes
是否记录未使用索引查询的语句 默认未off
分析慢sql
mysqldumpslow
MySQL Enterprise Monitor
性能监控
服务端最大连接数
show VARIABLES like '%max_connection%'
每一个用户的最大连接数
show variables like '%max_user_connections%';
数据库链接情况
show full processlist
当前连接中各个用户的连接数
select USER , count(*) from information_schema.processlist group by USER;
当前连接中各个IP的连接数
select SUBSTRING_INDEX(host,':',1) as ip , count(*) from information_schema.processlist group by ip;
当前连接中连接时间最长的的连接
select host,user,time,state,info from information_schema.processlist order by time desc limit 10;
查询链接超时时间
show global variables like 'wait_timeout';
redis
数据类型
String(KV结构)
应用场景
缓存
分布式session
分布式锁setnx
分布式ID
限流Spring Cloud
操作命令
set/mset
设置单个/多个Key的值
get/mget
获取单个/多个key的值
strlen
获取单个Key对应值长度
append
在key的值末位添加Value
getrange
从start-end截取字符串
incr/incrby/incrbyfloat
递增相应的值
decr/decrby
递减相应的值
Hash
特性
一个key对应多个键值对
优点
1.节省空间 2.减少key冲突 3.减少资源消耗
缺点
1.无法单独设置TTL time 2.分片存储不适合
操作命令
hset/hmset
设置单个/多个哈希值
hget/hmget
获取单个/多个哈希值
hkeys
获取所有的key
hvals
获取所有的value
hgetall
获取所有键值对
hexists
判断某个field是否存在
hincrby/hincrbyfloat
对某个字段递增
hlen
获取元素个数
hdel
删除某个元素
List
有序集合 从左到右
操作命令
lpush
向左添加元素 添加 a b 生成b-a
rpush
向右添加元素 添加 a b 生成 a-b
lpop
向左取出元素 如 a-b 取出 a-b
rpop
向右取出元素如 a-b 取出 b-a
lindex
从index处取出元素
lrange
从start-end取出元素
Set
存储的String的无序类型的集合 集合成员唯一
操作命令
sadd
集合添加数据
smembers
获取集合数据
scard
获取集合成员个数
srandmember
随机返回N条成员
spop
移除并返回集合中一个随机元素
srem
移除集合中元素
sismember
判断元素是否存在集合中
sdiff
返回一个集合不存在另外一个集合的元素
sinter
返回相同元素 交集
sunion
返回不同元素 去重
ZSet
有序集合
操作命令
zadd
添加多个元素 score 越小越靠前
zcard
获取集合成员个数
zcount
获取score 在min与max之间成员个数
zincrby
对key的field增加score分数
zrange
列举索引在min与max之间所有字段
zrevrange
列举区间内的成员。的位置按分数值递减(从大到小)来排列
zrangebyscore
列举出score 为min与max之间所有字段
zrem
移除一个元素
zrank
获取一个元素下标索引位置
zscore
获取一个元素分值
内存淘汰
过期策略
定时过期(redis 不采用)
设置了TTL的key,redis开辟定时器定时删除key
优点:实时性高,清理内存
缺点:占用大量cpu,消耗redis性能
定期过期
redis 默认是每隔一段时间就随机抽取一些设置了ttl的 key,检查其是否过期
平衡了系统cpu与内存问题
惰性过期
获取 key 的时候,如果此时 key 已经过期,就删除
优点:不会消耗cpu
缺点:当大量key过期了一直没有被访问,就会占用大量内存
内存淘汰机制
操作配置
maxmemory 2GB设置最大内存
maxmemory-policy allkeys-lru 设置内存淘汰策略
内存淘汰策略
random
随机删除
lru
最近最少使用(根据访问时间 推荐)
实现原理
每个key 都带有lru属性字段,包含访问时间
get key时候更新lru属性字段的访问时间
lfu
最不经常使用(根据访问次数)
实现原理
Lru属性字段增加counter字段 计算字段访问频率
1. 首先根据数据的访问次数进行筛选,把访问次数最低的数据淘汰出去
2. 如果两个数据的访问次数相同,再比较两个数据的访问时效性,把距离上一次访问时间更久的数据淘汰出去
ttl
优先淘汰更早过期的键值
noeviction
从不淘汰
持久化
rdb(默认 记录视图)
操作配置
save 900 1
900s内有1个Key 发生了变更触发备份
dbfilename dump.rdb
生成的rdb文件
rdbcompression yes
压缩rdb文件 节省空间 但是消耗cpu
rdbchecksum yes
验证rdb文件完整性
优缺点
优点
内容紧凑 占用空间小
不影响主进程
恢复快
缺点
可能会丢失数据,可靠性低
aof(记录命令)
操作配置
appendonly yes
开启AOF
appendfilename “appendonly.aof”
aof 文件名称
appendfsync (内存同步磁盘)
always
每次同步 效率低 安全性高
everysec
一秒一次 性能均衡
no
不同步 安全性能差
bgrewriteaof
重写aof 到达压缩文件大小目的,剔除重复的指令。
auto-aof-rewrite-min-size
aof文件重写最小的文件大小
auto-aof-rewrite-percentage
aof文件增长比例
优缺点
优点
同步频率快
可靠性高
缺点
文件大 占用空间大
性能低
主从复制
配置流程
1.修改从库redis.conf slaveof masterIp masterPort/masterauth password
2.重启从redis 生效。
原理解析
全量复制
场景
首次同步数据
流程
1.slave发送同步命令到master 并且与master建立长连接
2.master 收到命令,执行bgSave,生成rdb文件
3.生成rdb后 master 开始缓冲写命令
4.master发送rdb到slave
5.slave 清空脏数据,加载rdb 数据
6.master 将缓冲命令repl buffer发送给slave
7.slave接收repl buffer写命令,执行命令
8.master与slave 建立长连接,持续发送写命令
增量复制
场景
主从断开链接,期间有数据写入master
流程
1.从节点断开master缓冲写命令以及数据
- 2.从节点重新连上master,建立socket长链接
3.比较master与slave的offset偏移量,如果在master中 则将offset之后数据同步给master 否则全量同步
问题
保证从节点只读
slave-read-only=yes
主从延迟问题
repl-disable-tcp-nodelay 关闭
主节点产生的命令数据无论大小都会及时地发送给从节点,主从之间延迟变小
增加了网络带宽的消耗 适用于同机房
repl-disable-tcp-nodelay 开启
主节点会合并较小的TCP数据包从而节省带宽,主从延迟会变大
节省了带宽但增大主从之间的延迟
子主题
哨兵
配置流程
见备注
原理解析
选举算法
Raft 算法
影响因素
1.断开链接的时长
2.优先级
3.offset 数据备份越多
4.进程ID最小
主观下线
sentinal节点每隔一段时间向master发送心跳请求,如果超时down-after-milliseconds未收到回复 则sentinal认为master 主观下线
客观下线
主观下线后 sentinal会向其他sentinal发送ismaster-down-by-addr命令 如果过半sentinal认为master主观下线,则master升级为客观下线
客观下线会重新发起master选举
数据分片
客户端
jedis 实现数据分片 一致性哈希算法 不依赖中间件,逻辑可以自定义
代理端
Codis/twemproxy
问题
缓存穿透
问题
数据不在缓存,也不在数据库 比如请求一个不存在的订单号
解决方案
1. 布隆过滤器 将所有数据缓存到redis 布隆过滤器中
定义
本身是一个很长的二进制向量,存放的不是0就是1
原理
对数值进行多次哈希取得多个哈希值,并对数组小标取模 放在不同位置上
1 代表占位 0 代表未占位
优缺点
优点:高效 占用内存少
缺点:具有一定误判率 无法删除过期数据
2. 缓存一个空对象(只能针对相同Key,大量不存在的不同Key不可取)
缓存雪崩
问题
同一时间段内,大量缓存失效/redis挂掉了
解决方案
1. 分布式锁
2.设置不同过期时间
3.redis 高可用搭建
缓存击穿
问题
热点数据过期,大量并发请求同一个数据
解决方案
分布式锁
MongoDB
消息队列
rabbitMq
工作模型
发送消息
Broker->VHost->Exchange->Queue
接收消息
Connection->channel-Queue
Exchange路由
Direct直连 1-1
Topic 主题 1-n
Fanout 广播 1-n
Headers 头部匹配
死信队列
消息过期ttl
消息超长
消费者拒绝reject/nack 并且requeue=false
延迟队列
插件rabbitmq_delayed_message_exchange
消息可靠性
Transaction模式
发送消息效率低下(不建议使用)
Confirm模式
单条Confirm
效率不高
批量Confirm
效率相对较高
批量提交数目问题,过大失败问题,过少效率低下
异步AsyncConfirm
效率高,回调机制
集群高可用
普通集群
不能保证高可用,数据分散分布
镜像模式
高可用,性能低
kafka
基础介绍
特性
高吞吐,低延迟
stream
高伸缩性
partion
持久性,可靠性
副本机制
容错性,高并发
自动选举Leader
使用场景
消息传递
网站活动跟踪
指标监控(实时数据分析)
日志聚合(log)
架构分析
生产者producer
kafka服务Broker0
Topic1 队列
partion0 分区
Leader操作数据
手工指定ProducerRecord
自动指定 实现接口Partitioner
Follower 同步数据
partion1 分区
Topic2 队列
kafka服务Broker1
消费者consumer
单个消费者
效率低
消费者组consumer group
consumer:partion=1:1
一个consumer 消费一个 partion
offset 记录消费index
consumer>partion
存在空闲的consumer
consumer<partion
RangerAssignor 平均分配
RoundRobinAssignor 轮询分配
事务消息
原理:2PC
事务Topic:_transaction_state
事务ID:transaction_id
原理分析
发送消息
main线程
KafkaProducer
拦截器ProducerInterceptor
给消息增加自定义样式
序列化Serializer
分区器Partitioner
sender线程
ProducerBatch 批量发送消息
服务端acks
0 不需要服务端Ack 效率快 可靠性不高
1 leader落盘Ack 有丢消息风险
-1 所有Follower 全部落地Ack retries=0 消息重复发送问题
partition存储消息
Leader 读写消息
Follower 同步消息
接受消息
rocketMq
基础介绍
NameServer(服务中心)
Broker启动注册 定时发送心跳续约
NameServer 定时检测Borker 是否长时间未发送心跳
一致性
服务注册
NameServer集群都会收到消息
服务剔除
NameServer定时检测
路由发现
NameServer存储相同数据
Cilent定时器刷新路由列表
Broker(主机)
存储部分数据 分片存储
Borker0
0 2 4 6 8
Borker1
1 3 5 7 9
Replica(副本)
slave 不参与读写
slaveReadEnable=true 可以让slave 参与读负载
Topic(消息队列)
存储并非按照Topic分目录
autoCreateTopicEnable=true Topic不存在自动创建
MessageQueue(队列)
定义
Topic
消息队列名称
BrokerName
主机名称
queueId
队列ID位置
写队列数量
队列多少个数据存储目录 默认4
BrokerA
0->对应queueId
3
BrokerB
1
2
读队列数量
代表从多少数据目录读取数据 如为 2,代表消费0 1目录消息 2 3消息不会被消费
Producer(生产者)
Message
topic
消息队列ID
tags
过滤消息
key
索引键 多个空格隔开
发送消息
单条发送MessageQueue
批量发送Collection<MessageQueue>
同步发送消息
必须ACK 返回sendResult
异步发送消息
onSuccess回调接受结果
单向发送消息
不需要Ack
单向顺序消息
队列选择
Consumer(消费者)
消费模式(MessageModel)
集群模式
轮询消费
广播模式
重复消费所有消息
角色分析
Broker(主机)
消息存储
commitLog
存储所有Topic消息,利用了Liunx Group IO commit
对磁盘访问,完全的顺序写
顺序IO 提高写入性能
ConsumeQueue(索引)
offset
消息的offset
size
消息大小size
hashcode
tag的hashCode
初始化过程
1.Broker 的ReputMessageService 定时轮询CommitLog 查找未添加ConsumeQueue的log
2.获取到 offset,size,hashCode 添加到对应的ConsumeQueue目录
3.consumer消费 首先查找consumeQueue未消费的记录,根据OffSet 查找commitlog 消费消息
mmap 零拷贝
传统Copy
读取IO
文件->内核缓冲区->应用程序Buffer
发送IO
应用程序Buffer->内核发送缓冲区->文件
mmap
读取IO
文件->Buffer(内存映射)
发送IO
Buffer(内存映射)->文件
限制最大值2G
文件清理
清理类型
CommitLog
ConsumeQueue
清理策略
过期文件
MessageStoreCofig.FileReservedTime=72 小时
删除策略
MessageStoreCofig.deleteWhen=04 一天执行一次
磁盘已满
占用率>75%
自动清理过期文件
占用率>85%
按照设定规则清理文件,无论是否过期。默认会从最老的文件开始清理
占用率>90%
拒绝消息写入
主从同步
配置说明
brokerClusterName 集群名字相同
NameServer 相同
brokerId (定义master)
0-matser
1-slave
brokerRole
ASYNC_MASTER
异步复制
主写入成功Ack
优点:效率高 缺点:可靠性低
SYNC_MASTER
同步复制(推荐)
主从均写入成功ACK
优点:效率低 缺点:可靠性高
flushDiskType(刷盘类型)
ASYNC_FLUSH
异步刷盘(推荐)
写入内存PAGECACHE发送ACK
优点:效率高 缺点:消息丢失
SYNC_FLUSH
同步刷盘
每条message刷到磁盘 发送ACK
优点:效率低 缺点:消息不丢失
流程解析
commitLog复制
1.定时器 slave链接master 发送拉取请求 以及自己的commitLog的offset
2.master 接收请求,与master offset比较,生成要同步commitLog buffer,发送给slave
3.slave接收到master请求,写入本地commitLog
元数据的复制
定时任务处理
问题
master->slave 不能够自动切换的问题
故障转移(DLedger)
DLedgerCommitLog
Head
Body
commitLog
配置说明
enableDlegerCommitLog=true 是否启用
dLegerGroup=brokerA 分组名称
dLegerPeers=n0-IP:PORT;n1-IP:PORT;n2-IP:PORT; 至少3节点
dLegerSelfId=n0 本节点ID
producer(生产者)
MessageQueue选择
MessageQueueSelector(接口)
SelectMessageQueueByHash(默认)
通过Hash选择MessageQueue
SelectMessageQueueByRandom
随机选择MessageQueue
SelectMessageQueueByMachineRoom
未实现功能不可以用
自定义选择 实现接口MessageQueueSelector
顺序消息
CommunicationMode
SYNC:同步发送
ASYNC:异步发送
ONEWAY:单次发送 不需要服务端ACK
前提条件
单线程发送
单线程消费
全局有序
指定唯一队列发送
局部有序
根据业务需求指定队列
事务消息
消息主题Topic:RMQ_SYS_TRANS_HALF_TOPIC
producer 设置Listener setTransactionListener
half Message
1.发送未确认消息给Broker 不可见
2.执行本地事务
3.发送Ack消息给Broker 消息可见
事务状态回查
1.定时器 轮询未Ack的half Message,主动发送命令给producer
2.Producer检查本地事务 执行Commit/rollBack操作
默认回查transactionCheckMax=15次, 超次丢弃回滚消息
原理分析
发送half消息
设置TRAN_MSG=true
改写Topic=RMQ_SYS_TRANS_HALF_TOPIC, queueId=0
保存原有Topic,queueId到Properties中
写入CommitLog
commit 事务
获取事务消息commitLog
获取原Topic与queueId,重写组装CommitLog
half消息打上删除标记
写入Topic=**RMQ_SYS_TRANS_OP_HALF_TOPIC** 队列(打删除标记 op队列)
rollBack 事务
half消息打上删除标记
写入Topic=**RMQ_SYS_TRANS_OP_HALF_TOPIC** 队列(打删除标记 op队列)
延迟消息
api 实现 msg.setDelayTimeLevel=0/1/2
messageDelayLevel=1s 5s 10s 30s 1m 2m 3m 4m 5m 6m 7m 8m 9m 10m 20m 30m 1h 2h
不支持自定义时间 商业版本支持
原理分析
1.获取commitLog 属性DelayLevel判断是否延迟消息
2.延迟消息重写Topic=SCHEDULE_TOPIC_XXXX,queueId 保存原有的Topic与queueId到Properties中
3.定时器扫描 获取要触发的commitLog 改写Topic与queue写入原有队列
4.删除延迟队列commitLog(打标)
写入Topic=**RMQ_SYS_TRANS_OP_HALF_TOPIC** 队列(打删除标记 op队列)
Consumer(消费者)
负载均衡
rebalance
广播模式
所有消费者消费所有消息
集群模式
AllocateMessageQueueAveragely(默认)
平均分配算法
AllocateMessageQueueAveragelyByCircle
轮询
AllocateMessageQueueByMachineRoom
机房分配算法
AllocateMessageQueueConsistentHash
一致性hash算法
AllocateMessageQueueByConfig
通过配置
AllocateMachineRoomNearby
机房临近原则算法
重试消息
前提条件
1.集群模式CLUSTERING
2.返回状态RECONSUME_LATER
3.非OneWay消息
consumer.setMaxReconsumeTimes=2 设置重试次数
原理分析
1.获取待重试消息,重写Topic=%RETRY% + 消费者组名,重试次数+1 延迟级别+3 保存原信息到Properties
2.走延迟消息逻辑,写入延迟队列,执行消息
3.消费失败 重试次数+1,延迟级别叠加,重新再来一遍。超过最大次数写入死信队列Topic=%DLQ%+消费者组名
4.消费成功。删除commitLog(打标)
死信队列
消息会自动进行重试,达到最大重试次数后进入队列
中间件
dubbo
基础使用
项目集成
Spring
SpringBoot
集群容错
Failover Cluster(默认)
失败自动切换
重试次数过多 容易造成雪崩效应
Failback Cluster
失败自动恢复,通过定时任务不断重试
Failfast Cluster
快速失败,请求失败后返回异常,不进行任何重试
Failsafe Cluster
失败安全,请求失败后忽略异常,不进行任何重试
Forking Cluster
并行调用多个 Provider 节点,只要有一个成功就返回
Broadcast Cluster
广播多个 Provider 节点,只要有一个节点失败就失败
Available Cluster
找到可用节点调用
Mergeable Cluster
请求多个结果,并将结果合并
负载均衡
ConsistentHashLoadBalance 一致性哈希
RandomLoadBalance 随机权重算法(默认)
LeastActiveLoadBalance 最少活跃调用数
RoundRobinLoadBalance权重轮询
ShortestResponseLoadBalance最短响应时间
自定义负载均衡算法
协议
dubbo协议(默认)
结构
0~7位
Magic High
8~15位
Magic Low
与Magic High一起判断是否为Dubbo协议
16位
Req/Res标识,标识当前消息是请求还是响应
17位
2Way标识,用于标识当前消息是单向还是双向
18位
Event标识,用于标识当前消息是否为事件消息
19~23位
序列化类型的标志,用于标识当前消息使用哪一种序列化算法
24~31位
Status状态,用于记录响应的状态,当Req/Res为0时才有用
32~95位
Request ID,用于记录请求的唯一标识
96~127位
序列化后的内容长度,该值是按字节计算
128~
可变的数据
子主题
变长协议,适用于高并发 小数据传输,消费者比提供者个数多
常规远程服务方法调用
特性
默认单一链接
connections 连接数
accepts 限制最大接收连接数
长链接 | TCP协议 | NIO异步传输 | Hessian 二进制序列化
子主题
hession协议
实现方式
底层采用Http 通讯,采用 Servlet 暴露服务,Dubbo 缺省内嵌 Jetty 作为服务器实现
适用场景
传入传出参数数据包较大,提供者比消费者个数多,提供者压力较大,可传文件
页面传输,文件传输,或与原生hessian服务互操作
特性
默认 多连接
短连接 | Http协议 | 同步传输 | Hessian二进制序列化
thrift协议
Thrift不支持null值,不能在协议中传null
grpc协议
rest协议·
rmi协议
实现方式
采用JDK标准的java.rmi.*实现,采用阻塞式短连接和JDK标准序列化方式
适用场景
传入传出参数数据包大小混合,消费者与提供者个数差不多,可传文件。
常规远程服务方法调用,与原生RMI服务互操作
特性·
默认多链接
短连接 | TCP协议 | 同步传输 | jdk序列化
参数及返回值需实现Serializable接口
webService协议
实现方式
基于 Apache CXF的 frontend-simple 和 transports-http 实现
适用场景
系统集成,跨语言调用
特性
默认:多连接
短连接 | Http协议 | 同步传输 | SOAP文本序列化
参数及返回值需实现Serializable接口
http协议
实现方式
基于http表单的远程调用协议
适用场景·
传入传出参数数据包大小混合,提供者比消费者个数多,可用浏览器查看,可用表单或URL传入参数,暂不支持传文件
需同时给应用程序和浏览器JS使用的服务
特性
默认:多连接
短连接 | Http协议 | 同步传输 | JSON表单序列化
memcached 协议
泛化
不通过API调用dubbo接口
熔断降级
mock
注册中心
registry.address
注册中心地址
registries.shanghai.address
多注册中心地址
配置中心
IP获取流程
1.查找环境变量中是否存在启动参数DUBBO_IP_TO_BIND
2.读取配置文件dubbo.protocols.dubbo.host
3.InetAddress.getLocalHost().getHostAddress获取本机IP
4.socket.getLocalAddress().getHostAddress socket链接注册中心获取本机IP
5.轮询本机网卡 获取IP
配置优先级
⽅法级优先,接⼝级次之,全局配置再次之
如果级别⼀样,则消费⽅优先,提供⽅次之
配置中心加载
1.JVM System Properties JVM -D 参数
2.System environment,JVM进程的环境变量
3.Externalized Configuration,外部化配置,从配置中心读取
4.Application Configuration,应用的属性配置,从Spring应用的Environment中提取"dubbo"打头的属性集
5.API / XML /注解等编程接口采集的配置可以被理解成配置来源的一种,是直接面向用户编程的配置采集方式
6.从classpath读取配置文件 dubbo.properties
配置手册
dubbo:service
服务提供者暴露服务配置
配置类:com.alibaba.dubbo.config.ServiceConfig
dubbo:reference
服务消费者引用服务配置
配置类:com.alibaba.dubbo.config.ReferenceConfig
dubbo:protocol
服务提供者协议配置
配置类:com.alibaba.dubbo.config.ProtocolConfig
dubbo:registry
注册中心配置
配置类:com.alibaba.dubbo.config.RegistryConfig
dubbo:monitor
监控中心配置
配置类:com.alibaba.dubbo.config.MonitorConfig
dubbo:application
应用信息配置
配置类:com.alibaba.dubbo.config.ApplicationConfig
dubbo:module
模块信息配置
配置类:com.alibaba.dubbo.config.ModuleConfig
dubbo:provider
服务提供者缺省值配置
配置类:com.alibaba.dubbo.config.ProviderConfig
dubbo:consumer
服务消费者缺省值配置
配置类:com.alibaba.dubbo.config.ConsumerConfig
dubbo:method
方法级配置
配置类:com.alibaba.dubbo.config.MethodConfig
dubbo:argument
方法参数配置
配置类:com.alibaba.dubbo.config.ArgumentConfig
dubbo:parameter
选项参数配置
配置类:java.util.Map
配置中心插件
apollo
consul
etcd
nacos
zookeeper
缓存服务
本地缓存注册中心服务列表,防止注册中心Down导致服务不可用
Dubbo Admin
流程分析
框架分析
Service 服务接口层
该层是与实际业务逻辑相关的,根据服务提供方和服务消费方的业务设计对应的接口和实现
Config 配置层
对外配置接口,以ServiceConfig和ReferenceConfig为中心,可以直接new配置类,也可以通过spring解析配置生成配置类
Proxy 服务代理层
服务接口透明代理,生成服务的客户端Stub和服务器端Skeleton,以ServiceProxy为中心,扩展接口为ProxyFactory
Cluster 服务注册层
封装服务地址的注册与发现,以服务URL为中心,扩展接口为RegistryFactory、Registry和RegistryService
Monitor 监控层
RPC调用次数和调用时间监控,以Statistics为中心,扩展接口为MonitorFactory、Monitor和MonitorService
Protocol 远程调用层
封装RPC调用,以Invocation和Result为中心,扩展接口为Protocol、Invoker和Exporter
Exchange .信息交换层
封装请求响应模式,同步转异步,以Request和Response为中心,扩展接口为Exchanger、ExchangeChannel、ExchangeClient和ExchangeServer
Transport 网络传输层
抽象mina和netty为统一接口,以Message为中心,扩展接口为Channel、Transporter、Client、Server和Codec
Serialize 数据序列化层
可复用的一些工具,扩展接口为Serialization、 ObjectInput、ObjectOutput和ThreadPool
服务注册
Dubbo SPI
SPI
JAVA SPI
ServiceLoader
Java SPI 规定在 classpath 下的 META-INF/services/ 目录里创建一个以服务接口命名的文件,记录此 jar 包提供的具体实现类名
优点
实现解耦
可以不使用硬编码 import 导入实现类
缺点
懒加载浪费内存问题·
多线程不安全
Dubbo SPI
ExtensionLoader
接口添加@SPI注解,配置文件需放置在 META-INF/dubbo,通过键值对的方式进行配置
Spring SPI
SpringFactoriesLoader
Spring Boot自动装配META-INF/spring.factories
ExtensionLoader
getAdaptiveExtension
自适应扩展点 根据Url参数动态获取
@Adaptive
getExtension
指定名称扩展点
getActivateExtension
激活扩展点/条件扩展 根据Condition 条件获取
服务消费
zk
子主题
定时任务
xxlJob
Quartz
数据收集
es
基础认识
全文检索·
背景:传统数据库面临问题性能,存储,分词
lucece
单实例全文搜索引擎 不支持分布式
核心概念
索引Index
文档Document的集合,相当于数据库的database
必须全部是小写字母
类型 (type)
相当于数据库中table,7.*以后则去除了type的概念
文档Document
代表着es中一条记录,相当于table里面的一个row,以json存储
_index
文档所属索引名称
_type
文档所属类型名
_id
文档的ID值
id+type+index 确保唯一性
_version
文档的版本信息。ES通过使用version来保证对文档的变更能以正确的顺序执行,避免乱序造成的数据丢失。
_source
文档的原始JSON数据,这才是我们储存在ES中的业务数据
_seq_no
严格递增的顺序号,每个文档一个,Shard级别严格递增,保证后写入的Doc的_seq_no大于先写入的Doc的_seq_no。
primary_term
primary_term也和_seq_no一样是一个整数,每当Primary Shard发生重新分配时,比如重启,Primary选举等,_primary_term会递增1
found
查询的ID正确那么ture, 如果 Id 不正确,就查不到数据,found字段就是false
字段Field
相当于是数据表的字段
分片Shards
将索引划分成多份的能力,每一份就称之为分片
分片类型
主分片primary
用于索引文档增删改查,数量创建不可修改,默认5个
副本分片replica
冗余主分片数据,默认1个,可以指定多份,不可与主分片在同一个Node上
映射mapping
动态映射
如果mapping没有创建,elasticsearch将会根据写入的数据的key自行创建相应的mapping,并写入数据
静态映射
若在数据写入索引前,映射(mapping)已经创建,那么在写入数据时,ES会根据映射和写入数据的key进行对比,然后写入相应的映射中;
功能
哪些字段需要定义成全文索引字段
哪些字段定义为精确值,例如日期,数字、地理位置等
哪些字段需要被索引(能通过该字段的值查询文档)
日期值的格式。
动态添加字段的规则定义等。
集群cluster
集群是一个或多个节点(服务器)的集合,由一个唯一的名称标识
健康状态
green
主/复分片都可用
yellow
主分片可用,复制分片部分不可用
red
主分片部分不可用
节点node
一个ElasticSearch的实例,负责进行数据存储,并且参与集群的索引和搜索功能
默认名称随机UUID,可以自定义
节点类型
Master-eligible Node(默认)
可以参加选举成为Master Node
ode.master:false 可以禁止选举
Master Node
可以修改集群中节点信息
所有index
Mapping和Setting信息
分片的路由信息
Data Node
保存数据的节点,负责保存分片数据,对数据扩展有重要作用
Coordinating Node(每个节点)
负责接受Client请求,将请求分发到合适的节点获取响应后,将结果最终汇集在一起,每个节点默认都有Coordinating节点的职责
Machine Learning Node
负责运行机器学习的Job,用来做异常检测
Ingest Node
数据预处理的节点,支持Pipeline管道设置,可以使用Ingest对数据进行过滤、转换等操作
倒排索引·
ES为每个字段建立一个倒排索引
Term
分类索引,二分查找
term index
词典索引,存储前/后缀,存储在内存方便查找
FST 技术生成
节省内存空间
查找消耗CPU
term dictionary
Posting List
倒排表,文档ID数组[int]
Frame of Reference 索引帧
压缩算法,要求倒排表有序,增量算法,大数变成小数,仅存储增量值
节省posting list占用的磁盘空间和内存开销
Filter缓存
Roaring Bitmaps 咆哮位图 压缩位图索引
算法示例:(a,b) a=a/65536 b=a%65536
RoaringBitmap的Container
ArrayContainer
short[] 存储数据,占用2B,方便使用二分查找,且不会存储重复数值
存储数据没有任何压缩,因此只适合存储少量数据子主题
DEFAULT_MAX_SIZE值为4096,当容量超过这个值的时候会将当前Container替换为BitmapContainer。
BitmapContainer
long[]存储位图数据,初始化大小1024,占用空间8KB
RunContainer
行程长度压缩算法,对连续数据有比较好的压缩效果
联合索引
利用跳表(Skip List)的数据结构快速做“与”运算
利用bitset这种数据结构按位“与”运算
跳表数据结构
有序链表Level0,挑出其中几个元素到level1和level2,每一个level越往上,选出来的指针元素就越少,查找时候从高level往低查找。
注意事项
ES默认是自动建索引的,不需要索引的字段,要明确定义出来
对于string类型默认是会进行analysis(分词)的,不需要analysis的需要定义出来
文档的ID需要选择有规律的ID,随机性太大,比如UUID不利于查询
总结
ES之所以查询很快,主要是依赖于倒排索引的设计,尽量将数据放在内存,加上各种压缩算法和缓存算法
由于索引数据量很大,不能直接将数据丢在内存,所以通过构建有序状态转换器FST放在内存中。
为了避免Posting List大量的文档ID占用太多磁盘空间,ES使用了索引帧(Frame of Reference)技术压缩posting list。
ES还采用了Roaring Bitmap技术来缓存使用频率比较高的Filter搜索结果
API操作
增
自动生成ID
PUT /{index}/{doc}
自定义ID
PUT /{index}/{doc}/{id}
删
根据ID删除
DELETE /{index}/{doc}/{id}
改
根据ID修改
PUT /{index}/{doc}/{id}
查
根据ID查询
GET /{index}/{type}/{id}
只返回source
GET /{index}/{type}/{id}/_source
只返回source某个字段
GET /{index}/{type}/{id}/_source=field
其他查询
集群部署
部署·
es
调整虚拟内存
vim /etc/sysctl.conf
vm.max_map_count = 262144
调整文件描述符大小
/etc/security/limits.conf
hard nofile 6553/soft nofile 65536
kinbana
https://www.elastic.co/cn/downloads/kibana 官网
与elasticsearch版本要对应
绑定ES地址
vim ./config/kibana.yml
elasticsearch.hosts: ["http://192.168.31.221:9200"]/server.host: "0.0.0.0"
配置文件
elasticsearch.yml
配置 Elasticsearch
配置说明
日志目录
path.data
数据存放目录
path.logs
日志存放记录
其他配置
bootstrap.memory_lock
锁定物理内存,在es运行后锁定使用的内存大小,锁定大小一般是服务器内存的50%
node.name
配置ES集群内的节点名称,同一个集群内的节点名称要具备唯一性。
path.work
设置临时文件的存储路径,默认是es根目录下的work文件夹
node.data:true
指定该节点是否存储索引数据,默认为true
node.master:true
指定该节点是否有资格被选举成为master
node.attr.rack: r1
discovery.seed_hosts
当节点启动时,传递一个初始主机列表来执行发现
cluster.initial_master_nodes
写入候选主节点的设备地址,来开启服务时就可以被选为主节点
ingest.geoip.downloader.enabled
是否开启es启动时更新地图相关的数据库
跨域
http.cors.enable
是否开启跨域访问
http.cors.allow-origin: “*”
开启跨域后,能访问es的地址限制,*号表示无限制
集群配置
cluster.name
配置ES集群名称,同一个集群内的所有节点集群名称必须一致。
cluster.routing.allocation.same_shard.host:true
防止同一个shard的主副本存在同一个物理机上。
cluster.routing.allocation.node_initial_primaries_recoveries: 4
设置一个节点的并发数量,两种情况,第一种是在初始复苏过程中,默认是4个
cluster.routing.allocation.node_concurrent_recoveries: 4
设置一个节点的并发数量的第二种情况,在添加、删除节点及调整时。默认是4个
discovery.zen.minimum_master_nodes: 1
设置一个集群中主节点的数量,当多于三个节点时,该值可在2-4之间。
discovery.zen.ping.timeout: 3s
设置ping其他节点时的超时时间,网络比较慢时可将该值设大
discovery.zen.ping.multicast.enabled: false
禁止当前节点发现多个集群节点,默认值为true
cluster.fault_detection.leader_check.interval:2s
设置每个节点在选中的主节点的检查之间等待的时间。默认为1秒
discovery.cluster_formation_warning_timeout: 30s
启动后30秒内,如果集群未形成,那么将会记录一条警告信息,警告信息未master not fount开始,默认为10秒
cluster.join.timeout: 30s
点发送请求加入集群后,在认为请求失败后,再次发送请求的等待时间,默认为60秒
cluster.publish.timeout: 90s
设置主节点等待每个集群状态完全更新后发布到所有节点的时间,默认为30秒。
luster.routing.allocation.cluster_concurrent_rebalance:32
集群内同时启动的数据任务个数,默认是2个。
分片配置
index.number_of_shards:5
设置默认索引分片个数,默认为5片。主分片一经分配则无法更改。
index.number_of_replicas:1
设置默认索引副本个数,默认为1个副本。
indices.recovery.max_size_per_sec:0
设置数据恢复时限制的带宽,默认0及不限制,代表是无限的。
indices.recovery.concurrent_streams: 5
限制从其它分片恢复数据时最大同时打开并发流的个数,默认为5。
action.destructive_requires_name: false
是否允许通配符删除索引
IP绑定配置
network.host:
为es实例绑定特定的IP地址。
network.bind_host
设置绑定的ip地址,可以是ipv4或ipv6的,默认为0.0.0.0,绑定这台机器的任何一个ip
network.publish_host
设置其他节点连接此节点的地址,若不设置,则自动获取,值必须是个真实的ip地址,也可以用不配
端口配置
http.port:9200
设置对外服务的http端口,默认为9200
transport.tcp.port:9300
设置集群节点之间交互的tcp端口,默认是9300
transport.host: 0.0.0.0
允许任何人连接HTTP API
交互配置
transport.tcp.compress:true
设置是否压缩tcp传输时的数据,默认为false,不压缩
http.max_content_length:100mb
设置内容的最大容量,默认100mb
http.enabled:false
是否使用http协议对外提供服务,默认为true,开启
gateway.type: local
设置gateway的类型,默认为本地文件系统,也可以设置分布式文件系统、Hadoop的HDFS或者AWS的都可以
gateway.recover_after_nodes: 3
在完全重新启动集群之后阻塞初始恢复,直到启动N个节点为止
gateway.recover_after_time: 5m
设置初始化数据恢复进程的超时时间。默认是5分钟
gateway.expected_nodes: 2
设置该集群中节点的数量,默认为2个,一旦这N个节点启动,就会立即进行数据恢复
安全认证
Xpack
xpack.graph.enabled
图形展示
pack.reporting.enabled
报表统计
xpack.watcher.enabled
报警通知
xpack.security.enabled
安全认证
xpack.monitoring.enabled
监控跟踪
xpack.ml.enabled
设备资源分配
xpack.security.transport.ssl
https传输层认证
jvm.options
java环境进行设置参数的配置文件
log4j2.properties
配置日志
乐观锁
-version
增删改都会对-version字段加+1
失败问题
主分片写入成功,备份分片还未同步,主分片down机会有问题,版本号还未+1
主要用于ES内部并发控制
if_seq_no+if_primary_term(6.7+)
版本Version+分片No
脑裂问题
现象
主节点与其他节点响应不及时,重选主节点产生多个master
原因分析
超时分析
网络问题
集群网络问题 导致重新选举master
Master性能问题
负载过高
负载量大导致ES操作延迟,其他节点会认为主节点挂掉
JVM垃圾回收
ES占用内存过大 导致JVM垃圾回收时间过长
解决方案
网络问题·
增大触发条件
增大具有master资格的节点的数量discovery.zen.minimum_master_nodes:6(默认是1) 官方的推荐值是(N/2)+1
慎用,如果增加服务器可能会导致数据丢失
Master性能问题
角色分离
Master与Data节点不能为同一个,否则容易导致负载过高
减少误判
增加主节点的响应时间discovery.zen.ping_timeout 默认是3s
选举算法
原理解析
路由原理
路由算法
shard = hash(routing)%分片数
默认路由
PUT /{index}/{doc}/id(默认根据_id)
数据分布离散度好,查询需要每个shard上面获取数据
自定义路由
PUT /{index}/{doc}/id?routing=field
数据分布业务性强,根据业务查询效率高
存储流程
写入数据
1.memory buffer(不可查询)
3.refresh File system cache(1s 可查询到)
5.flush 磁盘(30m)
4.清空.memory buffer
2.事务日志translog
刷盘异常恢复用类似redo_log
commit point 记录最后刷盘位置
refresh操作
默认时间1s执行一次 可自定义index.refresh_interval修改刷新间隔
memory buffer写入segment ,segment被打开使得数据可以被查询到
清空memory buffer
flush操作
流程
1.把所有memory buffer写入到segment中
2.清空memory buffer
3.往磁盘里写入commit point信息
4.文件系统的page cache(segments) fsync到磁盘
5.删除旧的translog文件
参数
index.translog.flush_threshold_ops
执行多少次操作后执行一次flush,默认无限制
index.translog.flush_threshold_size
translog的大小超过这个参数后flush,默认512mb
index.translog.flush_threshold_period
多长时间强制flush一次,默认30m
index.translog.interval
es多久去检测一次translog是否满足flush条件
index.translog.sync_interval
控制translog多久fsync到磁盘,最小为100ms
index.translog.durability
request(默认值)
每次请求都执行fsync,es要等translog fsync到磁盘后才会返回成功
性能低 不会丢数据
async
translog每隔{index.translog.sync_interval}fsync一次
性能高 可能会丢数据
merge操作
背景:segment过多导致查询效率低下
1.合并零碎的segment
2.对合并的segment flush操作
3.删除零碎的segment 彻底删除
Spring
基础
IOC
基本使用
获取Bean
Id
ID唯一获取,只能声明一个
name
name 可以声明多个 a1:a2 a1与a2均可获取
Class
IOC容器只可以存在一个Bean
组合条件查找
primary=true 优先获取
顶层接口
BeanFactory
IOC容器顶层接口
初始化时候不会实例化对象
ApplicationContext
继承了BeanFactory接口,继承了其他接口 ,丰富了功能
初始化时候实例化对象
工厂注入
静态工厂注入
注入factory类 定义factory-method
动态工厂注入
实例化工厂对象
定义bean调用工厂对象初始化factory-bean/factory-method
构造注入
constructor-arg(构造函数)
name:属性名称
value:属性值
index:构造器下标
property(属性)
name:属性名称
value:属性值
ref
对象引用注入
array
数组注入
list
List列表注入
map
HashMap注入
配置类注入
@Configuration
声明一个类为配置类,用于取代bean.xml配置文件注册bean对象
@Bean
用于注册bean对象
@Scope
声明该bean的作用域
singleton
单例 默认
prototype
获取时候创建对象
request
同一个请求创建一个实例
session
同一个session创建一个实例
扫描注解
component-scan(xml)
base-package
包名
use-default-filters
是否使用默认注解
include-filter
包含注解
exclude-filter
剔除注解
@ComponentScan(默认扫描当前目前以及子目录)
value
要扫描的包路径
excludeFilters
Filter[] 指定排除的组件
includeFilters
Filter[] 指定包含的组件,要设置useDefaultFilters = false
FilterType
ANNOTATION
按照注解过滤
ASSIGNABLE_TYPE
按照给定的类型,指定具体的类,子类也会被扫描到
ASPECTJ
使用ASPECTJ表达式
REGEX
正则表达式
CUSTOM
自定义规则
注解
@Component
泛指注解,不好归类时候用
@Service
标注业务层组件
@Controller
标注控制层组件
@Repository
标注数据访问组件如Dao
@Value
属性赋值组件
@Autowired
按照类型装配
@PropertySource
读取配置文件赋值
@Qualifier
多实例组件
@Primary
多个相同Bean 首选Bean组件
@Resource
默认按照名称匹配,匹配不到按照类型匹配
@Lazy
延迟初始化,调用bean的时候再去执行初始化
@Conditional
按照一定条件判断,满足给容器注册Bean
实现condition接口 重写match方法
实现ConfigurationCondition接口
@Import
导入外部资源,IOC容器初始化
@Import(ClassName.class, ClassName.class, ...) 的方式注入
通过ImportSelector导入
通过 ImportBeanDefinitionRegistrar 导入 (其实是注册BeanDefintion)
@PostConstruct
用于初始化方法上
@PreDestory
用于销毁方法上
@DependsOn
指定Bean 初始化以及销毁的顺序
@Profile
类或方法在特定的 Profile 环境生效
spring.profiles.active=prod 多环境
AOP
核心概念
Aspect(切面)
面向规则,具有相同规则的方法集合体
Advice(通知)
回调函数
Pointcut(切入点)
需要被代理的方法
Target Object(目标对象)
需要被代理的对象
Aop Proxy(Aop 动态代理)
JDK或者CGLib
Before Advice(前置通知)
在invoke Pointcut之前调用,织入的方法
After Advice(后置通知)
在invoke Pointcut之后调用,织入的方法
After Return Advice(返回后通知)
返回值为非void , 织入的方法
Around Advice(环绕通知)
只要触发就调用,织入的方法
After Throwing Advice(异常通知)
调用Pointcut抛出异常,织入的方法
@EnableAspectJAutoProxy
放开Aspectj使用
@Import(AspectJAutoProxyRegistrar.class)
@Aspect
表示当前类是个切面类
@Pointcut
切入点表达式
execution
定位目标对象方法上
语法
execution(方法的修饰符 方法的返回值类型 方法所属的类 方法名 方法中参数列表 方法抛出的异常)
修饰符
支持通配符*,可以省略
返回值类型
支持通配符*,表示所有返回值,不可以省略
所属的类
支持通配符*,可以省略
方法名
支持通配符*,表示所有方法,不可以省略
参数列表
支持通配符*,不可以省略
()
一个无参方法
(…)
表示任意数量和类型的方法
(*)
一个任意类型的方法
(*,Integer)
)接受二个参数的方法,第一个可以是任意类型,第二个必须是Integer类型
异常
支持通配符*,可以省略
或
|| 或者 or
与
& 或者 and
非
!或者not
实例解析
execution(* com.baidu.dao.*(..))
*:接受任意返回值
com.baidu.dao.*:匹配方法名com.baidu.dao.任意方法名
(…):任意个方法列表
within
定位具体类型上
this
代理对象类型
target
目标对象类型
args
参数的类型
@target
@args
参数修饰的注解
@within
类型修饰的注解
@annotation
方法修饰的注解
reference pointcut
bean
@Before
MVC
restful风格
@RestController
@Controller + @ResponseBody
@GetMapping
@PostMapping
拦截器
功能
权限校验,日志记录,性能监控
继承HandlerInterceptor
preHandle
返回ModelAndView之前执行
postHandle
返回ModelAndView之后执行
afterCompletion
渲染页面完成之后执行
事务传播
1.PROPAGATION_REQUIRED(默认)
A,B单独执行均支持事务,并且合并是方法B调用的是方法A的事务
2.PROPAGATION_SUPPORTS
假设方法B是PROPAGATION_SUPPORTS,单独执行方法B 无事务处理.执行方法A ,事务处理,用的A的事务
3. PROPAGATION_MANDATORY
当单独调用methodB时,因为当前没有一个活动的事务,则会抛出异常。执行方法A时候会事务执行
4.PROPAGATION_REQUIRES_NEW
A执行到B事务时候,会将A事务挂起,执行完B事务之后恢复A事务执行完成
5.PROPAGATION_NOT_SUPPORTED
A执行到B时候,B没有事务也会将A事务挂起,执行完B之后恢复A事务执行完成
6. PROPAGATION_NEVER
总是非事务地执行,如果存在一个活动事务,则抛出异常
7. PROPAGATION_NESTED
外层事务A失败会回滚内层B事务,内层B事务失败不会回滚A事务
ApplicationListener
ContextRefreshedEvent
容器初始化或刷新时触发该事件
ContextStartedEvent
容器启动时触发该事件,即 Spring 容器启动时触发该事件。如使用命令行启动 Spring,则不会被触发。
ContextStoppedEvent
容器停止时触发该事件,即当 Spring 容器调用 stop() 方法停止容器时触发该事件。
ContextClosedEvent
容器关闭时触发该事件,当 Spring 容器调用 close() 方法关闭容器时,触发该事件。
RequestHandledEvent
一个 HTTP 请求结束时触发该事件。
权限
shiro
功能
java 安全框架,身份认证,授权,密码加密以及会话管理
概念
Subject
主题 身份信息
Security
安全
Realm
领域范围 dataSource
Autherticator
认证器
Authentication
认证
Authorizer
授权器
Authorization
授权
Cryptography
密码,加密
Credential
证书,凭证
Matcher
匹配器
Principal
身份
基础功能
Spring Secuirty
功能
认证
判断用户合法性
授权
控制用户可以访问的资源
框架说明
认证(AuthenticationManager)
Authentication authenticate(Authentication authentication)
getAuthorities
用户权限信息
getCredentials
用户凭证信息,一般指密码
getDetails
用户详细信息
getPrincipal
用户身份信息,用户名、用户对象
isAuthenticated
是否认证成功
实现类ProviderManager
AuthenticationProvider[]
多种认证方式
子主题
子主题
源码解析
IOC
流程
AbstractApplicationContext
ClassPathXmlApplicationContext.refresh()
prepareRefresh()
初始化Environment
ConfigurableListableBeanFactory beanFactory=obtainFreshBeanFactory() (IOC beanDefintion初始化)
解析XML/注解 生成BeanDefinitions
缓存BeanDefinitions到BeanFactory.beanDefinitionMap中
初始化BeanFactory
prepareBeanFactory(beanFactory);
beanExpressionResolver
解析SpEL表达式,解析#{}
propertyEditorRegistrars
注册一些类型转换器(spring在进行值注入的时候,需要把字符串类型转换为其他类型)
resolvableDependencies
去管理一些特殊的对象用来进行依赖注入。
beanPostProcessors
在Bean创建时,对Bean的功能进行一些扩展,对里面的注解进行一些识别
postProcessBeanFactory(beanFactory);
空实现,留给子类去实现。
invokeBeanFactoryPostProcessors(beanFactory);
beanFactory后处理器,充当beanFactory的扩展点,可以用来补充或修改BeanDefinition
ConfigurationClassPostProcessor-解析@Configuration、@Bean、@lmport、 @PropertySource
PropertySourcesPlaceHolderConfigurer -替换BeanDefinition中的${}
registerBeanPostProcessors(beanFactory);
bean 后处理器,充当bean的扩展点,可以工作在bean的实例化、依赖注入、初始化阶段
AutowiredAnnotationBeanPostProcessor功能有:解析@Autowired, @Value 注解
CommonAnnotationBeanPqstProcessor 功能有:解析@Resource, @PostConstruct, @PreDestroy
AnnotationAwareAspectJAutoProxyCreator 功能有:为符合切点的目标bean自动创建代理
initMessageSource();
实现国际化
容器中一个名为messageSource的bean,如果没有,则提供空的MessageSource实现
initApplicationEventMulticaster();
发布事件给 监听器
可以从容器中找名为applicationEventMulticaster的bean作为事件广播器,若没有,也会新建默认的事件广播器
可以调用ApplicationContext.publishEvent(事件对象)来发布事件
onRefresh();
空实现,留给子类扩展
registerListeners();
用来接收事件
实现ApplicationListener接口,重写其中onApplicationEvent(E e)方法即可
finishBeanFactoryInitialization(beanFactory);
初始化单例Bean,执行Bean后处理器扩展
finishRefresh();
准备生命周期管理器,发布ContextRefreshed事件
AnnotationConfigApplicationContext
DI
流程
applicationContext.getBean
AbstractBeanFactory.doGetBean
非单例:createBean
返回Bean
单例:factoryBeanObjectCach是否存在Key
存在:返回Bean
不存在:createBean 加入factoryBeanObjectCach
返回Bean
createBean
代理类
AOP
生成BeanWrapper
populateBean
BeanWrapperImpl.setPropertyValue
AOP
流程
继承接口:createBean
是:JDK动态代理
封装:BeanWrapper
否:CGLib动态代理
封装:BeanWrapper
创建代理类
1.BeanFactory.createBeanInstance
2.initializeBean
3.applyBeanPostProcessorsAfterInitialization
1.AbstractAutoProxyCreator.wrapIfNecessary
2.AbstractAdvisorAutoProxyCreator注册Advisor
1.getAdvicesAndAdvisorsForBean
2.FindEligibleAdvisors
3.sort
3.createProxy
MVC
流程
1.用户请求web->拦截->DispatchServlet
2.调用HandlerMapping->匹配->Controller与拦截器(HandlerExecutionChain)->返回DispatchServlet
3.调用HandlerAdapter->执行->Controller方法->生成->ModelAndView->返回DispatchServlet
4.调用ViewResolver->解析->ModelAndView->生成->View->HttpResponse
源码分析
Init初始化
1.HttpSerlvertBean.Init
2.FrameworkSerlvert.onRefresh
3.configureAndRefreshWebApplicationContext.onRefresh
4.dispatchSerlvert.initStrategies
1.initMultipartResolver
初始化文件上传组件
2.initLocaleResolver
初始化本地环境
3.initThemeResolver
初始化模板
4.initHandlerMappings
初始化HandlerMapping
5.initHandlerAdapters
初始化HandlerAdapter
6.initHandlerExceptionResolver
初始化异常拦截器
7.initRequestToViewNameTranslator
初始化视图预处理器
8.initViewReslovers
初始化ViewReslovers
9.initFlashMapManager
初始化FlashMap解析器
运行阶段
dispatcherServlet.doService
1.返回HandlerExecutionChain->getHandler()->abstractHandlerMapping.getHandler()
2.返回ModelAndView->getHandlerAdapter()->RequestMappingHandlerAdapter.invokerHandlerMethod()
3.输出View->processDispatchResult->abstractView.Render()
ApplicationListener
Sping Boot
基础使用
启动流程
SpringApplication.run
createApplicationContext
AnnotationConfigApplicationContext
refreshContext
obtainFreshBeanFactory
refreshBeanFactory
createBeanFactory
ConfigurableListableBeanFactory
loadBeanDefintions
扫描并完成BeanDefintions加载
常见注解
@SpringBootApplication
@SpringBootConfiguration
@Configuration
表示当前类是个配置类
@EnableAutoConfiguration
自动配置类注解,实例化的是依赖包中的类
@ComponentScan
初始化Spring容器会进行扫描,扫描路径为当前在解析的这个类所在的包路径
自动装配
@SpringBootApplication
@EnableAutoConfiguration
@Import
AutoConfigurationImportSelector
实现selectImport方法 导入Bean
getCandidateConfigurations()->SpringFactoriesLoader.loadFactoryNames
SPI方式从的META-INF/spring.factories中配置加载Bean
@AutoConfigurationPackage
@Import
Registrar
实现registerBeanDefinitions 注册Bean
将主配置类(@SpringBootApplication标注的类)的所在包及下面所有子包里面的所有组件扫描到Spring容器;
约定大于配置设计思想
Environment
SpringApplication.run()
prepareEnvironment()
1.getOrCreateEnvironment() 根据webApplicationType选择
StandardServletEnvironment
StandardReactiveWebEnvironment
StandardEnvironment(默认)
2.configureEnvironment(environment,?)
1.configurePropertySources
获取MutablePropertySources
List<PropertySource<?>> propertySourceList
String name
T source
2.configureProfiles
setActiveProfiles
3.bindToSpringApplication()
4.attach(environment)
MutablePropertySources都转换成了ConfigurationPropertySourcesPropertySource的形式,从而允许后面的方法能够对其进行统一调用
PropertyPlaceholderAutoConfiguration
PropertySourcesPlaceholderConfigurer
BeanFactoryPostProcessor
invokeBeanFactoryPostProcessors(beanFactory);
MutablePropertySources 初始化
Spring Boot SPI加载ConfigFileApplicationListener
ConfigFileApplicationListener.onApplicationEvent
ConfigFileApplicationListener.postProcessEnvironment
Load.load()完成对Spring Boot配置文件加载
发布ApplicationEnvironmentPreparedEvent
PropertySource
@Value
属性占位符解析
Spring Cloud
Ribbon
基本使用
作用
基于 Netflix Ribbon 实现的客户端负载均衡和服务调用工具
使用方法
LoadBalancerClient
@LoadBalanced
goods-service.ribbon.NFLoadBalancerRuleClassName=**.** 设置负载均衡策略
负载均衡策略
RoundRobinRule
线性轮询策略,即按照一定的顺序依次选取服务实例
RandomRule
随机选取一个服务实例
RetryRule
按照 RoundRobinRule(轮询)的策略来获取服务,如果获取的服务实例为 null 或已经失效,则在指定的时间之内不断地进行重试
WeightedResponseTimeRule
按照平均响应时间,来计算所有服务实例的权重,响应时间越短的服务实例权重越高,被选中的概率越大
BestAvailableRule
先过滤点故障或失效的服务实例,然后再选择并发量最小的服务实例。
AvailabilityFilteringRule
先过滤掉故障或失效的服务实例,选择并发较小的节点
ZoneAvoidanceRule(默认)
默认的负载均衡策略,综合判断服务在不同区域(zone)的性能和服务(server)的可用性,来选择服务实例。
自定义负载均衡策略
继承AbstractLoadBalancerRule
重写Choose方法
原理分析
@LoadBalanced解析原理
其实就是@Qualifier注解,具备它的所有特性
LoadBalancerAutoConfiguration
1.获取所有增加了@LoadBalanced注解的RestTemplate
2.为每个RestTemplate增加LoadBalancerInterceptor拦截器
LoadBalancerInterceptor
注入LoadBalancerClient
intercept(拦截请求)
LoadBalancerClient.execute(处理请求)
继承ClientHttpRequestInterceptor
RibbonAutoConfiguration
初始化LoadBalancerClient
1.存储并维护服务列表
2.根据路由规则,通过servicename获取一个服务地址
3.将请求数据发送到服务地址
LoadBalancerClient
RibbonLoadBalancerClient
1.获取负载均衡器ILoadBalancer
2.根据负载均衡器和规则选择服务(chooseServer)
3.执行request请求并返回结果
ILoadBalancer
ZoneAwareLoadBalancer
DynamicServerListLoadBalancer.restOfInit
enableAndInitLearnNewServersFeature
PollingServerListUpdater#start(UpdateAction)
定时任务 30s执行一次
UpdateAction.doUpdate
更新Server列表
updateListOfServers
更新Server列表
BaseLoadBalancer#setupPingTask
定时任务 Ping心跳检测
chooseServer
IRule#choose(PredicateBasedRule)
execute
1.封装ServiceRequestWrapper
2.重构请求URI
3.ClientHttpRequestExecution执行Http请求
NamedContextFactory
可以创建一个子容器(或者说子上下文),每个子容器可以通过 Specification 定义 Bean。
Eureka
基本使用
基础使用
关键注解
@EnableEurekaServer
服务端注册
@EnableEurekaClient
消费端注册
@EnableDiscoveryClient
可获取当前服务的相关信息
配置说明
instance配置项
eureka.instance.hostname
服务注册中心实例的主机名
eureka.instance.app-group-name
注册在Eureka服务中的应用组名
eureka.instance.appname
注册在的Eureka服务中的应用名称
eureka.instance.instance-id
该实例注册到服务中心的唯一ID
eureka.instance.ip-address
该实例的IP地址
eureka.instance.prefer-ip-address
该实例,相较于hostname是否优先使用IP
eureka.instance.a-s-g-name
用于AWS平台自动扩展的与此实例关联的组名
eureka.instance.data-center-info
部署此实例的数据中心
eureka.instance.default-address-resolution-order
默认的地址解析顺序
eureka.instance.environment
该实例的环境配置
eureka.instance.initial-status
初始化该实例,注册到服务中心的初始状态
eureka.instance.instance-enabled-onit
表明是否只要此实例注册到服务中心,立马就进行通信
eureka.instance.namespace
该服务实例的命名空间,用于查找属性
eureka.instance.metadata-map.test
该服务实例的子定义元数据,可以被服务中心接受到
eureka.instance.lease-expiration-duration-in-seconds
服务中心删除此服务实例的等待时间(秒为单位),时间间隔为最后一次服务中心接受到的心跳时间
eureka.instance.lease-renewal-interval-in-seconds=30
该实例给服务中心发送心跳的间隔时间,用于表明该服务实例可用
eureka.instance.registry.default-open-for-traffic-count
该实例,注册服务中心,默认打开的通信数量
eureka.instance.registry.expected-number-of-renews-per-min
每分钟续约次数
eureka.instance.health-check-url
该实例健康检查url,绝对路径
eureka.instance.health-check-url-path
该实例健康检查url,相对路径
eureka.instance.home-page-url-path
该实例的安全健康检查url,绝对路径
eureka.instance.secure-port
https通信端口
eureka.instance.secure-port-enabled
https通信端口是否启用
eureka.instance.non-secure-port
http通信端口
eureka.instance.non-secure-port-enabled
http通信端口是否启用
eureka.instance.secure-virtual-host-name
该实例的安全虚拟主机名称(https)
eureka.instance.virtual-host-name
该实例的虚拟主机名称(http)
eureka.instance.status-page-url
该实例的状态呈现url,绝对路径
eureka.instance.status-page-url-path
该实例的状态呈现url,相对路径
client配置项
eureka.client.enabled=true
#该客户端是否可用
eureka.client.register-with-eureka=false
#实例是否在eureka服务器上注册自己的信息以供其他服务发现,默认为true
eureka.client.fetch-registry=false
#此客户端是否获取eureka服务器注册表上的注册信息,默认为true
eureka.client.filter-only-up-instances=true
#是否过滤掉,非UP的实例。默认为true
eureka.client.serviceUrl.defaultZone
#与Eureka注册服务中心的通信zone和url地址
eureka.client.eureka-connection-idle-timeout-seconds=30
#client连接Eureka服务端后的空闲等待时间,默认为30 秒
eureka.client.eureka-server-connect-timeout-seconds=5
#client连接eureka服务端的连接超时时间,默认为5秒
eureka.client.eureka-server-read-timeout-seconds=8
#client对服务端的读超时时长
eureka.client.eureka-server-total-connections=200
#client连接all eureka服务端的总连接数,默认200
eureka.client.eureka-server-total-connections-per-host=50
#client连接eureka服务端的单机连接数量,默认50
eureka.client.cache-refresh-executor-exponential-back-off-bound=10
#执行程序指数回退刷新的相关属性,是重试延迟的最大倍数值,默认为10
eureka.client.cache-refresh-executor-thread-pool-size=2
#执行程序缓存刷新线程池的大小,默认为5
eureka.client.heartbeat-executor-exponential-back-off-bound=10
#心跳执行程序回退相关的属性,是重试延迟的最大倍数值,默认为10
eureka.client.heartbeat-executor-thread-pool-size=5
#心跳执行程序线程池的大小,默认为5
eureka.client.eureka-service-url-poll-interval-seconds=300
#询问Eureka服务url信息变化的频率(s),默认为300秒
eureka.client.initial-instance-info-replication-interval-seconds=40
#最初复制实例信息到eureka服务器所需的时间(s),默认为40秒
eureka.client.instance-info-replication-interval-seconds=30
#间隔多长时间再次复制实例信息到eureka服务器,默认为30秒
eureka.client.registry-fetch-interval-seconds=30
#从eureka服务器注册表中获取注册信息的时间间隔(s),默认为30秒
eureka.client.region=us-east-1
#获取实例所在的地区。默认为us-east-1
eureka.client.prefer-same-zone-eureka=true
#实例是否使用同一zone里的eureka服务器,默认为true,理想状态下,eureka客户端与服务端是在同一zone下
eureka.client.fetch-remote-regions-registry
#eureka服务注册表信息里的以逗号隔开的地区名单,如果不这样返回这些地区名单,则客户端启动将会出错。默认为null
eureka.client.allow-redirects=false
#服务器是否能够重定向客户端请求到备份服务器
eureka.client.client-data-ac
#客户端数据接收
eureka.client.healthcheck.enabled=true
#改变eureka server中注册的服务的健康检测方式
eureka.client.availability-zones.china
#获取实例所在的地区下可用性的区域列表
高可用
相互注册
自我保护机制(AP)
触发条件
在15min内超过85%的客户端节点都没有正常的心跳,Eureka进入自我保护机制
工作模式
不会剔除过期服务
可以接受新增或查询请求,但是不会同步到其他节点
网络故障恢复后,EurekaServer节点会自动退出自我保护模式
源码分析
OpenFeign
基本使用
定义
声明式伪RPC的Rest客户端
@EnableFeignClients
扫描所有使用注解@FeignClient定义的feign客户端,并把feign客户端注册到IOC容器中
@FeignClient
声明伪RPC的Rest接口,必需声明在Interface上
接口创建动态代理,然后通过这个代理发送HTTP请求到我们指定分服务端
配置说明
针对全部服务
default
针对某个服务
serviceName
数据压缩
GZIP 注意okhttp不生效
源码分析
@EnableFeignClients
@Import({FeignClientsRegistrar.class})
FeignClientsRegistrar.registerBeanDefinitions
registerDefaultConfiguration
加载默认配置
registerFeignClients
registerClientConfiguration
加载FeignClient对应的配置
registerFeignClient
FeignClientFactoryBean
将标注@FeignClient 类加载到IOC容器
getObject
getTarget
FeignContext context = this.applicationContext.getBean(FeignContext.class);
获取FeignContext上下文
NamedContextFactory
Feign.Builder builder = feign(context);
从FeignContext中,根据contextId获取ApplicationContext,然后获取Feign.Builder
Client client = getOptional(context, Client.class);
从FeignContext中,根据contextId获取ApplicationContext,然后获取Client
LoadBalancerFeignClient
Targeter targeter = get(context, Targeter.class);
从FeignContext中,根据contextId获取ApplicationContext,然后获取Targeter
targeter.target(this, builder, context,new HardCodedTarget<>(this.type, this.name, url))
创建并返回代理对象
实现ImportBeanDefinitionRegistrar接口
@FeignClient
Hystrix
基础使用
意义
保护线程资源
防止单个服务的故障耗尽系统中的所有线程资源
快速失败机制
当某个服务发生了故障,不让服务调用方一直等待,而是直接返回请求失败
提供降级(FallBack)方案
请求失败后,提供一个设计好的降级方案,通常是一个兜底方法,当请求失败后即调用该方法
防止故障扩散
使用熔断机制,防止故障扩散到其他服务
监控功能
提供熔断器故障监控组件 Hystrix Dashboard,随时监控熔断器的状态
注解说明
@HystrixCommand
fallbackMethod
单个服务降级
commandProperties
@HystrixProperty
name
HystrixCommandProperties找到Key
value
@HystrixProperty
@DefaultProperties
defaultFallback
全局服务降级
@EnableHystrix
启用Hystrix断路器
@EnableCircuitBreaker
启用Hystrix断路器,允许使用@CircuitBreaker注解来标记需要使用断路器的方法,支持其他断路器实现
监控
Hystrix Dashboard
集成GateWay
熔断机制
一定的时间窗口内,当请求的次数达到一定的失败比率后,hystrix就会主动拒绝服务,一段时间内不会处理请求(即使服务恢复了)
主要参数
hystrix.command.default.circuitBreaker.requestVolumeThreshold
熔断触发的最小个数,即在一定的时间窗口内请求达到一定的次数,默认20
hystrix.command.default.metrics.rollingStats.timeInMilliseconds=5000
时间窗口,默认10s
hystrix.command.default.circuitBreaker.errorThresholdPercentage=50
失败率达到多少百分比后熔断 默认值:50
hystrix.command.default.circuitBreaker.sleepWindowInMilliseconds=5000
熔断多长时间后,尝试放一次请求进来,默认5秒
隔离模式
execution.isolation.strategy
THREAD(线程池 默认)
SEMAPHORE(信号量)
模式对比
线程池
支持超时直接返回
支持熔断,线程池达到maxSize会降级调用fallBack方法
每个服务单独用线程池
可以异步
线程切换造成CPU负载高
信号量
不支持超时,会一直阻塞
支持熔断,信号量达到maxConcurrentRequest会降级调用fallBack方法
通过信号量计数器实现
同步调用
单线程
熔断算法
滑动窗口
Gateway
基本使用
定义
API网关是一个服务器,是系统的唯一入口
作用
鉴权,限流,日志,缓存等
工作流程
client->Gateway->Gateway Handler Mapping->Gateway Web Handler->Filter->Service
三大核心
路由(Route)
id
路由的ID
uri
匹配路由的转发地址
predicates
多个Predicate组合
各种 Predicates 同时存在于同一个路由时,请求必须同时满足所有的条件才被这个路由匹配
一个请求满足多个路由的断言条件时,请求只会被首个成功匹配的路由转发
order
路由的优先级,数字越小,优先级越高
Filter
过滤器 过滤掉一些请求, 满足则转发
断言(Predicate)
作用:匹配http请求
After
After某某时间以后,断言才会进行匹配
Before
在某某时间以前,断言才会进行匹配
Between
在区间内,断言匹配
Cookie
name=regexp 匹配cookie名称为name,值为正则匹配
Header
header=regexp 匹配请求Header名称为header,值为正则匹配
Host
一组匹配的域名列表
Method
子主题
匹配一个或多个Http请求方式
Path
请求路径匹配,包含1个或者多个路径,matchTrailingSlash=true才会生效
Query
例Query=red, gree匹配查询参数red=gree的请求,值为正则匹配
RemoteAddr
RemoteAddr=192.168.1.1/24 IP地址匹配 比如匹配192.168.1.1-192.168.1.24地址
部署在代理服务器(Nginx)获取不到真实请求IP
自定义获取remote address的处理器RemoteAddressResolver
基于X-Forwarded-For请求头的XForwardedRemoteAddressResolver
trustAllRemoteAddressResolver
返回始终采用标头中找到的第一个 IP 地址
maxTrustedIndex
采用与在 Spring Cloud Gateway 前面运行的可信基础设施数量相关的索引
X-Forwarded-For
背景
部署代理服务器应用获取不到真实请求的客户端IP,而是代理服务器IP
解决方案
HTTP代理会在HTTP协议头中添加X-Forwarded-For头,用来追踪请求的来源
格式:X-Forwarded-For: client1, proxy1, proxy2
问题
伪造X-Forwarded-For
发起请求时,请求头上带上一个伪造的X-Forwarded-For
解决方案
Nginx配置
最外层Nginx
proxy_set_header X-Forwarded-For $remote_addr;
里层Nginx
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
Tomcat服务器
RemoteIpValve
从右向左遍历 剔除内网IP与本身服务器IP,获取可信任IP
Egg.js
maxProxyCount
指定代理层数,然后取X-Forwarded-For头中从右往左数第maxProxyCount个IP即为真实 IP 地址
Weight
指定当前请求被路由的权重的,其接收两个参数:分组和比重,参与权重路由的地址必须在同一个分组,否则weight无效果,而权重为整型数字
自定义断言
继承AbstractRoutePredicateFactory重写apply方法
类必须加上RoutePredicateFactory作为结尾
过滤器(Filter)
作用:可以修改输入输出请求
GatewayFilter
说明
网关过滤器,需要通过spring.cloud.routes.filters配置在具体路由
通过spring.cloud.default-filters 配置在全局,作用在所有路由上
分类
AddRequestHeader
给当前请求添加一个请求头
AddRequestHeadersIfNotPresent
当前请求头不存在Key时,给当前请求添加请求头,冒号分隔的 name 和 value 键值对的集合
AddRequestParameter
给当前请求添加请求参数 多个参数添加多次
AddResponseHeader
给响应的请求添加一个请求头
CircuitBreaker
集成hystrix 支持错误fallBack
CacheRequestBody
缓存请求Body key在ServerWebExchangeUtils.CACHED_REQUEST_BODY_ATTR定义
DedupeResponseHeader
对指定响应头去重复。
去重策略strategy
RETAIN_FIRST保留第一个/RETAIN_LAST保留最后一个/RETAIN_UNIQUE保留唯一
FallbackHeaders
降级时在Header里面添加信息
JsonToGrpc
将一个JSON payload 转换为gRPC请求。
LocalResponseCache
过滤器允许缓存响应体和header,只能缓存Get
MapRequestHeader
接受 fromHeader 和 toHeader 参数 toHeader将匹配改写fromHeader 存在的值
ModifyRequestBody
发送至网关之前修改请求body
ModifyResponseBody
修改响应体发送给客户端
PrefixPath
给请求添加前缀/PrefixPath/url
PreserveHostHeader
无参,在转发请求到服务提供者的时候,会保留host信息
RedirectTo
跳转到指定位置
RemoveJsonAttributesResponseBody
移除Reponse的相关属性
RemoveRequestHeader
删除请求指定Header
RemoveRequestParameter
删除请求指定Parameter
RemoveResponseHeader
删除响应指定的Header
RequestHeaderSize
限定请求Head的大小,超过Size发送431状态码
RequestRateLimiter
限流 令牌桶算法 可使用redis 实现
RewriteLocationResponseHeader
重写Location 响应头的值
RewritePath
重写请求路径
RewriteResponseHeader
重写响应头的值
SaveSession
强制保存Session
SetPath
改写请求路径
SetRequestHeader
改写请求的header,将指定key改为指定value,如果该key不存在就创建
SetResponseHeader
改写响应的header,将指定key改为指定value,如果该key不存在就创建
SetStatus
控制返回http状态码
StripPrefix
改写/ path
Retry
重试请求
retries-重试次数/statuses-遇到什么样的返回状态才重试/methods-那些类型的方法会才重试/backoff-重试策略/exceptions-重试异常/series-series值重试
RequestSize
控制请求大小,可以使用KB或者MB等单位,超过这个大小就会返回413错误
SetRequestHostHeader
修改请求header中的host值
TokenRelay
将第三方的token转发到服务提供者那里去
自定义Filter
重写AbstractGatewayFilterFactory实现apply方法
GlobalFilter
说明
全局过滤器,不需要在配置文件中配置,作用在所有的路由上
分类
自定义路由
实现GlobalFilter, Ordered接口,重写filter,getOrder 方法
生命周期
pre
业务逻辑之前
post
业务逻辑之后
应用
限流
引入redis依赖,配置端口 登录信息
自定义KeyResolver,定义限流标识(比如IP)
添加RequestRateLimiter配置
burstCapacity:令牌桶总容量
replenishRate:填充令牌速率 每秒
key-resolver 自定义Bean 的name
负载均衡
引入注册中心Eureka/nacos
配置 uri:lb//serviceName
配置:discovery.locator.enabled= true
鉴权
定义全局过滤器AuthorizeFilter
登录请求
登录成功创建JWT令牌
非登录请求
校验JWT令牌合法性,获取登录用户信息
日志
定义全局过滤器LogFilter
记录请求Body等日志存储在NOSQL
动态路由
集成Actuator 具体操作查看actuator 官方API 动态创建 删除路由
持久化动态路由
实现RouteDefinitionRepository接口
流程解析
Nacos
基本使用
功能
配置中心
注册中心·
配置中心
基本组成
Data ID(应用名)
应用名-环境profile名.文件后缀(appName-dev.yaml)
GROUP
分组
Namespace
默认是空串,公共命名空间
项目集成
Spring
添加依赖nacos-spring-context
@EnableNacosConfig
启用 Nacos Spring 的配置管理服务
@NacosProperties
serverAddr(配置服务地址)
@NacosPropertySource
dataId=** 加载数据源为**
autoRefreshed 自动刷新配置
@NacosValue
获取注解设置属性值
Spring Boot
添加依赖nacos-config-spring-boot-starter
application.properties
nacos.config.server-addr=127.0.0.1:8848 配置服务地址
@NacosPropertySource 同Spring
@NacosValue 同Spring
Spring cloud
添加依赖spring-cloud-starter-alibaba-nacos-config(需注意版本对应)
spring.cloud.nacos.config.server-addr
配置服务地址bootstrap.properties 优先加载配置
dataId
${prefix}-${spring.profiles.active}.${file-extension} 多环境
prefix
spring.cloud.nacos.config.prefix 配置
spring.application.name 默认 未配置
@RefreshScope
配置自动更新
@Value
获取注解设置属性值
共享配置
spring.cloud.nacos.config.shared-configs
扩展配置
spring.cloud.nacos.config.extension-config
配置优先级
主配置 > 扩展配置(extension-configs) > 共享配置(shared-configs)。
shared-configs[3] > shared-configs[2] > shared-configs[1] > shared-configs[0]
extension-configs[3] > extension-configs[2] > extension-configs[1] > extension-configs[0]
相同配置 优先级高的配置覆盖优先级低的配置
持久化
derby数据库(默认)
Mysql
版本要求:5.6.5+
修改conf/application.properties
执行conf/nacos-mysql.sql脚本,重启nacos
配置优先级
共享配置shared-configs
大下标会覆盖小下标配置
扩展配置extension-configs
扩展配置会覆盖共享配置
集群
磁盘缓存同步
1.先写某个节点缓存,写入MySql数据库
2.发布一个事件通知,其他节点接收通知,从mysql中重新拉取缓存
存储Mysql不存在集群问题
注册中心
服务注册
服务发现
原理分析
配置中心
NacosConfigService初始化
HttpAgent
http请求的包装,对Http请求增强(记录请求时间)
ClientWork
ThreadPool:newScheduledThreadPool->?
ThreadPool:newScheduledThreadPool->longPolling
ThreadPool:scheduleWithFixedDelay->checkConfigInfo
LongPollingRunnable
1.checkLocalConfig 判断是否有更新
2.cacheData.checkListenerMd5(); 比较MD5有更新触发NotifyListener
safeNotifyListener
listener.receiveConfigInfo()
3.checkUpdateDataIds
需要对比的配置关键信息拼接成字符串发送到服务端对比
4.checkUpdateConfigStr
发送Http请求获取变化的groupKeys 长轮询请求
5.safeNotifyListener
md5与cachData.listener.md5比较 ->listener.receiveConfigInfo()
NacosContextRefresher
继承ApplicationListener
监听ApplicationReadyEvent事件
onApplicationEvent
registerNacosListenersForApplications
registerNacosListener
cachData->addListener
注册中心
Sentinel
基础使用
功能介绍
面向分布式服务架构的轻量级流量控制组件
基于滑动窗口算法实现,Hystrix已停止更新,Sentinel功能更为丰富,灵活性可用性更高
dashboard控制台
jar包下载
https://github.com/alibaba/Sentinel/releases
参数
-Dserver.port
指定启动的端口,默认8080
-Dproject.name
指定本服务的名称
-Dcsp.sentinel.dashboard.server
指定sentinel控制台的地址,用于将自己注册进入实现监控自己
-Dsentinel.dashboard.auth.username=sentinel
用于指定控制台的登录用户名为 "sentinel",默认值为 “sentinel”
-Dsentinel.dashboard.auth.password=123456
用于指定控制台的登录密码为 "123456",默认值为 "sentinel"
-Dserver.servlet.session.timeout
服务端 session 的过期时间
硬编码
SphU
抛出异常BlockException的方式定义资源
Entry entry = SphU.entry(resourceName);
entry.exit();
SphO
返回布尔值的方式定义资源
if(SphO.entry("自定义资源名"))
SphO.exit() 方法成对出现
@SentinelResource
value
资源名称,必需项
entryType
entry 类型 可选项(默认为 EntryType.OUT)
blockHandler
指定函数负责处理 BlockException(限流)
blockHandlerClass
指定处理BlockException异常的处理类 不指定默认本类
fallback
指定的函数负责处理业务运行的异常(降级),指定blockHandler时候不生效
fallbackClass
指定的类负责处理业务运行的异常
defaultFallback
默认的 fallback 函数名称,可选
exceptionsToIgnore
用于指定哪些异常被排除掉,不会计入异常统计中,也不会进入 fallback 逻辑中,而是会原样抛出。
限流规则FlowRule
resource
资源名,即限流规则的作用对象,默认请求路径
limitApp
流控针对的调用来源,若为 default 则不区分调用来源,默认值default
count
限流阈值
grade
限流阈值类型
strategy
流控模式
controlBehavior
流控效果
限流类型
1: QPS(默认)
每S允许的QPS请求个数
0 :并发线程数
当前请求上下文的线程个数,如果超出阈值,新的请求会被立即拒绝
流控模式
直接(默认)
接口达到限流条件时,直接限流
关联
当关联的资源达到阈值时,就限流自己(适合做应用让步)
高优先级资源触发阈值,对低优先级资源限流。
链路
只记录指定链路上的流量,指定资源从入口资源进来的流量,如果达到阈值,就可以限流
阈值统计时,只统计从指定资源进入当前资源的请求,是对请求来源的限流
流控效果
快速失败(默认)
当 QPS 超过任意规则的阈值后立即拒绝,拒绝方式为抛出FlowException
排队等待
所有的请求按照先后次序排队执行,两个请求的间隔不能小于指定时长
Warm Up
- QPS超过阈值时,拒绝新的请求;QPS阈值是逐渐提升的,可以避免冷启动时高并发导致服务宕机
持久化规则
基于nacos
基于ZK
集群限流
源码分析
Seata
基础使用
事务角色
TC
事务协调器,维护全局事务的运行状态
1.接收TM指令发起全局事务的提交与回滚
2.负责与RM通信,协调各个分支事务的提交或回滚
TM
事务管理器,开启一个全局事务,并定义范围
1.向TC发起全局提交或回滚指令
RM
接收事务协调器TC的指令,命令分支事务完成本地事务的提交或回滚。
事务模式
AT(默认)
执行流程
1.TM向TC申请开启一个全局事务
2.TC创建全局事务,并将全局事务ID(称为XID)返回给TM
3.RM向TC注册分支事务,并且绑定XID
4.执行所有本地事务,记录undo_log,执行结果给TC
5.TC发送提交或回滚命令给RM(提交-删除回滚日志,回滚执行undo_log)
提交->删除日志文件
回滚->执行回滚语句
特性
弱一致性
基于全局锁隔离
代码侵入性无,性能好
基于关系型数据库
TCC
执行流程
try
TC生成XID,执行自定义try方法
confirm
try 方法执行完成,执行自定义Confirm方法
cancel
try方法执行异常 执行cancel方法
存在问题
空回滚
try未执行/执行异常 调用了Cancel方法
思路:try方法记录xid,事务ID,Cancel方法判断try是否正常执行
幂等
重复调用Confirm/Cancel方法
思路:执行方法check事务日志表status,校验Confirm/Cancel是否已执行
悬挂
RPC调用超时,try请求未执行就调用了Cancel,之后请求真正到达try
Cancel记录到事务日志表中,try 判断是否已经Cancel,已经cancel直接退出
特性
弱一致性
基于资源预留隔离·
代码侵入,需要写三个接口,性能非常好
性能要求高的事务,非关系型数据库事务
SAGA
执行流程
每个Tran都对应一个补偿动作Cancel
依照调用链路Tran调用补偿Cancel
恢复策略
向前恢复
重试失败事务,务必保证成功
向后恢复
补偿所有已完成的事务,执行结果返回失败
特性
最终一致性
无隔离
代码侵入,需要写补偿业务,性能非常好
业务流程复杂,无法实现TCC的事务接口
XA
执行流程
数据库必须实现并支持XA协议,基于数据库的XA协议来实现2PC
Register:XA Start->sql->XA End->XA Prepare 数据不可见
Report:Report Prepare Status->TC
TC->Commit/Rollback
特性
强一致性
完全隔离
无代码侵入,性能差
适用于对一致性要求高,隔离性高的场景
事务隔离(AT模式)
写隔离
本地事务提交前,先拿到全局锁
本地事务全部提交释放全局锁
全局锁限定超时时间
脏写问题
@GlobalTransactional
串行化保证写隔离
@GlobalLock+select for update
读隔离
脏读问题
默认未提交读
select for update 实现已提交读,性能开销大
存储模式
File
优点
简单,易于部署和使用
高性能,低延迟
缺点
单点故障,文件系统故障导致数据丢失,无法使用等问题
扩展性较差,水平扩展时,需要考虑文件系统的共享和同步机制
数据备份和恢复的复杂性
DB
优点
可靠性,系统故障时候不会丢失数据·
ACID特性
技术成熟稳定
缺点
性能瓶颈,高并发处理性能存在问题
扩展性限制,水平扩展方面存在一定瓶颈
配置和管理复杂 需要初始化表
Redis
优点
性能较高
缺点
Seata-Server 1.3及以上版本支持
存在事务信息丢失风险
注册中心
可选nacos,作用: 存储和管理 Seata 事务参与者的信息的组件
子主题
源码解析
GlobalTransactionScanner
SeataAutoConfiguration 自动装配注入
功能
InitializingBean 接口
实现afterPropertiesSet
TMClient.init() 初始化TM
RMClient.init() 初始化RM
继承AbstractAutoProxyCreator
生成Aop代理对象
扫描@GlobalTransactional/GlobalLock
添加GlobalTransactionalInterceptor拦截器
TCC模式
添加TccActionInterceptor拦截器
GlobalTransactionalInterceptor
继承MethodInterceptor,对增强的方法进行增强
invoke
扫描@GlobalTransactional注解
handleGlobalTransaction
TransactionalExecutor.execute
1.创建全局事务(传播行为)
2.开启全局事务(锁资源)
3.执行业务逻辑
4.提交/回滚全局事务
5.释放资源
扫描@GlobalLock注解
handleGlobalLock
GlobalLockExecutor.execute
select for update 申请本地锁
检查全局锁checkLock
@GlobalTransactional
Seata 中的全局事务,默认实现类为DefaultGlobalTransaction
@GlobalLock
全局锁注解
分布式
分布式事务
强一致性
XA协议
弱一致性
TCC协议
分布式ID
redis
zk
原理分析
优劣势
雪花算法
组成
1个标识位
无作用
41位的时间戳
记录时间戳,毫秒级
10位WorkerID
记录工作机器id 前5位为数据中心id(可以理解为机器库房id),后5位为机器id(可以理解为不同实例的id)
12位序列号
用来记录同毫秒内产生的不同id
优劣势
优势
不依赖数据库 直接生成 速度快
劣势
时钟错误导致ID重复问题
分布式锁
redis
基本实现
setnx
常见问题
zk
限流算法
传统计数器
临界问题,不在特定区间内请求无法被统计到
滑动窗口计数器
解决临界问题,对大窗口切割小窗口,平滑移动窗口统计
漏桶算法
无法应对短时间的突发流量
消费速率固定问题
令牌桶算法
解决令牌桶问题
消费速率不受限
热门数据收集
1.历史热门数据
2.突发的热门数据 冷门变热门(口罩)
3.不存在的商品 变热门(新手机发布)
秒杀设计
设计原则
开闭原则(抽象定义框架,实现定义细节)
对修改关闭
对扩展开放
依赖倒置原则(细节依赖抽象 针对接口编程)
减少耦合性
提高可读性 可维护性 稳定性
单一职责原则(一个类,接口,方法只负责一个职责)
降低复杂度
提高可读性 可维护性
降低变更风险
接口隔离原则(细化接口)
多个专门接口替代单一总接口
迪米特法则(减少类之间耦合)
里氏替换原则(子类强化父类功能,不修改父类功能)
子类扩展父类,不能改变父类原有功能
子类可以增加独有方法
子类输入参数更加简洁宽松
子类输出参数更加全面
合成复用原则(尽量使用对象的组合,聚合)
降低类的耦合度
设计模式
工厂模式(FactoryBean)
简单工厂模式(适用于创建对象少Calendar)
逻辑简单,只需要传入参数即可
工厂类职责过重,不利于扩展
工厂方法模式(定义创建对象接口,子类实现 ILoggerFactory)
扩展性强,符合开闭原则
代码复杂,子类臃肿过多
抽象工厂模式(适用于一系列有关联系产品)
单例模式
饿汉式单例
优点:执行效率高 无锁
缺点:浪费内存
懒汉式单例
优点:节省内存
缺点:线程不安全
加锁懒汉式单例(double check)
优点:线程安全
缺点:效率问题
内部类单例
性能高,无线程安全问题
能够被反射破坏
容器式单例(IOC)
原型模式(对象拷贝复制)
浅拷贝
拷贝的是对象引用
深拷贝
序列化对象,生成全新对象
建造者模式(对象的创建Netty)
复杂的对象创建与使用分离,封装解耦优秀
内部结构变化 维护成本高
代理模式(AOP)
jdk动态代理
底层反射实现
被代理类必须实现接口
cglib代理
底层通过编码继承类实现
被代理类不需要实现接口,继承实现功能
门面模式(统一调度/工具类)
JdbcUtils
Dao/Controller
装饰器模式(扩展功能)
BeanWrapper
享元模式(资源共享)
系统需要大量相似对象,需要缓冲池
常用于底层开发(Integer)
适配器模式(适应不同接口开发的接口)
角色定义
目标角色(外部系统接口)
原角色(自己系统接口)
适配接口(适配接口)
适配器类型
类适配器
对象适配器
接口适配器
桥接模式(抽象与具体实现分离)
适用场景
抽象与具体实现之间存在灵活多变的场景
一个类存在多个变化过程,这个过程需要独立扩展
不希望被继承 实现功能
主要角色
Abstraction 抽象类
RefinedAbstraction 扩充抽象类
Implementor 实现类接口
ConcreteImplementor 具体实现类
委派模式
应用场景
本身不处理任务逻辑,任务交给委派对象处理
源码应用
jdk
ClassLoader
Springmvc
dispatchServlet
优缺点
优点
任务细化,统一跟进管理任务
缺点
任务复杂情况下,容易造成代码紊乱
模板方法模式
策略模式
应用场景
动态选择算法
动态选择实现类
源码应用
spring
动态加载Resource
动态选择代理
优缺点
优点
(1)算法可以自由切换
(2)避免使用多重条件判断
(3)扩展性良好,增加一个策略只需实现接口即可
缺点
(1)策略类数量会增多,每个策略都是一个类,复用性很小
(2)所有的策略类都需要对外暴露
责任链模式
使用场景
多个对象处理一个请求,运行时动态决定哪个对象处理请求
动态指定一组对象处理请求
源码应用
netty ChanelPipeline
java FilterChain
迭代器模式
命令模式
中介者模式
观察者模式
功能:主题对象被多个观察对象监听,主题对象发生变化,观察者对象做出相应的变化
核心角色
主题Subject
被观察者或发布者,它维护了一个观察者列表,并提供方法用于注册、注销和通知观察者。
观察者Observer
订阅者或监听器,它定义了一个接口或抽象类,包含了观察者所需实现的方法,通常包括更新方法,在主题状态改变时被调用
实现
JAVA
ISubject 接口
registerObserver(Observer observer);
unregisterObserver(Observer observer);
notifyObservers();
IObserver接口
update()
ConcreteSubject 实现类
registerObserver
List.add(observer)
unregisterObserver
List.remover(observer)
notifyObservers
List.foreach.update()
JDK
Observable接口
被观察者
Observer接口
观察者
Guava
访问者模式
多线程
基础
实现方式
继承Thread 重写run方法
实现Runnable接口 实现run方法
实现Callable接口 实现call方法 带返回值
操作说明
sleep
让当前线程睡一会
join
是等待调用join线程结束继续运行
yield
短暂放弃CPU使用权,让其他线程优先执行
interrupt
打断线程,但当打断阻塞线程 sleep wait join 会中断服务,打断后打断标记仍为false,不会打断线程
线程状态
NEW 初始状态
Thread t=new Thread()
READY 就绪状态
t.start()等CPU调度
Thread.yield()
Object.notify()
Object.notifyAll()
LockSupport.unpark()
RUNNING 运行状态
CPU正在调度
BLOCKED 阻塞状态
synchronized
WAITING 等待
Thread.join()
LockSupport.park()
Object.wait()
TIMED_WAITING 超时等待
Thread.sleep(long)
Thread.join(long)
LockSupport.parkUntil(long)
Object.wait(long)
TERMINATED 终止状态
终止线程
Thread.stop()
不推荐,会强制退出正在执行的任务
Thread.currentThread.isInterupted()
推荐使用,中断标志 判断是否结束线程
锁
synchronized
方法上
锁定整个方法
代码块上
锁定包含的代码块上
静态方法/类对象
类锁
实现原理
Object对象头部区域存储锁状态标记
JMM MonitorEnter 加锁/MonitorExit 释放锁 唤醒其他线程
锁优化
锁升级:偏向锁-轻量级锁-重量级锁
偏向锁
获取::当一个线程获取该对象锁时候。对象头存储当前线程ID 单次CAS
释放:线程结束/其他线程获取偏向锁
轻量级锁
CAS自旋退出,抢占到线程 多次CAS
重量级锁
监视器锁(Monitor)来实现的
通信
wait
锁定当前线程
wait(long)
锁定当前线程 如果经过long(毫秒)时间后没有收到notify或者notifyAll的通知,自动从等待队列转入锁池队列 会释放锁
notify
随机从等待队列中通知一个持有相同锁的一个线程唤醒
notifyAll
通知等待队列中的持有相同锁的所有线程,让这些线程转入锁池队,唤醒全部线程
CAS
作用
内存中的值V、旧的预估值X、要修改的新值B 如果V=X 则将V改成B
原理
while 循环比较直到V=X
原子类
AtomicInteger
原子更新整型变量
AtomicLong
原子更新长整型变量
AtomicBoolean
原子更新布尔变量
AtomicIntegerArray
原子更新整型数组的某个元素
AtomicLongArray
原子更新长整型数组的某个元素
AtomicReferenceArray
原子更新引用类型数组的某个元素
AtomicReference
原子更新引用类型
AtomicReferenceFieldUpdater
原子更新引用类型里的字段
AtomicMarkableReference
原子更新带有标记位的引用类型
AtomicIntegerFieldUpdater
原子更新整型字段
AtomicLongFieldUpdater
原子更新长整型字段
AtomicStampedReference
原子更新带有版本号的引用类型
问题
ABA问题 用AtomicStampedReference解决问题
自旋时间太长 带来性能开销问题
只能保证一个共享变量的原子操作
lock
设计思考
如何保证互斥性--共享资源state 0-无锁 1-有锁
被拒绝访问的线程如何挂起--lockSupport.park
被拒绝的线程如何保存恢复执行--内部维护链表保存挂起线程,lockSupport.unpark 唤醒链表挂起线程
同一个线程重复访问如何处理--可重入性保存抢锁线程ID
ReentrantLock(重入锁)
重入锁定义:一个线程多次抢占同一把锁,不需要抢占锁,只需要记录重入次数
实现
Lock(接口)
Sync(父类)
AQS父类AbstractQueuedSynchronizer
FairSync(公平锁 子类 实现类)
lock
跟NonfairSync大体一致, 区别 无抢锁过程 tryAcquire之前判断队列是否为空
unlock
跟NonfairSync大体一致
NonfairSync(非公平锁 子类 实现类)
lock(加锁)
抢锁 state(CAS 0-1)
失败
acquire
tryAcquire
getState 获取锁状态
0 无锁
CAS 抢锁 0-1 设置当前线程
1 有锁
exclusiveOwnerThread=currentThread当前锁定线程 记录重入次数
非当前线程 抢锁失败
addWaiter
构建双向链表Head-Node-Node-Tail
Node 存储线程节点Thread
WaitStatus=0
CANCELLED(1)
表示当前结点已取消调度。当timeout或被中断(响应中断的情况下),会触发变更为此状态,进入该状态后的结点将不会再变化
SIGNAL(-1)
表示后继结点在等待当前结点唤醒。后继结点入队时,会将前继结点的状态更新为SIGNAL。
CONDITION(-2)
表示结点等待在Condition上,当其他线程调用了Condition的signal()方法后,CONDITION状态的结点将从等待队列转移到同步队列中,等待获取同步锁
PROPAGATE(-3)
共享模式下,前继结点不仅会唤醒其后继结点,同时也可能会唤醒后继的后继结点。
INITAL(0)
新结点入队时的默认状态
aquireQueued
Node.Pre=Head
tryAcquire(抢锁)
成功:退出循环
失败:Node.Pre<>Head流程
Node.Pre<>Head
shouldParkAfterFailedAcquire
是否要挂起抢锁失败线程
parkAndCheckInterrupt
挂起线程
成功
保存当前线程setExclusiveOwnerThread
unlock(释放锁)
release(1)释放锁
tryRelease
操作
state=state-1
exclusiveOwnerThread=null
LockSupport.unpark Head.next 线程节点
ReentrantReadWriteLock(重入读写锁)
特性:写写互斥/读写互斥/读读不互斥
ReadLock(读锁)
WriteLock(写锁)
StampedLock
condition
用法
await
阻塞当前持有锁的线程
signal
唤醒处于condition阻塞状态下的线程
signalAll
唤醒处于condition阻塞状态下所有线程
实现原理
await
addConditionWaiter
构建condition单向链表,存储当前线程
fullyRelease
release(state)彻底的释放锁
unparkSuccessor 唤醒Lock 处于阻塞状态下线程
LockSupport.park
阻塞当前线程
signal
transferForSignal
将condition队列 第一个线程移动到AQS队列
LockSupport.park(node.Thread)
唤醒condition队列中的线程
组件/关键字
volatile
保证内存的可见性
禁止指令重排序
ThreadLocal
作用:线程独有变量
原理
get
获取当前线程currentThread.ThreadLocalMap.get(threadLocal)
set
获取当前线程currentThread
设置currentThread.ThreadLocalMap(threadLocal,threadLocal.value)
问题
内存泄漏
调用threadLocal.remove 删除弱引用
哈希冲突解决
线性探索,当前节点不为null 找下一个 若整个空间都找不到空余的地址,则产生溢出 扩容
ConcurrentHashMap
作用:线程安全的hashMap
原理
jdk1.7 数组+Segment+分段锁
jdk1.8 数组+链表+红黑树 CAS+Synchronized保证线程安全
问题
弱一致性 get可能获取到过期的值
线程组件
CountDownLatch
功能:一个线程(或者多个), 等待另外N个线程完成某个事情之后才能执行
原理
构造函数初始化state=n
countDown方法实现state=state-1,并且如果state=0唤醒await阻塞在AQS队列中线程
await 挂起当前线程,并且加入到AQS队列
自循环阻塞latch线程 当state=0时候退出循环
Semaphore
功能:同一时间段只能有N个线程访问,其他线程等待挂起,等到线程释放,等待线程恢复访问(限流)
原理
初始化 state=N N个线程可以同时访问
acquire
获得令牌 state=state-1
成功 线程继续执行
失败 线程保存在AQS阻塞队列
release
释放令牌state=state+1
唤醒处于AQS阻塞队列中的线程
CyclicBarrier
功能:可循环使用(Cyclic)的屏障(Barrier)
原理
初始化 state=n
await
condition.await
到达指定N个线程 condition.signalAll
reset 重新初始化
与CountDownLatch区别
1.CyclicBarrier基于Lock+condition实现的,CountDownLatch继承AQS实现的
2.CyclicBarrier可以重复使用;而CountDownLatch是一次性的,不可重复使用
3.CyclicBarrier中操作计数和阻塞的是同一个线程,调用方法只有一个await方法;而CountDownLatch中操作计数和阻塞等待是N个线程,控制计数调用方法countDown
ThreadPoolExecutor
基本类别
newFixedThreadPool
创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待
newSingleThreadExecutor
创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务
newCachedThreadPool
创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
newScheduledThreadPool
创建一个定长线程池,支持定时及周期性任务执行
ThreadPoolExecutor参数
corePoolSize(核心线程数)
线程池中的常驻线程数,即保持存活的线程数量
maximumPoolSize(最大线程数)
线程池中允许的最大线程数,即线程池中允许存在的最多线程数量。
workQueue(任务队列)
用于保存等待执行的任务的队列,有多种实现方式BlockQueue
ArrayBlockingQueue
由数组构成的有界阻塞队列
LinkedBlockingQueue
由链表构成的有界阻塞队列
PriorityBlockingQueue
支持优先级排序的无界阻塞队列
DelayQueue
支持优先级的延迟无界阻塞队列
SynchronousQueue
单个元素的阻塞队列
LinkedTransferQueue
由链表构成的无界阻塞队列
LinkedBlockingDeque
由链表构成的双向阻塞队列
keepAliveTime(线程存活时间)
当线程池中的线程数量大于核心线程数时,多余的空闲线程的存活时间
threadFactory(线程工厂)
用于创建新线程的工厂,可以定制线程名、线程优先级等
rejectedExecutionHandler(拒绝策略)
当任务队列满时,对新任务的处理策略
AbortPolicy
直接抛出 RejectedExecutionException 异常
CallerRunsPolicy
在任务被拒绝添加后,会使用调用线程池的线程来执行该任务
DiscardOldestPolicy
将等待时间最长的任务丢弃,然后尝试将当前任务添加到工作队列中
DiscardPolicy
直接将任务丢弃,不作任何处理
RejectedExecutionHandler
实现接口自定义策略
执行流程
execute提交执行任务
corePoolSize未满
addWork(**,true)创建线程
runWork执行线程
corePoolSize已满
workQueue队列已满
线程池已满
执行rejectedExecutionHandler拒绝策略
线程池未满
addWork(**,false)创建线程
runWork执行线程
workQueue队列未满
任务work存储队列
源码分析
execute
workerCountOf(c) <corePoolSize 线程池个数<核心线程数
true->addWorker(command, true)添加核心线程
false
isRuning(验证线程是否runing状态)
true->workQueue.offer(command)加入workQueue阻塞队列
true->isRuning判断线程running状态
true
false->remove(command) 删除任务
true->reject(command)执行拒绝策略
false->
false->addWorker(command, false)添加非核心线程
true->
false->reject(command)执行拒绝策略
false
addWork
true->HashSet.add(new Work(task))
thread.start()
false->addWorkerFailed
回滚操作
runWorker
while(task=getTask())
getTask
boolean timed = allowCoreThreadTimeOut || wc > corePoolSize
true->workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS)
从阻塞队列workQueue拿数据 不用等
false->workQueue.take()
从阻塞队列workQueue拿数据 阻塞 死等
processWorkerExit
自定义线程池
继承ThreadPoolExecutor
重写beforeExecute方法
重写afterExecute方法
Future
功能:获取线程的执行结果
用法
get
任务结束后返回一个结果,阻塞线程
cancel
停止一个任务
isDone
方法是否完成
isCancel
方法是否取消
原理分析(FutureTask)
run
result=Callable.call()
调用callable.call方法执行线程获取返回结果
outcome=set(result)
CAS操作 将返回结果赋值共享变量
finishCompletion
遍历waiters链表 unpark 唤醒线程
get
未完成<=COMPLETING
awaitDone
addWait
保存当前线程到waitNode 单项链表
park
挂起当前线程
已完成
report
CompletableFuture
功能:异步执行、链式操作、任务编排 默认线程池ForkJoinPool.commonPool()
用法
runAsync
异步执行一个任务 无返回值
supplyAsync
有返回值
whenComplete
获取前一个异步线程的结果和异常 无法修改返回结果
whenCompleteAsync
把whenCompleteAsync这个任务提交给线程池来执行
handle
有返回值 ,可以处理任务异常
handleAsync
handle中的任务提交到线程池运行
exceptionally
捕获范围包含前面的所有异步线程
thenRun
不关心任务的处理结果,无返回值,无输入参数
thenRunAsync
thenRun中的任务提交到线程池运行
thenApply
有返回值
thenApplyAsync
thenApply中的任务提交到线程池运行
thenAccept
无返回值
thenAcceptAsync
thenAccept中的任务提交到线程池运行
thenCompose
获取上一步的结果,而且有自己的返回值,与thenApply()具有相同的功能
thenComposeAsync
thenCompose中的任务提交到线程池运行
runAfterBoth
组合两个CompletableFuture,两个任务结束后执行,无参数,无返回值
runAfterBothAsync
runAfterBoth中的任务提交到线程池运行
thenAcceptBoth
组合两个CompletableFuture,两个任务结束后执行,有参数(执行结果),无返回值
thenAcceptBothAsync
thenAcceptBoth中的任务提交到线程池运行
thenCombine
组合两个CompletableFuture,两个任务结束后执行,有参数(执行结果),有返回值
thenCombineAsync
thenCombine中的任务提交到线程池运行
runAfterEither
两个异步任务相比较,有任何一个执行完成,就进行下一步操作,无参数,无返回值
runAfterEitherAsync
runAfterEither中的任务提交到线程池运行
acceptEither
两个任务有一个执行完成,获取它的返回值,处理任务,有参数,没有返回值
acceptEitherAsync
acceptEither中的任务提交到线程池运行
applyToEither
两个任务有一个执行完成,获取它的返回值,处理任务,有参数,有返回值
applyToEitherAsync
applyToEither中的任务提交到线程池运行
join
阻塞当前线程,直到任务完成并返回结果
get
阻塞当前线程,直到任务完成并返回结果 会抛出InterruptedException和ExecutionException异常,需要进行异常处理。
allOf
当所有的CompletableFuture完成后执行计算
anyOf
任意一个CompletableFuture完成后执行计算
complete
手动完成一个异步任务,并设置其结果
原理分析
待跟进
ForkJoin
功能:大任务拆分小任务,最后统计结果
用法:
ForkJoinPool
子任务ForkJoinTask线程池
WorkQueue(数组)
记录工作线程以及为工作线程分配的任务
ForkJoinTask(集合)
RecursiveAction
无返回结果的ForkJoinTask
RecursiveTask
有返回结果的ForkJoinTask
CountedCompleter
任务完成执行后会触发执行一个自定义的钩子函数
ForkJoinTask
fork
向当前任务所运行的线程池中提交任务
join
获取任务的执行结果。阻塞当前线程直到对应的子任务完成
原理解析
待跟进
BlockingQueue
问题
死锁
产生条件
互斥 共享资源X与Y只能被一个线程占用
占用且等待 线程1占用资源X等待获取资源Y时候不释放X
不可抢占 其他线程不能抢占线程1占用资源X
循环等待 线程1等待线程2资源Y释放,线程2等待线程1资源X释放
如何破坏
1.扩大锁粒度,例如 线程A 先同时锁Obj1, Obj2然后执行操作
2. 锁顺序一致性 例如 线程A,B均是锁Obj1 然后锁Obj2
3. 使用定时锁,设置timeout 锁自动失效
线程数量选择
CPU密集型
保持与CPU核心数量一直如8核CPU 可以设置8线程
IO密集型
可以适当提高线程数量 一般是CPU核心数*2
IO
分类
输入流I
InputStream(字节输入流)
FileInputStream
访问文件
ByteArrayInputStream
访问数组
PipedInputStream
访问管道
BufferdInputStream
缓冲流
ObjectInputStream
对象流(反序列化)
FilterInputStream
抽象基类流
PushbackInputStream
推回输入流
DataInputStream
特殊流
Reader(字符输入流)
FileReader
访问文件
CharArrayReader
访问数组
PipedReader
访问管道
StringReader
访问字符串
BufferedReader
缓冲流
InputStreamReader
转换流 字节流转换为字符流 解决编码问题
FilterReader
抽象基类流
PushbackReader
推回输入流
输出流o
OutputStream(字节输出流)
FileoutputStream
访问文件
ByteArrayOutputStream
访问数组
PipedOutputStream
访问管道
BufferedOutputStream
缓冲流
ObjectOutputStream
对象流(序列化)
PrintStream
打印流
DataOutputStream
特殊流
Writer(字符输出流)
FileWriter
访问文件
CharArrayWriter
访问数组
PipedWriter
访问管道
StringWriter
访问字符串
BufferedWriter
缓冲流
OutputStreamWriter
转换流 字节流转换为字符流 解决编码问题
FilterWriter
抽象基类流
区别
字节流
8位的二进制数据
以字节为单位进行读写,不涉及字符编码转换
用于处理图像、音频、视频等二进制数据。
字符流
16位Unicode字符
对数据进行编码和解码,可以用来处理不同字符集的数据
处理文本数据
基础使用
buffer
减少IO次数
源文件10B buffer=6B只会2次IO
flush
清空缓冲区,强制将缓冲区的数据写入文件或是读取
中文乱码
一个中文3b 每次读取1b导致乱码问题
序列化
ObjectOutputStream 对象流(序列化)
ObjectInputStream 对象流(反序列化)
原理分析
读取IO
本地磁盘(DMA)
内核缓冲区
应用程序缓冲区
内核缓冲区无数据,会挂起请求的用户请求,加载到数据会唤醒用户请求
写入IO
应用程序
内核缓冲区
本地磁盘
网络IO
Socket
client 端
getInputStream
获取输入流(接收消息)阻塞操作
getOutputStream
获取输出流 发送消息
ServerSocket
Server 端
accept
阻塞 获取客户端链接
网络协议
Http协议
请求过程
应用层->传输层->网络层->数据链路层->物理层
分层模型
应用层
http请求报文
传输层
http请求报文
tcp头
网络层
http请求报文
tcp头
ip头
数据链路层
http请求报文
tcp头
ip头
mac头
物理层
流传输
Https协议
BIO
阻塞IO,ServerSocket.accept 阻塞后续请求
流程分析
1.用户进程recvfrom
2.内核无数据包,准备接受数据
3.数据包接收完成
4.复制数据包
5.复制完成
6.处理成功 返回数据包
NIO
非阻塞IO 面向缓冲区
流程分析
1.用户进程recvfrom
2.内核无数据包,用户进程轮询recvfrom, 返回EWOULDBLOCK
3.数据包接收完成,用户进程recvfrom
4.复制数据包
5.复制完成
6.处理成功 返回数据包
核心组件
Channel(通道)
实现类
FileChannel
从文件中读写数据
DatagramChannel
从UDP协议中读取数据
SocketChannel
从TCP协议中读取数据
cofigureBlocking=false 非阻塞模式
ServerSocketChannel
监听一个Tcp链接,每个Tcp链接都会产生一个SocketChannel
cofigureBlocking=false 非阻塞模式
Buffer(缓冲区)
实现类
ByteBuffer
创建缓冲区
allocate(int capacity)
在堆中创建缓冲区(间接缓冲区)
创建和销毁效率高
工作效率低
allocatDirect(int capacity)
在系统内存创建缓冲区(直接缓冲区)
创建和销毁效率低
工作效率高
wrap(byte[] arr)
数组创建缓冲区
=堆缓冲区
添加数据
put(byte b)
向当前可用位置添加数据
put(byte[] byteArray)
向当前可用位置添加一个byte[]数组
put(byte[] byteArray,int offset,int len)
添加一个byte[]数组的一部分
容量(capacity)
Buffer所能够包含的元素的最大数量。定义了Buffer后,容量是不可变的
限制(limit)
limit以及之后限制写入与读取,不能大于capacity
位置(position)
当前可写入的索引位置,不能小于0 不能大于limit
标记(mark)
调用reset position=mark
重置(reset)
重置postion
还原(clear)
position=0
limit=capacity
mark舍弃
缩小范围(flip)
limit=position
position=0
mark丢弃
反转读写模式
重绕缓冲区(rewind)
position=0
mark 丢弃
只读(isReadOnly)
缓冲区是否只读
直接缓冲区(isDirect)
获取当前缓冲区是否为直接缓冲区
获取元素数(remaining)
获取position与limit之间的元素数
CharBuffer
DoubleBuffer
FloatBuffer
IntBuffer
LongBuffer
ShortBuffer
Selector(选择器)
定义:管理多个NIO的channel通道是否为读写事件做好准备的组件
注册:ServerSocketChannel.register(Selector,***)
select()
阻塞 所有注册事件
selectedKeys()
返回所有可执行事件(解除阻塞)的Keys
OP_CONNECT
连接就绪
OP_ACCEPT
接收就绪
OP_READ
读就绪
OP_WRITE
写就绪
IO复用
select/poll
定义:多个IO请求可以注册到select上,liunx监控所有select注册的链接,数据准备好就会返回
弊端:支持连接数有限 一般支持1024个链接,内核会扫描所有注册的select 所有链接 会带来性能下降
流程分析
1.用户IO请求注册select
2.内核无数据 不阻塞
3.数据包接收完成 select 返回状态 可读
4.复制数据包 系统调用 recvfrom
5.复制完成
6.处理成功 返回数据包
epoll(2.6内核之后)
定义:采用fd事件通知CallBack的方式,解决poll模式下轮询带来性能问题
优势:处理连接数不限制(受限于内存),连接数取决于最大句柄数,不需要轮询,性能得到提升 mmap复制内存 连接数少socket活跃情况下不如poll效率高
流程分析
1.用户IO请求注册select fd注册信号处理程序
2.内核无数据 不阻塞
3.数据包接收完成 select 返回状态
4.mmap 映射内存区域
5.复制完成 调用fd的callback 通知应用程序处理后续逻辑
aio
流程分析
1.应用程序调用sio_read 直接返回
2.系统接收数据完成 提交SIGIO信号
3.系统复制数据完成 递交aio_read 通知应用程序处理
零拷贝
mmap
原理解析:用户缓冲区与内核缓冲区 映射共享内存
拷贝过程:硬盘—>内核—>socket缓冲区—>网卡
API调用:MappedByteBuffer.map()
特点:用户可以修改内存,不能超过2G 适用于小文件 rocketMq
sendFile
原理解析:用户进程发送指令,内核空间内部进行 I/O 传输 无法映射共享内存
拷贝过程:硬盘—>内核—>socket缓冲区—>网卡
API调用:FileChannel.transferFrom()/transferTo()
特点:用户不可以修改内存,适合大数据量的传输,kafka
Netty
ByteBuf
优势
动态扩容
池化技术
读写索引区分
零拷贝机制
组成
容量上限=Integer.MaxValue
容量
已读字节
末尾读索引
可读字节
末尾写索引
可扩容容量
使用
池化
池化ByteBuf
可以被重用
高并发有很好的节约内存的效果
非池化ByteBuf
-Dio.netty.allocator.type={unpooled|pooled} 不开启|开启
扩容
扩容小于等于512,扩容为16的倍数大小
扩容大于512,扩容为2的n次方大小
内存类型
直接内存ByteBuf
读写性能高,创建和销毁代价大,不受JVM管控
ByteBufAllocator.DEFAULT.directBuffer()
堆内存ByteBuf
受JVM控制
ByteBufAllocator.DEFAULT.heapBuffer()
写入
writeBytes
writeBytes(byte[] bytes)
writeBytes(ByteBuffer buffer)
writeInt
writeLong
writeFloat
writeChar
writeCharSequence
writeCharSequence(String s)
writeCharSequence(StringBuffer sb)
读取
readByte
readInt
readFloat
markReaderIndex
标记读取索引位置
resetReaderIndex
重置读取索引
getByte
不移动读指针
修改
setByte
回收
切片
slice
对原始buf进行切片
slice是没有数据拷贝 浅克隆
复制
copy
深拷贝
组合
CompositeByteBuf.addComponents
逻辑上的组合 浅拷贝
CompositeByteBuf组成
Component[] components
ByteBuf
自己的读写索引
Unpooled.wrappedBuffer
逻辑上的组合 浅拷贝
支持多数据源 数据源的类型包括 byte[]、ByteBuf、ByteBuffer
ByteBuf.writeBytes
通过writeBytes方法组合多个ByteBuf。新组合的ByteBuf与之前的ByteBuf完全独立开
拆包粘包
背景
Socket缓冲区
发送缓冲区SO_SNDBUF
发送 数据拷贝进入 Socket 的内核发送缓冲区
接收缓冲区SO_RCVBUF
发送缓冲区可以多次发送到接收缓冲区 window size>0
原因
粘包
1.发送方每次写入数据 < 套接字缓冲区大小
2.接收方读取套接字缓冲区数据不够及时
拆包
1.发送方每次写入数据 > 套接字缓冲区大小
2.发送的数据大于协议 MTU,所以必须要拆包
解决方案
1.定长协议
原理解析
指定一个报文具有固定长度 空白部分补上空格
优点:实现简单
缺点:浪费带宽,超长报文会有问题
FixedLengthFrameDecoder
2.特殊字符分割协议
原理解析
在包的中添加指定的特殊字符
优点:
DelimiterBasedFrameDecoder
根据特殊字符进行解码
LineBasedFrameDecoder
默认换行符
3.变长协议
原理解析
报文长度+报文内容
LengthFieldBasedFrameDecoder
maxFrameLength
发送的数据包最大长度
lengthFieldOffset
长度域的偏移量
lengthFieldLength
长度域的所占的字节数
lengthAdjustment
长度值的调整值
=package.length- 长度域的值 – 长度域偏移 – 长度域长
initialBytesToStrip
需要跳过的字节数
序列化
Reactor模型
分类
Reactor单线程模型
小负载低并发模型
所有接受连接, 处理数据操作都在一个线程中完成, 有性能瓶颈
Reactor多线程模型
能满足大多数场景
高并发场景性能问题 ,单线程处理accept请求
Reactor主从多线程模型
子主题
启动流程
组件
Channel
Pipeline
JVM
类加载
执行流程
xx.java->javac->xx.class->jvm
javac
xx.java->词法分析器->token流->语法分析器->语法树->语义分析器->注解语法树->代码生成器->xx.class字节码
内存加载
装载
类加载
类加载器ClassLoader
Bootstrap ClassLoader
加载JAVA_HOME/jre/lib/rt.jar或Xbootclassoath选项指定目录jar包
Extension ClassLoader
加载java平台扩展功能包JAVA_HOME/jre/lib/*.jar 或者 -Djava.ext/dirs指定目录下jar包
App ClassLoader
加载classpath下jar包以及Djava.class.path指定目录类或者jar
Custom ClassLoader
继承ClassLoader 自定义加载class
双亲委派模式
类加载优先级Bootstrap ClassLoader>Extension ClassLoader>App ClassLoader>Custom ClassLoader
如何破坏?
继承classLoader 重写 loadClass 方法
Thread.currentThread.setContextClassloader(mysql驱动)
类的字节码文件流信息->jvm方法区
类文件中对象的class->jvm堆
链接
验证
验证被加载的类的正确性
准备
静态变量分配内存空间,初始化默认值(static int a=10;为a分配内存空间,初始化为0)
解析
将类中符号引用转为直接引用(映射内存地址)
初始化
为静态变量初始化真正的值 (a=10)
使用
卸载
运行时数据区
方法区Method
只有一个 线程共享 非线程安全 生命周期跟jvm虚拟机一样
存储结构(OOM)
类信息
常量
静态变量
即时编译器编译后的代码
堆Heap
只有一个 线程共享 非线程安全 生命周期跟jvm虚拟机一样
存储结构(OOM)
对象
数组
虚拟机栈stack
一个线程创建一个 线程私有 线程安全 生命周期跟线程一样
存储结构(StackOverflowError)
栈帧(1:n)
局部变量表
操作数栈
动态链接
方法的返回地址
本地方法栈native stack
c语言方法 native 方法
程序计数器pc resigter
线程私有,线程安全 记录线程代码运行位置
内存结构
老年代/元空间 old GC 2/3
大对象 新生代放不下
youngGC>15次还没有被垃圾回收
新生代 young gc 1/3
eden区 8/10
s区(解决空间碎片问题)
s0 1/10
空间不够可向old借用空间(担保机制)
s1 1/10
垃圾回收
判断垃圾
引用不可达算法GCRoot
栈中本地变量
static 成员
常量
本地方法栈中变量
类加载器
Thread[java线程]
垃圾回收算法
标记清除算法
空间碎片问题
复制算法
空间浪费问题,s区
标记整理算法
效率问题,老年代
垃圾回收器
Serial
单线程垃圾收集器 适用新生代 复制算法
Serial Old
Serial老年代版本 标记整理算法
ParNew
多线程垃圾收集器 适用于新生代 复制算法
Parallel Scavenge
与ParNew类似 更加关注吞吐量 复制算法
Parallel Old
Parallel 老年代垃圾收集器 标记整理算法
CMS(老年代,关注停顿时间,标记清除算法,后端任务)
1.初始标记
2.并发标记(不会终止用户线程)
3.重新标记
4.并发处理(不会终止用户线程
G1(新老年代,自设置停顿时间,标记整理算法,用户交互 web端)
1.初始标记
2.并发标记(不会终止用户线程)
3.最终标记
4.筛选回收(有选择性回收垃圾)
G1参数
-XX:InitiatingHeapOccupancyPercent
当老年代的大小占据了堆内存的% Full GC
-XX:MaxTenuringThreshold
young GC 多少次进入Old区
-XX:MaxGCPauseMillis
指定收集的停顿时间,默认是200ms
-XX:G1MixedGCCountTarget
设置在一次混合回收的过程中 后续回收次数
-XX:G1HeapWastePercent
设置空闲内存达到多少停止回收
常用命令
jps 查询Java进程信息
jinfo查看jvm参数/修改jvm参数
jstat 查看jvm运行时状态信息, 包括内存状态、垃圾回收
jstack 查看jvm线程快照的命令
jmap 生成dump文件,查询堆内对象示例的统计信息、查看classLoader的信息以及finalizer队列
jhat 分析dump文件 用于离线分析
性能优化
堆内存分析
jconsole
jvisualvm
MAT
arthas
GC日志
GCViewer
gceasy.io
问题
GC频繁
问题排查
1.jstat 打印gc日志,查询内存空间大小
2.minor gc/major gc 工具gceasy查看
3.jmap 查询内存使用情况
原因分析
1.堆内存空间不足
2.edm区域太小,频繁ygc 大量对象进入old区
3.代码问题 大对象
Full GC频繁
问题排查
1.jstat 打印gc日志,查询内存空间大小
2.jmap 查询内存使用情况
3.jstack 查询线程,cpu请求情况
4.dump堆文件,mat工具分析
5.增大S区
原因分析
1.大对象问题,系统创建了太多大对象进入了Old区域
2.高并发问题,S区太小,太多对象来不及销毁就进入了Old区域
3.Metaspace(永久代)因为加载类过多触发Full GC。
4.内存泄漏问题,垃圾对象无法被回收
5.错误调用System.gc()调用
6.垃圾收集器问题 空间碎片问题
CPU 飙升
问题排查
1.top查询cpu使用率高的应用ID
2.jstack 查询线程使用情况,排除死锁问题
3.jinfo 查询JVM参数信息,jmap查询堆内存使用情况
4.jstat 统计FullGC情况
原因分析
1.内存消耗过啊,导致Full GC次数过多
2.代码中有大量消耗CPU的操作,导致CPU过高,系统运行缓慢;
3.死锁
4.大量线程访问接口
OOM
问题排查
1.确定是堆上OOM还是方法区/元空间上OOM
2.方法区OOM 查询代码有没有动态生成类加载类
3.jmap dump 堆上内存信息。mat 分析有没有大对象
4.jinfo 查询堆内存大小,比例情况。元空间大小。垃圾收集器的选择。
5.查询线程cpu 使用情况,看看是否高并发,增加集群机器
原因分析
1.大对象问题,Old区域放不下
2.Metaspace 加载类过多触发OOM
3.本身内存空间过小问题,加大内存
4.高并发问题,太多对象创建来不及销毁回收
java 核心
集合
ArrayList
源码解析
初始化
add
delete
问题
LinkedList
HashMap
TreeMap
HashSet
TreeSet
泛型
反射
注解
JDK8
Lambda表达式
语法结构
样例: (参数列表)->{}
():参数列表
小括号内的参数类型可以省略
如果有且仅有一个参数,则小括号可以省略
->:连接符
{}: 方法体
如果有且仅有一个语句,可以同时省略大括号,return 关键字及语句分号
注意事项
Lambda表达式只能用于接口中只有一个抽象方法的情境中@FunctionalInterface
必须为接口才能使用Lambda
Stream API
初始化
Collection.stream()/parallelStream() 集合 parallelStream并行流 多线程处理
Arrays.stream(T[] array) 数组
Stream.of/iterate/generate
遍历(foreach)
list.stream().forEach(x->System.out.println(x.getName()));
查找(find)
findFirst 返回匹配的第一条
list.stream().filter(x->x.getAge()==55).findFirst().orElse(null)
findAny 返回匹配的任意一条 不能保证时第一条
匹配(match)
allMatch 全部匹配返回true
list.stream().allMatch(x->x.getAge()>40)
anyMatch 匹配一条返回true
noneMatch 全部不匹配返回true
条件匹配(filter)
过滤条件例:list.stream().filter(x->x.getAge()>10).findFirst().get()
聚合统计(max,min,count)
max
取最大值例:list.stream().max((l,r)->l.getAge()-r.getAge()).get()
min
取最小值例:list.stream().min((l,r)->l.getAge()-r.getAge()).get()
count
统计总数例:list.stream().filter(x->x.getAge()>25).count()
map
集合中素作为 参数 进行转换ArrayList例:list.stream().map(x->{
Map<String,Person> map=new HashMap();
map.put(x.getName(),x);
return map;
}).collect(Collectors.toList())
Map<String,Person> map=new HashMap();
map.put(x.getName(),x);
return map;
}).collect(Collectors.toList())
flatMap
就是在Map的基础上,会将集合的数据结构给展开
reduce
输入元素组合例:list.stream().filter(x->x.getAge()>29).map(x->x.getAge()).reduce(0,(x,y)-> x+y);
collect
收集数据到集合或数组stream.collect(Collectors.toList());
计数:Long count = personList.stream().collect(Collectors.counting());
平均值:Double average = personList.stream().collect(Collectors.averagingDouble(Person::getSalary));
最值:Optional<Integer> max = personList.stream().map(Person::getSalary).collect(Collectors.maxBy(Integer::compare));
求和:Integer sum = personList.stream().collect(Collectors.summingInt(Person::getSalary));
分组 groupingBy
分组:Map<String,List<Person>> map=list.stream().collect(Collectors.groupingBy(Person::getName));
分组统计:Map<String,Long> map=list.stream().collect(Collectors.groupingBy(Person::getName,Collectors.counting()));
分组转换:Map<String,List<Integer>> map=list.stream().collect(Collectors.groupingBy(Person::getName,Collectors.mapping(Person::getAge,Collectors.toList())));
多次分组:Map<String, Map<String, List<Employee>>> map = employees.stream()
.collect(Collectors.groupingBy(Employee::getCity, Collectors.groupingBy(Employee::getName)));
.collect(Collectors.groupingBy(Employee::getCity, Collectors.groupingBy(Employee::getName)));
条件分2组partitioningBy
Map<Boolean, List<String>> result = list.stream().collect(Collectors.partitioningBy(obj -> obj.length() > 4));
连接(joining)
拼接字符:String result3 = list.stream().collect(Collectors.joining("||","[","]")); [a||b]
排序(sorted)
正常排序:list=list.stream().sorted(Comparator.comparing(Person::getName)).collect(Collectors.toList());
倒序:list=list.stream().sorted(Comparator.comparing(Person::getName).reversed()).collect(Collectors.toList());
多次排序:list=list.stream().sorted(Comparator.comparing(Person::getName).thenComparing(Person::getAge)).collect(Collectors.toList());
合并concat
Stream.concat(list.stream(),list2.stream()).collect(Collectors.toList())
去重distinct
限制limit
跳过skip
运维/工具
maven
仓库类型
本地仓库
本地电脑上面的仓库 默认在当前系统用户.m2下
私服仓库
局域网搭建的仓库nexus
中央仓库
互联网上面的仓库 Apache维护
查找顺序:本地仓库->私服仓库->中央仓库
依赖冲突
1.优先声明原则
先定义优先使用
2.路径就近原则
路径最近优先使用
3.排除依赖
显示声明不依赖Bean exclusions
版本依赖
Properties 定义版本标签
${version}绑定指定版本标签
常用命令·
clean(清理命令)
删除target目录及其目录下所有内容
compile(编译命令)
1.src/main/resources 文件->拷贝->target/classes目录下
2.src/main/java **.java->编译->**.class
3.**.class->拷贝->target/classes
package(打包命令)
1.src/main/resources 资源->拷贝->target/classes目录下
2.src/main/java **.java->编译->**.class
3.**.class->拷贝->target/classes
4.src/test/resources资源->拷贝->target/test-classes目录下
5.src/test/java **.java->编译->**.class->拷贝->target/test-classes目录下
6.执行单元测试类
install(安装命令)
1.执行Maven package命令
2.maven 打成 jar 包或 war 包发布到本地仓库
test(测试命令)
执行src/test/java下的单元测试类
deploy(发布命令)
将项目发布到你配置的仓库位置
update(更新命令)
更新项目依赖的jar
标签说明·
parent
定义:父项目的坐标。子项目中没有规定某个元素的值,那么父项目中的对应值即为项目的默认值。
groupId
定义:groupId是项目组织唯一的标识符,实际对应java包的结构,是main目录里java的目录结构
命名规则:一般是 域.公司名称 ,可以后面跟多个,域又分为org、com、cn等等许多,其中org为非盈利阻止,com为商业阻止
artifactId
定义:artifactId就是项目唯一的标识符,实际项目的名称
version
定义:版本管理
命名规则:<主版本>.<次版本>.<增量版本> - <里程碑版本>
主版本: 表示项目的重大架构变化。如struts2和struts1采用不同的架构
次版本: 较大范围功能增加和变化,及bug修复,并且不涉及到架构变化的。
增量版本:表示重大bug的修复,如果发现项目发布之后,出现影响功能的bug,及时修复,则应该是增量版本的变化。
里程碑版本:往往表示某个版本的里程碑,经常见到snapshot,另外还有alpha、beta
开发版本:SNAPSHOT
测试版本:alpha、beta
内部测试:alpha
外部测试:beta
稳定版:rc、final、stable、release
正式发布版:GA
relativePath
从父级仓库查找依赖版本 查找顺序:relativePath元素中的地址–本地仓库–远程仓库 如果为空 直接从本地仓库找,只存在父模块中
modelVersion
描述这个POM文件是遵从哪个版本的项目描述符
groupId
见parent/groupId
artifactId
见parent/artifactId
packageing
定义:maven打包方式,有三种
pom
maven依赖文件
jar
java普通项目打包
war
java web项目打包
version
见parent/version
name
声明一个对于用户更为友好的项目名称,非必须
url
项目地址或者公司地址
description
项目描述
prerequisites
maven
定义的是构建该项目所需的最低maven版本号;默认值为2.0
issueManagement
定义问题管理系统(Bugzilla, Jira, Scarab)的名称和URL
system
问题管理系统名称
url
问题管理系统Url
ciManagement
定义:项目持续集成信息
system
持续集成系统的名字,例如continuum
url
持续集成系统的URL
notifiers
构建完成时,需要通知的开发者/用户的配置项
notifier
type
传送通知的途径
sendOnError
发生错误时是否通知
sendOnFailure
构建失败时是否通知
sendOnSuccess
构建成功时是否通知
sendOnWarning
发生警告时是否通知
address
通知发送到哪里
configuration
扩展配置项
inceptionYear
项目创建年份,4位数字。当产生版权信息时需要使用这个值
mailingLists
定义:项目相关的所有邮件列表。自动产生的网站引用这些信息
mailingList
name
邮件的名称
post
发送邮件的地址或链接
subscribe
订阅邮件的地址或链接
unsubscribe
取消订阅邮件的地址或链接
archive
你可以浏览邮件信息的URL
developers
定义:项目开发人员列表
developer
id
开发者的唯一标识符
name
开发者的全名
email
开发者的email
url
开发者的主页url
roles
role
开发者在项目中的角色
organization
开发者所属组织/公司
organizationUrl
开发者所属组织/公司的URL
properties
dept
项目开发者属性,如即时消息如何处理等
timezone
开发者所在时区, -11到12范围内的整数
contributors
contributor
项目的其他贡献者 见developer
icenses
license
name
license用于法律上的名称
url
官方的license正文页面的URL
distribution
项目分发的主要方式:repo,可以从Maven库下载 manual, 用户必须手动下载和安装依赖
comments
关于license的补充信息
scm
定义:源代码控制管理系统定义了该项目源代码控制管理的地址,例如git、svn等。
connection
读取该项目资源版本库的地址
developerConnection
类似于connection,使用去developer的地址
tag
默认值为HEAD,当前源代码库的版本,开发过程中默认设置为HEAD
url
通过浏览器等可以访问到的该项目的地址
organization
定义:描述项目所属组织的各种属性。Maven产生的文档用
name
组织的全名
url
组织主页的URL
build
sourceDirectory
主体源程序存放目录
scriptSourceDirectory
脚本源程序存放目录
testSourceDirectory
测试源程序存放目录
outputDirectory
主体源程序编译结果输出目录
testOutputDirectory
测试源程序编译结果输出目录
extensions
extension
groupId
artifactId
version
defaultGoal
resources
resource
targetPath
filtering
directory
includes
excludes
主体资源文件存放目录
testResources
testResource
测试资源文件存放目录
directory
构建结果输出目录
finalName
filters
pluginManagement
plugins
plugin
groupId
artifactId
version
extensions
executions
execution
id
phase
goals
inherited
configuration
dependencies
dependency
inherited
configuration
profiles
profile
id
activation
activeByDefault
jdk
os
name
family
arch
version
property
name
value
file
exists
missing
build
defaultGoal
resources
resource
testResources
testResource
directory
finalName
filters
pluginManagement
plugins
plugin
groupId
artifactId
version
extensions
executions
execution
id
phase
goals
inherited
configuration
dependencies
dependency
goals
inherited
configuration
plugins
modules
repositories
nexus
git
安装配置
基础操作
远程仓库
分支管理
jenkens
docker
基础认识
与VM区别
Docker:App+Bin/Libs
优势:虚拟硬件资源,直接使用容器引擎,所以速度快
VM:App+Bin/Libs+Os
核心概念
Image
docker镜像
提供容器运行时所需的程序、库、资源、配置等文件外,还包含一些配置参数(如匿名卷、环境变量、用户等)。
container
docker容器
轻量级的沙箱,docker利用容器来运行和隔离应用
repository
docker仓库
公开仓库Docker Hub
私有仓库:自己搭建
基础命令
run
创建一个新的容器
docker run [OPTIONS] IMAGE [COMMOND] [ARGS...]
OPTIONS
--name
为容器指定一个名称
-d/--detach
后台运行容器,并返回容器ID,也即启动守护式容器
-i/--interactive
以交互模式运行容器,通常与 -t 同时使用
-t/--tty
为容器重新分配一个伪输入终端,通常与 -i 同时使用
-P
随机端口映射
-p
指定端口映射 四种格式
ip:hostPort:containerPort
ip::containerPort
hostPort:containerPort
containerPort
--network
指定网络
--rm
容器停止自动删除容器
-v/--volume
挂在数据卷
-u/--user
指定用户 (格式: <name|uid>[:<group|gid>])
-w/--workdir
指定工作目录
IMAGE
XXX_IMAGE_NAME:XXX_IMAGE_VER
COMMOND
例:mvn -Duser.home=xxx -B clean package -Dmaven.test.skip=true
/bin/bash
执行/bin/bash命令
start
启动一个或多个已经被停止的容器
docker start [OPTIONS] CONTAINER [CONTAINER...]
OPTIONS
-a
附加到容器的标准输入、输出和错误输出
-i
以交互模式运行容器
stop
停止一个运行中的容器
docker stop [OPTIONS] CONTAINER [CONTAINER...]
OPTIONS
-t
指定停止容器前的超时时间(默认为10秒)
restart
重启容器
docker restart [OPTIONS] CONTAINER [CONTAINER...]
kill
杀掉一个运行中的容器
docker kill [OPTIONS] CONTAINER [CONTAINER...]
OPTIONS
-s
指定发送的信号,默认为“KILL”
与stop区别
docker stop命令给容器发送 SIGTERM 信号,默认行为是会导致容器退出,当然,容器内程序可以捕获该信号并自行处理
docker kill命令则是给容器的进程发送 SIGKILL 信号,该信号将必然使容器退出
rm
删除一个或多个容器
create
创建一个新的容器但不启动它
exec
运行的容器中执行命令
pause
暂停容器中所有的进程
unpause
恢复容器中所有的进程
ps
列出容器
inspect
获取容器/镜像的元数据
top
查看容器中运行的进程信息
events
获取实时事件
logs
获取容器的日志
export
将文件系统作为一个tar归档文件导出到STDOUT
port
列出指定的容器的端口映射
commit
从容器创建一个新的镜像
cp
用于容器与主机之间的数据拷贝
diff
检查容器里文件结构的更改
login
登陆到一个Docker镜像仓库
logout
登出Docker Hub
pull
从镜像仓库中拉取或者更新指定镜像
push
将本地的镜像上传到镜像仓库,要先登陆到镜像仓库
search
从Docker Hub查找镜像
images
列出本地镜像
rmi
删除本地一个或多个镜像
tag
标记本地镜像,将其归入某一仓库
build
用于使用 Dockerfile 创建镜像
docker build [OPTIONS] PATH | URL | -
OPTIONS
--build-arg=[] :设置镜像创建时的变量
--cpu-shares :设置 cpu 使用权重
--cpu-period :限制 CPU CFS周期
--cpu-quota :限制 CPU CFS配额
--cpuset-cpus :指定使用的CPU id
--cpuset-mems :指定使用的内存 id
--disable-content-trust :忽略校验,默认开启
-f :指定要使用的Dockerfile路径
--force-rm :设置镜像过程中删除中间容器
--isolation :使用容器隔离技术
--label=[] :设置镜像使用的元数据
-m :设置内存最大值
--memory-swap :设置Swap的最大值为内存+swap,"-1"表示不限swap
--no-cache :创建镜像的过程不使用缓存
--pull :尝试去更新镜像的新版本
--quiet, -q :安静模式,成功后只输出镜像 ID
--rm :设置镜像成功后删除中间容器
--shm-size :设置/dev/shm的大小,默认值是64M
--ulimit :Ulimit配置
--squash :将 Dockerfile 中所有的操作压缩为一层
--tag, -t: 镜像的名字及标签,通常 name:tag 或者 name 格式;可以在一次构建中为一个镜像设置多个标签。
--network: 默认 default。在构建期间设置RUN指令的网络模式
history
查看指定镜像的创建历史
save
将指定镜像保存成 tar 归档文件
load
导入使用 docker save 命令导出的镜像
import
从归档文件中创建镜像
info
显示 Docker 系统信息,包括镜像和容器数
version
显示 Docker 版本信息
安裝部署
k8s
nginx
基础介绍
正向代理
用户请求->目标服务器地址->代理服务器->目标服务器 例:VPN
反向代理
用户请求->代理服务器地址->目标服务器 例Nginx
操作配置
启动
nginx/nginx -c config/nginx -g "pid ***;"
停止
kill -quit pid/kill -term pid/kill -9 pid
配置文件
全局块
user
配置用户和组,默认为nobody nobody,表示所有用户有启停权限
daemon
设置是否以守护进程模式运行,默认on。
master_process
设置是否启用主进程,默认on。
worker_processes
设置为数字,表示启动后就具有几个worker process,设置为auto则表示自动检测
worker_rlimit_nofile
设置每个用户能够发往worker进程的信号数量(信号队列的大小)
worker_rlimit_sigpending
为worker进程绑定若干个CPU,OS为linux才能使用此参数。
worker_priority
设置worker进程的优先级
error_log
指定nginx的运行日志存放路径,必须包含文件名称。
pid
指定nginx的pid存放路径,必须包含文件名称。
timer_resolution
设置多长时间获取一次系统时间并更新nginx的缓存时钟。
include
引入的其他配置文件路径。
events块
use
设置事件驱动模动模型,建议让nginx自行选择。
debug_connection
设置指定的IP产生debug日志。
accept_mutex
是否开启负载均衡锁
lock_file
设置负载均衡锁文件路径
multi_accept
设置一个进程是否可以同时接受多个请求。
accept_mutex_delay
设置获得负载均衡锁的重试时间间隔。
worker_connections
允许每一个worker process同时开启的最大连接数,此值不能大于操作系统支持的打开的最大文件句柄数,默认512
http块
allow
配置允许访问服务的ip
deny
配置不允许访问服务的ip
default_type
默认为text/plain
sendfile
是否允许sendfile方式传输文件,默认on。
log_format
access_log
sendfile_max_chunk
每个进程每次调用传输数量不能大于设定的值,默认为0,即不设上限。
client_body_in_file_only
指定是否将用户请求体存储到一个文件里。
client_body_in_single_buffer
设置是否将完整的请求主体存储在单个缓冲区中。
client_body_buffer_size
指定用户请求体所使用的buffer的最大值。
client_body_temp_path
设置存储用户请求体的文件的目录路径
client_body_timeout
设置用户请求体的超时时间。
client_header_buffer_size
设置用户请求头所使用的buffer大小
large_client_header_buffers
设置用于读取大型客户端请求头的缓冲区的最大数量和大小
client_header_timeout
设置用户请求头的超时时间
client_max_body_size
设置所能接收的最大请求体的大小,默认1M。
send_timeout
指定响应客户端的超时时间,单位:秒,默认60
keepalive_timeout
设置用户会话连接的保持时间。
tcp_nopush
设置TCP链接是否不推送,默认on。
tcp_nodelay
设置TCP链接是否延迟,默认on。将tcp_nopush和tcp_nodelay两个指令设置为on用于防止网络阻塞。
set_real_ip_from
设置符合条件的网段,结合real_ip_header,设置新的$remote_addr
real_ip_header
结合set_real_ip_from,设置新的$remote_addr,如果设置X-Forwarded-For则为真实的ip
gzip
是否开启gzip压缩。
gzip_min_length
设置允许压缩的页面最小字节数,默认0。
gzip_buffers
设置系统获取几个单位的缓存用于存储gzip的压缩结果数据流。
gzip_http_version
识别http的协议版本。
gzip_comp_level
gzip压缩比,1压缩比最小处理速度最快,9压缩比最大但处理速度最慢(传输快但比较消耗cpu)。
gzip_types
匹配mime类型进行压缩,无论是否指定,”text/html”类型总是会被压缩的
gzip_vary
和http头有关系,加个vary头,给代理服务器用的
gzip_disable
指定版本浏览器不压缩。
upstream
负载均衡的后端服务器
weight
负载均衡策略权重, 默认为1
max_fails
在fail_timeout时间内检查这个服务器是否可用时产生的最多失败请求数
fail_timeout
在fail_timeout时间内经历了max_fails次失败后, 暂停服务
backup
备份服务器
down
永久不可用
proxy_cache_path
定义一个完整的缓存空间,指定缓存数据的磁盘路径、索引存放的内存空间以及一些其他参数
levels
配置在该目录下再分两层目录,一层1个随机字符作为名称,二层2个随机字符作为名称,levels最多三层
keys_zone
用来为这个缓存区起名,并设置大小;
max_size
指定最大缓存数据磁盘空间的大小;
inactive
在inactive指定的时间内,未被访问的缓存数据将从缓存中删除。
proxy_cache
开启缓存 off 关闭
proxy_cache_key
设置缓存唯一key
proxy_cache_valid
设置不同响应代码的缓存时间,比如200 304 12h;
underscores_in_headers
header中是否支持下划线,默认为off不支持,on为支持;
server块(就近原则)
server全局块
keepalive_requests
单连接请求上限次数
listen
设置监听地址和端口
server_name
虚拟主机名称,支持多个
server_name_hash_bucket_size
为实现快速主机查找,nginx使用hash表保存主机名,该参数用来设置hash表大小。
root
设置服务器收到请求后查找资源的根目录路径,最终路径拼接为:root路径+location路径。
alias
设置服务器收到请求后查找资源的根目录路径,最终路径拼接为:root路径+location路径
underscores_in_headers
header中是否支持下划线,默认为off不支持,on为支持;
location块
add_header
设置response响应报文的header
auth_basic
是否开启认证功能,并设置提示信息,off关闭。
auth_basic_user_file
指定包含用户名信息的文件路径。
rewrite
重写跳转地址,支持正则
last
重写完成后停止对当前URI在当前location中后续的其它重写操作,而后对新的URI启动新一轮(从第一个开始)重写检查,在循环中则提前重启新一轮循环;
break
重写完成后停止对当前URI在当前location中后续的其它重写操作,而后直接跳转至重写规则配置块之后的其它配置;在循环中则结束循环,建议在location中使用;
redirect
临时重定向,重写完成后以临时重定向方式直接返回重写后生成的新URI给客户端,由客户端重新发起请求;不能以http://或https://开头,使用相对路径,状态码:302;
permanent
重写完成后以永久重定向方式直接返回重写后生成的新URI给客户端,由客户端重新发起请求,状态码:301。
rewrite_log
是否把重写过程记录到错误日志中,默认为off,级别默认notice。
try_files
后面可以跟多个文件名,表示逐个匹配文件,如果没有则继续往后一个文件匹配
return
用于结束rewrite规则,并且为客户端返回状态码204,400,402-400,500-504等
index
设置网站的默认首页。
error_page
设置网站的错误页面。
proxy_pass
指定反向代理的服务器池,如:192.168.10.10 或使用upstream,服务器池是tomcat动态程序
proxy_redirect
url中末尾是没有后缀:/ 的目录时,nginx内置了301重定向,重定向追加/,此参数可以修改反向代理重定向的url
proxy_set_header
设置发往后端请求头,参数有:
Host:指定反向代理到哪个主机名;
X-REMOTE-IP:上一跳的ip;
X-Forwarded-For:设置客户端ip;
http_user_agent:设置客户端OS;
proxy_body_buffer_size
设置客户端请求主体缓冲区大小,可以理解为先保存到本地在传给用户。
proxy_connect_timeout
设置后端服务器连接的超时时间,即发起握手等候响应的超时时间。
proxy_send_timeout
设置后端服务器的数据回传时间,即在规定的时间内后端服务器必须传完所有的数据,否则nginx将断开这个连接。
proxy_read_timeout
设置从后端服务器获取信息的时间,表示连接建立成功之后,nginx等待后端服务器的响应时间,其实nginx已经进入后端的排队之中等候处理。
proxy_buffer_size
设置缓冲区大小。
proxy_buffers
设置缓冲区的数量和大小。
proxy_busy_buffers_size
设置系统忙碌时可以使用的proxy_buffers大小,官方推荐为proxy_buffers*2
proxy_tmep_file_write_size
指定proxy缓存临时文件的大小
proxy_next_upstream
请求出错后,转向下一个节点
fastcgi_pass
指定fastcgi进程监听的IP地址和端口
fastcgi_pass_header
设置请求fastcgi的请求头。
fastcgi_read_timeout
fastcgi服务器的响应超时时间。
expires
指定浏览器缓存失效时长,比如:30s
内置变量
$uri
当前请求的URI,不带参数
$document_uri
当前请求的URI,不带参数
$request_uri
请求的uri,带完整参数
$is_args
表示请求中的 URI 是否带参数,如果带参数,$is_args 值为 ?,如果不带参数,则是空字符串
$args
http请求的完整参数
$arg_[param]
http请求中某个参数的值
$query_string
http请求的完整参数,只读不可改变
$host
http请求报文中的host首部,如果请求中没有host首部,则以处理此请求的虚拟主机的主机名代替
$hostname
nginx服务运行在的主机的主机名。
$proxy_host
nginx对于upstream默认使用的是基于IP的转发,所以表示请求到对应的upstream配置的域名的ip
$remote_addr
客户端的ip地址,如果客户端有代理,则为最近的代理服务器的ip
$http_x_real_ip
客户端的ip地址,如果客户端有代理,则为已设置的最新的代理服务器的ip
$http_x_forwarded_for
客户端的ip地址,默认是空。
$proxy_add_x_forwarded_for
$http_x_forwarded_for和$remote_addr,中间用逗号隔开
$binary_remote_addr
二进制格式的客户端地址
$remote_port
客户端端口
$remote_user
启用用户认证时,客户端输入的用户名
$request_method
请求方法
$request_filename
用户请求中的uri经过本地root或alias转换后映射的本地文件路径
$request_body
表示http请求中的body体,该参数只在proxy_pass或fastcgi_pass中有意义
$request_body_file
表示http请求中的body体存储的临时文件名
$request_completion
当请求已经全部完成时,其值为 “ok” 。若没有完成,就要返回客户端,则其值为空字符串;
$server_addr
服务器地址
$server_name
服务器域名
$server_protocol
服务器向客户端发送响应时的协议,如http/1.1
$scheme
在请求中使用scheme,如https://www.magedu.com/中的https
$http_[header]
匹配请求报文中指定的HEADER,例如:$http_host匹配请求报文中的host首部
$sent_http_[header]
匹配响应报文中指定的HEADER,例如:$sent_http_content_type匹配响应报文中content-type首部
$document_root
当前请求映射到的root配置项
$time_local
访问时间与时区
$request
请求的url与http协议
$status
请求状态,成功是200
$body_bytes_sent
发送给客户端文件主体内容大小
$http_referer
记录从那个页面链接访问过来的
$http_user_agent
记录客户端浏览器的相关信息
$content_length
请求头部中的Content-Length字段
$content_type
请求头部中的Content-Type字段
$cookie_COOKIE
请求头部中的cookie字段
$limit_rate
表示当前连接的限速是多少,0表示无限速
$nginx_version
表示当前Nginx的版本号
location匹配
匹配规则
=
严格匹配。如果请求匹配这个 location,那么将停止搜索并立即处理此请求
~
正则匹配 区分大小写
~*
正则匹配 不区分大小写
!~
区分大小写不匹配
!~*
不区分大小写不匹配
^~
前缀匹配
@
子主题
/
通用匹配,任何请求都会匹配到
匹配顺序
1.= 精确匹配
2.^~ 前缀匹配
优先级是从长到短(匹配字符越多,则选择该匹配结果)
3.~/~* 正则匹配
按照配置文件里的顺序(从上到下),成功就停止其他匹配
4./ 通用匹配
反向代理
proxy_pass http://www.baidu.com
proxy_method POST
proxy_set_header Host $host
proxy_set_header X-Real_IP $remote_addr
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for
负载均衡
upstream
server
Ip:port
down
server已停用
backup
备用服务器
weight
负载权重 值越大 权重越高
负载均衡算法
轮询 默认
权重(weight)
server ip:port weight=xx
IP哈希
ip_hash;
fair
fair;需第三方插件 后端服务器的响应时间来分配请求,响应时间短的优先分配。
url哈希
需第三方插件 访问url的hash结果来分配请求,使每个url定向到同一个后端服务器,后端服务器为缓存时比较有效。
动静分离
配置 :location ~.*\.(jpg|png|gif|css|js)$ { root static;}
expires 1d;过期时间1d
数据压缩
Gzip压缩 详情见配置Http块
进程模型
多进程模型 异步处理机制
master进程
接收外部信号
向各worker进程发送信号
监控worker进程的执行状态
work进程
处理用户请求
个数一般与CPU数量一致
热部署
跨域问题
防盗链
高可用
分库分表
mycat(代理端)
sharding(JAR端)
算法
0 条评论
下一页