理解 Linux backlog/somaxconn 内核参数

November 21st, 2019 by JasonLe's Tech 133 views

引言

之前线上TcpExt.ListenOverflows,然后通过ss -tlnp 查看Send-Q偏小导致后端服务器 Socket accept 队列满,系统的 somaxconn 内核参数默认太小。

TCP SYN_REVD, ESTABELLISHED 状态对应的队列

TCP 建立连接时要经过 3 次握手,在客户端向服务器发起连接时,
对于服务器而言,一个完整的连接建立过程,服务器会经历 2 种 TCP 状态:SYN_REVD, ESTABELLISHED。

对应也会维护两个队列:
1. 一个存放 SYN 的队列(半连接队列)
2. 一个存放已经完成连接的队列(全连接队列)

当一个连接的状态是 SYN RECEIVED 时,它会被放在 SYN 队列中。
当它的状态变为 ESTABLISHED 时,它会被转移到另一个队列。
所以后端的应用程序只从已完成的连接的队列中获取请求。

如果一个服务器要处理大量网络连接,且并发性比较高,那么这两个队列长度就非常重要了。
因为,即使服务器的硬件配置非常高,服务器端程序性能很好,
但是这两个队列非常小,那么经常会出现客户端连接不上的现象,
因为这两个队列一旦满了后,很容易丢包,或者连接被复位。
所以,如果服务器并发访问量非常高,那么这两个队列的设置就非常重要了。

Linux backlog 参数意义

对于 Linux 而言,基本上任意语言实现的通信框架或服务器程序在构造 socket server 时,都提供了 backlog 这个参数,
因为在监听端口时,都会调用系统底层 API: int listen(int sockfd, int backlog);

listen 函数中 backlog 参数的定义如下:

Now it specifies the queue length for completely established sockets waiting to be accepted,
instead of the number of incomplete connection requests.
The maximum length of the queue for incomplete sockets can be set using the tcp_max_syn_backlog sysctl.
When syncookies are enabled there is no logical maximum length and this sysctl setting is ignored.
If the socket is of type AF_INET, and the backlog argument is greater than the constant SOMAXCONN(128 default),
it is silently truncated to SOMAXCONN.

backlog 参数描述的是服务器端 TCP ESTABELLISHED 状态对应的全连接队列长度。

全连接队列长度如何计算?
如果 backlog 大于内核参数 net.core.somaxconn,则以 net.core.somaxconn 为准,
即全连接队列长度 = min(backlog, 内核参数 net.core.somaxconn),net.core.somaxconn 默认为 128。
这个很好理解,net.core.somaxconn 定义了系统级别的全连接队列最大长度,
backlog 只是应用层传入的参数,不可能超过内核参数,所以 backlog 必须小于等于 net.core.somaxconn。

半连接队列长度如何计算?
半连接队列长度由内核参数 tcp_max_syn_backlog 决定,
当使用 SYN Cookie 时(就是内核参数 net.ipv4.tcp_syncookies = 1),这个参数无效,
半连接队列的最大长度为 backlog、内核参数 net.core.somaxconn、内核参数 tcp_max_syn_backlog 的最小值。
即半连接队列长度 = min(backlog, 内核参数 net.core.somaxconn,内核参数 tcp_max_syn_backlog)。
这个公式实际上规定半连接队列长度不能超过全连接队列长度。

其实,对于 Nginx/Tomcat 等这种 Web 服务器,都提供了 backlog 参数设置入口,
当然它们都会有默认值,通常这个默认值都不会太大(包括内核默认的半连接队列和全连接队列长度)。
如果应用并发访问非常高,只增大应用层 backlog 是没有意义的,因为可能内核参数关于连接队列设置的都很小,
一定要综合应用层 backlog 和内核参数一起看,通过公式很容易调整出正确的设置。

 

ACID/CAP/BASE/二段提交/三段提交/TCC

November 6th, 2019 by JasonLe's Tech 137 views

关系型数据库完全满足ACID的特性。

ACID指的是:A: Atomicity 原子性 C: Consistency 一致性 I: Isolation 隔离性 D: Durability 持久性

具有ACID的特性的数据库支持强一致性,强一致性代表数据库本身不会出现不一致,每个事务是原子的,或者成功或者失败,事物间是隔离的,互相完全不影响,而且最终状态是持久落盘的,因此,数据库会从一个明确的状态到另外一个明确的状态,中间的临时状态是不会出现的,如果出现也会及时的自动的修复,因此是强一致的。

如果你在为交易相关系统做技术选型,交易的存储应该只考虑关系型数据库,对于核心系统,如果需要较好的性能,可以考虑使用更强悍的硬件,这种向上扩展(升级硬件)虽然成本较高,但是是最简单粗暴有效的方式,另外,Nosql完全不适合交易场景,Nosql主要用来做数据分析、ETL、报表、数据挖掘、推荐、日志处理等非交易场景。

CAP(帽子理论)

C:Consistency,一致性, 数据一致更新,所有数据变动都是同步的

A:Availability,可用性, 好的响应性能,完全的可用性指的是在任何故障模型下,服务都会在有限的时间处理响应

P:Partition tolerance,分区容错性,可靠性

帽子理论证明,任何分布式系统只可同时满足二点,没法三者兼顾。关系型数据库由于关系型数据库是单节点的,因此,不具有分区容错性,但是具有一致性和可用性,而分布式的服务化系统都需要满足分区容错性,那么我们必须在一致性和可用性中进行权衡,具体表现在服务化系统处理的异常请求在某一个时间段内可能是不完全的,但是经过自动的或者手工的补偿后,达到了最终的一致性。

BASE模型与ACID模型截然不同,满足CAP理论,通过牺牲强一致性,获得可用性。

一般应用在服务化系统的应用层或者大数据处理系统,通过达到最终一致性来尽量满足业务的绝大部分需求。

BASE模型包含个三个元素:

1.BA:Basically Available,基本可用

2.S:Soft State,软状态,状态可以有一段时间不同步

3.E:Eventually Consistent,最终一致,最终数据是一致的就可以了,而不是时时保持强一致

分布式一致性协议

两阶段如下:

1.准备阶段:协调者向参与者发起指令,参与者评估自己的状态,如果参与者评估指令可以完成,参与者会写redo或者undo日志(这也是前面提起的Write-Ahead Log的一种),然后锁定资源,执行操作,但是并不提交

2.提交阶段:如果每个参与者明确返回准备成功,也就是预留资源和执行操作成功,协调者向参与者发起提交指令,参与者提交资源变更的事务,释放锁定的资源;如果任何一个参与者明确返回准备失败,也就是预留资源或者执行操作失败,协调者向参与者发起中止指令,参与者取消已经变更的事务,执行undo日志,释放锁定的资源

两阶段提交协议

我们看到两阶段提交协议在准备阶段锁定资源,是一个重量级的操作,并能保证强一致性,但是实现起来复杂、成本较高,不够灵活,更重要的是它有如下致命的问题:

1.阻塞:从上面的描述来看,对于任何一次指令必须收到明确的响应,才会继续做下一步,否则处于阻塞状态,占用的资源被一直锁定,不会被释放

2.单点故障:如果协调者宕机,参与者没有了协调者指挥,会一直阻塞,尽管可以通过选举新的协调者替代原有协调者,但是如果之前协调者在发送一个提交指令后宕机,而提交指令仅仅被一个参与者接受,并且参与者接收后也宕机,新上任的协调者无法处理这种情况

3.脑裂:协调者发送提交指令,有的参与者接收到执行了事务,有的参与者没有接收到事务,就没有执行事务,多个参与者之间是不一致的

上面所有的这些问题,都是需要人工干预处理,没有自动化的解决方案,因此两阶段提交协议在正常情况下能保证系统的强一致性,但是在出现异常情况下,当前处理的操作处于错误状态,需要管理员人工干预解决,因此可用性不够好,这也符合CAP协议的一致性和可用性不能兼得的原理。

三阶段提交协议

三阶段提交协议是两阶段提交协议的改进版本。它通过超时机制解决了阻塞的问题,并且把两个阶段增加为三个阶段:

1.询问阶段:协调者询问参与者是否可以完成指令,协调者只需要回答是还是不是,而不需要做真正的操作,这个阶段超时导致中止

2.准备阶段:如果在询问阶段所有的参与者都返回可以执行操作,协调者向参与者发送预执行请求,然后参与者写redo和undo日志,执行操作,但是不提交操作;如果在询问阶段任何参与者返回不能执行操作的结果,则协调者向参与者发送中止请求,这里的逻辑与两阶段提交协议的的准备阶段是相似的,这个阶段超时导致成功

3.提交阶段:如果每个参与者在准备阶段返回准备成功,也就是预留资源和执行操作成功,协调者向参与者发起提交指令,参与者提交资源变更的事务,释放锁定的资源;如果任何一个参与者返回准备失败,也就是预留资源或者执行操作失败,协调者向参与者发起中止指令,参与者取消已经变更的事务,执行undo日志,释放锁定的资源,这里的逻辑与两阶段提交协议的提交阶段一致

三阶段提交协议

然而,这里与两阶段提交协议有两个主要的不同:

1.增加了一个询问阶段,询问阶段可以确保尽可能早的发现无法执行操作而需要中止的行为,但是它并不能发现所有的这种行为,只会减少这种情况的发生

2.在准备阶段以后,协调者和参与者执行的任务中都增加了超时,一旦超时,协调者和参与者都继续提交事务,默认为成功,这也是根据概率统计上超时后默认成功的正确性最大

三阶段提交协议与两阶段提交协议相比,具有如上的优点,但是一旦发生超时,系统仍然会发生不一致,只不过这种情况很少见罢了,好处就是至少不会阻塞和永远锁定资源。

TCC

无论两阶段还是三阶段方案中都包含多个参与者、多个阶段实现一个事务,实现复杂,性能也是一个很大的问题,因此,在互联网高并发系统中,鲜有使用两阶段提交和三阶段提交协议的场景。

阿里巴巴提出了新的TCC协议,TCC协议将一个任务拆分成Try、Confirm、Cancel,正常的流程会先执行Try,如果执行没有问题,再执行Confirm,如果执行过程中出了问题,则执行操作的逆操Cancel,从正常的流程上讲,这仍然是一个两阶段的提交协议,但是,在执行出现问题的时候,有一定的自我修复能力,如果任何一个参与者出现了问题,协调者通过执行操作的逆操作来取消之前的操作,达到最终的一致状态。

可以看出,从时序上,如果遇到极端情况下TCC会有很多问题的,例如,如果在Cancel的时候一些参与者收到指令,而一些参与者没有收到指令,整个系统仍然是不一致的,这种复杂的情况,系统首先会通过补偿的方式,尝试自动修复的,如果系统无法修复,必须由人工参与解决。

从TCC的逻辑上看,可以说TCC是简化版的三阶段提交协议,解决了两阶段提交协议的阻塞问题,但是没有解决极端情况下会出现不一致和脑裂的问题。然而,TCC通过自动化补偿手段,会把需要人工处理的不一致情况降到到最少,也是一种非常有用的解决方案,根据线人,阿里在内部的一些中间件上实现了TCC模式。

我们给出一个使用TCC的实际案例,在秒杀的场景,用户发起下单请求,应用层先查询库存,确认商品库存还有余量,则锁定库存,此时订单状态为待支付,然后指引用户去支付,由于某种原因用户支付失败,或者支付超时,系统会自动将锁定的库存解锁供其他用户秒杀。

总结一下,两阶段提交协议、三阶段提交协议、TCC协议都能保证分布式事务的一致性,他们保证的分布式系统的一致性从强到弱,TCC达到的目标是最终一致性,其中任何一种方法都可以不同程度的解决案例2:转账、案例3:下订单和扣库存的问题,只是实现的一致性的级别不一样而已,对于案例4:同步超时可以通过TCC的理念解决,如果同步调用超时,调用方可以使用fastfail策略,返回调用方的使用方失败的结果,同时调用服务的逆向cancel操作,保证服务的最终一致性。

分布式一致性的技术包括:paxos算法、raft算法、zab算法、nwr算法、一致性哈希等。

参考:

案例2:转账
转账是经典的不一致案例,设想一下银行为你处理一笔转账,扣减你账户上的余额,然后增加别人账户的余额;如果扣减你的账户余额成功,增加别人账户余额失败,那么你就会损失这笔资金。反过来,如果扣减你的账户余额失败,增加别人账户余额成功,那么银行就会损失这笔资金,银行需要赔付。对于资金处理系统来说,上面任何一种场景都是不允许发生的,一旦发生就会有资金损失,后果是不堪设想的,严重情况会让一个公司瞬间倒闭,可参考案例。

案例3:下订单和扣库存
电商系统中也有一个经典的案例,下订单和扣库存如何保持一致,如果先下订单,扣库存失败,那么将会导致超卖;如果下订单没有成功,扣库存成功,那么会导致少卖。两种情况都会导致运营成本的增加,严重情况下需要赔付。

案例4:同步超时
服务化的系统间调用常常因为网络问题导致系统间调用超时,即使是网络很好的机房,在亿次流量的基数下,同步调用超时也是家常便饭。系统A同步调用系统B超时,系统A可以明确得到超时反馈,但是无法确定系统B是否已经完成了预定的功能或者没有完成预定的功能。于是,系统A就迷茫了,不知道应该继续做什么,如何反馈给使用方。(曾经的一个B2B产品的客户要求接口超时重新通知他们,这个在技术上是难以实现的,因为服务器本身可能并不知道自己超时,可能会继续正常的返回数据,只是客户端并没有接受到结果罢了,因此这不是一个合理的解决方案)。

https://blog.csdn.net/qq_31854907/article/details/92796788

docker 常用操作

November 4th, 2019 by JasonLe's Tech 130 views

sudo docker ps

sudo docker images

sudo docker run –name mysql -p 3306:3306 -v ~/mysql/data:/var/lib/mysql -e MYSQL_DATABASE=spider -e MYSQL_USER=admin -e MYSQL_PASSWORD=admin -e MYSQL_ROOT_PASSWORD=admin -d mysql

sudo docker run –name redis -p 6379:6379 -d redis

sudo docker run –name mongo -p 27017:27017 -v ~/mongo/db:/data/db -e MONGO_INITDB_ROOT_USERNAME=admin -e MONGO_INITDB_ROOT_PASSWORD=admin -d mongo

sudo docker exec -it mysql bash

sudo docker exec -it redis bash

 

docker run -it –name openjdk -d lzz5235/openjdk-8u202 /bin/bash 这样可以保证容器不被杀死

docker exec -it [name] /bin/bash 进入终端

 

 

 

GC调优

October 12th, 2019 by JasonLe's Tech 142 views

1.问题的发现与定位

1.1统计nginx每秒中流量时发现轮询到每台机器上的流量不均衡,找到后端机器,看gc 日志发现出现大量的full gc,对比gc时间和流量统计的时间,发现时间是完全吻合的,从而定位流量不均衡问题是因为线上服务full gc引起的。

2019-08-30T11:33:06.130+0800: 780570.463: [GC pause (G1 Evacuation Pause) (young)2019-08-30T11:33:06.352+0800: 780570.685: [SoftReference, 0 refs, 0.0000547 secs]2019-08-30T11:33:06.352+0800: 780570.685: [WeakReference, 0 refs, 0.0000128 secs]2019-08-30T11:33:06.352+0800: 780570.685: [FinalReference, 0 refs, 0.0000103 secs]2019-08-30T11:33:06.352+0800: 780570.685: [PhantomReference, 0 refs, 0 refs, 0.0000147 secs]2019-08-30T11:33:06.352+0800: 780570.685: [JNI Weak Reference, 0.0000183 secs] (to-space exhausted), 0.2410054 secs]
   [Parallel Time: 212.0 ms, GC Workers: 23]
      [GC Worker Start (ms): Min: 780570465.3, Avg: 780570465.5, Max: 780570465.9, Diff: 0.6]
      [Ext Root Scanning (ms): Min: 0.4, Avg: 0.8, Max: 2.2, Diff: 1.9, Sum: 18.4]
      [Update RS (ms): Min: 33.8, Avg: 37.4, Max: 40.3, Diff: 6.4, Sum: 861.1]
         [Processed Buffers: Min: 9, Avg: 30.3, Max: 137, Diff: 128, Sum: 697]
      [Scan RS (ms): Min: 0.0, Avg: 0.0, Max: 0.0, Diff: 0.0, Sum: 0.0]
      [Code Root Scanning (ms): Min: 0.0, Avg: 0.0, Max: 0.0, Diff: 0.0, Sum: 0.0]
      [Object Copy (ms): Min: 169.7, Avg: 173.0, Max: 176.7, Diff: 7.0, Sum: 3979.6]
      [Termination (ms): Min: 0.0, Avg: 0.3, Max: 0.4, Diff: 0.4, Sum: 5.8]
         [Termination Attempts: Min: 1, Avg: 1.3, Max: 3, Diff: 2, Sum: 30]
      [GC Worker Other (ms): Min: 0.0, Avg: 0.0, Max: 0.4, Diff: 0.4, Sum: 0.8]
      [GC Worker Total (ms): Min: 211.2, Avg: 211.6, Max: 211.8, Diff: 0.7, Sum: 4865.7]
      [GC Worker End (ms): Min: 780570677.0, Avg: 780570677.1, Max: 780570677.1, Diff: 0.0]
   [Code Root Fixup: 0.0 ms]
   [Code Root Purge: 0.0 ms]
   [Clear CT: 0.2 ms]
   [Other: 28.8 ms]
      [Evacuation Failure: 18.1 ms]
      [Choose CSet: 0.0 ms]
      [Ref Proc: 7.5 ms]
      [Ref Enq: 0.0 ms]
      [Redirty Cards: 0.4 ms]
      [Humongous Register: 1.5 ms]
      [Humongous Reclaim: 0.2 ms]
      [Free CSet: 0.1 ms]
   [Eden: 44.0M(6116.0M)->0.0B(6144.0M) Survivors: 28.0M->0.0B Heap: 9482.2M(12.0G)->9482.2M(12.0G)]
Heap after GC invocations=266041 (full 14579):
 garbage-first heap   total 12582912K, used 9709773K [0x00000004c0000000, 0x00000004c0406000, 0x00000007c0000000)
  region size 4096K, 0 young (0K), 0 survivors (0K)
 Metaspace       used 59825K, capacity 60428K, committed 62016K, reserved 1103872K
  class space    used 6597K, capacity 6776K, committed 7056K, reserved 1048576K
}
 [Times: user=0.57 sys=0.08, real=0.24 secs]
2019-08-30T11:33:06.372+0800: 780570.705: Total time for which application threads were stopped: 0.2499226 seconds, Stopping threads took: 0.0007422 seconds
{Heap before GC invocations=266041 (full 14579):
 garbage-first heap   total 12582912K, used 9709773K [0x00000004c0000000, 0x00000004c0406000, 0x00000007c0000000)
  region size 4096K, 0 young (0K), 0 survivors (0K)
 Metaspace       used 59825K, capacity 60428K, committed 62016K, reserved 1103872K
  class space    used 6597K, capacity 6776K, committed 7056K, reserved 1048576K
2019-08-30T11:33:06.380+0800: 780570.712: [GC pause (G1 Evacuation Pause) (young) (initial-mark)2019-08-30T11:33:06.392+0800: 780570.725: [SoftReference, 0 refs, 0.0000740 secs]2019-08-30T11:33:06.392+0800: 780570.725: [WeakReference, 0 refs, 0.0000127 secs]2019-08-30T11:33:06.392+0800: 780570.725: [FinalReference, 0 refs, 0.0000103 secs]2019-08-30T11:33:06.392+0800: 780570.725: [PhantomReference, 0 refs, 0 refs, 0.0000147 secs]2019-08-30T11:33:06.392+0800: 780570.725: [JNI Weak Reference, 0.0000174 secs], 0.0144402 secs]
   [Parallel Time: 10.2 ms, GC Workers: 23]
      [GC Worker Start (ms): Min: 780570714.5, Avg: 780570715.2, Max: 780570716.2, Diff: 1.7]
      [Ext Root Scanning (ms): Min: 1.1, Avg: 1.9, Max: 2.8, Diff: 1.7, Sum: 44.1]
      [Update RS (ms): Min: 6.1, Avg: 6.5, Max: 7.3, Diff: 1.2, Sum: 150.3]
         [Processed Buffers: Min: 3, Avg: 9.9, Max: 18, Diff: 15, Sum: 227]
      [Scan RS (ms): Min: 0.0, Avg: 0.0, Max: 0.0, Diff: 0.0, Sum: 0.0]
      [Code Root Scanning (ms): Min: 0.0, Avg: 0.0, Max: 0.0, Diff: 0.0, Sum: 0.0]
      [Object Copy (ms): Min: 0.0, Avg: 0.2, Max: 0.4, Diff: 0.4, Sum: 4.7]
      [Termination (ms): Min: 0.0, Avg: 0.5, Max: 0.7, Diff: 0.7, Sum: 12.5]
         [Termination Attempts: Min: 1, Avg: 1.0, Max: 1, Diff: 0, Sum: 23]
      [GC Worker Other (ms): Min: 0.0, Avg: 0.0, Max: 0.0, Diff: 0.0, Sum: 0.3]
      [GC Worker Total (ms): Min: 8.3, Avg: 9.2, Max: 10.0, Diff: 1.7, Sum: 211.9]
      [GC Worker End (ms): Min: 780570724.4, Avg: 780570724.4, Max: 780570724.4, Diff: 0.0]
   [Code Root Fixup: 0.0 ms]
   [Code Root Purge: 0.0 ms]
   [Clear CT: 0.3 ms]
   [Other: 3.9 ms]
      [Choose CSet: 0.0 ms]
      [Ref Proc: 0.7 ms]
      [Ref Enq: 0.0 ms]
      [Redirty Cards: 0.3 ms]
      [Humongous Register: 1.4 ms]
      [Humongous Reclaim: 0.2 ms]
      [Free CSet: 0.0 ms]
   [Eden: 0.0B(6144.0M)->0.0B(6144.0M) Survivors: 0.0B->0.0B Heap: 9482.2M(12.0G)->9482.2M(12.0G)]
Heap after GC invocations=266042 (full 14579):
 garbage-first heap   total 12582912K, used 9709773K [0x00000004c0000000, 0x00000004c0406000, 0x00000007c0000000)
  region size 4096K, 0 young (0K), 0 survivors (0K)
 Metaspace       used 59825K, capacity 60428K, committed 62016K, reserved 1103872K
  class space    used 6597K, capacity 6776K, committed 7056K, reserved 1048576K
}
 [Times: user=0.13 sys=0.01, real=0.02 secs]
2019-08-30T11:33:06.394+0800: 780570.727: [GC concurrent-root-region-scan-start]
2019-08-30T11:33:06.394+0800: 780570.727: [GC concurrent-root-region-scan-end, 0.0000314 secs]
2019-08-30T11:33:06.394+0800: 780570.727: [GC concurrent-mark-start]
2019-08-30T11:33:06.394+0800: 780570.727: Total time for which application threads were stopped: 0.0225686 seconds, Stopping threads took: 0.0003015 seconds
{Heap before GC invocations=266042 (full 14579):
 garbage-first heap   total 12582912K, used 9709773K [0x00000004c0000000, 0x00000004c0406000, 0x00000007c0000000)
  region size 4096K, 0 young (0K), 0 survivors (0K)
 Metaspace       used 59825K, capacity 60428K, committed 62016K, reserved 1103872K
  class space    used 6597K, capacity 6776K, committed 7056K, reserved 1048576K
2019-08-30T11:33:06.402+0800: 780570.735: [Full GC (Allocation Failure) 2019-08-30T11:33:06.812+0800: 780571.145: [SoftReference, 155 refs, 0.0000827 secs]2019-08-30T11:33:06.812+0800: 780571.145: [WeakReference, 4919 refs, 0.0004444 secs]2019-08-30T11:33:06.812+0800: 780571.145: [FinalReference, 38797 refs, 0.0256226 secs]2019-08-30T11:33:06.838+0800: 780571.171: [PhantomReference, 0 refs, 4 refs, 0.0000267 secs]2019-08-30T11:33:06.838+0800: 780571.171: [JNI Weak Reference, 0.0000255 secs] 9482M->3317M(12G), 1.3316541 secs]
   [Eden: 0.0B(6144.0M)->0.0B(6144.0M) Survivors: 0.0B->0.0B Heap: 9482.2M(12.0G)->3317.3M(12.0G)], [Metaspace: 59825K->59825K(1103872K)]
Heap after GC invocations=266043 (full 14580):
 garbage-first heap   total 12582912K, used 3396899K [0x00000004c0000000, 0x00000004c0406000, 0x00000007c0000000)
  region size 4096K, 0 young (0K), 0 survivors (0K)
 Metaspace       used 59825K, capacity 60428K, committed 62016K, reserved 1103872K
  class space    used 6597K, capacity 6776K, committed 7056K, reserved 1048576K
}
 [Times: user=1.83 sys=0.12, real=1.34 secs]

2 问题分析与处理

2.1 分析日志发现在新生代回收时触发了老年代的担保机制,导致新生代对象直接晋升到了老年代,然后触发并发周期,这时由于老年代对象太多已经不足以触发mixed GC,而是采用了最耗时的Full GC进行垃圾回收,由于Full GC耗时很长导致,后续的新生代在垃圾回收时还是会触发老年代担保机制,从而整个程序陷入循环Full GC的状态。

2.2 根据to-space exhausted我们知道,调整空闲区域预留百分比是能缓解新生代垃圾回收空间溢出问题,我们尝试增加XX:G1ReservePercent=15;另外我们为了降低Full GC触发概率,减小了InitiatingHeapOccupancyPercent的大小,这样我们可以用更加频繁的mixed gc降低 full gc问题

2.3 根据G1的启发式算法,我们为了控制gc时间,决定放弃原有的gc用法,让g1决定新生代和老年代大小,我们删除了Xmn参数设置

2-4 在gc日志中我们也发现了大对象分配与回收的现象,考虑到我们线上视频大小,我们调整region大小到16M

3 观察对比后再次处理

3.1 通过上述调整对比观察四台机器,两天以后,原有的机器出现Full GC 调整后的机器运行正常

3.2 观察调整后日志发现新调整的gc没有出现Full gc,但是mixed gc问题出现频率在20min一次,这个频率出现理论上对整个gc的吞吐几乎没有影响,但是分析后会发现mixed gc回收效率很低,所以我们尝试改善mixed gc的效率

3.3 根据上述我们对InitiatingHeapOccupancyPercent参数的调整,我们根据线上观察到的老年代大小和新生代大小,调整值为50

3.4 对比观察后发现调整后mixed gc频率在流量高峰期间为2小时一次,流量低峰期间为6小时一次,并且mixed gc 回收效率大大提高

4.调优后效果

经过调优后线上没有触发 full gc, yang gc 和mixed gc 效率都很高,整个gc的吞吐达到 99%以上

对称加密和非对称加密

October 7th, 2019 by JasonLe's Tech 219 views

对称加密和非对称加密的概念是两种非常重要的加密方式,二者各有应用的领域,今天看完一片博文系统性的把这个弄明白了。

在对称加密算法中,加密使用的密钥和解密使用的密钥是相同的。也就是说,加密和解密都是使用的同一个密钥(举例密钥A,甲方用密钥A加密报文,乙方用密钥A解密报文)。显而易见对称加密算法要保证安全性的话,密钥A非常重要,密钥A丢失的话,黑客就可以监听甲方和乙方之间的通信。

在非对称加密中,会同时存在两个密钥(公钥&私钥)然后可以使用公钥加密->私钥解密(或者私钥解密->公钥加密)。 加密使用的密钥和解密使用的密钥是不相同的,因此它是一个非对称加密算法。注意:公钥和私钥只是名义上这么说,主要表达的意思是公钥人人都可以获取,私钥只有自己留存。RSA就是一种非对称加密算法,这一对公钥、私钥都可以用来加密和解密,并且一方加密的内容可以由并且只能由对方进行解密。

什么时候用公钥加密->私钥解密,还是私钥解密->公钥加密主要依靠使用场景:

1.私钥加密公钥解密,能证明“私钥拥有者” 的唯一身份,用于签名。

2. 公钥加密私钥解密,确保发送的信息,只有有“私钥拥有者” 能够接收(如果用私钥加密,传递数据,则会被公钥持有者(可能有很多持有者) 解密,失去对信息的保护)

但是仅有RSA还无法完全保证通信的安全,因此一般通信流程是先使用非对称加密验证双方身份,然后采用对称加密进行数据通信。但是!谁都可以生成公钥私钥,如果黑客向“客户”发送他自己的私钥就可以冒充“服务器”了!因此对于验证身份采用证书方式是现在通用方式。申请证书后,公司会得到这个这个证书和私钥,公钥嵌入在证书中!私钥只能由公司自己知道。

一个证书包含下面的具体内容:

  • 证书的颁发者
  • 证书的有效期
  • 证书的使用者
  • 公钥(这个公司证书的公钥)
  • 证书所有者(Subject)
  • 签名所使用的算法
  • 指纹以及指纹算法(机构的证书)

指纹算法主要用来保证这个证书的完整性,机构会使用自己加密算法和私钥加密证书:生成方式就是”SecureTrust CA”这个证书机构利用签名算法(Signature algorithm)使用私钥加密hash(证书)后和证书放在一起,以保证证书完整性。用户只需要使用机构的公钥解密证书,得到hash’(证书)并和该证书hash对比得出是否被篡改。

如果证书没有篡改,那么使用指纹算法计算这个证书的指纹,将这个计算的指纹与证书中的指纹对比,如果一致,说明这个的证书肯定没有被修改过并且证书是由这个证书机构发布的,证书中的公钥肯定是这个证书的,客户然后就可以放心的使用这个公钥和服务器进行通信。

下面来说HTTPS通信模式:

step1: “客户”向服务端发送一个通信请求

“客户”->“服务器”:你好

step2: “服务器”向客户发送自己的数字证书。证书中有一个公钥用来加密信息,私钥由“服务器”持有

“服务器”->“客户”:你好,我是服务器,这里是我的数字证书

step3: “客户”收到“服务器”的证书后,它会去验证这个数字证书到底是不是“服务器”的,数字证书有没有什么问题,数字证书如果检查没有问题,就说明数字证书中的公钥确实是“服务器”的。检查数字证书后,“客户”会发送一个随机的字符串给“服务器”,“服务器”用私钥去加密然后返回给“客户”,“客户”用公钥解密这个返回结果,如果解密结果与之前生成的随机字符串一致,那说明对方确实是私钥的持有者,或者说对方确实是“服务器”。

“客户”->“服务器”:向我证明你就是服务器,这是一个随机字符串 //前面的例子中为了方便解释,用的是“你好”等内容,实际情况下一般是随机生成的一个字符串。

“服务器”->“客户”:{一个随机字符串}[私钥|RSA]

step4: 验证“服务器”的身份后,“客户”生成一个对称加密算法和密钥,用于后面的通信的加密和解密。这个对称加密算法和密钥,“客户”会用公钥加密后发送给“服务器”,别人截获了也没用,因为只有“服务器”手中有可以解密的私钥。这样,后面“服务器”和“客户”就都可以用对称加密算法来加密和解密通信内容了。

“服务器”->“客户”:{OK,已经收到你发来的对称加密算法和密钥!有什么可以帮到你的?}[密钥|对称加密算法]

“客户”->“服务器”:{我的帐号是aaa,密码是123,把我的余额的信息发给我看看}[密钥|对称加密算法]

“服务器”->“客户”:{你好,你的余额是100元}[密钥|对称加密算法]

…… //继续其它的通信

 

http://www.cnblogs.com/JeffreySun/archive/2010/06/24/1627247.html