first commit

This commit is contained in:
iProbe 2022-10-18 16:59:37 +08:00
commit ba848e218d
1001 changed files with 152333 additions and 0 deletions

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 200 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 74 KiB

View file

@ -0,0 +1,165 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="tool" content="leanote-desktop-app">
<title>2</title>
<style>
*{font-family:"lucida grande","lucida sans unicode",lucida,helvetica,"Hiragino Sans GB","Microsoft YaHei","WenQuanYi Micro Hei",sans-serif;}
body {
margin: 0;
}
/*公用文字样式*/
h1{font-size:30px}h2{font-size:24px}h3{font-size:18px}h4{font-size:14px}
.note-container{
width:850px;
margin:auto;
padding: 10px 20px;
box-shadow: 1px 1px 10px #eee;
}
#title {
margin: 0;
}
table {
margin-bottom: 16px;
border-collapse: collapse;
}
table th, table td {
padding: 6px 13px;
border: 1px solid #ddd;
}
table th {
font-weight: bold;
}
table tr {
background-color: none;
border-top: 1px solid #ccc;
}
table tr:nth-child(2n) {
background-color: rgb(247, 247, 249);
}
.mce-item-table, .mce-item-table td, .mce-item-table th, .mce-item-table caption {
border: 1px solid #ddd;
border-collapse: collapse;
padding: 6px 13px;
}
blockquote {
border-left-width:10px;
background-color:rgba(128,128,128,0.05);
border-top-right-radius:5px;
border-bottom-right-radius:5px;
padding:15px 20px;
border-left:5px solid rgba(128,128,128,0.075);
}
blockquote p {
margin-bottom:1.1em;
font-size:1em;
line-height:1.45
}
blockquote ul:last-child,blockquote ol:last-child {
margin-bottom:0
}
pre {
padding: 18px;
background-color: #f7f7f9;
border: 1px solid #e1e1e8;
border-radius: 3px;
display: block;
}
code {
padding: 2px 4px;
font-size: 90%;
color: #c7254e;
white-space: nowrap;
background-color: #f9f2f4;
border-radius: 4px;
}
.footnote {
vertical-align: top;
position: relative;
top: -0.5em;
font-size: .8em;
}
hr {
margin:2em 0
}
img {
max-width:100%
}
pre {
word-break:break-word
}
p,pre,pre.prettyprint,blockquote {
margin:0 0 1.1em
}
hr {
margin:2em 0
}
img {
max-width:100%
}
.sequence-diagram,.flow-chart {
text-align:center;
margin-bottom:1.1em
}
.sequence-diagram text,.flow-chart text {
font-size:15px !important;
font-family:"Source Sans Pro",sans-serif !important
}
.sequence-diagram [fill="#ffffff"],.flow-chart [fill="#ffffff"] {
fill:#f6f6f6
}
.sequence-diagram [stroke="#000000"],.flow-chart [stroke="#000000"] {
stroke:#3f3f3f
}
.sequence-diagram text[stroke="#000000"],.flow-chart text[stroke="#000000"] {
stroke:none
}
.sequence-diagram [fill="#000"],.flow-chart [fill="#000"],.sequence-diagram [fill="#000000"],.flow-chart [fill="#000000"],.sequence-diagram [fill="black"],.flow-chart [fill="black"] {
fill:#3f3f3f
}
ul,ol {
margin-bottom:1.1em
}
ul ul,ol ul,ul ol,ol ol {
margin-bottom:1.1em
}
kbd {
padding:.1em .6em;
border:1px solid rgba(63,63,63,0.25);
-webkit-box-shadow:0 1px 0 rgba(63,63,63,0.25);
box-shadow:0 1px 0 rgba(63,63,63,0.25);
font-size:.7em;
font-family:sans-serif;
background-color:#fff;
color:#333;
border-radius:3px;
display:inline-block;
margin:0 .1em;
white-space:nowrap
}
.toc ul {
list-style-type:none;
margin-bottom:15px
}
</style>
<!-- 该css供自定义样式 -->
<link href="../leanote-html.css" rel="stylesheet">
</head>
<body>
<div class="note-container">
<h1 class="title" id="leanote-title">2</h1>
<div class="content-html" id="leanote-content"><h2>万能的图表</h2><p>我们不能通过多次随机压力的结果来得出结论,因为这样的数据没有意义。为了能够获取有意义的结果,必须设计一系列测试场景。因此我们参照了这个图:&nbsp;</p><p><img id="__LEANOTE_D_IMG_1505975062984" src="2_files/59c3cd3bd01cce1c4d00002a.png" alt="" data-mce-src="/api/file/getImage?fileId=59c3cd3bd01cce1c4d00002a"></p><p>该图表明,直到一个特定的点,随着请求总数的增长,延迟基本上没有变化。然而,当这个拐点之后,响应延迟几乎以指数级增长。这就是我们期望度量的机器或者配置的拐点。</p><h2>Ganglia</h2><p>在提供一些测试结果之前,首先介绍下<a href="http://ganglia.sourceforge.net/" data-mce-href="http://ganglia.sourceforge.net/">Ganglia</a>工具。</p><blockquote><p>Ganglia是一个为高性能计算系统例如集群和网格计算设计的可扩展分布式监控系统</p></blockquote><p>下面的一些图表是我们一台服务器的监控数据截图通过它们我们可以直观的了解Ganglia及其能够提供的图表信息。&nbsp;</p><p><img id="__LEANOTE_D_IMG_1505975094335" src="2_files/59c3cd3bd01cce1c4d00002b.png" alt="" width="550" data-mce-src="/api/file/getImage?fileId=59c3cd3bd01cce1c4d00002b"><img id="__LEANOTE_D_IMG_1505975094336" src="2_files/59c3cd3bd01cce1c4d000029.png" alt="" width="550" data-mce-src="/api/file/getImage?fileId=59c3cd3bd01cce1c4d000029"></p><p>看起来不错吧?</p><p>我们使用Ganglia来监控HAProxy服务器以提供一些核心指标包括</p><ol><li>TCP连接数能够让我们了解当前系统上创建创建的TCP连接总数。注意该数据是输入输出连接的总和。</li><li>数据包收发量HAProxy实际发送和接收到的TCP包数量。</li><li>数据收发量:实际发送和接收的数据总量。</li><li>内存:压力测试过程中服务器的内存变化情况。</li><li>网络:了解压力测试过程中的网络带宽情况。</li></ol><p>以下是基于之前的测试所得到的一些限制,也是我们希望在这次压力测试中能够达到的成绩:</p><ul><li>TCP连接数700k</li><li>发送数据包50k个接收数据包60k个</li><li>收发数据量均在1015MB字节左右</li><li>内存消耗约1415G</li><li>网络带宽7MB</li></ul><p>以上数据均为每秒数据</p><h2></h2><div class="article_page_left text_content_container" style="margin: 0px; padding: 0px; border: 0px; float: left; width: 610px; color: #000000; font-family: Helvetica, 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, sans-serif; font-variant-ligatures: normal; orphans: 2; widows: 2;" data-mce-style="margin: 0px; padding: 0px; border: 0px; float: left; width: 610px; color: #000000; font-family: Helvetica, 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, sans-serif; font-variant-ligatures: normal; orphans: 2; widows: 2;"></div></div>
</div>
<!-- 该js供其它处理 -->
<script src="../leanote-html.js"></script>
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 444 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 492 KiB

View file

@ -0,0 +1,170 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="tool" content="leanote-desktop-app">
<title>3</title>
<style>
*{font-family:"lucida grande","lucida sans unicode",lucida,helvetica,"Hiragino Sans GB","Microsoft YaHei","WenQuanYi Micro Hei",sans-serif;}
body {
margin: 0;
}
/*公用文字样式*/
h1{font-size:30px}h2{font-size:24px}h3{font-size:18px}h4{font-size:14px}
.note-container{
width:850px;
margin:auto;
padding: 10px 20px;
box-shadow: 1px 1px 10px #eee;
}
#title {
margin: 0;
}
table {
margin-bottom: 16px;
border-collapse: collapse;
}
table th, table td {
padding: 6px 13px;
border: 1px solid #ddd;
}
table th {
font-weight: bold;
}
table tr {
background-color: none;
border-top: 1px solid #ccc;
}
table tr:nth-child(2n) {
background-color: rgb(247, 247, 249);
}
.mce-item-table, .mce-item-table td, .mce-item-table th, .mce-item-table caption {
border: 1px solid #ddd;
border-collapse: collapse;
padding: 6px 13px;
}
blockquote {
border-left-width:10px;
background-color:rgba(128,128,128,0.05);
border-top-right-radius:5px;
border-bottom-right-radius:5px;
padding:15px 20px;
border-left:5px solid rgba(128,128,128,0.075);
}
blockquote p {
margin-bottom:1.1em;
font-size:1em;
line-height:1.45
}
blockquote ul:last-child,blockquote ol:last-child {
margin-bottom:0
}
pre {
padding: 18px;
background-color: #f7f7f9;
border: 1px solid #e1e1e8;
border-radius: 3px;
display: block;
}
code {
padding: 2px 4px;
font-size: 90%;
color: #c7254e;
white-space: nowrap;
background-color: #f9f2f4;
border-radius: 4px;
}
.footnote {
vertical-align: top;
position: relative;
top: -0.5em;
font-size: .8em;
}
hr {
margin:2em 0
}
img {
max-width:100%
}
pre {
word-break:break-word
}
p,pre,pre.prettyprint,blockquote {
margin:0 0 1.1em
}
hr {
margin:2em 0
}
img {
max-width:100%
}
.sequence-diagram,.flow-chart {
text-align:center;
margin-bottom:1.1em
}
.sequence-diagram text,.flow-chart text {
font-size:15px !important;
font-family:"Source Sans Pro",sans-serif !important
}
.sequence-diagram [fill="#ffffff"],.flow-chart [fill="#ffffff"] {
fill:#f6f6f6
}
.sequence-diagram [stroke="#000000"],.flow-chart [stroke="#000000"] {
stroke:#3f3f3f
}
.sequence-diagram text[stroke="#000000"],.flow-chart text[stroke="#000000"] {
stroke:none
}
.sequence-diagram [fill="#000"],.flow-chart [fill="#000"],.sequence-diagram [fill="#000000"],.flow-chart [fill="#000000"],.sequence-diagram [fill="black"],.flow-chart [fill="black"] {
fill:#3f3f3f
}
ul,ol {
margin-bottom:1.1em
}
ul ul,ol ul,ul ol,ol ol {
margin-bottom:1.1em
}
kbd {
padding:.1em .6em;
border:1px solid rgba(63,63,63,0.25);
-webkit-box-shadow:0 1px 0 rgba(63,63,63,0.25);
box-shadow:0 1px 0 rgba(63,63,63,0.25);
font-size:.7em;
font-family:sans-serif;
background-color:#fff;
color:#333;
border-radius:3px;
display:inline-block;
margin:0 .1em;
white-space:nowrap
}
.toc ul {
list-style-type:none;
margin-bottom:15px
}
</style>
<!-- 该css供自定义样式 -->
<link href="../leanote-html.css" rel="stylesheet">
</head>
<body>
<div class="note-container">
<h1 class="title" id="leanote-title">3</h1>
<div class="content-html" id="leanote-content"><h2>HAProxy Nbproc配置</h2><p>刚开始对HAProxy进行压力测试的时候我们发现增加了SSL之后CPU使用率一下子就飙升但此时的每秒请求数却很低。通过<a href="http://www.tecmint.com/12-top-command-examples-in-linux/" data-mce-href="http://www.tecmint.com/12-top-command-examples-in-linux/">top命令</a>排查之后发现HAProxy只使用了1个CPU内核而我们的机器上还有15个空闲的内核。</p><p>通过Google发现HAProxy有一个设置可以使其充分利用多核。这个配置称为<code>nbproc</code>,详情及其具体配置可以参照这篇文章:</p><p><a href="http://blog.onefellow.com/post/82478335338/haproxy-mapping-process-to-cpu-core-for-maximum">http://blog.onefellow.com/post/82478335338/haproxy-mapping-process-to-cpu-core-for-maximum</a></p><p>这项配置调优使得后面的压力测试能够继续因为让HAProxy能够充分利用多核才能继续后续压力测试集中的各种混合场景。</p><h2>使用AB进行压力测试</h2><p>从这里开始正式进入压力测试环节,以后将不再赘述我们的度量数据和期望达到的指标。</p><p>刚开始我们的唯一目标是通过分析前面描述的ab命令参数变化找到性能拐点。&nbsp;</p><p><img id="__LEANOTE_D_IMG_1505975248438" src="3_files/59c3ceadd01cce1c4d00002d.png" alt="" width="550" data-mce-src="/api/file/getImage?fileId=59c3ceadd01cce1c4d00002d"></p><p>上表是我们进行了多次压力测试之后的结果数据。为了获得这样的结果我们进行了超过500次测试从数据上可以明显看出每次测试结果都有多项数据有变动。</p><h2>单客户端问题</h2><p>随着压力的逐渐增加我们发现施压客户端成了瓶颈。从Apache bench文档来看它在发起请求时只使用单核并且没有设置可以利用多核提升其性能。</p><p>为了能够提升客户端性能我们使用了Linux平台上的一个工具叫做<a href="http://www.shakthimaan.com/posts/2014/11/27/gnu-parallel/news.html" data-mce-href="http://www.shakthimaan.com/posts/2014/11/27/gnu-parallel/news.html">Parallel</a>。如果其名称一样该工具能够并行命令以充分利用CPU核心。这也是我们所期望的。以下是使用Parallel运行多个ab客户端的示例命令</p><pre id="leanote_ace_1505975287236_0" class="brush:sh ace-tomorrow">cat hosts.txt | parallel 'ab -S -p post_smaller.txt -T
application/json -n 100000 -c 3000 {}'
sachinm@ip-192-168-0-124:~$ cat hosts.txt
http://test.haproxy.in:80/ping
http://test.haproxy.in:80/ping
http://test.haproxy.in:80/ping</pre><p>上述命令可以并行运行3个ab客户端同时访问相同的URL。这样能够帮我我们解决客户端性能瓶颈。</p><h2>服务端的Sleep和Times参数</h2><p>前面我们提到了一些通过Ganglia收集的数据这里先来讨论下如何模拟这些数据的产生。</p><ol><li>发送和接收数据包数量。该数据可以通过POST请求中发送一些数据来模拟。该方式也能帮助提升带宽和收发字节数两项Ganglia数据项。</li><li>TCP连接建立数。为了模拟该数据着实让我们花了好多时间。试想如果一个请求响应时间是1秒需要大约每秒700k个请求才能达到我们预订的场景。这个数据在生产环境中很容易达到但是在我们的测试场景中却几乎不可能产生。</li></ol><p>这时候读者可能会问那么你们是怎么实现的呢我们在POST请求参数中引入了sleep参数可以通过该参数让服务端休眠特定毫秒之后再返回响应数据。这样能够模拟生产环境中的耗时请求。所以我们设置了休眠20分钟这样每秒请求数达到583个左右的时候就能够维持700k个连接数的水位。</p><p>除此之外我们还在向HAProxy发起POST请求的时候引入了另一个参数times。该参数可以指定服务端在关闭TCP连接之前响应数据的重复次数。这样能够帮助我们模拟产生更多的数据量。</p><p><br data-mce-bogus="1"></p></div>
</div>
<!-- 该js供其它处理 -->
<script src="../leanote-html.js"></script>
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 287 KiB

View file

@ -0,0 +1,169 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="tool" content="leanote-desktop-app">
<title>4</title>
<style>
*{font-family:"lucida grande","lucida sans unicode",lucida,helvetica,"Hiragino Sans GB","Microsoft YaHei","WenQuanYi Micro Hei",sans-serif;}
body {
margin: 0;
}
/*公用文字样式*/
h1{font-size:30px}h2{font-size:24px}h3{font-size:18px}h4{font-size:14px}
.note-container{
width:850px;
margin:auto;
padding: 10px 20px;
box-shadow: 1px 1px 10px #eee;
}
#title {
margin: 0;
}
table {
margin-bottom: 16px;
border-collapse: collapse;
}
table th, table td {
padding: 6px 13px;
border: 1px solid #ddd;
}
table th {
font-weight: bold;
}
table tr {
background-color: none;
border-top: 1px solid #ccc;
}
table tr:nth-child(2n) {
background-color: rgb(247, 247, 249);
}
.mce-item-table, .mce-item-table td, .mce-item-table th, .mce-item-table caption {
border: 1px solid #ddd;
border-collapse: collapse;
padding: 6px 13px;
}
blockquote {
border-left-width:10px;
background-color:rgba(128,128,128,0.05);
border-top-right-radius:5px;
border-bottom-right-radius:5px;
padding:15px 20px;
border-left:5px solid rgba(128,128,128,0.075);
}
blockquote p {
margin-bottom:1.1em;
font-size:1em;
line-height:1.45
}
blockquote ul:last-child,blockquote ol:last-child {
margin-bottom:0
}
pre {
padding: 18px;
background-color: #f7f7f9;
border: 1px solid #e1e1e8;
border-radius: 3px;
display: block;
}
code {
padding: 2px 4px;
font-size: 90%;
color: #c7254e;
white-space: nowrap;
background-color: #f9f2f4;
border-radius: 4px;
}
.footnote {
vertical-align: top;
position: relative;
top: -0.5em;
font-size: .8em;
}
hr {
margin:2em 0
}
img {
max-width:100%
}
pre {
word-break:break-word
}
p,pre,pre.prettyprint,blockquote {
margin:0 0 1.1em
}
hr {
margin:2em 0
}
img {
max-width:100%
}
.sequence-diagram,.flow-chart {
text-align:center;
margin-bottom:1.1em
}
.sequence-diagram text,.flow-chart text {
font-size:15px !important;
font-family:"Source Sans Pro",sans-serif !important
}
.sequence-diagram [fill="#ffffff"],.flow-chart [fill="#ffffff"] {
fill:#f6f6f6
}
.sequence-diagram [stroke="#000000"],.flow-chart [stroke="#000000"] {
stroke:#3f3f3f
}
.sequence-diagram text[stroke="#000000"],.flow-chart text[stroke="#000000"] {
stroke:none
}
.sequence-diagram [fill="#000"],.flow-chart [fill="#000"],.sequence-diagram [fill="#000000"],.flow-chart [fill="#000000"],.sequence-diagram [fill="black"],.flow-chart [fill="black"] {
fill:#3f3f3f
}
ul,ol {
margin-bottom:1.1em
}
ul ul,ol ul,ul ol,ol ol {
margin-bottom:1.1em
}
kbd {
padding:.1em .6em;
border:1px solid rgba(63,63,63,0.25);
-webkit-box-shadow:0 1px 0 rgba(63,63,63,0.25);
box-shadow:0 1px 0 rgba(63,63,63,0.25);
font-size:.7em;
font-family:sans-serif;
background-color:#fff;
color:#333;
border-radius:3px;
display:inline-block;
margin:0 .1em;
white-space:nowrap
}
.toc ul {
list-style-type:none;
margin-bottom:15px
}
</style>
<!-- 该css供自定义样式 -->
<link href="../leanote-html.css" rel="stylesheet">
</head>
<body>
<div class="note-container">
<h1 class="title" id="leanote-title">4</h1>
<div class="content-html" id="leanote-content"><h2>Apache Bench遇到的问题</h2><p>虽然通过Apache Bench我们获取了很多结果数据但同时也遇到了很多问题。这里不会说明所有遇到的问题因为这不是本文的终点而且后面将会介绍新的压测客户端。</p><p>我们对从Apache Bench获取到了不错的结果数据但是每次获取一个点数据时TCP连接数这个要求总是难以达到。不知道为何Apache Bench无法正确处理前面提到的sleep参数同时也还是没法满足我们对容量的需求。</p><p>前面提到了我们在单台施压机上通过Parallel工具并行执行多个ab客户端但这种方式无法跨多台施压机。当时还没有发现<a href="https://github.com/grondo/pdsh" data-mce-href="https://github.com/grondo/pdsh">pdsh</a>这个工具,也算是一个遗憾。</p><p>同时之前的数据我们还缺少超时数据。在HAProxy上我们会有一些默认的超时设置但是ab客户端和后端服务完全忽略了这些配置。对此我们花了大量时间进行这方面的研究试图修正压力测试的方案。</p><p>前面提到过拐点图,但是随着各种问题的出现,目标有所偏移。但是,为了获取有意义的结论,必须重新聚焦于此。</p><p>通过Apache Bench我们获得了拐点但是TCP连接数一直没有上升。这些数据基于5到6台施压机上运行的大约40到45个ab客户端获得但是TCP连接数一直没能够达到期望的量级。理论上随着sleep参数值的上升TCP连接数应该会上升但是事实上却没有效果。</p><h2>引入Vegeta</h2><p>基于使用Apache Bench所遇到的问题我继续搜索其他功能更为强大、更易扩容的压力测试工具最终找到了<a href="https://github.com/tsenart/vegeta" data-mce-href="https://github.com/tsenart/vegeta">Vegeta</a></p><p>从我个人经验来看Vegeta相比于Apache Bench非常易扩容并且提供了更多的功能。在我们的压力测试场景中一个Vegeta客户端可以产生相当于15个Apache Bench客户端的吞吐量。</p><p>下面会介绍使用Vegeta获取到的压力测试结果。</p><h2>使用Vegeta进行压力测试</h2><p>首先来看下单个Vegeta客户端的使用命令。有趣的是其中用来向后端服务器施压的命令参数叫做<code>attack</code>&nbsp;:p</p><pre id="leanote_ace_1505975378362_0" class="brush:sh ace-tomorrow" data-mce-style="line-height: 1.5; font-size: 14px; height: 63px;">echo "POST https://test.haproxy.in:443/ping" | vegeta -cpus=
32 attack -duration=10m -header="sleep:30000" -body=
post_smaller.txt -rate=2000 -workers=500 | tee reports.bin | vegeta report</pre><p>这里我们简单了解下Vegeta提供的一些参数细节</p><ol><li><code>-cpus=32</code>定义客户端使用的内核数量。为了能够达到需要的压力值我们将施压机配置调整撑了32核64GB内存。仔细观察结果数据会发现实际压力并不大配置调整的主要目的是为了能够支撑大量状态为后端服务器休眠的连接。</li><li><code>-duration=10m</code>,该参数顾名思义,如果没有指定执行时间,测试将永久运行。</li><li><code>-rate=2000</code>,每秒钟请求数。</li></ol><p><img id="__LEANOTE_D_IMG_1505975405565" src="4_files/59c3ceadd01cce1c4d000030.png" alt="" width="550" data-mce-src="/api/file/getImage?fileId=59c3ceadd01cce1c4d000030"></p><p>从上图可以看出我们仅仅使用一台4核机器就达到了每秒32k个请求。这个结果比之前得出的拐点图有更高的性能这里针对非SSL请求的拐点在31.5k。</p><p>下面是更多压力测试的数据:</p><p><img id="__LEANOTE_D_IMG_1505975405566" src="4_files/59c3ceadd01cce1c4d000032.png" alt="" width="550" data-mce-src="/api/file/getImage?fileId=59c3ceadd01cce1c4d000032"></p><p>对于SSL连接来说每秒请求数16k也不算差了。由于更换了新的客户端整个压力测试过程都需要从头开始但是从整体来看结果都优于ab客户端的结果。&nbsp;<img id="__LEANOTE_D_IMG_1505975425862" src="4_files/59c3ceadd01cce1c4d00002f.png" alt="" width="550" data-mce-src="/api/file/getImage?fileId=59c3ceadd01cce1c4d00002f"></p><p>随着CPU内核数的增加在相同压力下响应延迟都有所降低直到压力达到CPU性能极限。</p><p>但是我们发现当CPU内核数从8增加到16的时候每秒请求数没有太多的增长。不过如果我们最终决定在生产环境使用8核机器也不可能将所有核心都分配给HAProxy而不被其他任何进程占用。因此我们决定使用6核心进行一些测试验证是否可以接受性能结果。&nbsp;</p><p><img id="__LEANOTE_D_IMG_1505975425863" src="4_files/59c3ceadd01cce1c4d000033.png" alt="" width="550" data-mce-src="/api/file/getImage?fileId=59c3ceadd01cce1c4d000033"></p><p>也不差吧。</p><h2>引入sleep参数</h2><p>目前为止我们对于压力测试的结果非常满意。然而现在场景没有模拟真实生产环境场景直到引入了sleep参数。</p><pre id="leanote_ace_1505975458341_0" class="brush:sh ace-tomorrow" data-mce-style="line-height: 1.5; font-size: 14px; height: 63px;">echo "POST https://test.haproxy.in:443/ping" | vegeta
-cpus=32 attack -duration=10m -header="sleep:1000"
-body=post_smaller.txt-rate=2000 -workers=500 | tee reports.bin | vegeta report</pre><p>上述命令设置了1000毫秒的休眠时间会让服务端应用随机休眠0到1000毫秒。因此上述命令的平均延迟是≥ 500ms。</p><p>&nbsp;<img id="__LEANOTE_D_IMG_1505975471693" src="4_files/59c3ceadd01cce1c4d000031.png" alt="" width="550" data-mce-src="/api/file/getImage?fileId=59c3ceadd01cce1c4d000031"></p><p>最后一个单元格中的数字分别表示:</p><pre>TCP连接建立数包发送数包接收数<br></pre></div>
</div>
<!-- 该js供其它处理 -->
<script src="../leanote-html.js"></script>
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 82 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 63 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

View file

@ -0,0 +1,165 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="tool" content="leanote-desktop-app">
<title>5</title>
<style>
*{font-family:"lucida grande","lucida sans unicode",lucida,helvetica,"Hiragino Sans GB","Microsoft YaHei","WenQuanYi Micro Hei",sans-serif;}
body {
margin: 0;
}
/*公用文字样式*/
h1{font-size:30px}h2{font-size:24px}h3{font-size:18px}h4{font-size:14px}
.note-container{
width:850px;
margin:auto;
padding: 10px 20px;
box-shadow: 1px 1px 10px #eee;
}
#title {
margin: 0;
}
table {
margin-bottom: 16px;
border-collapse: collapse;
}
table th, table td {
padding: 6px 13px;
border: 1px solid #ddd;
}
table th {
font-weight: bold;
}
table tr {
background-color: none;
border-top: 1px solid #ccc;
}
table tr:nth-child(2n) {
background-color: rgb(247, 247, 249);
}
.mce-item-table, .mce-item-table td, .mce-item-table th, .mce-item-table caption {
border: 1px solid #ddd;
border-collapse: collapse;
padding: 6px 13px;
}
blockquote {
border-left-width:10px;
background-color:rgba(128,128,128,0.05);
border-top-right-radius:5px;
border-bottom-right-radius:5px;
padding:15px 20px;
border-left:5px solid rgba(128,128,128,0.075);
}
blockquote p {
margin-bottom:1.1em;
font-size:1em;
line-height:1.45
}
blockquote ul:last-child,blockquote ol:last-child {
margin-bottom:0
}
pre {
padding: 18px;
background-color: #f7f7f9;
border: 1px solid #e1e1e8;
border-radius: 3px;
display: block;
}
code {
padding: 2px 4px;
font-size: 90%;
color: #c7254e;
white-space: nowrap;
background-color: #f9f2f4;
border-radius: 4px;
}
.footnote {
vertical-align: top;
position: relative;
top: -0.5em;
font-size: .8em;
}
hr {
margin:2em 0
}
img {
max-width:100%
}
pre {
word-break:break-word
}
p,pre,pre.prettyprint,blockquote {
margin:0 0 1.1em
}
hr {
margin:2em 0
}
img {
max-width:100%
}
.sequence-diagram,.flow-chart {
text-align:center;
margin-bottom:1.1em
}
.sequence-diagram text,.flow-chart text {
font-size:15px !important;
font-family:"Source Sans Pro",sans-serif !important
}
.sequence-diagram [fill="#ffffff"],.flow-chart [fill="#ffffff"] {
fill:#f6f6f6
}
.sequence-diagram [stroke="#000000"],.flow-chart [stroke="#000000"] {
stroke:#3f3f3f
}
.sequence-diagram text[stroke="#000000"],.flow-chart text[stroke="#000000"] {
stroke:none
}
.sequence-diagram [fill="#000"],.flow-chart [fill="#000"],.sequence-diagram [fill="#000000"],.flow-chart [fill="#000000"],.sequence-diagram [fill="black"],.flow-chart [fill="black"] {
fill:#3f3f3f
}
ul,ol {
margin-bottom:1.1em
}
ul ul,ol ul,ul ol,ol ol {
margin-bottom:1.1em
}
kbd {
padding:.1em .6em;
border:1px solid rgba(63,63,63,0.25);
-webkit-box-shadow:0 1px 0 rgba(63,63,63,0.25);
box-shadow:0 1px 0 rgba(63,63,63,0.25);
font-size:.7em;
font-family:sans-serif;
background-color:#fff;
color:#333;
border-radius:3px;
display:inline-block;
margin:0 .1em;
white-space:nowrap
}
.toc ul {
list-style-type:none;
margin-bottom:15px
}
</style>
<!-- 该css供自定义样式 -->
<link href="../leanote-html.css" rel="stylesheet">
</head>
<body>
<div class="note-container">
<h1 class="title" id="leanote-title">5</h1>
<div class="content-html" id="leanote-content"><p>从中我们可以清晰看出在6核心机器上最大每秒请求数从20k降低到了8k。显然增加了休眠时间之后由于大量的TCP连接数对结果产生了较大影响。不过此时总的连接数已经接近我们期望的700k的水位。</p><h2>里程碑 #1</h2><p>我们如何增加TCP连接数非常简单只需要通过sleep参数增加休眠时间。我们持续增加该参数最终停留在60秒既最终平均延迟在30秒左右。</p><p>Vegeta提供了一个有趣的参数请求成功率。我们发现在该休眠时间下只有50%的请求成功率。参见下面数据:</p><p>&nbsp;<img id="__LEANOTE_D_IMG_1505975516327" src="5_files/59c3ceadd01cce1c4d000035.png" alt="" width="550" data-mce-src="/api/file/getImage?fileId=59c3ceadd01cce1c4d000035"></p><p>通过设置60000毫秒休眠时间我们达到了高达400k TCP连接数同时每秒请求数8k的结果。图表中60000R中的R代表随机。</p><p>对此我们发现的第一个问题是Vegeta的默认请求超时时间是30秒因此会有50%的请求失败。因此我们将这个超时时间设置撑了70s以避免在后续测试到再次遇到。&nbsp;<img id="__LEANOTE_D_IMG_1505975516328" src="5_files/59c3ceadd01cce1c4d000036.png" alt="" width="550" data-mce-src="/api/file/getImage?fileId=59c3ceadd01cce1c4d000036"></p><p>修改了客户端超时时间之后我们很容易的达到了700k个连接。唯一的问题是连接数这个数据不稳定只是峰值数据能够达到。因此系统峰值连接数能够达到600k到700k但是并不能长时间维持。</p><p>我们希望能够达到这样的效果:</p><p><img id="__LEANOTE_D_IMG_1505975516329" src="5_files/59c3ceadd01cce1c4d000037.png" alt="" width="550" data-mce-src="/api/file/getImage?fileId=59c3ceadd01cce1c4d000037"></p><p>该图展示了连接数稳定维持在780k。上面表格数据中每秒钟请求数非常高但在实际生产环境中单台HAProxy机器上的请求数要少很多大约在300左右</p><p>但是我们如果大幅削减生产环境中的HAProxy机器目前大约在30台这意味着集群每秒请求数为30*300大约9k首先遇到的瓶颈会是TCP连接数而不是CPU。</p><blockquote><p>因此我们决定尝试验证每秒请求数900、网络带宽30MB/s和2.1M TCP连接数的场景下验证。我们使用该场景是因为这是生产环境单台HAProxy机器压力的3倍。</p></blockquote><p>另外目前仅仅给HAProxy分配了6个内核。我们希望测试分配3个内核时的性能因为这是我们模拟生产环境机器配置的最简单方式前面提到过我们的生产环境机器配置是4核30GB内存。因此设置<code>nbproc = 3</code>是最方便的方式。</p><pre>记住现在我们使用的机器是16核30GB内存其中3个内核分配给HAProxy。</pre></div>
</div>
<!-- 该js供其它处理 -->
<script src="../leanote-html.js"></script>
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 188 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 81 KiB

View file

@ -0,0 +1,235 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="tool" content="leanote-desktop-app">
<title>6</title>
<style>
*{font-family:"lucida grande","lucida sans unicode",lucida,helvetica,"Hiragino Sans GB","Microsoft YaHei","WenQuanYi Micro Hei",sans-serif;}
body {
margin: 0;
}
/*公用文字样式*/
h1{font-size:30px}h2{font-size:24px}h3{font-size:18px}h4{font-size:14px}
.note-container{
width:850px;
margin:auto;
padding: 10px 20px;
box-shadow: 1px 1px 10px #eee;
}
#title {
margin: 0;
}
table {
margin-bottom: 16px;
border-collapse: collapse;
}
table th, table td {
padding: 6px 13px;
border: 1px solid #ddd;
}
table th {
font-weight: bold;
}
table tr {
background-color: none;
border-top: 1px solid #ccc;
}
table tr:nth-child(2n) {
background-color: rgb(247, 247, 249);
}
.mce-item-table, .mce-item-table td, .mce-item-table th, .mce-item-table caption {
border: 1px solid #ddd;
border-collapse: collapse;
padding: 6px 13px;
}
blockquote {
border-left-width:10px;
background-color:rgba(128,128,128,0.05);
border-top-right-radius:5px;
border-bottom-right-radius:5px;
padding:15px 20px;
border-left:5px solid rgba(128,128,128,0.075);
}
blockquote p {
margin-bottom:1.1em;
font-size:1em;
line-height:1.45
}
blockquote ul:last-child,blockquote ol:last-child {
margin-bottom:0
}
pre {
padding: 18px;
background-color: #f7f7f9;
border: 1px solid #e1e1e8;
border-radius: 3px;
display: block;
}
code {
padding: 2px 4px;
font-size: 90%;
color: #c7254e;
white-space: nowrap;
background-color: #f9f2f4;
border-radius: 4px;
}
.footnote {
vertical-align: top;
position: relative;
top: -0.5em;
font-size: .8em;
}
hr {
margin:2em 0
}
img {
max-width:100%
}
pre {
word-break:break-word
}
p,pre,pre.prettyprint,blockquote {
margin:0 0 1.1em
}
hr {
margin:2em 0
}
img {
max-width:100%
}
.sequence-diagram,.flow-chart {
text-align:center;
margin-bottom:1.1em
}
.sequence-diagram text,.flow-chart text {
font-size:15px !important;
font-family:"Source Sans Pro",sans-serif !important
}
.sequence-diagram [fill="#ffffff"],.flow-chart [fill="#ffffff"] {
fill:#f6f6f6
}
.sequence-diagram [stroke="#000000"],.flow-chart [stroke="#000000"] {
stroke:#3f3f3f
}
.sequence-diagram text[stroke="#000000"],.flow-chart text[stroke="#000000"] {
stroke:none
}
.sequence-diagram [fill="#000"],.flow-chart [fill="#000"],.sequence-diagram [fill="#000000"],.flow-chart [fill="#000000"],.sequence-diagram [fill="black"],.flow-chart [fill="black"] {
fill:#3f3f3f
}
ul,ol {
margin-bottom:1.1em
}
ul ul,ol ul,ul ol,ol ol {
margin-bottom:1.1em
}
kbd {
padding:.1em .6em;
border:1px solid rgba(63,63,63,0.25);
-webkit-box-shadow:0 1px 0 rgba(63,63,63,0.25);
box-shadow:0 1px 0 rgba(63,63,63,0.25);
font-size:.7em;
font-family:sans-serif;
background-color:#fff;
color:#333;
border-radius:3px;
display:inline-block;
margin:0 .1em;
white-space:nowrap
}
.toc ul {
list-style-type:none;
margin-bottom:15px
}
</style>
<!-- 该css供自定义样式 -->
<link href="../leanote-html.css" rel="stylesheet">
</head>
<body>
<div class="note-container">
<h1 class="title" id="leanote-title">6</h1>
<div class="content-html" id="leanote-content"><h2>里程碑 #2</h2><p>我们获得了不同机器配置下的每秒请求数上限现在我们仅剩下前面提到的一个任务达到生产环境的3倍负载</p><ul><li>每秒请求数900</li><li>TCP连接数2.1m</li><li>网络带宽30MB/s</li></ul><p>我们再次在达到220k个TCP连接数上受阻。无论怎么设置休眠时间TCP连接数就是无法再上升。</p><p>让我们来计算下220k个TCP连接和每秒请求数900110,000 / 900 ~= 120秒。这里使用110k因为220k个连接同时包含了输入和输出既双向总数。</p><p>这让我们怀疑2分钟是系统某处的一个限制通过查看HAProxy日志可以验证日志中大部分连接的总耗时都在120000毫秒。</p><pre>Mar 23 13:24:24 localhost haproxy[53750]: 172.168.0.232:48380
[23/Mar/2017:13:22:22.686] api~ api-backend/http31 39/0/2062/-1/122101
-1 0 - - SD-- 1714/1714/1678/35/0 0/0 {0,"",""}
"POST /ping HTTP/1.1"</pre><p>其中122101是总处理时长。日志中所有字段详细值参见HAProxy文档。</p><p>经过进一步研究我们发现Node.js有2分钟的默认超时时间。</p><p>具体信息参见下面一些资料:</p><ul><li><a href="http://stackoverflow.com/questions/23925284/how-to-modify-the-nodejs-request-default-timeout-time" data-mce-href="http://stackoverflow.com/questions/23925284/how-to-modify-the-nodejs-request-default-timeout-time">如何修改Node.js请求默认超时时间</a></li><li><a href="https://nodejs.org/api/http.html#http_server_settimeout_msecs_callback" data-mce-href="https://nodejs.org/api/http.html#http_server_settimeout_msecs_callback">Node.js Http server文档</a></li></ul><p>解决了超时时间之后事情并没有想象中的顺利。当连接数达到1.3m个时HAProxy连接数突然下降到0,然后再次开始上升。通过<a href="http://www.linfo.org/dmesg.html" data-mce-href="http://www.linfo.org/dmesg.html">dmesg</a>命令查看内核日志之后发现该现象是系统内存不足造成的。通过更换成16核64GB内存并设置<code>nbproc = 3</code>之后最终达到了2.4m个连接。</p><h2>后端代码</h2><p>下面是HAProxy后端服务的源码。我们在代码中使用了statsd库以获取服务端每秒请求数。</p><pre class=" language-nolanguage">var http = require('http');
var createStatsd = require('uber-statsd-client');
qs = require('querystring');
var sdc = createStatsd({
host: '172.168.0.134',
port: 8125
});
var argv = process.argv;
var port = argv[2];
function randomIntInc (low, high)
{
return Math.floor(Math.random() * (high - low + 1) + low);
}
function sendResponse(res,times, old_sleep)
{
res.write('pong');
if(times==0)
{
res.end();
}
else
{
sleep = randomIntInc(0, old_sleep+1);
setTimeout(sendResponse, sleep, res,times-1, old_sleep);
}
}
var server = http.createServer(function(req, res)
{
headers = req.headers;
old_sleep = parseInt(headers["sleep"]);
times = headers["times"] || 0;
sleep = randomIntInc(0, old_sleep+1);
console.log(sleep);
sdc.increment("ssl.server.http");
res.writeHead(200);
setTimeout(sendResponse, sleep, res, times, old_sleep)
});
server.timeout = 3600000;
server.listen(port);</pre><p>同时我们还有一个小脚本来运行多个后端服务。整个测试中我们使用了8台服务器每台服务器上运行了10个后端服务进程以避免后端服务称为压力测试的瓶颈。</p><pre>counter=0
while [ $counter -le 9 ]
do
port=$((8282+$counter))
nodejs /opt/local/share/test-tools/HikeCLI/nodeclient/httpserver.js $port &amp;
echo "Server created on port " $port
((counter++))
done
echo "Created all servers"</pre><h2>客户端代码</h2><p>对于客户端每个IP有63k个TCP连接的限制。如果对此不了解参见本系列的<a href="https://medium.freecodecamp.com/load-testing-haproxy-part-2-4c8677780df6" data-mce-href="https://medium.freecodecamp.com/load-testing-haproxy-part-2-4c8677780df6">前面一篇文章</a></p><p>因此为了达到2.4m个连接双向连接对于客户端来说要发起1.2m个连接我们需要大约20台机器。在所有20台机器上同时运行Vegeta命令非常痛苦即使使用了类似<a href="https://github.com/brockgr/csshx" data-mce-href="https://github.com/brockgr/csshx">csshx工具</a>仍然需要从所有Vegeta合并最终测试结果。</p><p>脚本如下:</p><pre class="brush:sh">result_file=$1
declare -a machines=("172.168.0.138" "172.168.0.141
" "172.168.0.142" "172.168.0.18" "
172.168.0.5" "172.168.0.122" "172.168.0.123" "
172.168.0.124" "172.168.0.232" " 172.168.0.24
4" "172.168.0.170" "172.168.0.179" "
172.168.0.59" "172.168.0.68" "172.168.0.137" "
;172.168.0.155" "172.168.0.154" "172.168.0.45" "
172.168.0.136" "172.168.0.143")
bins=""
commas=""
for i in "${machines[@]}"; do bins=$bins","$i".
bin"; commas=$commas","$i; done;
bins=${bins:1}
commas=${commas:1}
pdsh -b -w "$commas" 'echo "POST
http://test.haproxy.in:80/ping" | /home/sachinm/.linuxbrew/bin/vegeta -cpus=32
attack -connections=1000000 -header="sleep:20" -header="
times:2" -body=post_smaller.txt -timeout=2h -rate=3000 -workers=
500 &gt; ' $result_file for i in "${machines[@]}"; do scp sachinm
@$i:/home/sachinm/$result_file $i.bin ; done;
vegeta report -inputs="$bins"</pre><p>幸好这里使用了<a href="https://github.com/grondo/pdsh" data-mce-href="https://github.com/grondo/pdsh">pdsh工具</a>使得我们能够在多台远程服务器上并行的执行命令。同时Vegeta也提供了结果合并功能这也是我们急需的。</p><h2>HAProxy配置</h2><p>本节大概是读者最希望了解的内容下面是我们在压力测试场景中使用的HAProxy配置。其中最重要的部分是<code>nbproc</code><code>maxconn</code>设置。其中<code>maxconn</code>设置允许HAProxy能够支持我们期望达到的TCP连接数。</p><p><code>maxconn</code>&nbsp;设置会影响HAProxy进程的ulimit例如</p><p>&nbsp;<img id="__LEANOTE_D_IMG_1505976168009" src="6_files/59c3d21bd01cce1c4d00003c.png" alt="" width="550" data-mce-src="/api/file/getImage?fileId=59c3d21bd01cce1c4d00003c"></p><p>最大文件打开数设置到4m因为HAProxy的最大连接数设置成了2m。干净利落</p><p><br></p></div>
</div>
<!-- 该js供其它处理 -->
<script src="../leanote-html.js"></script>
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 111 KiB

View file

@ -0,0 +1,165 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="tool" content="leanote-desktop-app">
<title>7</title>
<style>
*{font-family:"lucida grande","lucida sans unicode",lucida,helvetica,"Hiragino Sans GB","Microsoft YaHei","WenQuanYi Micro Hei",sans-serif;}
body {
margin: 0;
}
/*公用文字样式*/
h1{font-size:30px}h2{font-size:24px}h3{font-size:18px}h4{font-size:14px}
.note-container{
width:850px;
margin:auto;
padding: 10px 20px;
box-shadow: 1px 1px 10px #eee;
}
#title {
margin: 0;
}
table {
margin-bottom: 16px;
border-collapse: collapse;
}
table th, table td {
padding: 6px 13px;
border: 1px solid #ddd;
}
table th {
font-weight: bold;
}
table tr {
background-color: none;
border-top: 1px solid #ccc;
}
table tr:nth-child(2n) {
background-color: rgb(247, 247, 249);
}
.mce-item-table, .mce-item-table td, .mce-item-table th, .mce-item-table caption {
border: 1px solid #ddd;
border-collapse: collapse;
padding: 6px 13px;
}
blockquote {
border-left-width:10px;
background-color:rgba(128,128,128,0.05);
border-top-right-radius:5px;
border-bottom-right-radius:5px;
padding:15px 20px;
border-left:5px solid rgba(128,128,128,0.075);
}
blockquote p {
margin-bottom:1.1em;
font-size:1em;
line-height:1.45
}
blockquote ul:last-child,blockquote ol:last-child {
margin-bottom:0
}
pre {
padding: 18px;
background-color: #f7f7f9;
border: 1px solid #e1e1e8;
border-radius: 3px;
display: block;
}
code {
padding: 2px 4px;
font-size: 90%;
color: #c7254e;
white-space: nowrap;
background-color: #f9f2f4;
border-radius: 4px;
}
.footnote {
vertical-align: top;
position: relative;
top: -0.5em;
font-size: .8em;
}
hr {
margin:2em 0
}
img {
max-width:100%
}
pre {
word-break:break-word
}
p,pre,pre.prettyprint,blockquote {
margin:0 0 1.1em
}
hr {
margin:2em 0
}
img {
max-width:100%
}
.sequence-diagram,.flow-chart {
text-align:center;
margin-bottom:1.1em
}
.sequence-diagram text,.flow-chart text {
font-size:15px !important;
font-family:"Source Sans Pro",sans-serif !important
}
.sequence-diagram [fill="#ffffff"],.flow-chart [fill="#ffffff"] {
fill:#f6f6f6
}
.sequence-diagram [stroke="#000000"],.flow-chart [stroke="#000000"] {
stroke:#3f3f3f
}
.sequence-diagram text[stroke="#000000"],.flow-chart text[stroke="#000000"] {
stroke:none
}
.sequence-diagram [fill="#000"],.flow-chart [fill="#000"],.sequence-diagram [fill="#000000"],.flow-chart [fill="#000000"],.sequence-diagram [fill="black"],.flow-chart [fill="black"] {
fill:#3f3f3f
}
ul,ol {
margin-bottom:1.1em
}
ul ul,ol ul,ul ol,ol ol {
margin-bottom:1.1em
}
kbd {
padding:.1em .6em;
border:1px solid rgba(63,63,63,0.25);
-webkit-box-shadow:0 1px 0 rgba(63,63,63,0.25);
box-shadow:0 1px 0 rgba(63,63,63,0.25);
font-size:.7em;
font-family:sans-serif;
background-color:#fff;
color:#333;
border-radius:3px;
display:inline-block;
margin:0 .1em;
white-space:nowrap
}
.toc ul {
list-style-type:none;
margin-bottom:15px
}
</style>
<!-- 该css供自定义样式 -->
<link href="../leanote-html.css" rel="stylesheet">
</head>
<body>
<div class="note-container">
<h1 class="title" id="leanote-title">7</h1>
<div class="content-html" id="leanote-content"><p>下文介绍了一些HAProxy优化方式以达到我们期望的指标</p><p><a href="https://www.linangran.com/?p=547">https://www.linangran.com/?p=547</a><a href="https://www.linangran.com/?p=547" data-mce-href="https://www.linangran.com/?p=547"></a></p><p>&nbsp;<img id="__LEANOTE_D_IMG_1505976395521" src="7_files/59c3d21bd01cce1c4d00003a.png" alt="" width="550" data-mce-src="/api/file/getImage?fileId=59c3d21bd01cce1c4d00003a"></p><p><img id="__LEANOTE_D_IMG_1505976395522" src="7_files/59c3d21bd01cce1c4d000039.png" alt="" width="550" data-mce-src="/api/file/getImage?fileId=59c3d21bd01cce1c4d000039"></p><p>这里从http30一直到http83 :p</p><p>以上就是本文所有内容,如果您能阅读到这里,我真心佩服 :)</p></div>
</div>
<!-- 该js供其它处理 -->
<script src="../leanote-html.js"></script>
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 279 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 106 KiB