-
Notifications
You must be signed in to change notification settings - Fork 1
/
atom.xml
1668 lines (1473 loc) · 652 KB
/
atom.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title>roc wong</title>
<subtitle>九万里风鹏正举</subtitle>
<link href="/atom.xml" rel="self"/>
<link href="https://roc-wong.github.io/"/>
<updated>2018-11-22T01:44:57.541Z</updated>
<id>https://roc-wong.github.io/</id>
<author>
<name>roc.wong</name>
</author>
<generator uri="http://hexo.io/">Hexo</generator>
<entry>
<title>RocketMQ at a glance</title>
<link href="https://roc-wong.github.io/blog/2018/11/RocketMQ-at-a-glance.html"/>
<id>https://roc-wong.github.io/blog/2018/11/RocketMQ-at-a-glance.html</id>
<published>2018-11-22T01:40:09.000Z</published>
<updated>2018-11-22T01:44:57.541Z</updated>
<content type="html"><![CDATA[<h2 id="1-安装"><a href="#1-安装" class="headerlink" title="1. 安装"></a>1. 安装</h2><h3 id="1-1-Prerequisite"><a href="#1-1-Prerequisite" class="headerlink" title="1.1 Prerequisite"></a>1.1 Prerequisite</h3><p>64位操作系统,建议使用Linux / Unix /</p>
<ul>
<li>CentOs 7.3 +</li>
<li>64bit JDK 1.8 +</li>
<li>Maven 3.2.x +</li>
</ul>
<h3 id="1-2-Download-amp-Build-from-Release"><a href="#1-2-Download-amp-Build-from-Release" class="headerlink" title="1.2 Download & Build from Release"></a>1.2 Download & Build from Release</h3><p>Click <a href="https://www.apache.org/dyn/closer.cgi?path=rocketmq/4.3.0/rocketmq-all-4.3.0-source-release.zip" target="_blank" rel="external">here</a> to download the 4.3.0 source release. Also you could download a binary release from <a href="http://rocketmq.apache.org/release_notes/release-notes-4.3.0/" target="_blank" rel="external">here</a>.</p>
<p>Build from source release:<br><figure class="highlight vim"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line">> unzip rocketmq-<span class="keyword">all</span>-<span class="number">4.3</span>.<span class="number">0</span>-<span class="keyword">source</span>-release.zip</div><div class="line">> <span class="keyword">cd</span> rocketmq-<span class="keyword">all</span>-<span class="number">4.3</span>.<span class="number">0</span>/</div><div class="line">> mvn -Prelease-<span class="keyword">all</span> -DskipTests clean install -U</div><div class="line">> <span class="keyword">cd</span> distribution/target/apache-rocketmq</div></pre></td></tr></table></figure></p>
<h3 id="1-3-Start-Name-Server"><a href="#1-3-Start-Name-Server" class="headerlink" title="1.3 Start Name Server"></a>1.3 Start Name Server</h3><p>Name Server 默认配置Xmx=4G,调整以适合部署:</p>
<figure class="highlight nginx"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line"><span class="attribute">vi</span> /bin/runserver.sh</div><div class="line"></div><div class="line">JAVA_OPT=<span class="string">"<span class="variable">${JAVA_OPT}</span> -server -Xms4g -Xmx4g -Xmn2g -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=320m"</span></div></pre></td></tr></table></figure>
<p>调整为<br><figure class="highlight ini"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line"><span class="attr">JAVA_OPT</span>=<span class="string">"${JAVA_OPT} -server -Xms1g -Xmx1g -Xmn512m -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=320m"</span></div></pre></td></tr></table></figure></p>
<p><strong>启动Name Server</strong><br><figure class="highlight dts"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line">nohup sh bin/mqnamesrv > <span class="meta-keyword">/dev/</span>null <span class="number">2</span>><span class="variable">&1</span> &</div><div class="line"></div><div class="line">tail -f ~<span class="meta-keyword">/logs/</span>rocketmqlogs/namesrv.log</div></pre></td></tr></table></figure></p>
<h3 id="1-4-Start-Broker"><a href="#1-4-Start-Broker" class="headerlink" title="1.4 Start Broker"></a>1.4 Start Broker</h3><p>调整java opt:</p>
<figure class="highlight nginx"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line"><span class="attribute">vi</span> /bin/runbroker.sh</div><div class="line"></div><div class="line">JAVA_OPT=<span class="string">"<span class="variable">${JAVA_OPT}</span> -server -Xms8g -Xmx8g -Xmn4g"</span></div></pre></td></tr></table></figure>
<p>调整为:<br><figure class="highlight ini"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line"><span class="attr">JAVA_OPT</span>=<span class="string">"${JAVA_OPT} -server -Xms2g -Xmx2g -Xmn1g"</span></div></pre></td></tr></table></figure></p>
<p>启动Broker</p>
<figure class="highlight dts"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line">nohup sh bin/mqbroker -n localhost:<span class="number">9876</span> > <span class="meta-keyword">/dev/</span>null <span class="number">2</span>><span class="variable">&1</span> &</div><div class="line"></div><div class="line">tail -f ~<span class="meta-keyword">/logs/</span>rocketmqlogs/broker.log</div></pre></td></tr></table></figure>
<p>或指定配置文件启动</p>
<figure class="highlight stata"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">nohup <span class="keyword">sh</span> mqbroker -c <span class="variable">$ROCKETMQ_HOME</span>/<span class="keyword">conf</span>/broker.<span class="keyword">conf</span> > /dev/null 2>&1 &</div></pre></td></tr></table></figure>
<h3 id="1-5-查看进程"><a href="#1-5-查看进程" class="headerlink" title="1.5 查看进程"></a>1.5 查看进程</h3><figure class="highlight autoit"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line">[root<span class="symbol">@node1</span> apache-rocketmq]<span class="meta"># jps</span></div><div class="line"><span class="number">2374</span> BrokerStartup</div><div class="line"><span class="number">2350</span> NamesrvStartup</div></pre></td></tr></table></figure>
<figure class="highlight tap"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div></pre></td><td class="code"><pre><div class="line">[root@node1 apache-rocketmq]<span class="comment"># netstat -ntlp</span></div><div class="line">Active Internet connections (only servers)</div><div class="line">Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name </div><div class="line">tcp <span class="number"> 0 </span> <span class="number"> 0 </span>127.0.0.1:25 0.0.0.0:* LISTEN 1508/master </div><div class="line">tcp6 <span class="number"> 0 </span> <span class="number"> 0 </span>:::9876 :::* LISTEN 2350/java </div><div class="line">tcp6 <span class="number"> 0 </span> <span class="number"> 0 </span>::1:25 :::* LISTEN 1508/master </div><div class="line">tcp6 <span class="number"> 0 </span> <span class="number"> 0 </span>:::10909 :::* LISTEN 2374/java </div><div class="line">tcp6 <span class="number"> 0 </span> <span class="number"> 0 </span>:::10911 :::* LISTEN 2374/java </div><div class="line">tcp6 <span class="number"> 0 </span> <span class="number"> 0 </span>:::10912 :::* LISTEN 2374/java</div></pre></td></tr></table></figure>
<h3 id="1-6-Send-amp-Receive-Messages"><a href="#1-6-Send-amp-Receive-Messages" class="headerlink" title="1.6 Send & Receive Messages"></a>1.6 Send & Receive Messages</h3><p>RocketMQ提供命令行工具便于快速测试:</p>
<p>Before sending/receiving messages, we need to tell clients the location of name servers. RocketMQ provides multiple ways to achieve this. For simplicity, we use environment variable NAMESRV_ADDR</p>
<figure class="highlight mipsasm"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div></pre></td><td class="code"><pre><div class="line">> export NAMESRV_ADDR=localhost:<span class="number">9876</span></div><div class="line">> <span class="keyword">sh </span><span class="keyword">bin/tools.sh </span><span class="keyword">org.apache.rocketmq.example.quickstart.Producer</span></div><div class="line"> SendResult [sendStatus=SEND_OK, msgId= ...</div><div class="line"></div><div class="line">> <span class="keyword">sh </span><span class="keyword">bin/tools.sh </span><span class="keyword">org.apache.rocketmq.example.quickstart.Consumer</span></div><div class="line"> ConsumeMessageThread_%d Receive New Messages: [MessageExt...</div></pre></td></tr></table></figure>
<h3 id="1-7-Shutdown-Servers"><a href="#1-7-Shutdown-Servers" class="headerlink" title="1.7 Shutdown Servers"></a>1.7 Shutdown Servers</h3><figure class="highlight mipsasm"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div></pre></td><td class="code"><pre><div class="line">> <span class="keyword">sh </span><span class="keyword">bin/mqshutdown </span><span class="keyword">broker</span></div><div class="line">The mqbroker(<span class="number">2374</span>) is running...</div><div class="line">Send <span class="keyword">shutdown </span>request to mqbroker(<span class="number">2374</span>) OK</div><div class="line"></div><div class="line">> <span class="keyword">sh </span><span class="keyword">bin/mqshutdown </span>namesrv</div><div class="line">The mqnamesrv(<span class="number">2350</span>) is running...</div><div class="line">Send <span class="keyword">shutdown </span>request to mqnamesrv(<span class="number">2350</span>) OK</div></pre></td></tr></table></figure>
<h2 id="2-部署方案"><a href="#2-部署方案" class="headerlink" title="2. 部署方案"></a>2. 部署方案</h2><p>RocketMQ集群由NameServer和Broker两种角色组成,NameServer是无状态的可以横向部署多台达到消除单点的目的;Broker分多master、多master多slave同步、多master多slave异步这三种部署方案,一般生产环境都使用的是多master多slave异步这种方案,关于这三种方案的优缺点对比如下:</p>
<h3 id="2-1-多Master模式(2m-noslave)"><a href="#2-1-多Master模式(2m-noslave)" class="headerlink" title="2.1 多Master模式(2m-noslave)"></a>2.1 多Master模式(2m-noslave)</h3><p>一个集群无Slave,全是Master,例如2个Master或者3个Master</p>
<p>优点:配置简单,单个Master宕机或重启维护对应用无影响,在磁盘配置为RAID10时,即使机器宕机不可恢复情况下,由于RAID10磁盘非常可靠,消息也不会丢(异步刷盘丢失少量消息,同步刷盘一条不丢)。性能最高。</p>
<p>缺点:单台机器宕机期间,这台机器上未被消费的消息在机器恢复之前不可订阅,消息实时性会受到受到影响。</p>
<h3 id="2-2-多Master多Slave模式,异步复制(2m-2s-async)"><a href="#2-2-多Master多Slave模式,异步复制(2m-2s-async)" class="headerlink" title="2.2 多Master多Slave模式,异步复制(2m-2s-async)"></a>2.2 多Master多Slave模式,异步复制(2m-2s-async)</h3><p>每个Master配置一个Slave,有多对Master-Slave,HA采用异步复制方式,主备有短暂消息延迟,毫秒级。</p>
<p>优点:即使磁盘损坏,消息丢失的非常少,且消息实时性不会受影响,因为Master宕机后,消费者仍然可以从Slave消费,此过程对应用透明。不需要人工干预。性能同多Master模式几乎一样。</p>
<p>缺点:Master宕机,磁盘损坏情况,会丢失少量消息。</p>
<h3 id="2-3-多Master多Slave模式,同步双写(2m-2s-sync)"><a href="#2-3-多Master多Slave模式,同步双写(2m-2s-sync)" class="headerlink" title="2.3 多Master多Slave模式,同步双写(2m-2s-sync)"></a>2.3 多Master多Slave模式,同步双写(2m-2s-sync)</h3><p>每个Master配置一个Slave,有多对Master-Slave,HA采用同步双写方式,主备都写成功,向应用返回成功。</p>
<p>优点:数据与服务都无单点,Master宕机情况下,消息无延迟,服务可用性与数据可用性都非常高</p>
<p>缺点:性能比异步复制模式略低,大约低10%左右,发送单个消息的RT会略高。目前主宕机后,备机不能自动切换为主机,后续会支持自动切换功能。</p>
<table>
<thead>
<tr>
<th style="text-align:center">部署方式</th>
<th style="text-align:center">优点</th>
<th style="text-align:center">缺点</th>
<th style="text-align:center">备注</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:center">单个Master模式</td>
<td style="text-align:center">一旦Broker重启或者宕机时,会导致整个服务不可用,不建议线上环境使用;</td>
<td style="text-align:center"></td>
<td style="text-align:center"></td>
</tr>
<tr>
<td style="text-align:center">多个Master模式</td>
<td style="text-align:center">配置简单,单个Master宕机或重启维护对应用无影响,在磁盘配置为RAID10时,即使机器宕机不可恢复情况下,由于RAID10磁盘非常可靠,消息也不会丢(异步刷盘丢失少量消息,同步刷盘一条不丢),性能最高。</td>
<td style="text-align:center">单台机器宕机期间,这台机器上未被消费的消息在机器恢复之前不可订阅,消息实时性会收到影响。</td>
<td style="text-align:center">当使用多master无slave的集群搭建方式时,master的brokerRole配置必须为ASYNC_MASTER。如果配置为SYNC_MASTER,则producer发送消息时,返回值的SendStatus会一直是SLAVE_NOT_AVAILABLE。</td>
</tr>
<tr>
<td style="text-align:center">多Master多Slave模式——异步复制</td>
<td style="text-align:center">即使磁盘损坏,消息丢失的非常少,但消息实时性不会受影响,因为Master宕机后,消费者仍然可以从Slave消费,此过程对应用透明,不需要人工干预,性能同多Master模式几乎一样。</td>
<td style="text-align:center">Master宕机,磁盘损坏情况,会丢失少量信息。</td>
<td style="text-align:center"></td>
</tr>
<tr>
<td style="text-align:center">多Master多Slave模式——同步双写</td>
<td style="text-align:center">数据与服务都无单点,Master宕机情况下,消息无延迟,服务可用性与数据可用性都非常高;</td>
<td style="text-align:center">性能比异步复制模式稍低,大约低10%左右,发送单个消息的RT会稍高,目前主宕机后,备机不能自动切换为主机,后续会支持自动切换功能。</td>
</tr>
</tbody>
</table>
<h2 id="3-常用命令"><a href="#3-常用命令" class="headerlink" title="3. 常用命令"></a>3. 常用命令</h2><h3 id="3-1-shmqadmin"><a href="#3-1-shmqadmin" class="headerlink" title="3.1 shmqadmin"></a>3.1 shmqadmin</h3><p>RocketMQ提供有控制台及一系列控制台命令,用于管理员对主题,集群,broker等信息的管理;</p>
<p>首先进入RocketMQ工程,进入/RocketMQ/bin,在该目录下有个mqadmin脚本。</p>
<p>查看帮助,在mqadmin下可以查看有哪些命令:<br><figure class="highlight ebnf"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line"><span class="attribute">shmqadmin</span></div></pre></td></tr></table></figure></p>
<p>查看具体命令的使用:<br><figure class="highlight stata"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">sh</span> mqadmin <span class="keyword">help</span> 命令名称</div></pre></td></tr></table></figure></p>
<figure class="highlight clean"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">## 例如,查看updateTopic的使用</div><div class="line">sh mqadmin helpupdateTopic</div></pre></td></tr></table></figure>
<h3 id="3-2-创建Topic"><a href="#3-2-创建Topic" class="headerlink" title="3.2 创建Topic"></a>3.2 创建Topic</h3><p>详见:<a href="https://blog.csdn.net/zhu_tianwei/article/details/40951301" target="_blank" rel="external">https://blog.csdn.net/zhu_tianwei/article/details/40951301</a></p>
<h2 id="4-RocketMQ-Console"><a href="#4-RocketMQ-Console" class="headerlink" title="4. RocketMQ Console"></a>4. RocketMQ Console</h2><h3 id="4-1-Prerequisite"><a href="#4-1-Prerequisite" class="headerlink" title="4.1 Prerequisite"></a>4.1 Prerequisite</h3><p>Console下载地址:<a href="https://github.com/apache/rocketmq-externals/tree/master/rocketmq-console" target="_blank" rel="external">https://github.com/apache/rocketmq-externals/tree/master/rocketmq-console</a></p>
<ul>
<li>require java 1.7</li>
<li>maven 3.2 + </li>
</ul>
<h3 id="4-2-Build-and-Run"><a href="#4-2-Build-and-Run" class="headerlink" title="4.2 Build and Run"></a>4.2 Build and Run</h3><p>修改rocketmq-console/src/main/resources/application.properties:</p>
<figure class="highlight stylus"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line">server.port=<span class="number">8999</span></div><div class="line"></div><div class="line">rocketmq<span class="selector-class">.config</span><span class="selector-class">.namesrvAddr</span>=<span class="number">10.29</span>.<span class="number">181.16</span>:<span class="number">9876</span></div></pre></td></tr></table></figure>
<p>进入rocketmq-console目录,执行:</p>
<figure class="highlight stylus"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div></pre></td><td class="code"><pre><div class="line">mvn spring-boot:run</div><div class="line"></div><div class="line">or</div><div class="line"></div><div class="line">mvn clean package -Dmaven<span class="selector-class">.test</span><span class="selector-class">.skip</span>=true</div><div class="line">java -jar target/rocketmq-console-ng-<span class="number">1.0</span>.<span class="number">0</span><span class="selector-class">.jar</span></div><div class="line">Tips</div></pre></td></tr></table></figure>
<blockquote>
<p>if you download package slow,you can change maven’s mirror(maven’s settings.xml)<br><figure class="highlight xml"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div></pre></td><td class="code"><pre><div class="line"><span class="tag"><<span class="name">mirrors</span>></span></div><div class="line"> <span class="tag"><<span class="name">mirror</span>></span></div><div class="line"> <span class="tag"><<span class="name">id</span>></span>alimaven<span class="tag"></<span class="name">id</span>></span></div><div class="line"> <span class="tag"><<span class="name">name</span>></span>aliyun maven<span class="tag"></<span class="name">name</span>></span></div><div class="line"> <span class="tag"><<span class="name">url</span>></span>http://maven.aliyun.com/nexus/content/groups/public/<span class="tag"></<span class="name">url</span>></span></div><div class="line"> <span class="tag"><<span class="name">mirrorOf</span>></span>central<span class="tag"></<span class="name">mirrorOf</span>></span> </div><div class="line"> <span class="tag"></<span class="name">mirror</span>></span></div><div class="line"><span class="tag"></<span class="name">mirrors</span>></span></div></pre></td></tr></table></figure></p>
</blockquote>
<h2 id="5-FAQ"><a href="#5-FAQ" class="headerlink" title="5. FAQ"></a>5. FAQ</h2><h3 id="5-1-broker启动报错-runbroker-sh-line-62-126674-Killed-JAVA-JAVA-OPT"><a href="#5-1-broker启动报错-runbroker-sh-line-62-126674-Killed-JAVA-JAVA-OPT" class="headerlink" title="5.1 broker启动报错/runbroker.sh: line 62: 126674 Killed $JAVA ${JAVA_OPT} $@"></a>5.1 broker启动报错<code>/runbroker.sh: line 62: 126674 Killed $JAVA ${JAVA_OPT} $@</code></h3><p>runbroker.sh 默认参数:Xms=8G,机器可用内存无法支配时会产生该问题,全部改小即可解决。</p>
<h3 id="5-2-com-alibaba-rocketmq-client-exception-MQClientException-No-route-info-of-this-topic-TopicTest1"><a href="#5-2-com-alibaba-rocketmq-client-exception-MQClientException-No-route-info-of-this-topic-TopicTest1" class="headerlink" title="5.2 com.alibaba.rocketmq.client.exception.MQClientException: No route info of this topic, TopicTest1"></a>5.2 <code>com.alibaba.rocketmq.client.exception.MQClientException: No route info of this topic, TopicTest1</code></h3><p>启动broker时,指定autoCreateTopicEnable=true,建议线上关闭<br><figure class="highlight groovy"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">nohup sh mqbroker -n <span class="string">localhost:</span><span class="number">9876</span> autoCreateTopicEnable=<span class="literal">true</span> > <span class="regexp">/dev/</span><span class="literal">null</span> <span class="number">2</span>>&<span class="number">1</span> &</div></pre></td></tr></table></figure></p>
<p>或在配置文件中设置<br><figure class="highlight stata"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">nohup <span class="keyword">sh</span> mqbroker -c <span class="variable">$ROCKETMQ_HOME</span>/<span class="keyword">conf</span>/broker.<span class="keyword">conf</span> > /dev/null 2>&1 &</div></pre></td></tr></table></figure></p>
<figure class="highlight ini"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div></pre></td><td class="code"><pre><div class="line"><span class="attr">brokerClusterName</span> = DefaultCluster</div><div class="line"><span class="attr">brokerName</span> = broker-a</div><div class="line"><span class="attr">brokerId</span> = <span class="number">0</span></div><div class="line"><span class="attr">brokerIP1</span> = <span class="number">10.29</span>.<span class="number">181.16</span></div><div class="line"><span class="attr">deleteWhen</span> = <span class="number">04</span></div><div class="line"><span class="attr">fileReservedTime</span> = <span class="number">48</span></div><div class="line"><span class="attr">brokerRole</span> = ASYNC_MASTER</div><div class="line"><span class="attr">flushDiskType</span> = ASYNC_FLUSH</div><div class="line"></div><div class="line"><span class="comment"># NameServer地址列表,多个nameServer地址用分号隔开</span></div><div class="line"><span class="attr">namesrvAddr</span> = <span class="number">10.29</span>.<span class="number">181.16</span>:<span class="number">9876</span></div><div class="line"></div><div class="line"><span class="attr">autoCreateTopicEnable</span> = <span class="literal">true</span></div></pre></td></tr></table></figure>
<h3 id="5-3-org-apache-rocketmq-remoting-exception-RemotingConnectException-connect-to-lt-172-19-0-1-10909-gt-failed"><a href="#5-3-org-apache-rocketmq-remoting-exception-RemotingConnectException-connect-to-lt-172-19-0-1-10909-gt-failed" class="headerlink" title="5.3 org.apache.rocketmq.remoting.exception.RemotingConnectException: connect to <172.19.0.1:10909> failed"></a>5.3 <code>org.apache.rocketmq.remoting.exception.RemotingConnectException: connect to <172.19.0.1:10909> failed</code></h3><p>10.29.181.15服务器上有多个网卡,172.19.0.1 为docker0的虚拟网卡的IP,但是启动RocketMQ时并没有设置这个IP地址。</p>
<figure class="highlight armasm"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div></pre></td><td class="code"><pre><div class="line"> Docker 服务启动后默认会创建一个 docker0 网桥(其上有一个 docker0 内部接口),它在内核层连通了其他的物理或虚拟网卡,这就将所有容器和本地主机都放到同一个物理网络。</div><div class="line"></div><div class="line"> Docker 默认指定了 docker0 接口 的 <span class="built_in">IP</span> 地址和子网掩码,让主机和容器之间可以通过网桥相互通信,它还给出了 MTU(接口允许接收的最大传输单元),通常是 <span class="number">1500</span> <span class="keyword">Bytes,或宿主主机网络路由上支持的默认值。这些值都可以在服务启动的时候进行配置。</span></div><div class="line"></div><div class="line">可以用编辑/etc/docker/daemon.json文件,添加内容 <span class="string">"bip"</span>: <span class="string">"ip/netmask"</span> [ 切勿与宿主机同网段 ]</div></pre></td></tr></table></figure>
<p><a href="http://rocketmq.apache.org/docs/rmq-deployment/" target="_blank" rel="external">RocketMQ 官方broker配置</a>:</p>
<table>
<thead>
<tr>
<th style="text-align:center">参数名</th>
<th style="text-align:center">默认值</th>
<th style="text-align:center">说明</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:center">brokerIP1</td>
<td style="text-align:center">本机IP</td>
<td style="text-align:center">本机ip地址,默认系统自动识别,但是某些多网卡机器会存在识别错误的情况,这种情况下可以人工配置</td>
</tr>
</tbody>
</table>
<p>解决办法:</p>
<ol>
<li>把不需要的网卡全部禁用,只留下有效的网卡,这样Broker不会生成奇怪的代理地址。</li>
<li>在<code>broker.properties</code>中设置<code>brokerIP1=10.29.181.16</code></li>
</ol>
<h3 id="5-4-No-route-info-of-this-topic"><a href="#5-4-No-route-info-of-this-topic" class="headerlink" title="5.4 No route info of this topic"></a>5.4 <code>No route info of this topic</code></h3><p>产生<code>No route info of this topic</code>异常原因可能有如下几种:</p>
<ul>
<li>1> Broker禁止自动创建Topic,且用户没有通过手工方式创建Topic。</li>
</ul>
<p>启动borker时指定<code>autoCreateTopicEnable=true</code></p>
<ul>
<li>2> Broker未连接到Name Server</li>
</ul>
<p>查看broker的启动日志:<br><figure class="highlight css"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">2018<span class="selector-tag">-09-13</span> 16<span class="selector-pseudo">:21</span><span class="selector-pseudo">:35</span> <span class="selector-tag">INFO</span> <span class="selector-tag">BrokerControllerScheduledThread1</span> <span class="selector-tag">-</span> <span class="selector-tag">register</span> <span class="selector-tag">broker</span> <span class="selector-tag">to</span> <span class="selector-tag">name</span> <span class="selector-tag">server</span> 10<span class="selector-class">.29</span><span class="selector-class">.181</span><span class="selector-class">.16</span><span class="selector-pseudo">:9876</span> <span class="selector-tag">OK</span></div><div class="line">2018<span class="selector-tag">-09-13</span> 16<span class="selector-pseudo">:22</span><span class="selector-pseudo">:05</span> <span class="selector-tag">INFO</span> <span class="selector-tag">BrokerControllerScheduledThread1</span> <span class="selector-tag">-</span> <span class="selector-tag">register</span> <span class="selector-tag">broker</span> <span class="selector-tag">to</span> <span class="selector-tag">name</span> <span class="selector-tag">server</span> 10<span class="selector-class">.29</span><span class="selector-class">.181</span><span class="selector-class">.16</span><span class="selector-pseudo">:9876</span> <span class="selector-tag">OK</span></div></pre></td></tr></table></figure></p>
<p>说明broker已经成功连接到Name Server.</p>
<p>或执行<code>sh mqadmin clusterList -n localhost:9876</code></p>
<figure class="highlight css"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line"><span class="selector-id">#Cluster</span> <span class="selector-tag">Name</span> <span class="selector-id">#Broker</span> <span class="selector-tag">Name</span> <span class="selector-id">#BID</span> <span class="selector-id">#Addr</span> <span class="selector-id">#Version</span> <span class="selector-id">#InTPS</span>(<span class="selector-tag">LOAD</span>) <span class="selector-id">#OutTPS</span>(<span class="selector-tag">LOAD</span>) <span class="selector-id">#PCWait</span>(<span class="selector-tag">ms</span>) <span class="selector-id">#Hour</span> <span class="selector-id">#SPACE</span></div><div class="line"><span class="selector-tag">DefaultCluster</span> <span class="selector-tag">DEFAULT_BROKER</span> 0 10<span class="selector-class">.29</span><span class="selector-class">.181</span><span class="selector-class">.16</span><span class="selector-pseudo">:10911</span> <span class="selector-tag">V4_2_0_SNAPSHOT</span> 0<span class="selector-class">.00</span>(0,0<span class="selector-tag">ms</span>) 0<span class="selector-class">.00</span>(0,0<span class="selector-tag">ms</span>) 0 422168<span class="selector-class">.55</span> <span class="selector-tag">-1</span><span class="selector-class">.0000</span></div></pre></td></tr></table></figure>
<ul>
<li>3> Producer未连接到Name Server </li>
</ul>
<p>关闭防火墙:<code>systemctl stop firewalld.service</code>,再做重试。</p>
<h3 id="5-5-The-producer-service-state-not-OK-CREATE-JUST"><a href="#5-5-The-producer-service-state-not-OK-CREATE-JUST" class="headerlink" title="5.5 The producer service state not OK, CREATE_JUST"></a>5.5 <code>The producer service state not OK, CREATE_JUST</code></h3><p>检查是否调用:<code>producer.start();</code></p>
<h2 id="6-术语"><a href="#6-术语" class="headerlink" title="6 术语"></a>6 术语</h2><h3 id="6-1-Disk-Flush(磁盘刷新-同步操作)"><a href="#6-1-Disk-Flush(磁盘刷新-同步操作)" class="headerlink" title="6.1 Disk Flush(磁盘刷新/同步操作)"></a>6.1 Disk Flush(磁盘刷新/同步操作)</h3><p>将内存的数据落地,存储在磁盘中,RocketMQ提供了以下两种模式:</p>
<ul>
<li>SYNC_FLUSH(同步刷盘):生产者发送的每一条消息都在保存到磁盘成功后才返回告诉生产者成功。这种方式不会存在消息丢失的问题,但是有很大的磁盘IO开销,性能有一定影响。</li>
<li>ASYNC_FLUSH(异步刷盘):生产者发送的每一条消息并不是立即保存到磁盘,而是暂时缓存起来,然后就返回生产者成功。随后再异步的将缓存数据保存到磁盘,有两种情况:1是定期将缓存中更新的数据进行刷盘,2是当缓存中更新的数据条数达到某一设定值后进行刷盘。这种方式会存在消息丢失(在还未来得及同步到磁盘的时候宕机),但是性能很好。默认是这种模式。</li>
</ul>
<h3 id="6-2-Broker-Replication(Broker间数据同步-复制)"><a href="#6-2-Broker-Replication(Broker间数据同步-复制)" class="headerlink" title="6.2 Broker Replication(Broker间数据同步/复制)"></a>6.2 Broker Replication(Broker间数据同步/复制)</h3><p>集群环境下需要部署多个Broker,Broker分为两种角色:一种是master,即可以写也可以读,其brokerId=0,只能有一个;另外一种是slave,只允许读,其brokerId为非0。一个master与多个slave通过指定相同的brokerName被归为一个broker set(broker集)。通常生产环境中,我们至少需要2个broker set。Broker Replication只的就是slave获取或者是复制master的数据。</p>
<ul>
<li>Sync Broker:生产者发送的每一条消息都至少同步复制到一个slave后才返回告诉生产者成功,即“同步双写”。</li>
<li>Async Broker:生产者发送的每一条消息只要写入master就返回告诉生产者成功。然后再“异步复制”到slave。</li>
</ul>
<p>推荐的几种Broker集群方式:(官网提供了下面几种集群方式的配置文件供参考,在$ROCKETMQ_HOME/target/apache-rocketmq-all/conf目录下)</p>
<ul>
<li>2m-2s-sync:两主两从同步双写(两个master,两个slave,数据同步双写到master和slave)</li>
<li>2m-2s-async:两主两从异步复制(两个master,两个slave,master数据通过异步复制到slave)</li>
<li>2m-noslave:两主(只有两个master,没有slave)</li>
</ul>
<blockquote>
<p>注意:<br>1、上述“2”只是说作为一个集群的最低配置数量,可以根据实际情况扩展。<br>2、所有的刷盘(Dish Flush)操作全部默认为:ASYNC_FLUSH(异步刷盘)。</p>
</blockquote>
<p>Name Server集群:Name Server集群比较简单,只要部署多个实例就行了,多个实例间不需要进行数据共享,只要保证一个实例存活就可以正常运转。</p>
<h3 id="6-3-核心概念"><a href="#6-3-核心概念" class="headerlink" title="6.3 核心概念"></a>6.3 核心概念</h3><ul>
<li><p>生产者(Producer):消息发送方,将业务系统中产生的消息发送到brokers(brokers可以理解为消息代理,生产者和消费者之间是通过brokers进行消息的通信),rocketmq提供了以下消息发送方式:同步、异步、单向。</p>
</li>
<li><p>生产者组(Producer Group):相同角色的生产者被归为同一组,比如通常情况下一个服务会部署多个实例,这多个实例就是一个组,生产者分组的作用只体现在消息回查的时候,即如果一个生产者组中的一个生产者实例发送一个事务消息到broker后挂掉了,那么broker会回查此实例所在组的其他实例,从而进行消息的提交或回滚操作。</p>
</li>
<li><p>消费者(Consumer):消息消费方,从brokers拉取消息。站在用户的角度,有以下两种消费者。</p>
<ul>
<li>主动消费者(PullConsumer):从brokers拉取消息并消费。</li>
<li>被动消费者(PushConsumer):内部也是通过pull方式获取消息,只是进行了扩展和封装,并给用户预留了一个回调接口去实现,当消息到底的时候会执行用户自定义的回调接口。</li>
</ul>
</li>
<li><p>消费者组(Consumer Group):和生产者组类似。其作用体现在实现消费者的负载均衡和容错,有了消费者组变得异常容易。需要注意的是:同一个消费者组的每个消费者实例订阅的主题必须相同。</p>
</li>
<li><p>主题(Topic):主题就是消息传递的类型。一个生产者实例可以发送消息到多个主题,多个生产者实例也可以发送消息到同一个主题。同样的,对于消费者端来说,一个消费者组可以订阅多个主题的消息,一个主题的消息也可以被多个消费者组订阅。</p>
</li>
<li><p>消息(Message):消息就像是你传递信息的信封。每个消息必须指定一个主题,就好比每个信封上都必须写明收件人。</p>
</li>
<li><p>消息队列(Message Queues):在主题内部,逻辑划分了多个子主题,每个子主题被称为消息队列。这个概念在实现最大并发数、故障切换等功能上有巨大的作用。</p>
</li>
<li><p>标签(Tag):标签,可以被认为是子主题。通常用于区分同一个主题下的不同作用或者说不同业务的消息。同时也是避免主题定义过多引起性能问题,通常情况下一个生产者组只向一个主题发送消息,其中不同业务的消息通过标签或者说子主题来区分。</p>
</li>
<li><p>消息代理(Broker):消息代理是RockerMQ中很重要的角色。它接收生产者发送的消息,进行消息存储,为消费者拉取消息服务。它还存储消息消耗相关的元数据,包括消费群体,消费进度偏移和主题/队列信息。</p>
</li>
<li><p>命名服务(Name Server):命名服务作为路由信息提供程序。生产者/消费者进行主题查找、消息代理查找、读取/写入消息都需要通过命名服务获取路由信息。</p>
</li>
<li><p>消息顺序(Message Order):当我们使用DefaultMQPushConsumer时,我们可以选择使用“orderly”还是“concurrently”。</p>
<ul>
<li>orderly:消费消息的有序化意味着消息被生产者按照每个消息队列发送的顺序消费。如果您正在处理全局顺序为强制的场景,请确保您使用的主题只有一个消息队列。注意:如果指定了消费顺序,则消息消费的最大并发性是消费组订阅的消息队列数。</li>
<li>concurrently:当同时消费时,消息消费的最大并发仅限于为每个消费客户端指定的线程池。注意:此模式不再保证消息顺序。</li>
</ul>
</li>
</ul>
]]></content>
<summary type="html">
Apache RocketMQ™ is an open source distributed messaging and streaming data platform.
</summary>
<category term="RocketMQ" scheme="https://roc-wong.github.io/categories/RocketMQ/"/>
<category term="RocketMQ" scheme="https://roc-wong.github.io/tags/RocketMQ/"/>
</entry>
<entry>
<title>eureka dns cluster</title>
<link href="https://roc-wong.github.io/blog/2018/11/eureka-dns-cluster.html"/>
<id>https://roc-wong.github.io/blog/2018/11/eureka-dns-cluster.html</id>
<published>2018-11-20T13:34:38.000Z</published>
<updated>2018-11-21T02:18:42.950Z</updated>
<content type="html"><![CDATA[<h2 id="Netflix-Eureka集群配置"><a href="#Netflix-Eureka集群配置" class="headerlink" title="Netflix Eureka集群配置"></a>Netflix Eureka集群配置</h2><p>Spring Cloud Netflix Eureka集群配置方式主要用两种:Static servers list config和dns,本文主要介绍基于DNS的方式搭建Eureka集群。</p>
<h3 id="Static-servers-list-config"><a href="#Static-servers-list-config" class="headerlink" title="Static servers list config"></a>Static servers list config</h3><p>client启动后从config中获取region和zone以及serviceUrl,进行服务注册、发现,这种静态集群模式无法动态扩容,一旦新增节点,只能挨个修改server和client端的配置文件,大致配置如下:<br><figure class="highlight yaml"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div></pre></td><td class="code"><pre><div class="line"><span class="attr">eureka:</span></div><div class="line"><span class="attr"> server:</span></div><div class="line"><span class="attr"> enable-self-preservation:</span> <span class="literal">false</span></div><div class="line"><span class="attr"> instance:</span></div><div class="line"><span class="attr"> prefer-ip-address:</span> <span class="literal">true</span></div><div class="line"><span class="attr"> instance-id:</span> ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}</div><div class="line"><span class="attr"> client:</span></div><div class="line"><span class="attr"> register-with-eureka:</span> <span class="literal">true</span></div><div class="line"><span class="attr"> fetch-registry:</span> <span class="literal">true</span></div><div class="line"><span class="attr"> service-url:</span></div><div class="line"><span class="attr"> defaultZone:</span> http://<span class="number">10.25</span><span class="number">.102</span><span class="number">.174</span>:<span class="number">8082</span>/eureka/,http://<span class="number">10.25</span><span class="number">.102</span><span class="number">.174</span>:<span class="number">8083</span>/eureka/</div></pre></td></tr></table></figure></p>
<h3 id="DNS-configuration"><a href="#DNS-configuration" class="headerlink" title="DNS configuration"></a>DNS configuration</h3><p>基于DNS的Eureka Cluster架构图如下:</p>
<p><img src="https://raw.githubusercontent.com/roc-wong/images/master/eureka/eureka-dns-cluster-architecture-diagram.png" alt="eureka-dns-cluster-architecture-diagram"></p>
<p><img src="https://raw.githubusercontent.com/roc-wong/images/master/eureka/eureka-client-invoke-process.png" alt="eureka-client-invoke-process"></p>
<p>简单来说就是使用DNS服务器管理Eureka Server的地址,弹性伸缩对客户端没有影响。</p>
<p>大致流程如下:</p>
<ol>
<li>客户端开启DNS方式获取serviceUrl:<code>use-dns-for-fetching-service-urls: true</code>;</li>
<li>根据<code>client.region</code>配置的区域region,查询DNS区域配置文件中该区域下的所有可用区zone;</li>
<li>循环所有可用区zone,获取可用区配置的eureka-server地址;</li>
<li>拼接成完整的serviceUrl并加入serviceUrls列表中,serviceUrl格式为:<code>"http://" + ec2Url + ":" + clientConfig.getEurekaServerPort() + "/" + clientConfig.getEurekaServerURLContext() + "/";</code>。</li>
</ol>
<p><strong>只要解决DNS服务器配置就可以达到动态集群的效果,关于如何搭建DNS服务器集群,请移步另一篇文章:<a href="https://roc-wong.github.io/blog/2018/11/Centos%E6%90%AD%E5%BB%BADNS%E4%B8%BB%E4%BB%8E%E6%9C%8D%E5%8A%A1%E5%99%A8%E9%9B%86%E7%BE%A4.html">CentOS 搭建DNS主从服务器集群</a>,文中详细介绍了如何在区域配置文件中配置TXT记录,本文不在赘述。</strong></p>
<h4 id="1-DNS-区域文件配置TXT记录"><a href="#1-DNS-区域文件配置TXT记录" class="headerlink" title="1.DNS 区域文件配置TXT记录"></a>1.DNS 区域文件配置TXT记录</h4><p><a href="https://roc-wong.github.io/blog/2018/11/Centos%E6%90%AD%E5%BB%BADNS%E4%B8%BB%E4%BB%8E%E6%9C%8D%E5%8A%A1%E5%99%A8%E9%9B%86%E7%BE%A4.html#a-%E5%88%9B%E5%BB%BA%E8%BD%AC%E5%8F%91%E5%9F%9F">zts.local.zone</a>区域配置文件中有关eureka的配置:</p>
<figure class="highlight css"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div></pre></td><td class="code"><pre><div class="line">; <span class="selector-tag">eureka</span> <span class="selector-tag">cluster</span>配置</div><div class="line"><span class="selector-tag">txt</span><span class="selector-class">.shanghai</span> <span class="selector-tag">IN</span> <span class="selector-tag">TXT</span> "<span class="selector-tag">defaultZone</span><span class="selector-class">.zts</span><span class="selector-class">.local</span>"</div><div class="line"><span class="selector-tag">txt</span><span class="selector-class">.defaultZone</span> <span class="selector-tag">IN</span> <span class="selector-tag">TXT</span> "10<span class="selector-class">.29</span><span class="selector-class">.181</span><span class="selector-class">.56</span>" "10<span class="selector-class">.29</span><span class="selector-class">.181</span><span class="selector-class">.57</span>" "10<span class="selector-class">.29</span><span class="selector-class">.181</span><span class="selector-class">.58</span>" "10<span class="selector-class">.29</span><span class="selector-class">.181</span><span class="selector-class">.60</span>"</div><div class="line"></div><div class="line">;通过查看<span class="selector-tag">Eureka</span>的源码,它的实现是通过寻找<span class="selector-tag">txt</span><span class="selector-class">.beijing-a</span><span class="selector-class">.zts</span><span class="selector-class">.local</span>(<span class="selector-tag">txt</span><span class="selector-class">.region</span><span class="selector-class">.eureka-server-d-n-s-name</span>)获取"<span class="selector-tag">beijing-a</span><span class="selector-class">.zts</span><span class="selector-class">.local</span>" "<span class="selector-tag">beijing-b</span><span class="selector-class">.zts</span><span class="selector-class">.local</span>"的<span class="selector-tag">zone</span>:<span class="selector-tag">beijing-a</span>和<span class="selector-tag">beijing-b</span>,</div><div class="line">;然后再去获取<span class="selector-tag">txt</span><span class="selector-class">.beijing-a</span><span class="selector-class">.zts</span><span class="selector-class">.local</span>和<span class="selector-tag">txt</span><span class="selector-class">.beijing-b</span><span class="selector-class">.zts</span><span class="selector-class">.local</span>中对应的<span class="selector-tag">ServiceUrls</span>的数据,也就是<span class="selector-tag">IP</span>地址: "10<span class="selector-class">.29</span><span class="selector-class">.181</span><span class="selector-class">.61</span>" "10<span class="selector-class">.29</span><span class="selector-class">.181</span><span class="selector-class">.62</span>"</div><div class="line">;这样服务间就可以获取到固定端口下的不同<span class="selector-tag">IP</span>的机器的注册中心服务地址,并相互注册</div><div class="line"><span class="selector-tag">txt</span><span class="selector-class">.beijing</span> <span class="selector-tag">IN</span> <span class="selector-tag">TXT</span> "<span class="selector-tag">beijing-a</span><span class="selector-class">.zts</span><span class="selector-class">.local</span>" "<span class="selector-tag">beijing-b</span><span class="selector-class">.zts</span><span class="selector-class">.local</span>"</div><div class="line"><span class="selector-tag">txt</span><span class="selector-class">.beijing-a</span> <span class="selector-tag">IN</span> <span class="selector-tag">TXT</span> "10<span class="selector-class">.29</span><span class="selector-class">.181</span><span class="selector-class">.61</span>" "10<span class="selector-class">.29</span><span class="selector-class">.181</span><span class="selector-class">.62</span>"</div><div class="line"><span class="selector-tag">txt</span><span class="selector-class">.beijing-b</span> <span class="selector-tag">IN</span> <span class="selector-tag">TXT</span> "10<span class="selector-class">.29</span><span class="selector-class">.181</span><span class="selector-class">.63</span>" "10<span class="selector-class">.29</span><span class="selector-class">.181</span><span class="selector-class">.64</span>"</div></pre></td></tr></table></figure>
<h4 id="2-Eureka-Server-Client端配置"><a href="#2-Eureka-Server-Client端配置" class="headerlink" title="2.Eureka Server/Client端配置"></a>2.Eureka Server/Client端配置</h4><figure class="highlight yaml"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div></pre></td><td class="code"><pre><div class="line"><span class="meta">---</span></div><div class="line"><span class="attr">spring:</span></div><div class="line"><span class="attr"> application:</span></div><div class="line"><span class="attr"> name:</span> eureka-server</div><div class="line"><span class="attr">server:</span></div><div class="line"><span class="attr"> port:</span> <span class="number">8081</span></div><div class="line"><span class="attr">eureka:</span></div><div class="line"><span class="attr"> server:</span></div><div class="line"><span class="attr"> enable-self-preservation:</span> <span class="literal">false</span></div><div class="line"><span class="attr"> instance:</span></div><div class="line"><span class="attr"> prefer-ip-address:</span> <span class="literal">true</span></div><div class="line"><span class="attr"> instance-id:</span> ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}</div><div class="line"><span class="attr"> client:</span></div><div class="line"> <span class="comment">## 是否将自己注册到eureka</span></div><div class="line"><span class="attr"> register-with-eureka:</span> <span class="literal">true</span></div><div class="line"> <span class="comment">## 是否获取注册信息到本地</span></div><div class="line"><span class="attr"> fetch-registry:</span> <span class="literal">true</span></div><div class="line"> <span class="comment">## 开启DNS方式获取serviceUrl,默认为false</span></div><div class="line"><span class="attr"> use-dns-for-fetching-service-urls:</span> <span class="literal">true</span></div><div class="line"> <span class="comment">## DNS域名,获取其他信息将以该域名为根域名</span></div><div class="line"><span class="attr"> eureka-server-d-n-s-name:</span> zts.local</div><div class="line"> <span class="comment">## 当前应用所在区域,默认为us-east-1</span></div><div class="line"><span class="attr"> region:</span> beijing</div><div class="line"> <span class="comment">## 配置中心的eureka目录</span></div><div class="line"><span class="attr"> eureka-server-u-r-l-context:</span> eureka</div><div class="line"> <span class="comment">## 映射其他eurekaServer的端口,这里注意采用这种方式 server.port和这个端口最好一致</span></div><div class="line"> <span class="comment">## 因为dns是控制地址的变化,端口不变,所以不像前面的哪些配置方式可以自己定义url和port。</span></div><div class="line"> <span class="comment">## 所以每个IP都是用的相同的port进行注册中心服务的部署</span></div><div class="line"><span class="attr"> eureka-server-port:</span> <span class="number">8081</span></div><div class="line"> <span class="comment">## 获取serviceUrl时候是否优先获取相同zone的列表(如果获取为空则获取所在region第一个zone),如果为false则优先获取不在相同zone的列表</span></div><div class="line"><span class="attr"> prefer-same-zone-eureka:</span> <span class="literal">true</span></div></pre></td></tr></table></figure>
<h4 id="3-测试"><a href="#3-测试" class="headerlink" title="3.测试"></a>3.测试</h4><blockquote>
<p>修改客户端DNS服务器配置为10.29.181.61,DNS服务器的域名为zts.local</p>
</blockquote>
<p>依次启动4台Eureka Server服务器,查看启动日志(删减版的日志),:</p>
<figure class="highlight stylus"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div></pre></td><td class="code"><pre><div class="line"><span class="number">2018</span>-<span class="number">11</span>-<span class="number">20</span> <span class="number">16</span>:<span class="number">17</span>:<span class="number">14.962</span> INFO <span class="number">49750</span> --- [ main] c<span class="selector-class">.n</span><span class="selector-class">.d</span><span class="selector-class">.s</span><span class="selector-class">.r</span><span class="selector-class">.aws</span><span class="selector-class">.ConfigClusterResolver</span> : Resolving eureka endpoints via DNS: txt<span class="selector-class">.beijing</span><span class="selector-class">.zts</span><span class="selector-class">.local</span> (<------注意这里)</div><div class="line"><span class="number">2018</span>-<span class="number">11</span>-<span class="number">20</span> <span class="number">16</span>:<span class="number">17</span>:<span class="number">15.012</span> INFO <span class="number">49750</span> --- [ main] com<span class="selector-class">.netflix</span><span class="selector-class">.discovery</span><span class="selector-class">.DiscoveryClient</span> : Disable delta property : false</div><div class="line"><span class="number">2018</span>-<span class="number">11</span>-<span class="number">20</span> <span class="number">16</span>:<span class="number">17</span>:<span class="number">15.262</span> INFO <span class="number">49750</span> --- [ main] com<span class="selector-class">.netflix</span><span class="selector-class">.discovery</span><span class="selector-class">.DiscoveryClient</span> : Discovery Client initialized at timestamp <span class="number">1542701835260</span> with <span class="attribute">initial</span> instances count: <span class="number">5</span></div><div class="line"><span class="number">2018</span>-<span class="number">11</span>-<span class="number">20</span> <span class="number">16</span>:<span class="number">17</span>:<span class="number">15.326</span> INFO <span class="number">49750</span> --- [ main] c<span class="selector-class">.n</span><span class="selector-class">.eureka</span><span class="selector-class">.DefaultEurekaServerContext</span> : Initializing ...</div><div class="line"><span class="number">2018</span>-<span class="number">11</span>-<span class="number">20</span> <span class="number">16</span>:<span class="number">17</span>:<span class="number">15.559</span> INFO <span class="number">49750</span> --- [ main] c<span class="selector-class">.n</span><span class="selector-class">.eureka</span><span class="selector-class">.cluster</span><span class="selector-class">.PeerEurekaNodes</span> : Replica node URL: http:<span class="comment">//10.29.181.62:8081/eureka/</span></div><div class="line"><span class="number">2018</span>-<span class="number">11</span>-<span class="number">20</span> <span class="number">16</span>:<span class="number">17</span>:<span class="number">15.560</span> INFO <span class="number">49750</span> --- [ main] c<span class="selector-class">.n</span><span class="selector-class">.eureka</span><span class="selector-class">.cluster</span><span class="selector-class">.PeerEurekaNodes</span> : Replica node URL: http:<span class="comment">//10.29.181.64:8081/eureka/</span></div><div class="line"><span class="number">2018</span>-<span class="number">11</span>-<span class="number">20</span> <span class="number">16</span>:<span class="number">17</span>:<span class="number">15.560</span> INFO <span class="number">49750</span> --- [ main] c<span class="selector-class">.n</span><span class="selector-class">.eureka</span><span class="selector-class">.cluster</span><span class="selector-class">.PeerEurekaNodes</span> : Replica node URL: http:<span class="comment">//10.29.181.61:8081/eureka/</span></div><div class="line"></div><div class="line"><span class="number">2018</span>-<span class="number">11</span>-<span class="number">20</span> <span class="number">16</span>:<span class="number">17</span>:<span class="number">16.052</span> INFO <span class="number">49750</span> --- [ Thread-<span class="number">14</span>] o<span class="selector-class">.s</span><span class="selector-class">.c</span><span class="selector-class">.n</span><span class="selector-class">.e</span><span class="selector-class">.server</span><span class="selector-class">.EurekaServerBootstrap</span> : isAws returned false</div><div class="line"><span class="number">2018</span>-<span class="number">11</span>-<span class="number">20</span> <span class="number">16</span>:<span class="number">17</span>:<span class="number">16.053</span> INFO <span class="number">49750</span> --- [ Thread-<span class="number">14</span>] o<span class="selector-class">.s</span><span class="selector-class">.c</span><span class="selector-class">.n</span><span class="selector-class">.e</span><span class="selector-class">.server</span><span class="selector-class">.EurekaServerBootstrap</span> : Initialized server context</div><div class="line"><span class="number">2018</span>-<span class="number">11</span>-<span class="number">20</span> <span class="number">16</span>:<span class="number">17</span>:<span class="number">16.056</span> INFO <span class="number">49750</span> --- [ main] c<span class="selector-class">.z</span><span class="selector-class">.e</span><span class="selector-class">.server</span><span class="selector-class">.EurekaServerApplication</span> : Started EurekaServerApplication <span class="keyword">in</span> <span class="number">7.112</span> seconds (JVM running <span class="keyword">for</span> <span class="number">7.625</span>)</div><div class="line"><span class="number">2018</span>-<span class="number">11</span>-<span class="number">20</span> <span class="number">16</span>:<span class="number">17</span>:<span class="number">16.060</span> INFO <span class="number">49750</span> --- [ Thread-<span class="number">14</span>] c<span class="selector-class">.n</span><span class="selector-class">.e</span><span class="selector-class">.registry</span><span class="selector-class">.AbstractInstanceRegistry</span> : Registered instance EUREKA-SERVER/<span class="number">10.29</span>.<span class="number">181.61</span>:eureka-server:<span class="number">8081</span> with status UP (replication=true)</div><div class="line"><span class="number">2018</span>-<span class="number">11</span>-<span class="number">20</span> <span class="number">16</span>:<span class="number">17</span>:<span class="number">16.061</span> INFO <span class="number">49750</span> --- [ Thread-<span class="number">14</span>] c<span class="selector-class">.n</span><span class="selector-class">.e</span><span class="selector-class">.registry</span><span class="selector-class">.AbstractInstanceRegistry</span> : Registered instance EUREKA-SERVER/<span class="number">10.29</span>.<span class="number">181.62</span>:eureka-server:<span class="number">8081</span> with status UP (replication=true)</div><div class="line"><span class="number">2018</span>-<span class="number">11</span>-<span class="number">20</span> <span class="number">16</span>:<span class="number">17</span>:<span class="number">16.061</span> INFO <span class="number">49750</span> --- [ Thread-<span class="number">14</span>] c<span class="selector-class">.n</span><span class="selector-class">.e</span><span class="selector-class">.registry</span><span class="selector-class">.AbstractInstanceRegistry</span> : Registered instance EUREKA-SERVER/<span class="number">10.29</span>.<span class="number">181.64</span>:eureka-server:<span class="number">8081</span> with status UP (replication=true)</div><div class="line"><span class="number">2018</span>-<span class="number">11</span>-<span class="number">20</span> <span class="number">16</span>:<span class="number">17</span>:<span class="number">16.062</span> INFO <span class="number">49750</span> --- [ Thread-<span class="number">14</span>] c<span class="selector-class">.n</span><span class="selector-class">.e</span><span class="selector-class">.registry</span><span class="selector-class">.AbstractInstanceRegistry</span> : Registered instance EUREKA-SERVER/<span class="number">10.29</span>.<span class="number">181.63</span>:eureka-server:<span class="number">8081</span> with status UP (replication=true)</div><div class="line"><span class="number">2018</span>-<span class="number">11</span>-<span class="number">20</span> <span class="number">16</span>:<span class="number">17</span>:<span class="number">16.062</span> INFO <span class="number">49750</span> --- [ Thread-<span class="number">14</span>] c<span class="selector-class">.n</span><span class="selector-class">.e</span><span class="selector-class">.registry</span><span class="selector-class">.AbstractInstanceRegistry</span> : Registered instance ACCOUNT-CENTER/<span class="number">10.25</span>.<span class="number">102.174</span>:account-center:<span class="number">8891</span> with status UP (replication=true)</div><div class="line"></div><div class="line"><span class="number">2018</span>-<span class="number">11</span>-<span class="number">20</span> <span class="number">16</span>:<span class="number">17</span>:<span class="number">16.062</span> INFO <span class="number">49750</span> --- [ Thread-<span class="number">14</span>] c<span class="selector-class">.n</span><span class="selector-class">.e</span><span class="selector-class">.r</span><span class="selector-class">.PeerAwareInstanceRegistryImpl</span> : Got <span class="number">5</span> instances from neighboring DS node</div><div class="line"><span class="number">2018</span>-<span class="number">11</span>-<span class="number">20</span> <span class="number">16</span>:<span class="number">17</span>:<span class="number">16.062</span> INFO <span class="number">49750</span> --- [ Thread-<span class="number">14</span>] c<span class="selector-class">.n</span><span class="selector-class">.e</span><span class="selector-class">.r</span><span class="selector-class">.PeerAwareInstanceRegistryImpl</span> : Renew threshold is: <span class="number">8</span></div><div class="line"><span class="number">2018</span>-<span class="number">11</span>-<span class="number">20</span> <span class="number">16</span>:<span class="number">17</span>:<span class="number">16.062</span> INFO <span class="number">49750</span> --- [ Thread-<span class="number">14</span>] c<span class="selector-class">.n</span><span class="selector-class">.e</span><span class="selector-class">.r</span><span class="selector-class">.PeerAwareInstanceRegistryImpl</span> : Changing status to UP</div><div class="line"><span class="number">2018</span>-<span class="number">11</span>-<span class="number">20</span> <span class="number">16</span>:<span class="number">17</span>:<span class="number">16.070</span> INFO <span class="number">49750</span> --- [nfoReplicator-<span class="number">0</span>] com<span class="selector-class">.netflix</span><span class="selector-class">.discovery</span><span class="selector-class">.DiscoveryClient</span> : DiscoveryClient_EUREKA-SERVER/<span class="number">10.29</span>.<span class="number">181.63</span>:eureka-server:<span class="number">8081</span> - registration status: <span class="number">204</span></div><div class="line"><span class="number">2018</span>-<span class="number">11</span>-<span class="number">20</span> <span class="number">16</span>:<span class="number">17</span>:<span class="number">16.070</span> INFO <span class="number">49750</span> --- [ Thread-<span class="number">14</span>] e<span class="selector-class">.s</span><span class="selector-class">.EurekaServerInitializerConfiguration</span> : Started Eureka Server</div><div class="line"><span class="number">2018</span>-<span class="number">11</span>-<span class="number">20</span> <span class="number">16</span>:<span class="number">17</span>:<span class="number">16.310</span> INFO <span class="number">49750</span> --- [nio-<span class="number">8081</span>-exec-<span class="number">1</span>] o<span class="selector-class">.a</span><span class="selector-class">.c</span><span class="selector-class">.c</span><span class="selector-class">.C</span>.[Tomcat].[localhost].[/] : Initializing Spring FrameworkServlet <span class="string">'dispatcherServlet'</span></div><div class="line"><span class="number">2018</span>-<span class="number">11</span>-<span class="number">20</span> <span class="number">16</span>:<span class="number">17</span>:<span class="number">16.310</span> INFO <span class="number">49750</span> --- [nio-<span class="number">8081</span>-exec-<span class="number">1</span>] o<span class="selector-class">.s</span><span class="selector-class">.web</span><span class="selector-class">.servlet</span><span class="selector-class">.DispatcherServlet</span> : FrameworkServlet <span class="string">'dispatcherServlet'</span>: initialization started</div><div class="line"><span class="number">2018</span>-<span class="number">11</span>-<span class="number">20</span> <span class="number">16</span>:<span class="number">17</span>:<span class="number">16.327</span> INFO <span class="number">49750</span> --- [nio-<span class="number">8081</span>-exec-<span class="number">1</span>] o<span class="selector-class">.s</span><span class="selector-class">.web</span><span class="selector-class">.servlet</span><span class="selector-class">.DispatcherServlet</span> : FrameworkServlet <span class="string">'dispatcherServlet'</span>: initialization completed <span class="keyword">in</span> <span class="number">17</span> ms</div><div class="line"><span class="number">2018</span>-<span class="number">11</span>-<span class="number">20</span> <span class="number">16</span>:<span class="number">17</span>:<span class="number">16.578</span> INFO <span class="number">49750</span> --- [nio-<span class="number">8081</span>-exec-<span class="number">1</span>] c<span class="selector-class">.n</span><span class="selector-class">.e</span><span class="selector-class">.registry</span><span class="selector-class">.AbstractInstanceRegistry</span> : Registered instance EUREKA-SERVER/<span class="number">10.29</span>.<span class="number">181.63</span>:eureka-server:<span class="number">8081</span> with status UP (replication=true)</div><div class="line"><span class="number">2018</span>-<span class="number">11</span>-<span class="number">20</span> <span class="number">16</span>:<span class="number">17</span>:<span class="number">17.457</span> INFO <span class="number">49750</span> --- [nio-<span class="number">8081</span>-exec-<span class="number">2</span>] c<span class="selector-class">.n</span><span class="selector-class">.e</span><span class="selector-class">.registry</span><span class="selector-class">.AbstractInstanceRegistry</span> : Registered instance EUREKA-SERVER/<span class="number">10.29</span>.<span class="number">181.63</span>:eureka-server:<span class="number">8081</span> with status UP (replication=true)</div></pre></td></tr></table></figure>
<p><strong>Eureka Client端</strong></p>
<p>Account服务配置</p>
<figure class="highlight yaml"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div><div class="line">41</div></pre></td><td class="code"><pre><div class="line"><span class="attr">logging:</span></div><div class="line"><span class="attr"> level:</span></div><div class="line"> org.springframework.boot: info</div><div class="line"> org.springframework.cloud: debug</div><div class="line"><span class="attr">spring:</span></div><div class="line"><span class="attr"> application:</span></div><div class="line"><span class="attr"> name:</span> account-center</div><div class="line"><span class="attr">server:</span></div><div class="line"><span class="attr"> port:</span> <span class="number">8891</span></div><div class="line"><span class="attr">eureka:</span></div><div class="line"><span class="attr"> server:</span></div><div class="line"><span class="attr"> enable-self-preservation:</span> <span class="literal">false</span></div><div class="line"><span class="attr"> instance:</span></div><div class="line"><span class="attr"> prefer-ip-address:</span> <span class="literal">true</span></div><div class="line"><span class="attr"> instance-id:</span> ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}</div><div class="line"><span class="attr"> metadata-map:</span></div><div class="line"><span class="attr"> configPath:</span> ${server.servlet.context-path}</div><div class="line"><span class="attr"> home-page-url-path:</span> ${server.servlet.context-path}</div><div class="line"> <span class="comment">## 服务过期时间配置,超过这个时间没有接收到心跳EurekaServer就会将这个实例剔除</span></div><div class="line"><span class="attr"> lease-expiration-duration-in-seconds:</span> <span class="number">10</span></div><div class="line"> <span class="comment">## 服务刷新时间配置,每隔这个时间会主动心跳一次</span></div><div class="line"><span class="attr"> lease-renewal-interval-in-seconds:</span> <span class="number">5</span></div><div class="line"><span class="attr"> client:</span></div><div class="line"> <span class="comment">## 是否将自己注册到eureka</span></div><div class="line"><span class="attr"> register-with-eureka:</span> <span class="literal">true</span></div><div class="line"> <span class="comment">## 是否获取注册信息到本地</span></div><div class="line"><span class="attr"> fetch-registry:</span> <span class="literal">true</span></div><div class="line"> <span class="comment">## 开启DNS方式获取serviceUrl,默认为false</span></div><div class="line"><span class="attr"> use-dns-for-fetching-service-urls:</span> <span class="literal">true</span></div><div class="line"> <span class="comment">## DNS域名,获取其他信息将以该域名为根域名</span></div><div class="line"><span class="attr"> eureka-server-d-n-s-name:</span> zts.local</div><div class="line"> <span class="comment">## 当前应用所在区域,默认为us-east-1</span></div><div class="line"><span class="attr"> region:</span> beijing</div><div class="line"> <span class="comment">## 配置中心的eureka目录</span></div><div class="line"><span class="attr"> eureka-server-u-r-l-context:</span> eureka</div><div class="line"> <span class="comment">## 映射其他eurekaServer的端口,这里注意采用这种方式 server.port和这个端口最好一致</span></div><div class="line"> <span class="comment">## 因为dns是控制地址的变化,端口不变,所以不像前面的哪些配置方式可以自己定义url和port。</span></div><div class="line"> <span class="comment">## 所以每个IP都是用的相同的port进行注册中心服务的部署</span></div><div class="line"><span class="attr"> eureka-server-port:</span> <span class="number">8081</span></div><div class="line"> <span class="comment">## 获取serviceUrl时候是否优先获取相同zone的列表(如果获取为空则获取所在region第一个zone),如果为false则优先获取不在相同zone的列表</span></div><div class="line"><span class="attr"> prefer-same-zone-eureka:</span> <span class="literal">true</span></div></pre></td></tr></table></figure>
<p>Account启动日志:</p>
<figure class="highlight css"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div></pre></td><td class="code"><pre><div class="line">2018<span class="selector-tag">-11-20</span> 16<span class="selector-pseudo">:11</span><span class="selector-pseudo">:05.373</span> <span class="selector-tag">INFO</span> 5824 <span class="selector-tag">---</span> <span class="selector-attr">[ restartedMain]</span> <span class="selector-tag">c</span><span class="selector-class">.n</span><span class="selector-class">.d</span><span class="selector-class">.s</span><span class="selector-class">.r</span><span class="selector-class">.aws</span><span class="selector-class">.ConfigClusterResolver</span> : <span class="selector-tag">Resolving</span> <span class="selector-tag">eureka</span> <span class="selector-tag">endpoints</span> <span class="selector-tag">via</span> <span class="selector-tag">DNS</span>: <span class="selector-tag">txt</span><span class="selector-class">.beijing</span><span class="selector-class">.zts</span><span class="selector-class">.local</span> (<<span class="selector-tag">------</span>看这里)</div><div class="line">2018<span class="selector-tag">-11-20</span> 16<span class="selector-pseudo">:11</span><span class="selector-pseudo">:05.529</span> <span class="selector-tag">INFO</span> 5824 <span class="selector-tag">---</span> <span class="selector-attr">[ restartedMain]</span> <span class="selector-tag">com</span><span class="selector-class">.netflix</span><span class="selector-class">.discovery</span><span class="selector-class">.DiscoveryClient</span> : <span class="selector-tag">Disable</span> <span class="selector-tag">delta</span> <span class="selector-tag">property</span> : <span class="selector-tag">false</span></div><div class="line">2018<span class="selector-tag">-11-20</span> 16<span class="selector-pseudo">:11</span><span class="selector-pseudo">:05.529</span> <span class="selector-tag">INFO</span> 5824 <span class="selector-tag">---</span> <span class="selector-attr">[ restartedMain]</span> <span class="selector-tag">com</span><span class="selector-class">.netflix</span><span class="selector-class">.discovery</span><span class="selector-class">.DiscoveryClient</span> : <span class="selector-tag">Single</span> <span class="selector-tag">vip</span> <span class="selector-tag">registry</span> <span class="selector-tag">refresh</span> <span class="selector-tag">property</span> : <span class="selector-tag">null</span></div><div class="line">2018<span class="selector-tag">-11-20</span> 16<span class="selector-pseudo">:11</span><span class="selector-pseudo">:05.529</span> <span class="selector-tag">INFO</span> 5824 <span class="selector-tag">---</span> <span class="selector-attr">[ restartedMain]</span> <span class="selector-tag">com</span><span class="selector-class">.netflix</span><span class="selector-class">.discovery</span><span class="selector-class">.DiscoveryClient</span> : <span class="selector-tag">Force</span> <span class="selector-tag">full</span> <span class="selector-tag">registry</span> <span class="selector-tag">fetch</span> : <span class="selector-tag">false</span></div><div class="line">2018<span class="selector-tag">-11-20</span> 16<span class="selector-pseudo">:11</span><span class="selector-pseudo">:05.529</span> <span class="selector-tag">INFO</span> 5824 <span class="selector-tag">---</span> <span class="selector-attr">[ restartedMain]</span> <span class="selector-tag">com</span><span class="selector-class">.netflix</span><span class="selector-class">.discovery</span><span class="selector-class">.DiscoveryClient</span> : <span class="selector-tag">Application</span> <span class="selector-tag">is</span> <span class="selector-tag">null</span> : <span class="selector-tag">false</span></div><div class="line">201</div></pre></td></tr></table></figure>
<p>打开Eureka console,查看注册效果:<br><img src="https://raw.githubusercontent.com/roc-wong/images/master/eureka/eureka%E9%9B%86%E7%BE%A4%E5%90%AF%E5%8A%A8%E6%95%88%E6%9E%9C.png" alt="查看效果"></p>
<h2 id="参考资料"><a href="#参考资料" class="headerlink" title="参考资料"></a>参考资料</h2><h3 id="1-com-netflix-discovery-endpoint-EndpointUtils-getServiceUrlsFromDNS"><a href="#1-com-netflix-discovery-endpoint-EndpointUtils-getServiceUrlsFromDNS" class="headerlink" title="1.com.netflix.discovery.endpoint.EndpointUtils.getServiceUrlsFromDNS"></a>1.com.netflix.discovery.endpoint.EndpointUtils.getServiceUrlsFromDNS</h3><p>版本:eureka-client:1.9.3 </p>
<figure class="highlight processing"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div><div class="line">41</div><div class="line">42</div><div class="line">43</div><div class="line">44</div><div class="line">45</div><div class="line">46</div><div class="line">47</div><div class="line">48</div><div class="line">49</div><div class="line">50</div><div class="line">51</div><div class="line">52</div><div class="line">53</div><div class="line">54</div><div class="line">55</div><div class="line">56</div><div class="line">57</div><div class="line">58</div><div class="line">59</div><div class="line">60</div><div class="line">61</div><div class="line">62</div><div class="line">63</div><div class="line">64</div><div class="line">65</div><div class="line">66</div><div class="line">67</div><div class="line">68</div><div class="line">69</div><div class="line">70</div><div class="line">71</div><div class="line">72</div><div class="line">73</div><div class="line">74</div><div class="line">75</div><div class="line">76</div><div class="line">77</div><div class="line">78</div><div class="line">79</div><div class="line">80</div><div class="line">81</div><div class="line">82</div><div class="line">83</div><div class="line">84</div><div class="line">85</div><div class="line">86</div><div class="line">87</div><div class="line">88</div><div class="line">89</div><div class="line">90</div><div class="line">91</div><div class="line">92</div><div class="line">93</div><div class="line">94</div><div class="line">95</div><div class="line">96</div><div class="line">97</div><div class="line">98</div><div class="line">99</div><div class="line">100</div><div class="line">101</div><div class="line">102</div><div class="line">103</div><div class="line">104</div><div class="line">105</div><div class="line">106</div><div class="line">107</div><div class="line">108</div><div class="line">109</div><div class="line">110</div><div class="line">111</div><div class="line">112</div><div class="line">113</div><div class="line">114</div><div class="line">115</div><div class="line">116</div></pre></td><td class="code"><pre><div class="line"><span class="comment">/**</span></div><div class="line"> * Get the list of all eureka service urls for the eureka client to talk to.</div><div class="line"> *</div><div class="line"> * @param clientConfig the clientConfig to use</div><div class="line"> * @param zone the zone in which the client resides</div><div class="line"> * @param randomizer a randomizer to randomized returned urls, if loading from dns</div><div class="line"> *</div><div class="line"> * @return The list of all eureka service urls for the eureka client to talk to.</div><div class="line"> */</div><div class="line"> <span class="keyword">public</span> <span class="keyword">static</span> List<<span class="keyword">String</span>> getDiscoveryServiceUrls(EurekaClientConfig clientConfig, <span class="keyword">String</span> zone, ServiceUrlRandomizer randomizer) {</div><div class="line"> <span class="built_in">boolean</span> shouldUseDns = clientConfig.shouldUseDnsForFetchingServiceUrls();</div><div class="line"> <span class="keyword">if</span> (shouldUseDns) {</div><div class="line"> <span class="keyword">return</span> getServiceUrlsFromDNS(clientConfig, zone, clientConfig.shouldPreferSameZoneEureka(), randomizer);</div><div class="line"> }</div><div class="line"> <span class="keyword">return</span> getServiceUrlsFromConfig(clientConfig, zone, clientConfig.shouldPreferSameZoneEureka());</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="comment">/**</span></div><div class="line"> * Get the list of all eureka service urls from DNS for the eureka client to</div><div class="line"> * talk to. The client picks up the service url from its zone and then fails over to</div><div class="line"> * other zones randomly. If there are multiple servers in the same zone, the client once</div><div class="line"> * again picks one randomly. This way the traffic will be distributed in the case of failures.</div><div class="line"> *</div><div class="line"> * @param clientConfig the clientConfig to use</div><div class="line"> * @param instanceZone The zone in which the client resides.</div><div class="line"> * @param preferSameZone true if we have to prefer the same zone as the client, false otherwise.</div><div class="line"> * @param randomizer a randomizer to randomized returned urls</div><div class="line"> *</div><div class="line"> * @return The list of all eureka service urls for the eureka client to talk to.</div><div class="line"> */</div><div class="line"> <span class="keyword">public</span> <span class="keyword">static</span> List<<span class="keyword">String</span>> getServiceUrlsFromDNS(EurekaClientConfig clientConfig, <span class="keyword">String</span> instanceZone, <span class="built_in">boolean</span> preferSameZone, ServiceUrlRandomizer randomizer) {</div><div class="line"> <span class="keyword">String</span> region = getRegion(clientConfig);</div><div class="line"> <span class="comment">// Get zone-specific DNS names for the given region so that we can get a</span></div><div class="line"> <span class="comment">// list of available zones</span></div><div class="line"> Map<<span class="keyword">String</span>, List<<span class="keyword">String</span>>> zoneDnsNamesMap = getZoneBasedDiscoveryUrlsFromRegion(clientConfig, region);</div><div class="line"> Set<<span class="keyword">String</span>> availableZones = zoneDnsNamesMap.keySet();</div><div class="line"> List<<span class="keyword">String</span>> zones = <span class="keyword">new</span> ArrayList<<span class="keyword">String</span>>(availableZones);</div><div class="line"> <span class="keyword">if</span> (zones.isEmpty()) {</div><div class="line"> <span class="keyword">throw</span> <span class="keyword">new</span> RuntimeException(<span class="string">"No available zones configured for the instanceZone "</span> + instanceZone);</div><div class="line"> }</div><div class="line"> <span class="built_in">int</span> zoneIndex = <span class="number">0</span>;</div><div class="line"> <span class="built_in">boolean</span> zoneFound = <span class="keyword">false</span>;</div><div class="line"> <span class="keyword">for</span> (<span class="keyword">String</span> zone : zones) {</div><div class="line"> logger.debug(<span class="string">"Checking if the instance zone {} is the same as the zone from DNS {}"</span>, instanceZone, zone);</div><div class="line"> <span class="keyword">if</span> (preferSameZone) {</div><div class="line"> <span class="keyword">if</span> (instanceZone.equalsIgnoreCase(zone)) {</div><div class="line"> zoneFound = <span class="keyword">true</span>;</div><div class="line"> }</div><div class="line"> } <span class="keyword">else</span> {</div><div class="line"> <span class="keyword">if</span> (!instanceZone.equalsIgnoreCase(zone)) {</div><div class="line"> zoneFound = <span class="keyword">true</span>;</div><div class="line"> }</div><div class="line"> }</div><div class="line"> <span class="keyword">if</span> (zoneFound) {</div><div class="line"> logger.debug(<span class="string">"The zone index from the list {} that matches the instance zone {} is {}"</span>,</div><div class="line"> zones, instanceZone, zoneIndex);</div><div class="line"> <span class="keyword">break</span>;</div><div class="line"> }</div><div class="line"> zoneIndex++;</div><div class="line"> }</div><div class="line"> <span class="keyword">if</span> (zoneIndex >= zones.<span class="built_in">size</span>()) {</div><div class="line"> <span class="keyword">if</span> (logger.isWarnEnabled()) {</div><div class="line"> logger.warn(<span class="string">"No match for the zone {} in the list of available zones {}"</span>,</div><div class="line"> instanceZone, zones.toArray());</div><div class="line"> }</div><div class="line"> } <span class="keyword">else</span> {</div><div class="line"> <span class="comment">// Rearrange the zones with the instance zone first</span></div><div class="line"> <span class="keyword">for</span> (<span class="built_in">int</span> i = <span class="number">0</span>; i < zoneIndex; i++) {</div><div class="line"> <span class="keyword">String</span> zone = zones.remove(<span class="number">0</span>);</div><div class="line"> zones.<span class="built_in">add</span>(zone);</div><div class="line"> }</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="comment">// Now get the eureka urls for all the zones in the order and return it</span></div><div class="line"> List<<span class="keyword">String</span>> serviceUrls = <span class="keyword">new</span> ArrayList<<span class="keyword">String</span>>();</div><div class="line"> <span class="keyword">for</span> (<span class="keyword">String</span> zone : zones) {</div><div class="line"> <span class="keyword">for</span> (<span class="keyword">String</span> zoneCname : zoneDnsNamesMap.<span class="built_in">get</span>(zone)) {</div><div class="line"> List<<span class="keyword">String</span>> ec2Urls = <span class="keyword">new</span> ArrayList<<span class="keyword">String</span>>(getEC2DiscoveryUrlsFromZone(zoneCname, DiscoveryUrlType.CNAME));</div><div class="line"> <span class="comment">// Rearrange the list to distribute the load in case of multiple servers</span></div><div class="line"> <span class="keyword">if</span> (ec2Urls.<span class="built_in">size</span>() > <span class="number">1</span>) {</div><div class="line"> randomizer.randomize(ec2Urls);</div><div class="line"> }</div><div class="line"> <span class="keyword">for</span> (<span class="keyword">String</span> ec2Url : ec2Urls) {</div><div class="line"> StringBuilder sb = <span class="keyword">new</span> StringBuilder()</div><div class="line"> .<span class="built_in">append</span>(<span class="string">"http://"</span>)</div><div class="line"> .<span class="built_in">append</span>(ec2Url)</div><div class="line"> .<span class="built_in">append</span>(<span class="string">":"</span>)</div><div class="line"> .<span class="built_in">append</span>(clientConfig.getEurekaServerPort());</div><div class="line"> <span class="keyword">if</span> (clientConfig.getEurekaServerURLContext() != <span class="keyword">null</span>) {</div><div class="line"> <span class="keyword">if</span> (!clientConfig.getEurekaServerURLContext().startsWith(<span class="string">"/"</span>)) {</div><div class="line"> sb.<span class="built_in">append</span>(<span class="string">"/"</span>);</div><div class="line"> }</div><div class="line"> sb.<span class="built_in">append</span>(clientConfig.getEurekaServerURLContext());</div><div class="line"> <span class="keyword">if</span> (!clientConfig.getEurekaServerURLContext().endsWith(<span class="string">"/"</span>)) {</div><div class="line"> sb.<span class="built_in">append</span>(<span class="string">"/"</span>);</div><div class="line"> }</div><div class="line"> } <span class="keyword">else</span> {</div><div class="line"> sb.<span class="built_in">append</span>(<span class="string">"/"</span>);</div><div class="line"> }</div><div class="line"> <span class="keyword">String</span> serviceUrl = sb.toString();</div><div class="line"> logger.debug(<span class="string">"The EC2 url is {}"</span>, serviceUrl);</div><div class="line"> serviceUrls.<span class="built_in">add</span>(serviceUrl);</div><div class="line"> }</div><div class="line"> }</div><div class="line"> }</div><div class="line"> <span class="comment">// Rearrange the fail over server list to distribute the load</span></div><div class="line"> <span class="keyword">String</span> primaryServiceUrl = serviceUrls.remove(<span class="number">0</span>);</div><div class="line"> randomizer.randomize(serviceUrls);</div><div class="line"> serviceUrls.<span class="built_in">add</span>(<span class="number">0</span>, primaryServiceUrl);</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (logger.isDebugEnabled()) {</div><div class="line"> logger.debug(<span class="string">"This client will talk to the following serviceUrls in order : {} "</span>,</div><div class="line"> (<span class="keyword">Object</span>) serviceUrls.toArray());</div><div class="line"> }</div><div class="line"> <span class="keyword">return</span> serviceUrls;</div><div class="line"> }</div></pre></td></tr></table></figure>
<h3 id="2-dns-config配置参考文章"><a href="#2-dns-config配置参考文章" class="headerlink" title="2. dns config配置参考文章"></a>2. dns config配置参考文章</h3><ul>
<li><a href="https://www.todaysoftmag.com/article/1429/micro-service-discovery-using-netflix-eureka" target="_blank" rel="external">micro-service-discovery-using-netflix-eureka</a></li>
<li><a href="http://www.cnblogs.com/relinson/p/eureka_ha_use_dns.html" target="_blank" rel="external">eureka集群基于DNS配置方式</a> (给予我了不少灵感)</li>
<li><a href="https://blog.csdn.net/ankeway/article/details/79745810" target="_blank" rel="external">Spring Cloud Eureka 集群使用DNS方式进行服务分区</a>(– 简单介绍了windows dns搭建)</li>
</ul>
]]></content>
<summary type="html">
基于DNS服务器搭建Eureka动态集群,由DNS服务器负责维护Eureka serverUrl,弹性伸缩对eureka client端无影响。
</summary>
<category term="SpringCloud" scheme="https://roc-wong.github.io/categories/SpringCloud/"/>
<category term="MicroServices" scheme="https://roc-wong.github.io/categories/SpringCloud/MicroServices/"/>
<category term="SpringCloud" scheme="https://roc-wong.github.io/tags/SpringCloud/"/>
<category term="Eureka" scheme="https://roc-wong.github.io/tags/Eureka/"/>
</entry>
<entry>
<title>CentOS 搭建DNS主从服务器集群</title>
<link href="https://roc-wong.github.io/blog/2018/11/Centos%E6%90%AD%E5%BB%BADNS%E4%B8%BB%E4%BB%8E%E6%9C%8D%E5%8A%A1%E5%99%A8%E9%9B%86%E7%BE%A4.html"/>
<id>https://roc-wong.github.io/blog/2018/11/Centos搭建DNS主从服务器集群.html</id>
<published>2018-11-19T13:32:17.000Z</published>
<updated>2018-11-21T02:18:25.558Z</updated>
<content type="html"><![CDATA[<p>BIND(Berkeley internet Name Daemon)也叫做NAMED,是现今互联网上使用最为广泛的DNS 服务器程序。这篇文章将要讲述如何在 chroot 监牢中运行 BIND,这样它就无法访问文件系统中除“监牢”以外的其它部分。</p>
<p>在这篇文章中,我会将BIND的运行根目录改为 /var/named/chroot/。当然,对于BIND来说,这个目录就是 /(根目录)。 “jail”(监牢,下同)是一个软件机制,其功能是使得某个程序无法访问规定区域之外的资源,同样也为了增强安全性(LCTT 译注:chroot “监牢”,所谓“监牢”就是指通过chroot机制来更改某个进程所能看到的根目录,即将某进程限制在指定目录中,保证该进程只能对该目录及其子目录的文件进行操作,从而保证整个服务器的安全)。Bind Chroot DNS 服务器的默认“监牢”为 /var/named/chroot。</p>
<h2 id="基本环境"><a href="#基本环境" class="headerlink" title="基本环境"></a>基本环境</h2><p>10.29.181.61 Master DNS服务器<br>10.29.181.62 Slave DNS服务器</p>
<p>DNS服务器的合法域名:zts.local</p>
<p><strong>要求</strong></p>
<p>允许所有来源的主机对改域名进行解析,内网其他主机访问外网时候走ISP的DNS,只解析内网IP主机的请求进行转发,不会对外网主机的解析请求进行转发。</p>
<h2 id="搭建主从DNS服务器集群"><a href="#搭建主从DNS服务器集群" class="headerlink" title="搭建主从DNS服务器集群"></a>搭建主从DNS服务器集群</h2><h3 id="1、安装Bind-Chroot-DNS-服务器"><a href="#1、安装Bind-Chroot-DNS-服务器" class="headerlink" title="1、安装Bind Chroot DNS 服务器"></a>1、安装Bind Chroot DNS 服务器</h3><figure class="highlight fortran"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">[root@nrozntgbd2 ~]# yum install <span class="keyword">bind</span>-chroot <span class="keyword">bind</span> <span class="keyword">bind</span>-utils dig -y</div></pre></td></tr></table></figure>
<h3 id="2、拷贝bind相关文件-准备bind-chroot-环境"><a href="#2、拷贝bind相关文件-准备bind-chroot-环境" class="headerlink" title="2、拷贝bind相关文件,准备bind chroot 环境"></a>2、拷贝bind相关文件,准备bind chroot 环境</h3><figure class="highlight gradle"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">[root@nrozntgbd2 ~]# cp -R <span class="regexp">/usr/</span>share<span class="regexp">/doc/</span>bind-*<span class="regexp">/sample/</span>var<span class="regexp">/named/</span>* <span class="regexp">/var/</span>named<span class="regexp">/chroot/</span>var<span class="regexp">/named/</span></div></pre></td></tr></table></figure>
<h3 id="3、在bind-chroot-的目录中创建相关文件"><a href="#3、在bind-chroot-的目录中创建相关文件" class="headerlink" title="3、在bind chroot 的目录中创建相关文件"></a>3、在bind chroot 的目录中创建相关文件</h3><figure class="highlight kotlin"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div></pre></td><td class="code"><pre><div class="line">[<span class="symbol">root@</span>nrozntgbd2 ~]# touch /<span class="keyword">var</span>/named/chroot/<span class="keyword">var</span>/named/<span class="keyword">data</span>/cache_dump.db</div><div class="line">[<span class="symbol">root@</span>nrozntgbd2 ~]# touch /<span class="keyword">var</span>/named/chroot/<span class="keyword">var</span>/named/<span class="keyword">data</span>/named_stats.txt</div><div class="line">[<span class="symbol">root@</span>nrozntgbd2 ~]# touch /<span class="keyword">var</span>/named/chroot/<span class="keyword">var</span>/named/<span class="keyword">data</span>/named_mem_stats.txt</div><div class="line">[<span class="symbol">root@</span>nrozntgbd2 ~]# touch /<span class="keyword">var</span>/named/chroot/<span class="keyword">var</span>/named/<span class="keyword">data</span>/named.run</div><div class="line">[<span class="symbol">root@</span>nrozntgbd2 ~]# mkdir /<span class="keyword">var</span>/named/chroot/<span class="keyword">var</span>/named/<span class="keyword">dynamic</span></div><div class="line">[<span class="symbol">root@</span>nrozntgbd2 ~]# touch /<span class="keyword">var</span>/named/chroot/<span class="keyword">var</span>/named/<span class="keyword">dynamic</span>/managed-keys.bind</div></pre></td></tr></table></figure>
<h3 id="4、-将-Bind-锁定文件设置为可写"><a href="#4、-将-Bind-锁定文件设置为可写" class="headerlink" title="4、 将 Bind 锁定文件设置为可写"></a>4、 将 Bind 锁定文件设置为可写</h3><figure class="highlight kotlin"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">[<span class="symbol">root@</span>nrozntgbd2 ~]# chmod -R <span class="number">777</span> /<span class="keyword">var</span>/named/chroot/<span class="keyword">var</span>/named/<span class="keyword">data</span></div><div class="line">[<span class="symbol">root@</span>nrozntgbd2 ~]# chmod -R <span class="number">777</span> /<span class="keyword">var</span>/named/chroot/<span class="keyword">var</span>/named/<span class="keyword">dynamic</span></div></pre></td></tr></table></figure>
<h3 id="5、-将-etc-named-conf-拷贝到-bind-chroot目录"><a href="#5、-将-etc-named-conf-拷贝到-bind-chroot目录" class="headerlink" title="5、 将 /etc/named.conf 拷贝到 bind chroot目录"></a>5、 将 /etc/named.conf 拷贝到 bind chroot目录</h3><figure class="highlight fortran"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">[root@nrozntgbd2 ~]# cp -p /etc/<span class="keyword">named</span>.conf /var/<span class="keyword">named</span>/chroot/etc/<span class="keyword">named</span>.conf</div></pre></td></tr></table></figure>
<h3 id="6、-在-etc-named-conf中对-bind-进行配置"><a href="#6、-在-etc-named-conf中对-bind-进行配置" class="headerlink" title="6、 在/etc/named.conf中对 bind 进行配置"></a>6、 在/etc/named.conf中对 bind 进行配置</h3><p>在 named.conf 文件尾添加 zts.local 域信息, 创建转发域(Forward Zone)与反向域(Reverse Zone)(LCTT 译注:这里zts.local 并非一个真实有效的互联网域名,而是通常用于本地测试的一个域名;如果你需要做权威 DNS 解析,你可以将你拥有的域名如这里所示配置解析。):</p>
<p>[root@nrozntgbd2 ~]# vi /var/named/chroot/etc/named.conf</p>
<p>a. 编辑配置文件/etc/named.conf,找到listen-on这一行,改为:</p>
<figure class="highlight applescript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">listen-<span class="keyword">on</span> port <span class="number">53</span> { any; }; <span class="comment">#any是匹配所有的意思</span></div></pre></td></tr></table></figure>
<p>b. 找到allow-query这一行,改为:</p>
<figure class="highlight abnf"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">allow-query { any<span class="comment">; };</span></div></pre></td></tr></table></figure>
<p>c. 添加要解析的域</p>
<figure class="highlight stata"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div></pre></td><td class="code"><pre><div class="line"><span class="comment">//正向解析</span></div><div class="line">zone <span class="string">"zts.local"</span> {</div><div class="line"> <span class="keyword">type</span> master;</div><div class="line"> <span class="keyword">file</span> <span class="string">"zts.local.zone"</span>;</div><div class="line">};</div><div class="line"></div><div class="line"><span class="comment">//反向解析</span></div><div class="line">zone <span class="string">"181.29.10.in-addr.arpa"</span> <span class="keyword">IN</span> {</div><div class="line"> <span class="keyword">type</span> master;</div><div class="line"> <span class="keyword">file</span> <span class="string">"10.29.181.zone"</span>;</div><div class="line">};</div></pre></td></tr></table></figure>
<p>d. 对DNS配置文件进行一下语法检查:<code>named-checkconf /var/named/chroot/etc/named.conf</code></p>
<p><strong>named.conf 完全配置如下:</strong></p>
<figure class="highlight stata"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div><div class="line">41</div><div class="line">42</div><div class="line">43</div><div class="line">44</div><div class="line">45</div><div class="line">46</div><div class="line">47</div><div class="line">48</div><div class="line">49</div><div class="line">50</div><div class="line">51</div><div class="line">52</div><div class="line">53</div><div class="line">54</div><div class="line">55</div><div class="line">56</div><div class="line">57</div><div class="line">58</div><div class="line">59</div><div class="line">60</div><div class="line">61</div><div class="line">62</div><div class="line">63</div><div class="line">64</div></pre></td><td class="code"><pre><div class="line"><span class="comment">//</span></div><div class="line"><span class="comment">// named.conf</span></div><div class="line"><span class="comment">//</span></div><div class="line"><span class="comment">// 由Red Hat提供,将 ISC BIND named(8) DNS服务器 </span></div><div class="line"><span class="comment">// 配置为暂存域名服务器 (用来做本地DNS解析).</span></div><div class="line"><span class="comment">//</span></div><div class="line"><span class="comment">// See /usr/share/doc/bind*/sample/ for example named configuration files.</span></div><div class="line"><span class="comment">//</span></div><div class="line"></div><div class="line">options {</div><div class="line"> listen-<span class="keyword">on</span> port 53 { any; };</div><div class="line"> listen-<span class="keyword">on</span>-v6 port 53 { ::1; };</div><div class="line"> directory <span class="string">"/var/named"</span>;</div><div class="line"> dump-<span class="keyword">file</span> <span class="string">"/var/named/data/cache_dump.db"</span>;</div><div class="line"> statistics-<span class="keyword">file</span> <span class="string">"/var/named/data/named_stats.txt"</span>;</div><div class="line"> memstatistics-<span class="keyword">file</span> <span class="string">"/var/named/data/named_mem_stats.txt"</span>;</div><div class="line"> allow-<span class="keyword">query</span> { any; };</div><div class="line"></div><div class="line"> <span class="comment">/*</span></div><div class="line"> - 如果你要建立一个 授权域名服务器 服务器, 那么不要开启 recursion(递归) 功能。</div><div class="line"> - 如果你要建立一个 递归 DNS 服务器, 那么需要开启recursion 功能。</div><div class="line"> - 如果你的递归DNS服务器有公网IP地址, 你必须开启访问控制功能,</div><div class="line"> 只有那些合法用户才可以发询问. 如果不这么做的话,那么你的服</div><div class="line"> 服务就会受到DNS 放大攻击。实现BCP38将有效抵御这类攻击。</div><div class="line"> */</div><div class="line"> recursion yes;</div><div class="line"></div><div class="line"> dnssec-enable yes;</div><div class="line"> dnssec-validation yes;</div><div class="line"> dnssec-lookaside auto;</div><div class="line"></div><div class="line"> <span class="comment">/* Path to ISC DLV key */</span></div><div class="line"> bindkeys-<span class="keyword">file</span> <span class="string">"/etc/named.iscdlv.key"</span>;</div><div class="line"></div><div class="line"> managed-keys-directory <span class="string">"/var/named/dynamic"</span>;</div><div class="line"></div><div class="line"> pid-<span class="keyword">file</span> <span class="string">"/run/named/named.pid"</span>;</div><div class="line"> session-keyfile <span class="string">"/run/named/session.key"</span>;</div><div class="line">};</div><div class="line"></div><div class="line">logging {</div><div class="line"> channel default_debug {</div><div class="line"> <span class="keyword">file</span> <span class="string">"data/named.run"</span>;</div><div class="line"> severity dynamic;</div><div class="line"> };</div><div class="line">};</div><div class="line"></div><div class="line">zone <span class="string">"."</span> <span class="keyword">IN</span> {</div><div class="line"> <span class="keyword">type</span> hint;</div><div class="line"> <span class="keyword">file</span> <span class="string">"named.ca"</span>;</div><div class="line">};</div><div class="line"></div><div class="line">zone <span class="string">"zts.local"</span> {</div><div class="line"> <span class="keyword">type</span> master;</div><div class="line"> <span class="keyword">file</span> <span class="string">"zts.local.zone"</span>;</div><div class="line">};</div><div class="line"></div><div class="line">zone <span class="string">"181.29.10.in-addr.arpa"</span> <span class="keyword">IN</span> {</div><div class="line"> <span class="keyword">type</span> master;</div><div class="line"> <span class="keyword">file</span> <span class="string">"10.29.181.zone"</span>;</div><div class="line">};</div><div class="line"></div><div class="line"><span class="keyword">include</span> <span class="string">"/etc/named.rfc1912.zones"</span>;</div><div class="line"><span class="keyword">include</span> <span class="string">"/etc/named.root.key"</span>;</div></pre></td></tr></table></figure>
<h3 id="7、-为-zts-local-域名创建转发域与反向域文件"><a href="#7、-为-zts-local-域名创建转发域与反向域文件" class="headerlink" title="7、 为 zts.local 域名创建转发域与反向域文件"></a>7、 为 zts.local 域名创建转发域与反向域文件</h3><h4 id="a-创建转发域"><a href="#a-创建转发域" class="headerlink" title="a)创建转发域"></a>a)创建转发域</h4><p><code>[root@nrozntgbd2 ~]# vi /var/named/chroot/var/named/zts.local.zone</code></p>
<p>添加如下内容并保存:<br><figure class="highlight mipsasm"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div><div class="line">41</div><div class="line">42</div><div class="line">43</div><div class="line">44</div><div class="line">45</div><div class="line">46</div><div class="line">47</div><div class="line">48</div><div class="line">49</div><div class="line">50</div><div class="line">51</div><div class="line">52</div><div class="line">53</div><div class="line">54</div><div class="line">55</div><div class="line">56</div><div class="line">57</div><div class="line">58</div><div class="line">59</div><div class="line">60</div><div class="line">61</div><div class="line">62</div><div class="line">63</div><div class="line">64</div><div class="line">65</div><div class="line">66</div><div class="line">67</div><div class="line">68</div><div class="line">69</div><div class="line">70</div><div class="line">71</div></pre></td><td class="code"><pre><div class="line">$<span class="keyword">ORIGIN </span>zts.local.</div><div class="line">$TTL <span class="number">86400</span></div><div class="line"><span class="comment">;</span></div><div class="line"><span class="comment">;在zone的配置文件中,它是以分号来作为批注语句标识符的。</span></div><div class="line"><span class="comment">;修改这个配置文件时,要注意,名称最后面没有加句点的是主机名,最后面加了句点的是FQDN(除了$ORIGIN那里)。</span></div><div class="line"><span class="comment">;$ORIGIN那里填域名。下面的@符号会引用这里填写的值。如果不填,则会引用主配置文件中zone语句后面的值。</span></div><div class="line"><span class="comment">;$TTL表示timeto live值,表示当其它DNS查询到本zone的DNS记录时,这个记录能在它的DNS缓存中存在多久,单位为秒。</span></div><div class="line">@ IN SOA dns1.zts.local. roc.fly.qq.com. (</div><div class="line"> <span class="number">2018111901</span></div><div class="line"> <span class="number">1</span>H</div><div class="line"> <span class="number">5</span>m</div><div class="line"> <span class="number">2</span>D</div><div class="line"> <span class="number">6</span>H )</div><div class="line"><span class="comment">;</span></div><div class="line"><span class="comment">;SOA后面的两个参数分别是主DNS服务器主机名和管理者邮箱([email protected])。因为@符号有特殊含义,所以写成这样。</span></div><div class="line"><span class="comment">;括号内的第一个参数是序号,代表本配置文档的新旧,序号越大,表示越新。每次修改本文档后,都要将这个值改大。</span></div><div class="line"><span class="comment">;第二个参数是刷新频率,表示slave隔多久会跟master比对一次配置档案,单位为秒。</span></div><div class="line"><span class="comment">;第三个参数是失败重新尝试时间,单位为秒</span></div><div class="line"><span class="comment">;第四个参数是失效时间,单位为秒。</span></div><div class="line"><span class="comment">;在BIND9中,第五个参数表示其它DNS服务器能缓存negative answers的时间,单位为秒。</span></div><div class="line"><span class="comment">;</span></div><div class="line"></div><div class="line"></div><div class="line">@ IN NS dns1.zts.local.</div><div class="line"> IN NS dns2.zts.local.</div><div class="line">dns1 IN A <span class="number">10</span>.<span class="number">29</span>.<span class="number">181</span>.<span class="number">61</span></div><div class="line">dns2 IN A <span class="number">10</span>.<span class="number">29</span>.<span class="number">181</span>.<span class="number">62</span></div><div class="line"><span class="comment">;</span></div><div class="line"><span class="comment">;类型NS定义指定域的DNS服务器主机名(如dns1.zts.local),不管是主DNS还是从DNS。</span></div><div class="line"><span class="comment">;类型A定义指定主机(如dns1)的IP地址。如果是使用的IPv6地址,则需使用类型AAAA。</span></div><div class="line"><span class="comment">;</span></div><div class="line"></div><div class="line"></div><div class="line"><span class="comment">;@ IN MX 10 mail1.zts.local.</span></div><div class="line"><span class="comment">; IN MX 20 mail2.zts.local.</span></div><div class="line"><span class="comment">;mail1 IN A 10.29.181.61</span></div><div class="line"><span class="comment">;mail2 IN A 10.29.181.62</span></div><div class="line"><span class="comment">;</span></div><div class="line"><span class="comment">;类型MX定义指定域的邮件服务器主机名(如mail1.zts.local)。</span></div><div class="line"><span class="comment">;MX后面的数字为优先级,越小越优先。同样的优先级值则可以在多台邮件服务器之间进行负载分担。</span></div><div class="line"><span class="comment">;</span></div><div class="line"></div><div class="line"></div><div class="line"><span class="comment">;www IN CNAME servs.zts.local.</span></div><div class="line"><span class="comment">;ftp IN CNAME servs.zts.local.</span></div><div class="line"><span class="comment">;servs IN A 10.29.181.6</span></div><div class="line"><span class="comment">;</span></div><div class="line"><span class="comment">;类型CNAME用于定义别名。通常用于同一台主机提供多个服务的情况。</span></div><div class="line"><span class="comment">;以这里的设定为例,当要解析ftp.zts.local的IP时,它会解析成主机servs.zts.local的IP。</span></div><div class="line"><span class="comment">;</span></div><div class="line"></div><div class="line"></div><div class="line">forum IN A <span class="number">10</span>.<span class="number">29</span>.<span class="number">181</span>.<span class="number">61</span></div><div class="line"><span class="comment">;travel IN A 10.29.181.8</span></div><div class="line"><span class="comment">; IN A 10.29.181.9</span></div><div class="line"><span class="comment">;</span></div><div class="line"><span class="comment">;如上面所示,也可以直接设定某一台主机(如forum.zts.local)的IP。</span></div><div class="line"><span class="comment">;同一台主机(如travel.zts.local)也可以设定多个IP。</span></div><div class="line"></div><div class="line"></div><div class="line"></div><div class="line"><span class="comment">; eureka cluster配置</span></div><div class="line">txt.<span class="keyword">shanghai </span>IN TXT <span class="string">"defaultZone.zts.local"</span></div><div class="line">txt.defaultZone IN TXT <span class="string">"10.29.181.56"</span> <span class="string">"10.29.181.57"</span> <span class="string">"10.29.181.58"</span> <span class="string">"10.29.181.60"</span></div><div class="line"></div><div class="line"><span class="comment">;通过查看Eureka的源码,它的实现是通过寻找txt.beijing-a.zts.local(txt.region.eureka-server-d-n-s-name)获取"beijing-a.zts.local" "beijing-b.zts.local"的zone:beijing-a和beijing-b,</span></div><div class="line"><span class="comment">;然后再去获取txt.beijing-a.zts.local和txt.beijing-b.zts.local中对应的ServiceUrls的数据,也就是IP地址: "10.29.181.61" "10.29.181.62"</span></div><div class="line"><span class="comment">;这样服务间就可以获取到固定端口下的不同IP的机器的注册中心服务地址,并相互注册</span></div><div class="line">txt.<span class="keyword">beijing </span>IN TXT <span class="string">"beijing-a.zts.local"</span> <span class="string">"beijing-b.zts.local"</span></div><div class="line">txt.<span class="keyword">beijing-a </span>IN TXT <span class="string">"10.29.181.61"</span> <span class="string">"10.29.181.62"</span></div><div class="line">txt.<span class="keyword">beijing-b </span>IN TXT <span class="string">"10.29.181.63"</span> <span class="string">"10.29.181.64"</span></div></pre></td></tr></table></figure></p>
<p>对区域文件进行有效性检查:<br><figure class="highlight css"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line"><span class="selector-tag">named-checkzone</span> 181<span class="selector-class">.29</span><span class="selector-class">.10</span><span class="selector-class">.in-addr</span><span class="selector-class">.arpa</span> 10<span class="selector-class">.29</span><span class="selector-class">.181</span><span class="selector-class">.zone</span></div></pre></td></tr></table></figure></p>
<h4 id="b-创建反向域"><a href="#b-创建反向域" class="headerlink" title="b)创建反向域"></a>b)创建反向域</h4><p><code>[root@nrozntgbd2 ~]# vi /var/named/chroot/var/named/10.29.181.zone</code></p>
<figure class="highlight lasso"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div></pre></td><td class="code"><pre><div class="line">$ORIGIN <span class="number">181.29</span><span class="number">.10</span>.<span class="keyword">in</span><span class="params">-addr.arpa.</span></div><div class="line">$TTL <span class="number">86400</span></div><div class="line">;</div><div class="line">;在zone的配置文件中,它是以分号来作为批注语句标识符的。</div><div class="line">;修改这个配置文件时,要注意,名称最后面没有加句点的是主机名,最后面加了句点的是FQDN(除了$ORIGIN那里)。</div><div class="line">;$ORIGIN那里填域名。下面的@符号会引用这里填写的值。如果不填,则会引用主配置文件中zone语句后面的值。</div><div class="line">;$TTL表示timeto live值,表示当其它DNS查询到本zone的DNS记录时,这个记录能在它的DNS缓存中存在多久,单位为秒。</div><div class="line">@ <span class="keyword">IN</span> SOA dns1.zts.<span class="built_in">local</span>. roc.fly.qq.com. (</div><div class="line"> <span class="number">2018111902</span></div><div class="line"> <span class="number">1</span>H</div><div class="line"> <span class="number">5</span>m</div><div class="line"> <span class="number">2</span>D</div><div class="line"> <span class="number">6</span>H )</div><div class="line">;</div><div class="line">;SOA后面的两个参数分别是主DNS服务器主机名和管理者邮箱(xie@zts.<span class="built_in">local</span>)。因为@符号有特殊含义,所以写成这样。</div><div class="line">;括号内的第一个参数是序号,代表本配置文档的新旧,序号越大,表示越新。每次修改本文档后,都要将这个值改大。</div><div class="line">;第二个参数是刷新频率,表示slave隔多久会跟master比对一次配置档案,单位为秒。</div><div class="line">;第三个参数是失败重新尝试时间,单位为秒</div><div class="line">;第四个参数是失效时间,单位为秒。</div><div class="line">;在BIND9中,第五个参数表示其它DNS服务器能缓存negative answers的时间,单位为秒。</div><div class="line">;</div><div class="line"></div><div class="line">;<span class="number">61.181</span><span class="number">.29</span><span class="number">.10</span>.<span class="keyword">in</span><span class="params">-addr.arpa.</span> <span class="keyword">IN</span> PTR dns1.zts.<span class="built_in">local</span>.</div><div class="line">;<span class="number">62.181</span><span class="number">.29</span><span class="number">.10</span>.<span class="keyword">in</span><span class="params">-addr.arpa.</span> <span class="keyword">IN</span> PTR dns2.zts.<span class="built_in">local</span>.</div><div class="line">@ <span class="keyword">IN</span> NS dns1.zts.<span class="built_in">local</span>.</div><div class="line"> <span class="keyword">IN</span> NS dns2.zts.<span class="built_in">local</span>.</div><div class="line"><span class="number">61</span> <span class="keyword">IN</span> PTR dns1.zts.<span class="built_in">local</span>.</div><div class="line"><span class="number">62</span> <span class="keyword">IN</span> PTR dns2.zts.<span class="built_in">local</span>.</div></pre></td></tr></table></figure>
<p>对区域文件进行有效性检查:<br><figure class="highlight stylus"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">named-checkzone zts<span class="selector-class">.local</span> /var/named/chroot/var/named/zts<span class="selector-class">.local</span><span class="selector-class">.zone</span></div></pre></td></tr></table></figure></p>
<h3 id="8、启动-bind-chroot-服务"><a href="#8、启动-bind-chroot-服务" class="headerlink" title="8、启动 bind-chroot 服务"></a>8、启动 bind-chroot 服务</h3><p>启动named,日志可以在<code>/var/log/messages</code>下查看<br><figure class="highlight fortran"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line">[root@nrozntgbd2 <span class="keyword">named</span>]# service <span class="keyword">named</span> restart</div><div class="line">Stopping <span class="keyword">named</span>: . [ OK ]</div><div class="line">Starting <span class="keyword">named</span>: [ OK ]</div><div class="line">[root@nrozntgbd2 <span class="keyword">named</span>]# vim /var/<span class="built_in">log</span>/messages</div></pre></td></tr></table></figure></p>
<p><strong>设置开机启动</strong><br><figure class="highlight applescript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line"><span class="comment"># centos 6</span></div><div class="line">chkconfig named <span class="keyword">on</span></div></pre></td></tr></table></figure></p>
<figure class="highlight autoit"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div></pre></td><td class="code"><pre><div class="line"><span class="meta"># centos 7</span></div><div class="line">[root<span class="symbol">@nrozntgbd2</span> ~]<span class="meta"># /usr/libexec/setup-named-chroot.sh /var/named/chroot on</span></div><div class="line">[root<span class="symbol">@nrozntgbd2</span> ~]<span class="meta"># systemctl stop named</span></div><div class="line">[root<span class="symbol">@nrozntgbd2</span> ~]<span class="meta"># systemctl disable named</span></div><div class="line">[root<span class="symbol">@nrozntgbd2</span> ~]<span class="meta"># systemctl start named-chroot</span></div><div class="line">[root<span class="symbol">@nrozntgbd2</span> ~]<span class="meta"># systemctl enable named-chroot</span></div><div class="line">ln -s <span class="string">'/usr/lib/systemd/system/named-chroot.service'</span> <span class="string">'/etc/systemd/system/multi-user.target.wants/named-chroot.service'</span></div></pre></td></tr></table></figure>
<h3 id="9、搭建从DNS服务器"><a href="#9、搭建从DNS服务器" class="headerlink" title="9、搭建从DNS服务器"></a>9、搭建从DNS服务器</h3><h4 id="a-安装从DNS服务器"><a href="#a-安装从DNS服务器" class="headerlink" title="a)安装从DNS服务器"></a>a)安装从DNS服务器</h4><ul>
<li><p>1.<strong>重复步骤1-5</strong></p>
</li>
<li><p>2.编辑配置文件/var/named/chroot/etc/named.conf,找到listen-on这一行,改为:</p>
</li>
</ul>
<figure class="highlight applescript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">listen-<span class="keyword">on</span> port <span class="number">53</span> { any; }; <span class="comment">#any是匹配所有的意思</span></div></pre></td></tr></table></figure>
<ul>
<li>3.找到allow-query这一行,改为:</li>
</ul>
<figure class="highlight abnf"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">allow-query { any<span class="comment">; };</span></div></pre></td></tr></table></figure>
<ul>
<li><p>4.在/var/named/chroot/etc/named.conf中增加区域配置</p>
<figure class="highlight clean"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div></pre></td><td class="code"><pre><div class="line">zone <span class="string">"zts.local"</span> {</div><div class="line"> type slave;</div><div class="line"> file <span class="string">"zts.local.zone"</span>; ###将同步后的文件放置在哪里,这里是/var/named/</div><div class="line"> masters { <span class="number">10.29</span><span class="number">.181</span><span class="number">.61</span>; }; ###指定主服务器的ip地址</div><div class="line">};</div><div class="line"></div><div class="line">zone <span class="string">"181.29.10.in-addr.arpa"</span> IN {</div><div class="line"> type slave;</div><div class="line"> file <span class="string">"10.29.181.zone"</span>;</div><div class="line"> masters { <span class="number">10.29</span><span class="number">.181</span><span class="number">.61</span>; }; ###指定主服务器的ip地址</div><div class="line">};</div></pre></td></tr></table></figure>
</li>
<li><p>5.修改权限(建议同时修改主、从DNS服务器)</p>
<figure class="highlight fortran"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">chown <span class="keyword">named</span>:<span class="keyword">named</span> /var/<span class="keyword">named</span>/chroot/var/<span class="keyword">named</span></div></pre></td></tr></table></figure>
</li>
</ul>
<h4 id="b-修改主DNS服务器配置"><a href="#b-修改主DNS服务器配置" class="headerlink" title="b)修改主DNS服务器配置"></a>b)修改主DNS服务器配置</h4><p>修改<code>/var/named/chroot/etc/named.conf</code>,并验证:<code>named-checkconf named.conf</code></p>
<figure class="highlight lsl"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div></pre></td><td class="code"><pre><div class="line">zone <span class="string">"zts.local"</span> {</div><div class="line"> type master;</div><div class="line"> file <span class="string">"zts.local.zone"</span>;</div><div class="line"> allow-transfer { <span class="number">10.29</span><span class="number">.181</span><span class="number">.62</span>; }; <span class="comment">//指定这个域的从DNS服务器的IP</span></div><div class="line"> allow-query { any; }; <span class="comment">//允许来自任意IP对这个域的解析请求</span></div><div class="line"> notify yes;</div><div class="line"> also-notify { <span class="number">10.29</span><span class="number">.181</span><span class="number">.62</span>; };</div><div class="line">};</div><div class="line"></div><div class="line">zone <span class="string">"181.29.10.in-addr.arpa"</span> IN {</div><div class="line"> type master;</div><div class="line"> file <span class="string">"10.29.181.zone"</span>;</div><div class="line"> allow-transfer { <span class="number">10.29</span><span class="number">.181</span><span class="number">.62</span>; }; <span class="comment">//指定这个域的从DNS服务器的IP</span></div><div class="line"> allow-query { any; }; <span class="comment">//允许来自任意IP对这个域的解析请求</span></div><div class="line"> notify yes;</div><div class="line"> also-notify { <span class="number">10.29</span><span class="number">.181</span><span class="number">.62</span>; };</div><div class="line">};</div></pre></td></tr></table></figure>
<h4 id="c-重启主、从DNS服务器"><a href="#c-重启主、从DNS服务器" class="headerlink" title="c)重启主、从DNS服务器"></a>c)重启主、从DNS服务器</h4><ul>
<li>1.重启主服务器:<code>service named restart</code></li>
<li>2.重启从服务器:<code>service named restart</code></li>
<li>3.若报错,可检查日志文件<code>vim /var/log/messages</code>,这里我们检查下从服务器同步日志</li>
</ul>
<figure class="highlight x86asm"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div></pre></td><td class="code"><pre><div class="line">Nov <span class="number">19</span> <span class="number">21</span>:<span class="number">06</span>:<span class="number">40</span> nrozntgbd3 named[<span class="number">90312</span>]: adjusted limit on open files from <span class="number">100000</span> to <span class="number">1048576</span></div><div class="line">Nov <span class="number">19</span> <span class="number">21</span>:<span class="number">06</span>:<span class="number">40</span> nrozntgbd3 named[<span class="number">90312</span>]: found <span class="number">8</span> CPUs, using <span class="number">8</span> worker threads</div><div class="line">Nov <span class="number">19</span> <span class="number">21</span>:<span class="number">06</span>:<span class="number">40</span> nrozntgbd3 named[<span class="number">90312</span>]: using <span class="meta">up</span> to <span class="number">4096</span> sockets</div><div class="line">Nov <span class="number">19</span> <span class="number">21</span>:<span class="number">06</span>:<span class="number">40</span> nrozntgbd3 named[<span class="number">90312</span>]: loading configuration from <span class="string">'/etc/named.conf'</span></div><div class="line">Nov <span class="number">19</span> <span class="number">21</span>:<span class="number">06</span>:<span class="number">40</span> nrozntgbd3 named[<span class="number">90312</span>]: reading built-<span class="keyword">in</span> trusted keys from file <span class="string">'/etc/named.iscdlv.key'</span></div><div class="line">Nov <span class="number">19</span> <span class="number">21</span>:<span class="number">06</span>:<span class="number">40</span> nrozntgbd3 named[<span class="number">90312</span>]: using <span class="meta">default</span> UDP/IPv4 port range: [<span class="number">1024</span>, <span class="number">65535</span>]</div><div class="line">Nov <span class="number">19</span> <span class="number">21</span>:<span class="number">06</span>:<span class="number">40</span> nrozntgbd3 named[<span class="number">90312</span>]: using <span class="meta">default</span> UDP/IPv6 port range: [<span class="number">1024</span>, <span class="number">65535</span>]</div><div class="line">Nov <span class="number">19</span> <span class="number">21</span>:<span class="number">06</span>:<span class="number">40</span> nrozntgbd3 named[<span class="number">90312</span>]: listening on IPv4 interface lo, <span class="number">127.0</span><span class="meta">.0</span><span class="meta">.1</span>#<span class="number">53</span></div><div class="line">Nov <span class="number">19</span> <span class="number">21</span>:<span class="number">06</span>:<span class="number">40</span> nrozntgbd3 named[<span class="number">90312</span>]: listening on IPv4 interface eth3, <span class="number">10.29</span><span class="meta">.181</span><span class="meta">.62</span>#<span class="number">53</span></div><div class="line">Nov <span class="number">19</span> <span class="number">21</span>:<span class="number">06</span>:<span class="number">40</span> nrozntgbd3 named[<span class="number">90312</span>]: listening on IPv6 interface lo, ::<span class="number">1</span>#<span class="number">53</span></div><div class="line">Nov <span class="number">19</span> <span class="number">21</span>:<span class="number">06</span>:<span class="number">40</span> nrozntgbd3 named[<span class="number">90312</span>]: generating session key for dynamic DNS</div><div class="line">Nov <span class="number">19</span> <span class="number">21</span>:<span class="number">06</span>:<span class="number">40</span> nrozntgbd3 named[<span class="number">90312</span>]: sizing zone task pool based on <span class="number">7</span> zones</div><div class="line">Nov <span class="number">19</span> <span class="number">21</span>:<span class="number">06</span>:<span class="number">40</span> nrozntgbd3 named[<span class="number">90312</span>]: set <span class="meta">up</span> managed keys zone for view _<span class="meta">default</span>, file <span class="string">'/var/named/dynamic/managed-keys.bind'</span></div><div class="line">Nov <span class="number">19</span> <span class="number">21</span>:<span class="number">06</span>:<span class="number">40</span> nrozntgbd3 named[<span class="number">90312</span>]: Warning: <span class="string">'empty-zones-enable/disable-empty-zone'</span> <span class="keyword">not</span> set: disabling RFC <span class="number">1918</span> empty zones</div><div class="line">Nov <span class="number">19</span> <span class="number">21</span>:<span class="number">06</span>:<span class="number">40</span> nrozntgbd3 named[<span class="number">90312</span>]: automatic empty zone: <span class="number">127.</span><span class="keyword">IN</span>-ADDR.ARPA</div><div class="line">Nov <span class="number">19</span> <span class="number">21</span>:<span class="number">06</span>:<span class="number">40</span> nrozntgbd3 named[<span class="number">90312</span>]: automatic empty zone: <span class="number">254.169</span>.IN-ADDR.ARPA</div><div class="line">Nov <span class="number">19</span> <span class="number">21</span>:<span class="number">06</span>:<span class="number">40</span> nrozntgbd3 named[<span class="number">90312</span>]: automatic empty zone: <span class="number">2.0</span><span class="meta">.192</span>.IN-ADDR.ARPA</div><div class="line">Nov <span class="number">19</span> <span class="number">21</span>:<span class="number">06</span>:<span class="number">40</span> nrozntgbd3 named[<span class="number">90312</span>]: automatic empty zone: <span class="number">100.51</span><span class="meta">.198</span>.IN-ADDR.ARPA</div><div class="line">Nov <span class="number">19</span> <span class="number">21</span>:<span class="number">06</span>:<span class="number">40</span> nrozntgbd3 named[<span class="number">90312</span>]: automatic empty zone: <span class="number">113.0</span><span class="meta">.203</span>.IN-ADDR.ARPA</div><div class="line">Nov <span class="number">19</span> <span class="number">21</span>:<span class="number">06</span>:<span class="number">40</span> nrozntgbd3 named[<span class="number">90312</span>]: automatic empty zone: <span class="number">255.255</span><span class="meta">.255</span><span class="meta">.255</span>.IN-ADDR.ARPA</div><div class="line">Nov <span class="number">19</span> <span class="number">21</span>:<span class="number">06</span>:<span class="number">40</span> nrozntgbd3 named[<span class="number">90312</span>]: automatic empty zone: <span class="number">0.0</span><span class="meta">.0</span><span class="meta">.0</span><span class="meta">.0</span><span class="meta">.0</span><span class="meta">.0</span><span class="meta">.0</span><span class="meta">.0</span><span class="meta">.0</span><span class="meta">.0</span><span class="meta">.0</span><span class="meta">.0</span><span class="meta">.0</span><span class="meta">.0</span><span class="meta">.0</span><span class="meta">.0</span><span class="meta">.0</span><span class="meta">.0</span><span class="meta">.0</span><span class="meta">.0</span><span class="meta">.0</span><span class="meta">.0</span><span class="meta">.0</span><span class="meta">.0</span><span class="meta">.0</span><span class="meta">.0</span><span class="meta">.0</span><span class="meta">.0</span><span class="meta">.0</span><span class="meta">.0</span><span class="meta">.0</span>.IP6.ARPA</div><div class="line">Nov <span class="number">19</span> <span class="number">21</span>:<span class="number">06</span>:<span class="number">40</span> nrozntgbd3 named[<span class="number">90312</span>]: automatic empty zone: D.F.IP6.ARPA</div><div class="line">Nov <span class="number">19</span> <span class="number">21</span>:<span class="number">06</span>:<span class="number">40</span> nrozntgbd3 named[<span class="number">90312</span>]: automatic empty zone: <span class="number">8.</span>E.F.IP6.ARPA</div><div class="line">Nov <span class="number">19</span> <span class="number">21</span>:<span class="number">06</span>:<span class="number">40</span> nrozntgbd3 named[<span class="number">90312</span>]: automatic empty zone: <span class="number">9.</span>E.F.IP6.ARPA</div><div class="line">Nov <span class="number">19</span> <span class="number">21</span>:<span class="number">06</span>:<span class="number">40</span> nrozntgbd3 named[<span class="number">90312</span>]: automatic empty zone: A.E.F.IP6.ARPA</div><div class="line">Nov <span class="number">19</span> <span class="number">21</span>:<span class="number">06</span>:<span class="number">40</span> nrozntgbd3 named[<span class="number">90312</span>]: automatic empty zone: B.E.F.IP6.ARPA</div><div class="line">Nov <span class="number">19</span> <span class="number">21</span>:<span class="number">06</span>:<span class="number">40</span> nrozntgbd3 named[<span class="number">90312</span>]: automatic empty zone: <span class="number">8.</span>B.D<span class="meta">.0</span><span class="meta">.1</span><span class="meta">.0</span><span class="meta">.0</span><span class="meta">.2</span>.IP6.ARPA</div><div class="line">Nov <span class="number">19</span> <span class="number">21</span>:<span class="number">06</span>:<span class="number">40</span> nrozntgbd3 named[<span class="number">90312</span>]: command channel listening on <span class="number">127.0</span><span class="meta">.0</span><span class="meta">.1</span>#<span class="number">953</span></div><div class="line">Nov <span class="number">19</span> <span class="number">21</span>:<span class="number">06</span>:<span class="number">40</span> nrozntgbd3 named[<span class="number">90312</span>]: command channel listening on ::<span class="number">1</span>#<span class="number">953</span></div><div class="line">Nov <span class="number">19</span> <span class="number">21</span>:<span class="number">06</span>:<span class="number">40</span> nrozntgbd3 named[<span class="number">90312</span>]: zone <span class="number">0.</span><span class="keyword">in</span>-addr.arpa/<span class="keyword">IN</span>: loaded serial <span class="number">0</span></div><div class="line">Nov <span class="number">19</span> <span class="number">21</span>:<span class="number">06</span>:<span class="number">40</span> nrozntgbd3 named[<span class="number">90312</span>]: zone <span class="number">1.0</span><span class="meta">.0</span><span class="meta">.127</span>.in-addr.arpa/<span class="keyword">IN</span>: loaded serial <span class="number">0</span></div><div class="line">Nov <span class="number">19</span> <span class="number">21</span>:<span class="number">06</span>:<span class="number">40</span> nrozntgbd3 named[<span class="number">90312</span>]: zone <span class="number">1.0</span><span class="meta">.0</span><span class="meta">.0</span><span class="meta">.0</span><span class="meta">.0</span><span class="meta">.0</span><span class="meta">.0</span><span class="meta">.0</span><span class="meta">.0</span><span class="meta">.0</span><span class="meta">.0</span><span class="meta">.0</span><span class="meta">.0</span><span class="meta">.0</span><span class="meta">.0</span><span class="meta">.0</span><span class="meta">.0</span><span class="meta">.0</span><span class="meta">.0</span><span class="meta">.0</span><span class="meta">.0</span><span class="meta">.0</span><span class="meta">.0</span><span class="meta">.0</span><span class="meta">.0</span><span class="meta">.0</span><span class="meta">.0</span><span class="meta">.0</span><span class="meta">.0</span><span class="meta">.0</span><span class="meta">.0</span>.ip6.arpa/<span class="keyword">IN</span>: loaded serial <span class="number">0</span></div><div class="line">Nov <span class="number">19</span> <span class="number">21</span>:<span class="number">06</span>:<span class="number">40</span> nrozntgbd3 named[<span class="number">90312</span>]: zone zts.local/<span class="keyword">IN</span>: loaded serial <span class="number">2018111901</span></div><div class="line">Nov <span class="number">19</span> <span class="number">21</span>:<span class="number">06</span>:<span class="number">40</span> nrozntgbd3 named[<span class="number">90312</span>]: zone localhost.localdomain/<span class="keyword">IN</span>: loaded serial <span class="number">0</span></div><div class="line">Nov <span class="number">19</span> <span class="number">21</span>:<span class="number">06</span>:<span class="number">40</span> nrozntgbd3 named[<span class="number">90312</span>]: zone localhost/<span class="keyword">IN</span>: loaded serial <span class="number">0</span></div><div class="line">Nov <span class="number">19</span> <span class="number">21</span>:<span class="number">06</span>:<span class="number">40</span> nrozntgbd3 named[<span class="number">90312</span>]: managed-keys-zone ./<span class="keyword">IN</span>: loaded serial <span class="number">2</span></div><div class="line">Nov <span class="number">19</span> <span class="number">21</span>:<span class="number">06</span>:<span class="number">40</span> nrozntgbd3 named[<span class="number">90312</span>]: running</div><div class="line">Nov <span class="number">19</span> <span class="number">21</span>:<span class="number">06</span>:<span class="number">40</span> nrozntgbd3 named[<span class="number">90312</span>]: zone zts.local/<span class="keyword">IN</span>: sending notifies (serial <span class="number">2018111901</span>)</div></pre></td></tr></table></figure>
<ul>
<li>4.检查从服务器<code>/var/named/chroot/var/named/zts.local.zone</code>、<code>/var/named/chroot/var/named/10.29.181.zone</code>文件是否生成。</li>
</ul>
<figure class="highlight css"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div></pre></td><td class="code"><pre><div class="line"><span class="selector-attr">[root@nrozntgbd3 named]</span># <span class="selector-tag">ls</span> <span class="selector-tag">-alh</span></div><div class="line"><span class="selector-tag">total</span> 48<span class="selector-tag">K</span></div><div class="line"><span class="selector-tag">drwxr-xr-x</span> 5 <span class="selector-tag">named</span> <span class="selector-tag">named</span> 4<span class="selector-class">.0K</span> <span class="selector-tag">Nov</span> 19 21<span class="selector-pseudo">:06</span> .</div><div class="line"><span class="selector-tag">drwxr-x---</span> 6 <span class="selector-tag">root</span> <span class="selector-tag">named</span> 4<span class="selector-class">.0K</span> <span class="selector-tag">Nov</span> 19 20<span class="selector-pseudo">:48</span> ..</div><div class="line"><span class="selector-tag">drwxrwxrwx</span> 2 <span class="selector-tag">root</span> <span class="selector-tag">root</span> 4<span class="selector-class">.0K</span> <span class="selector-tag">Nov</span> 19 20<span class="selector-pseudo">:48</span> <span class="selector-tag">data</span></div><div class="line"><span class="selector-tag">drwxrwxrwx</span> 2 <span class="selector-tag">root</span> <span class="selector-tag">root</span> 4<span class="selector-class">.0K</span> <span class="selector-tag">Nov</span> 19 20<span class="selector-pseudo">:58</span> <span class="selector-tag">dynamic</span></div><div class="line"><span class="selector-tag">-rw-r--r--</span> 1 <span class="selector-tag">root</span> <span class="selector-tag">root</span> 56 <span class="selector-tag">Nov</span> 19 20<span class="selector-pseudo">:48</span> <span class="selector-tag">my</span><span class="selector-class">.external</span><span class="selector-class">.zone</span><span class="selector-class">.db</span></div><div class="line"><span class="selector-tag">-rw-r--r--</span> 1 <span class="selector-tag">root</span> <span class="selector-tag">root</span> 56 <span class="selector-tag">Nov</span> 19 20<span class="selector-pseudo">:48</span> <span class="selector-tag">my</span><span class="selector-class">.internal</span><span class="selector-class">.zone</span><span class="selector-class">.db</span></div><div class="line"><span class="selector-tag">-rw-r--r--</span> 1 <span class="selector-tag">root</span> <span class="selector-tag">root</span> 3<span class="selector-class">.3K</span> <span class="selector-tag">Nov</span> 19 20<span class="selector-pseudo">:48</span> <span class="selector-tag">named</span><span class="selector-class">.ca</span></div><div class="line"><span class="selector-tag">-rw-r--r--</span> 1 <span class="selector-tag">root</span> <span class="selector-tag">root</span> 152 <span class="selector-tag">Nov</span> 19 20<span class="selector-pseudo">:48</span> <span class="selector-tag">named</span><span class="selector-class">.empty</span></div><div class="line"><span class="selector-tag">-rw-r--r--</span> 1 <span class="selector-tag">root</span> <span class="selector-tag">root</span> 152 <span class="selector-tag">Nov</span> 19 20<span class="selector-pseudo">:48</span> <span class="selector-tag">named</span><span class="selector-class">.localhost</span></div><div class="line"><span class="selector-tag">-rw-r--r--</span> 1 <span class="selector-tag">root</span> <span class="selector-tag">root</span> 168 <span class="selector-tag">Nov</span> 19 20<span class="selector-pseudo">:48</span> <span class="selector-tag">named</span><span class="selector-class">.loopback</span></div><div class="line"><span class="selector-tag">drwxr-xr-x</span> 2 <span class="selector-tag">root</span> <span class="selector-tag">root</span> 4<span class="selector-class">.0K</span> <span class="selector-tag">Nov</span> 19 20<span class="selector-pseudo">:48</span> <span class="selector-tag">slaves</span></div><div class="line"><span class="selector-tag">-rw-r--r--</span> 1 <span class="selector-tag">named</span> <span class="selector-tag">named</span> 660 <span class="selector-tag">Nov</span> 19 21<span class="selector-pseudo">:12</span> <span class="selector-tag">zts</span><span class="selector-class">.local</span><span class="selector-class">.zone</span> (<<span class="selector-tag">------</span>看,已经自动生成了)</div></pre></td></tr></table></figure>
<h3 id="9、测试"><a href="#9、测试" class="headerlink" title="9、测试"></a>9、测试</h3><p>登录10.29.181.62,修改DNS服务器地址<code>vim /etc/resolv.conf</code>(这种方式是临时的,重启网卡后,就刷新掉了):</p>
<p><code>[root@nrozntgbd3 roc]# vim /etc/resolv.conf</code></p>
<figure class="highlight css"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line"><span class="selector-id">#search</span> <span class="selector-tag">xx</span><span class="selector-class">.zts</span><span class="selector-class">.com</span></div><div class="line"><span class="selector-tag">nameserver</span> 10<span class="selector-class">.29</span><span class="selector-class">.181</span><span class="selector-class">.61</span></div></pre></td></tr></table></figure>
<blockquote>
<p>建议使用修改网卡的dns的方式:vim /etc/sysconfig/network-scripts/ifcfg-eth0,这种方式会永久设定dns</p>
</blockquote>
<p><strong>使用dig测试</strong></p>
<p>注意查看<code>;; ANSWER SECTION:</code>输出</p>
<figure class="highlight css"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div><div class="line">41</div><div class="line">42</div><div class="line">43</div><div class="line">44</div><div class="line">45</div><div class="line">46</div><div class="line">47</div><div class="line">48</div><div class="line">49</div><div class="line">50</div><div class="line">51</div><div class="line">52</div><div class="line">53</div></pre></td><td class="code"><pre><div class="line"><span class="selector-attr">[root@nrozntgbd3 roc]</span># <span class="selector-tag">dig</span> <span class="selector-tag">-t</span> <span class="selector-tag">A</span> <span class="selector-tag">forum</span><span class="selector-class">.zts</span><span class="selector-class">.local</span> @<span class="keyword">10</span>.<span class="keyword">29</span>.<span class="keyword">181</span>.<span class="keyword">61</span></div><div class="line"></div><div class="line">; <<>> <span class="selector-tag">DiG</span> 9<span class="selector-class">.8</span><span class="selector-class">.2rc1-RedHat-9</span><span class="selector-class">.8</span><span class="selector-class">.2-0</span><span class="selector-class">.68</span><span class="selector-class">.rc1</span><span class="selector-class">.el6_10</span><span class="selector-class">.1</span> <<>> <span class="selector-tag">-t</span> <span class="selector-tag">A</span> <span class="selector-tag">forum</span><span class="selector-class">.zts</span><span class="selector-class">.local</span> @<span class="keyword">10</span>.<span class="keyword">29</span>.<span class="keyword">181</span>.<span class="keyword">61</span></div><div class="line">;; <span class="selector-tag">global</span> <span class="selector-tag">options</span>: +<span class="selector-tag">cmd</span></div><div class="line">;; <span class="selector-tag">Got</span> <span class="selector-tag">answer</span>:</div><div class="line">;; <span class="selector-tag">-</span>>><span class="selector-tag">HEADER</span><<<span class="selector-tag">-</span> <span class="selector-tag">opcode</span>: <span class="selector-tag">QUERY</span>, <span class="selector-tag">status</span>: <span class="selector-tag">NOERROR</span>, <span class="selector-tag">id</span>: 35607</div><div class="line">;; <span class="selector-tag">flags</span>: <span class="selector-tag">qr</span> <span class="selector-tag">aa</span> <span class="selector-tag">rd</span> <span class="selector-tag">ra</span>; <span class="selector-tag">QUERY</span>: 1, <span class="selector-tag">ANSWER</span>: 1, <span class="selector-tag">AUTHORITY</span>: 2, <span class="selector-tag">ADDITIONAL</span>: 2</div><div class="line"></div><div class="line">;; <span class="selector-tag">QUESTION</span> <span class="selector-tag">SECTION</span>:</div><div class="line">;<span class="selector-tag">forum</span><span class="selector-class">.zts</span><span class="selector-class">.local</span>. <span class="selector-tag">IN</span> <span class="selector-tag">A</span></div><div class="line"></div><div class="line">;; <span class="selector-tag">ANSWER</span> <span class="selector-tag">SECTION</span>:</div><div class="line"><span class="selector-tag">forum</span><span class="selector-class">.zts</span><span class="selector-class">.local</span>. 86400 <span class="selector-tag">IN</span> <span class="selector-tag">A</span> 10<span class="selector-class">.29</span><span class="selector-class">.181</span><span class="selector-class">.61</span> (<<span class="selector-tag">-------</span>看这个输出)</div><div class="line"></div><div class="line">;; <span class="selector-tag">AUTHORITY</span> <span class="selector-tag">SECTION</span>:</div><div class="line"><span class="selector-tag">zts</span><span class="selector-class">.local</span>. 86400 <span class="selector-tag">IN</span> <span class="selector-tag">NS</span> <span class="selector-tag">dns1</span><span class="selector-class">.zts</span><span class="selector-class">.local</span>.</div><div class="line"><span class="selector-tag">zts</span><span class="selector-class">.local</span>. 86400 <span class="selector-tag">IN</span> <span class="selector-tag">NS</span> <span class="selector-tag">dns2</span><span class="selector-class">.zts</span><span class="selector-class">.local</span>.</div><div class="line"></div><div class="line">;; <span class="selector-tag">ADDITIONAL</span> <span class="selector-tag">SECTION</span>:</div><div class="line"><span class="selector-tag">dns1</span><span class="selector-class">.zts</span><span class="selector-class">.local</span>. 86400 <span class="selector-tag">IN</span> <span class="selector-tag">A</span> 10<span class="selector-class">.29</span><span class="selector-class">.181</span><span class="selector-class">.61</span></div><div class="line"><span class="selector-tag">dns2</span><span class="selector-class">.zts</span><span class="selector-class">.local</span>. 86400 <span class="selector-tag">IN</span> <span class="selector-tag">A</span> 10<span class="selector-class">.29</span><span class="selector-class">.181</span><span class="selector-class">.62</span></div><div class="line"></div><div class="line">;; <span class="selector-tag">Query</span> <span class="selector-tag">time</span>: 0 <span class="selector-tag">msec</span></div><div class="line">;; <span class="selector-tag">SERVER</span>: 10<span class="selector-class">.29</span><span class="selector-class">.181</span><span class="selector-class">.61</span><span class="selector-id">#53</span>(10<span class="selector-class">.29</span><span class="selector-class">.181</span><span class="selector-class">.61</span>)</div><div class="line">;; <span class="selector-tag">WHEN</span>: <span class="selector-tag">Mon</span> <span class="selector-tag">Nov</span> 19 20<span class="selector-pseudo">:24</span><span class="selector-pseudo">:11</span> 2018</div><div class="line">;; <span class="selector-tag">MSG</span> <span class="selector-tag">SIZE</span> <span class="selector-tag">rcvd</span>: 119</div><div class="line"></div><div class="line"><span class="selector-attr">[root@nrozntgbd3 roc]</span># <span class="selector-tag">dig</span> <span class="selector-tag">-t</span> <span class="selector-tag">TXT</span> <span class="selector-tag">txt</span><span class="selector-class">.shanghai</span><span class="selector-class">.zts</span><span class="selector-class">.local</span></div><div class="line"></div><div class="line">; <<>> <span class="selector-tag">DiG</span> 9<span class="selector-class">.8</span><span class="selector-class">.2rc1-RedHat-9</span><span class="selector-class">.8</span><span class="selector-class">.2-0</span><span class="selector-class">.68</span><span class="selector-class">.rc1</span><span class="selector-class">.el6_10</span><span class="selector-class">.1</span> <<>> <span class="selector-tag">-t</span> <span class="selector-tag">TXT</span> <span class="selector-tag">txt</span><span class="selector-class">.shanghai</span><span class="selector-class">.zts</span><span class="selector-class">.local</span></div><div class="line">;; <span class="selector-tag">global</span> <span class="selector-tag">options</span>: +<span class="selector-tag">cmd</span></div><div class="line">;; <span class="selector-tag">Got</span> <span class="selector-tag">answer</span>:</div><div class="line">;; <span class="selector-tag">-</span>>><span class="selector-tag">HEADER</span><<<span class="selector-tag">-</span> <span class="selector-tag">opcode</span>: <span class="selector-tag">QUERY</span>, <span class="selector-tag">status</span>: <span class="selector-tag">NOERROR</span>, <span class="selector-tag">id</span>: 19185</div><div class="line">;; <span class="selector-tag">flags</span>: <span class="selector-tag">qr</span> <span class="selector-tag">aa</span> <span class="selector-tag">rd</span> <span class="selector-tag">ra</span>; <span class="selector-tag">QUERY</span>: 1, <span class="selector-tag">ANSWER</span>: 1, <span class="selector-tag">AUTHORITY</span>: 2, <span class="selector-tag">ADDITIONAL</span>: 2</div><div class="line"></div><div class="line">;; <span class="selector-tag">QUESTION</span> <span class="selector-tag">SECTION</span>:</div><div class="line">;<span class="selector-tag">txt</span><span class="selector-class">.shanghai</span><span class="selector-class">.zts</span><span class="selector-class">.local</span>. <span class="selector-tag">IN</span> <span class="selector-tag">TXT</span></div><div class="line"></div><div class="line">;; <span class="selector-tag">ANSWER</span> <span class="selector-tag">SECTION</span>:</div><div class="line"><span class="selector-tag">txt</span><span class="selector-class">.shanghai</span><span class="selector-class">.zts</span><span class="selector-class">.local</span>. 86400 <span class="selector-tag">IN</span> <span class="selector-tag">TXT</span> "<span class="selector-tag">defaultZone</span><span class="selector-class">.zts</span><span class="selector-class">.local</span>" (<<span class="selector-tag">-------</span>看这个输出)</div><div class="line"></div><div class="line">;; <span class="selector-tag">AUTHORITY</span> <span class="selector-tag">SECTION</span>:</div><div class="line"><span class="selector-tag">zts</span><span class="selector-class">.local</span>. 86400 <span class="selector-tag">IN</span> <span class="selector-tag">NS</span> <span class="selector-tag">dns2</span><span class="selector-class">.zts</span><span class="selector-class">.local</span>.</div><div class="line"><span class="selector-tag">zts</span><span class="selector-class">.local</span>. 86400 <span class="selector-tag">IN</span> <span class="selector-tag">NS</span> <span class="selector-tag">dns1</span><span class="selector-class">.zts</span><span class="selector-class">.local</span>.</div><div class="line"></div><div class="line">;; <span class="selector-tag">ADDITIONAL</span> <span class="selector-tag">SECTION</span>:</div><div class="line"><span class="selector-tag">dns1</span><span class="selector-class">.zts</span><span class="selector-class">.local</span>. 86400 <span class="selector-tag">IN</span> <span class="selector-tag">A</span> 10<span class="selector-class">.29</span><span class="selector-class">.181</span><span class="selector-class">.61</span></div><div class="line"><span class="selector-tag">dns2</span><span class="selector-class">.zts</span><span class="selector-class">.local</span>. 86400 <span class="selector-tag">IN</span> <span class="selector-tag">A</span> 10<span class="selector-class">.29</span><span class="selector-class">.181</span><span class="selector-class">.62</span></div><div class="line"></div><div class="line">;; <span class="selector-tag">Query</span> <span class="selector-tag">time</span>: 0 <span class="selector-tag">msec</span></div><div class="line">;; <span class="selector-tag">SERVER</span>: 10<span class="selector-class">.29</span><span class="selector-class">.181</span><span class="selector-class">.61</span><span class="selector-id">#53</span>(10<span class="selector-class">.29</span><span class="selector-class">.181</span><span class="selector-class">.61</span>)</div><div class="line">;; <span class="selector-tag">WHEN</span>: <span class="selector-tag">Mon</span> <span class="selector-tag">Nov</span> 19 20<span class="selector-pseudo">:24</span><span class="selector-pseudo">:22</span> 2018</div><div class="line">;; <span class="selector-tag">MSG</span> <span class="selector-tag">SIZE</span> <span class="selector-tag">rcvd</span>: 144</div></pre></td></tr></table></figure>
<p><strong>使用nslookup测试</strong></p>
<figure class="highlight applescript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div></pre></td><td class="code"><pre><div class="line">[root@nrozntgbd3 named]<span class="comment"># nslookup </span></div><div class="line">> <span class="keyword">set</span> queryType=TXT</div><div class="line">> txt.shanghai.zts.<span class="keyword">local</span></div><div class="line">Server: <span class="number">10.29</span><span class="number">.181</span><span class="number">.61</span></div><div class="line">Address: <span class="number">10.29</span><span class="number">.181</span><span class="number">.61</span><span class="comment">#53</span></div><div class="line"></div><div class="line">txt.shanghai.zts.<span class="keyword">local</span> <span class="built_in">text</span> = <span class="string">"defaultZone.zts.local"</span></div><div class="line">> txt.beijing.zts.<span class="keyword">local</span></div><div class="line">Server: <span class="number">10.29</span><span class="number">.181</span><span class="number">.61</span></div><div class="line">Address: <span class="number">10.29</span><span class="number">.181</span><span class="number">.61</span><span class="comment">#53</span></div><div class="line"></div><div class="line">txt.beijing.zts.<span class="keyword">local</span> <span class="built_in">text</span> = <span class="string">"beijing-a.zts.local"</span> <span class="string">"beijing-b.zts.local"</span></div></pre></td></tr></table></figure>
<p><strong>测试反向代理</strong></p>
<figure class="highlight css"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div></pre></td><td class="code"><pre><div class="line"><span class="selector-attr">[root@nrozntgbd3 roc]</span># <span class="selector-tag">dig</span> <span class="selector-tag">-x</span> 10<span class="selector-class">.29</span><span class="selector-class">.181</span><span class="selector-class">.61</span> @<span class="keyword">10</span>.<span class="keyword">29</span>.<span class="keyword">181</span>.<span class="keyword">61</span></div><div class="line"></div><div class="line">; <<>> <span class="selector-tag">DiG</span> 9<span class="selector-class">.8</span><span class="selector-class">.2rc1-RedHat-9</span><span class="selector-class">.8</span><span class="selector-class">.2-0</span><span class="selector-class">.68</span><span class="selector-class">.rc1</span><span class="selector-class">.el6_10</span><span class="selector-class">.1</span> <<>> <span class="selector-tag">-x</span> 10<span class="selector-class">.29</span><span class="selector-class">.181</span><span class="selector-class">.61</span> @<span class="keyword">10</span>.<span class="keyword">29</span>.<span class="keyword">181</span>.<span class="keyword">61</span></div><div class="line">;; <span class="selector-tag">global</span> <span class="selector-tag">options</span>: +<span class="selector-tag">cmd</span></div><div class="line">;; <span class="selector-tag">Got</span> <span class="selector-tag">answer</span>:</div><div class="line">;; <span class="selector-tag">-</span>>><span class="selector-tag">HEADER</span><<<span class="selector-tag">-</span> <span class="selector-tag">opcode</span>: <span class="selector-tag">QUERY</span>, <span class="selector-tag">status</span>: <span class="selector-tag">NOERROR</span>, <span class="selector-tag">id</span>: 55778</div><div class="line">;; <span class="selector-tag">flags</span>: <span class="selector-tag">qr</span> <span class="selector-tag">aa</span> <span class="selector-tag">rd</span> <span class="selector-tag">ra</span>; <span class="selector-tag">QUERY</span>: 1, <span class="selector-tag">ANSWER</span>: 1, <span class="selector-tag">AUTHORITY</span>: 2, <span class="selector-tag">ADDITIONAL</span>: 2</div><div class="line"></div><div class="line">;; <span class="selector-tag">QUESTION</span> <span class="selector-tag">SECTION</span>:</div><div class="line">;61<span class="selector-class">.181</span><span class="selector-class">.29</span><span class="selector-class">.10</span><span class="selector-class">.in-addr</span><span class="selector-class">.arpa</span>. <span class="selector-tag">IN</span> <span class="selector-tag">PTR</span></div><div class="line"></div><div class="line">;; <span class="selector-tag">ANSWER</span> <span class="selector-tag">SECTION</span>:</div><div class="line">61<span class="selector-class">.181</span><span class="selector-class">.29</span><span class="selector-class">.10</span><span class="selector-class">.in-addr</span><span class="selector-class">.arpa</span>. 86400 <span class="selector-tag">IN</span> <span class="selector-tag">PTR</span> <span class="selector-tag">dns1</span><span class="selector-class">.zts</span><span class="selector-class">.local</span>.</div><div class="line"></div><div class="line">;; <span class="selector-tag">AUTHORITY</span> <span class="selector-tag">SECTION</span>:</div><div class="line">181<span class="selector-class">.29</span><span class="selector-class">.10</span><span class="selector-class">.in-addr</span><span class="selector-class">.arpa</span>. 86400 <span class="selector-tag">IN</span> <span class="selector-tag">NS</span> <span class="selector-tag">dns1</span><span class="selector-class">.zts</span><span class="selector-class">.local</span>.</div><div class="line">181<span class="selector-class">.29</span><span class="selector-class">.10</span><span class="selector-class">.in-addr</span><span class="selector-class">.arpa</span>. 86400 <span class="selector-tag">IN</span> <span class="selector-tag">NS</span> <span class="selector-tag">dns2</span><span class="selector-class">.zts</span><span class="selector-class">.local</span>.</div><div class="line"></div><div class="line">;; <span class="selector-tag">ADDITIONAL</span> <span class="selector-tag">SECTION</span>:</div><div class="line"><span class="selector-tag">dns1</span><span class="selector-class">.zts</span><span class="selector-class">.local</span>. 86400 <span class="selector-tag">IN</span> <span class="selector-tag">A</span> 10<span class="selector-class">.29</span><span class="selector-class">.181</span><span class="selector-class">.61</span></div><div class="line"><span class="selector-tag">dns2</span><span class="selector-class">.zts</span><span class="selector-class">.local</span>. 86400 <span class="selector-tag">IN</span> <span class="selector-tag">A</span> 10<span class="selector-class">.29</span><span class="selector-class">.181</span><span class="selector-class">.62</span></div><div class="line"></div><div class="line">;; <span class="selector-tag">Query</span> <span class="selector-tag">time</span>: 0 <span class="selector-tag">msec</span></div><div class="line">;; <span class="selector-tag">SERVER</span>: 10<span class="selector-class">.29</span><span class="selector-class">.181</span><span class="selector-class">.61</span><span class="selector-id">#53</span>(10<span class="selector-class">.29</span><span class="selector-class">.181</span><span class="selector-class">.61</span>)</div><div class="line">;; <span class="selector-tag">WHEN</span>: <span class="selector-tag">Mon</span> <span class="selector-tag">Nov</span> 19 20<span class="selector-pseudo">:27</span><span class="selector-pseudo">:42</span> 2018</div><div class="line">;; <span class="selector-tag">MSG</span> <span class="selector-tag">SIZE</span> <span class="selector-tag">rcvd</span>: 136</div></pre></td></tr></table></figure>
<p><strong>解析内部、外部域名</strong></p>
<figure class="highlight avrasm"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div></pre></td><td class="code"><pre><div class="line">[root@nrozntgbd3 roc]<span class="meta"># nslookup forum.zts.local </span></div><div class="line"><span class="symbol">Server:</span> <span class="number">10.29</span><span class="number">.181</span><span class="number">.61</span></div><div class="line"><span class="symbol">Address:</span> <span class="number">10.29</span><span class="number">.181</span><span class="number">.61</span><span class="meta">#53</span></div><div class="line"></div><div class="line"><span class="symbol">Name:</span> forum.zts.local</div><div class="line"><span class="symbol">Address:</span> <span class="number">10.29</span><span class="number">.181</span><span class="number">.61</span></div><div class="line"></div><div class="line">[root@nrozntgbd3 roc]<span class="meta"># nslookup www.baidu.com</span></div><div class="line"><span class="symbol">Server:</span> <span class="number">10.29</span><span class="number">.181</span><span class="number">.61</span></div><div class="line"><span class="symbol">Address:</span> <span class="number">10.29</span><span class="number">.181</span><span class="number">.61</span><span class="meta">#53</span></div><div class="line"></div><div class="line">Non-authoritative answer:</div><div class="line">www.baidu.com canonical name = www.a.shifen.com.</div><div class="line"><span class="symbol">Name:</span> www.a.shifen.com</div><div class="line"><span class="symbol">Address:</span> <span class="number">115.239</span><span class="number">.211</span><span class="number">.112</span></div><div class="line"><span class="symbol">Name:</span> www.a.shifen.com</div><div class="line"><span class="symbol">Address:</span> <span class="number">115.239</span><span class="number">.210</span><span class="number">.27</span></div></pre></td></tr></table></figure>
<h2 id="参考"><a href="#参考" class="headerlink" title="参考"></a>参考</h2><ul>
<li><a href="https://www.linuxprobe.com/centos7-chroot-bind-dns.html://www.linuxprobe.com/centos7-chroot-bind-dns.html" target="_blank" rel="external">在 CentOS7.0 上搭建DNS服务器</a></li>
<li><a href="https://www.liuliya.com/archive/761.html" target="_blank" rel="external">Centos7上搭建DNS服务</a></li>
<li><a href="https://blog.csdn.net/huluedeai/article/details/50674286" target="_blank" rel="external">Linux命令学习之nslookup</a></li>
<li><a href="http://blog.51cto.com/vinsent/1967876" target="_blank" rel="external">搭建一个互联网DNS服务器架构</a></li>
<li><a href="https://blog.csdn.net/yelllowcong/article/details/78823520" target="_blank" rel="external">CentOS之DNS服务器安装-yellowcong</a></li>
<li><a href="https://blog.csdn.net/xiaoyuanfannao/article/details/82885120" target="_blank" rel="external">centos7搭建主从DNS服务器</a></li>
<li><a href="https://blog.csdn.net/weixin_41004350/article/details/79107732" target="_blank" rel="external">Centos7 搭建DNS服务器与原理配置详解</a></li>
</ul>
]]></content>
<summary type="html">
DNS(Domain Name Server,域名服务器)是进行域名(domain name)和与之相对应的IP地址 (IP address)转换的服务器。DNS中保存了一张域名(domain name)和与之相对应的IP地址 (IP address)的表,以解析消息的域名。 域名是Internet上某一台计算机或计算机组的名称,用于在数据传输时标识计算机的电子方位(有时也指地理位置)。域名是由一串用点分隔的名字组成的,通常包含组织名,而且始终包括两到三个字母的后缀,以指明组织的类型或该域所在的国家或地区。
</summary>
<category term="Linux" scheme="https://roc-wong.github.io/categories/Linux/"/>
<category term="Linux" scheme="https://roc-wong.github.io/tags/Linux/"/>
<category term="Shell" scheme="https://roc-wong.github.io/tags/Shell/"/>
</entry>
<entry>
<title>bash-support.vim-Bash-IDE</title>
<link href="https://roc-wong.github.io/blog/2018/02/bash-support-vim-Bash-IDE.html"/>
<id>https://roc-wong.github.io/blog/2018/02/bash-support-vim-Bash-IDE.html</id>
<published>2018-02-12T07:10:46.000Z</published>
<updated>2018-11-21T02:18:25.563Z</updated>
<content type="html"><![CDATA[<p>IDE(集成开发环境)就是这样一个软件,它为了最大化程序员生产效率,提供了很多编程所需的设施和组件。 IDE 将所有开发工作集中到一个程序中,使得程序员可以编写、修改、编译、部署以及调试程序。</p>
<p>在这篇文章中,我们会介绍如何通过使用 bash-support vim 插件将 Vim 编辑器安装和配置 为一个编写 Bash 脚本的 IDE。</p>
<a id="more"></a>
<p>一键安装Bash-support脚本:</p>
<blockquote>
<ul>
<li><a href="https://github.com/roc-wong/shell-tools/blob/master/xpress_install/bash_support.sh" target="_blank" rel="external">https://github.com/roc-wong/shell-tools/blob/master/xpress_install/bash_support.sh</a></li>
</ul>
</blockquote>
<p>本篇博客整理自Linux中国:</p>
<blockquote>
<ul>
<li><a href="https://linux.cn/article-8467-1.html" target="_blank" rel="external">如何用bash-support插件将Vim编辑器打造成编写Bash脚本的IDE</a></li>
</ul>
</blockquote>
<h2 id="什么是-bash-support-vim-插件"><a href="#什么是-bash-support-vim-插件" class="headerlink" title="什么是 bash-support.vim 插件"></a>什么是 bash-support.vim 插件</h2><p>bash-support 是一个高度定制化的 vim 插件,它允许你插入:文件头、补全语句、注释、函数、以及代码块。它也使你可以进行语法检查、使脚本可执行、一键启动调试器;而完成所有的这些而不需要关闭编辑器。</p>
<p>它使用快捷键(映射),通过有组织地、一致的文件内容编写/插入,使得 bash 脚本编程变得有趣和愉快。</p>
<p>插件当前版本是 4.3,4.0 版本 重写了之前的 3.12.1 版本,4.0 及之后的版本基于一个全新的、更强大的、和之前版本模板语法不同的模板系统。</p>
<h2 id="如何在-Linux-中安装-Bash-support-插件"><a href="#如何在-Linux-中安装-Bash-support-插件" class="headerlink" title="如何在 Linux 中安装 Bash-support 插件"></a>如何在 Linux 中安装 Bash-support 插件</h2><p>用下面的命令下载最新版本的 bash-support 插件:</p>
<figure class="highlight elixir"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line"><span class="variable">$ </span>cd Downloads</div><div class="line"><span class="variable">$ </span>curl <span class="symbol">http:</span>/<span class="regexp">/www.vim.org/scripts</span><span class="regexp">/download_script.php?src_id=24452 >bash-support.zip</span></div></pre></td></tr></table></figure>
<p>按照如下步骤安装;在你的主目录创建 .vim 目录(如果它不存在的话),进入该目录并提取 bash-support.zip 内容:</p>
<figure class="highlight stylus"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line">$ mkdir ~/<span class="selector-class">.vim</span></div><div class="line">$ cd <span class="selector-class">.vim</span></div><div class="line">$ unzip ~/Downloads/bash-support.zip</div></pre></td></tr></table></figure>
<p>下一步,在 .vimrc 文件中激活它:</p>
<figure class="highlight elixir"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line"><span class="variable">$ </span>vi ~<span class="regexp">/.vimrc</span></div></pre></td></tr></table></figure>
<p>并插入下面一行:</p>
<figure class="highlight applescript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">filetype plug-<span class="keyword">in</span> <span class="keyword">on</span> </div><div class="line"><span class="keyword">set</span> <span class="built_in">number</span> <span class="comment"># 可选,增加这行以在 vim 中显示行号</span></div></pre></td></tr></table></figure>
<h2 id="如何在-Vim-编辑器中使用-Bash-support-插件"><a href="#如何在-Vim-编辑器中使用-Bash-support-插件" class="headerlink" title="如何在 Vim 编辑器中使用 Bash-support 插件"></a>如何在 Vim 编辑器中使用 Bash-support 插件</h2><p>为了简化使用,通常使用的结构和特定操作可以分别通过键映射来插入/执行。 ~/.vim/doc/bashsupport.txt 和 ~/.vim/bash-support/doc/bash-hotkeys.pdf 或者 ~/.vim/bash-support/doc/bash-hotkeys.tex 文件中介绍了映射。</p>
<p><strong>重要</strong>:</p>
<ol>
<li><strong>所有映射(+字符 组合)都是针对特定文件类型的:为了避免和其它插件的映射冲突,它们只适用于 sh 文件。</strong></li>
<li><strong>使用键映射的时候打字速度也有关系,引导符”\”和后面字符的组合要在特定短时间内才能识别出来(很可能少于 3 秒 - 基于假设)。</strong></li>
</ol>
<h2 id="如何为新脚本自动生成文件头"><a href="#如何为新脚本自动生成文件头" class="headerlink" title="如何为新脚本自动生成文件头"></a>如何为新脚本自动生成文件头</h2><p>下面我们会介绍和学习使用这个插件一些显著的功能。看下面的示例文件头,为了要在你所有的新脚本中自动创建该文件头,请按照以下步骤操作。</p>
<p><img src="https://dn-linuxcn.qbox.me/data/attachment/album/201705/02/005111cw2zxty9yd2ww3ow.png" alt="脚本示例文件头选项"></p>
<p>首先设置你的个人信息(作者名称、作者参考、组织、公司等)。在一个 Bash 缓冲区(像下面这样打开一个测试脚本)中使用映射 \ntw 启动模板设置向导。</p>
<p>选中选项 1 设置个性化文件,然后按回车键。</p>
<figure class="highlight stata"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">$ vi <span class="keyword">test</span>.<span class="keyword">sh</span></div></pre></td></tr></table></figure>
<p><img src="https://dn-linuxcn.qbox.me/data/attachment/album/201705/02/005111c6kdizyg4ie16k70.png" alt="在脚本文件中设置个性化信息"></p>
<p>之后,再次输入回车键。然后再一次选中选项 1 设置个性化文件的路径并输入回车。</p>
<p><img src="https://dn-linuxcn.qbox.me/data/attachment/album/201705/02/005112cpp9l6w922g0nu9j.png" alt="设置个性化文件路径"></p>
<p>设置向导会把目标文件 .vim/bash-support/rc/personal.templates 拷贝到 .vim/templates/personal.templates,打开并编辑它,在这里你可以输入你的信息。</p>
<p>按 i 键像截图那样在单引号中插入合适的值。</p>
<p><img src="https://dn-linuxcn.qbox.me/data/attachment/album/201705/02/005112x12kbb66z6gnxxgg.png" alt="在脚本文件头添加信息"></p>
<p>一旦你设置了正确的值,输入 :wq 保存并退出文件。关闭 Bash 测试脚本,打开另一个脚本来测试新的配置。现在文件头中应该有和下面截图类似的你的个人信息:<br><figure class="highlight vim"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">$ <span class="keyword">vi</span> test2.<span class="keyword">sh</span></div></pre></td></tr></table></figure></p>
<p><img src="https://dn-linuxcn.qbox.me/data/attachment/album/201705/02/005113cv0myl26mbn1h370.png" alt="自动添加文件头到脚本"></p>
<h2 id="添加-Bash-support-插件帮助信息"><a href="#添加-Bash-support-插件帮助信息" class="headerlink" title="添加 Bash-support 插件帮助信息"></a>添加 Bash-support 插件帮助信息</h2><p>为此,在 Vim 命令行输入下面的命令并按回车键,它会创建 .vim/doc/tags 文件:</p>
<figure class="highlight awk"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">:helptags <span class="variable">$HOME</span><span class="regexp">/.vim/</span>doc<span class="regexp">/</span></div></pre></td></tr></table></figure>
<p><img src="https://dn-linuxcn.qbox.me/data/attachment/album/201705/02/005113gixlnxzsxe58i8n8.png" alt="在 Vi 编辑器添加插件帮助"></p>
<h2 id="如何在-Shell-脚本中插入注释"><a href="#如何在-Shell-脚本中插入注释" class="headerlink" title="如何在 Shell 脚本中插入注释"></a>如何在 Shell 脚本中插入注释</h2><p>要插入一个块注释,在普通模式下输入 \cfr:</p>
<p><img src="https://dn-linuxcn.qbox.me/data/attachment/album/201705/02/005113hr1vsvdih7iy7d1s.png" alt="添加注释到脚本"></p>
<h2 id="如何在-Shell-脚本中插入语句"><a href="#如何在-Shell-脚本中插入语句" class="headerlink" title="如何在 Shell 脚本中插入语句"></a>如何在 Shell 脚本中插入语句</h2><p>下面是一些用于插入语句的键映射(n – 普通模式, i – 插入模式,v 可视模式):</p>
<figure class="highlight livescript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div></pre></td><td class="code"><pre><div class="line"><span class="string">\sc</span> – <span class="keyword">case</span> <span class="keyword">in</span> … esac (n, i)</div><div class="line"><span class="string">\sei</span> – elif <span class="keyword">then</span> (n, i)</div><div class="line"><span class="string">\sf</span> – <span class="keyword">for</span> <span class="keyword">in</span> <span class="keyword">do</span> done (n, i, v)</div><div class="line"><span class="string">\sfo</span> – <span class="keyword">for</span> ((…)) <span class="keyword">do</span> done (n, i, v)</div><div class="line"><span class="string">\si</span> – <span class="keyword">if</span> <span class="keyword">then</span> fi (n, i, v)</div><div class="line"><span class="string">\sie</span> – <span class="keyword">if</span> <span class="keyword">then</span> <span class="keyword">else</span> fi (n, i, v)</div><div class="line"><span class="string">\ss</span> – select <span class="keyword">in</span> <span class="keyword">do</span> done (n, i, v)</div><div class="line"><span class="string">\su</span> – <span class="keyword">until</span> <span class="keyword">do</span> done (n, i, v)</div><div class="line"><span class="string">\sw</span> – <span class="keyword">while</span> <span class="keyword">do</span> done (n, i, v)</div><div class="line"><span class="string">\sfu</span> – <span class="keyword">function</span> (n, i, v)</div><div class="line"><span class="string">\se</span> – echo -e <span class="string">"…"</span> (n, i, v)</div><div class="line"><span class="string">\sp</span> – printf <span class="string">"…"</span> (n, i, v)</div><div class="line"><span class="string">\sa</span> – 数组元素, ${.[.]} (n, i, v) 和其它更多的数组功能。</div></pre></td></tr></table></figure>
<h2 id="插入一个函数和函数头"><a href="#插入一个函数和函数头" class="headerlink" title="插入一个函数和函数头"></a>插入一个函数和函数头</h2><p>输入 \sfu 添加一个新的空函数,然后添加函数名并按回车键创建它。之后,添加你的函数代码。</p>
<p><img src="https://dn-linuxcn.qbox.me/data/attachment/album/201705/02/005114jz0iplcmz10imi7j.png" alt="在脚本中插入新函数"></p>
<p>为了给上面的函数创建函数头,输入 \cfu,输入函数名称,按回车键并填入合适的值(名称、介绍、参数、返回值):</p>
<p><img src="https://dn-linuxcn.qbox.me/data/attachment/album/201705/02/005114jz0iplcmz10imi7j.png" alt="在脚本中创建函数头"></p>
<h2 id="更多关于添加-Bash-语句的例子"><a href="#更多关于添加-Bash-语句的例子" class="headerlink" title="更多关于添加 Bash 语句的例子"></a>更多关于添加 Bash 语句的例子</h2><p>下面是一个使用 \si 插入一条 if 语句的例子:</p>
<p><img src="https://dn-linuxcn.qbox.me/data/attachment/album/201705/02/005114bd11zhj3b338ej33.png" alt="在脚本中插入语句"></p>
<p>下面的例子显示使用 \se 添加一条 echo 语句:</p>
<p><img src="https://dn-linuxcn.qbox.me/data/attachment/album/201705/02/005115i2rh71k7rz3c88xh.png" alt="在脚本中添加 echo 语句"></p>
<h2 id="如何在-Vi-编辑器中使用运行操作"><a href="#如何在-Vi-编辑器中使用运行操作" class="headerlink" title="如何在 Vi 编辑器中使用运行操作"></a>如何在 Vi 编辑器中使用运行操作</h2><p>下面是一些运行操作键映射的列表:</p>
<figure class="highlight excel"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div></pre></td><td class="code"><pre><div class="line">\rr – 更新文件,运行脚本(<span class="built_in">n</span>, i)</div><div class="line">\ra – 设置脚本命令行参数 (<span class="built_in">n</span>, i)</div><div class="line">\rc – 更新文件,检查语法 (<span class="built_in">n</span>, i)</div><div class="line">\rco – 语法检查选项 (<span class="built_in">n</span>, i)</div><div class="line">\rd – 启动调试器(<span class="built_in">n</span>, i)</div><div class="line">\re – 使脚本可/不可执行(*) (<span class="built_in">n</span>, i)</div></pre></td></tr></table></figure>
<h2 id="使脚本可执行"><a href="#使脚本可执行" class="headerlink" title="使脚本可执行"></a>使脚本可执行</h2><p>编写完脚本后,保存它然后输入 \re 和回车键使它可执行。</p>
<p><img src="https://dn-linuxcn.qbox.me/data/attachment/album/201705/02/005115ezuvseyjvkksyosn.png" alt="使脚本可执行"></p>
<h2 id="如何在-Bash-脚本中使用预定义代码片段"><a href="#如何在-Bash-脚本中使用预定义代码片段" class="headerlink" title="如何在 Bash 脚本中使用预定义代码片段"></a>如何在 Bash 脚本中使用预定义代码片段</h2><p>预定义代码片段是为了特定目的包含了已写好代码的文件。为了添加代码段,输入 \nr 和 \nw 读/写预定义代码段。输入下面的命令列出默认的代码段:</p>
<p>$ ls ~/.vim/bash-support/codesnippets/<br><img src="https://dn-linuxcn.qbox.me/data/attachment/album/201705/02/005115vgjeagjassxxkzk6.png" alt="代码段列表"></p>
<p>为了使用代码段,例如 free-software-comment,输入 \nr 并使用自动补全功能选择它的名称,然后输入回车键:</p>
<p><img src="https://dn-linuxcn.qbox.me/data/attachment/album/201705/02/005116e9ouzri0iyaghr5h.png" alt="添加代码段到脚本"></p>
<h2 id="创建自定义预定义代码段"><a href="#创建自定义预定义代码段" class="headerlink" title="创建自定义预定义代码段"></a>创建自定义预定义代码段</h2><p>可以在 ~/.vim/bash-support/codesnippets/目录下编写你自己的代码段。另外,你还可以从你正常的脚本代码中创建你自己的代码段:</p>
<ol>
<li>选择你想作为代码段的部分代码,然后输入 \nw 并给它一个相近的文件名。</li>
<li>要读入它,只需要输入 \nr 然后使用文件名就可以添加你自定义的代码段。</li>
</ol>
<h2 id="在当前光标处查看内建和命令帮助"><a href="#在当前光标处查看内建和命令帮助" class="headerlink" title="在当前光标处查看内建和命令帮助"></a>在当前光标处查看内建和命令帮助</h2><p>要显示帮助,在普通模式下输入:</p>
<ol>
<li>\hh – 内建帮助</li>
<li>\hm – 命令帮助</li>
</ol>
<p><img src="https://dn-linuxcn.qbox.me/data/attachment/album/201705/02/005116v16e1vnarxovx1x9.png" alt="查看内建命令帮助"></p>
<p>更多参考资料,可以查看文件:</p>
<figure class="highlight dts"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">~/.vim<span class="meta-keyword">/doc/</span>bashsupport.txt <span class="meta">#在线文档的副本</span></div><div class="line">~/.vim<span class="meta-keyword">/doc/</span>tags</div></pre></td></tr></table></figure>
<ul>
<li>访问 Bash-support 插件 GitHub 仓库:<a href="https://github.com/WolfgangMehner/bash-support" target="_blank" rel="external">https://github.com/WolfgangMehner/bash-support</a></li>
<li>在 Vim 网站访问 Bash-support 插件:<a href="http://www.vim.org/scripts/script.php?script_id=365" target="_blank" rel="external">http://www.vim.org/scripts/script.php?script_id=365</a></li>
</ul>
<p>就是这些啦,在这篇文章中,我们介绍了在 Linux 中使用 Bash-support 插件安装和配置 Vim 为一个 Bash-IDE 的步骤。快去发现这个插件其它令人兴奋的功能吧,一定要在评论中和我们分享哦。</p>
<p>作者简介:</p>
<p>Aaron Kili 是一个 Linux 和 F.O.S.S 爱好者、Linux 系统管理员、网络开发人员,现在也是 TecMint 的内容创作者,她喜欢和电脑一起工作,坚信共享知识。</p>
<p>via: <a href="http://www.tecmint.com/use-vim-as-bash-ide-using-bash-support-in-linux/" target="_blank" rel="external">http://www.tecmint.com/use-vim-as-bash-ide-using-bash-support-in-linux/</a></p>
<p>作者:Aaron Kili 译者:ictlyh 校对:wxy</p>
<p>本文由 LCTT 原创编译,Linux中国 荣誉推出</p>
]]></content>
<summary type="html">
bash-support是一个高度定制化的 vim 插件,它允许你插入:文件头、补全语句、注释、函数、以及代码块。它也使你可以进行语法检查、使脚本可执行、一键启动调试器;而完成所有的这些而不需要关闭编辑器。
</summary>
<category term="Linux" scheme="https://roc-wong.github.io/categories/Linux/"/>
<category term="Linux" scheme="https://roc-wong.github.io/tags/Linux/"/>
<category term="Shell" scheme="https://roc-wong.github.io/tags/Shell/"/>
</entry>
<entry>
<title>极光推送服务限流方案</title>
<link href="https://roc-wong.github.io/blog/2018/01/%E6%9C%8D%E5%8A%A1%E9%99%90%E6%B5%81%E6%96%B9%E6%A1%88.html"/>
<id>https://roc-wong.github.io/blog/2018/01/服务限流方案.html</id>
<published>2018-01-31T13:41:04.000Z</published>
<updated>2018-09-12T15:18:00.000Z</updated>
<content type="html"><![CDATA[<p>如何让系统在汹涌澎湃的流量面前谈笑风生?我们的策略是不要让系统超负荷工作。如果现有的系统扛不住业务目标怎么办?加机器!机器不够怎么办?业务降级,服务限流!</p>
<p>正所谓「他强任他强,清风拂山岗;他横任他横,明月照大江」,降级和限流是系统可用性保障中必不可少的神兵利器,丢卒保车,以暂停边缘业务为代价保障核心业务的资源,以系统不被突发流量压挂为第一要务。</p>
<a id="more"></a>
<h2 id="现状"><a href="#现状" class="headerlink" title="现状"></a>现状</h2><h3 id="JPush-API-频率控制"><a href="#JPush-API-频率控制" class="headerlink" title="JPush API 频率控制"></a>JPush API 频率控制</h3><p>JPush API对访问次数,具有频率控制。即一定的时间窗口内,API允许调用的次数是有限制的。免费版:1分钟600次。</p>
<p>超出后:<br><figure class="highlight json"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">{<span class="attr">"error"</span>:{<span class="attr">"code"</span>:<span class="number">2002</span>,<span class="attr">"message"</span>:<span class="string">"Request times of the app_key exceed the limit of current time window"</span>}}</div></pre></td></tr></table></figure></p>
<h3 id="各业务组直接对接极光API"><a href="#各业务组直接对接极光API" class="headerlink" title="各业务组直接对接极光API"></a>各业务组直接对接极光API</h3><p>目前各业务线都在使用极光推送服务,并且是直接调用极光API。水归一源,终汇聚一处。想实现流量管控,只有将调用出口整合到一处,方可达到限流管控的目的。</p>
<p><img src="https://raw.githubusercontent.com/roc-wong/images/master/%E6%9E%81%E5%85%89%E6%8E%A8%E9%80%81%E8%B0%83%E7%94%A8%E7%8E%B0%E7%8A%B6.png" alt="现状"></p>
<h2 id="解决方案"><a href="#解决方案" class="headerlink" title="解决方案"></a>解决方案</h2><h3 id="令牌桶算法"><a href="#令牌桶算法" class="headerlink" title="令牌桶算法"></a>令牌桶算法</h3><p>令牌桶算法是网络流量整形(Traffic Shaping)和速率限制(Rate Limiting)中最常使用的一种算法。典型情况下,令牌桶算法用来控制发送到网络上的数据的数目,并允许突发数据的发送。令牌桶属于控制速率类型的。令牌桶算法最初来源于计算机网络。在网络传输数据时,为了防止网络拥塞,需限制流出网络的流量,使流量以比较均匀的速度向外发送。令牌桶算法就实现了这个功能,可控制发送到网络上数据的数目,并允许突发数据的发送。</p>
<p>在 Wikipedia 上,令牌桶算法是这么描述的:</p>
<ol>
<li>每秒会有 r 个令牌放入桶中,或者说,每过 1/r 秒桶中增加一个令牌。</li>
<li>桶中最多存放 b 个令牌,如果桶满了,新放入的令牌会被丢弃。</li>
<li>当一个 n 字节的数据包到达时,消耗 n 个令牌,然后发送该数据包。</li>
<li>如果桶中可用令牌小于 n,则该数据包将被缓存或丢弃。</li>
</ol>
<p><img src="http://xiaobaoqiu.github.io/images/guava/token_bucket.JPG" alt="令牌桶"></p>
<p>大小固定的令牌桶可自行以恒定的速率源源不断地产生令牌。如果令牌不被消耗,或者被消耗的速度小于产生的速度,令牌就会不断地增多,直到把桶填满。后面再产生的令牌就会从桶中溢出。最后桶中可以保存的最大令牌数永远不会超过桶的大小。传送到令牌桶的数据包需要消耗令牌。不同大小的数据包,消耗的令牌数量不一样。</p>
<p>令牌桶这种控制机制基于令牌桶中是否存在令牌来指示什么时候可以发送流量。令牌桶中的每一个令牌都代表一个字节。如果令牌桶中存在令牌,则允许发送流量;而如果令牌桶中不存在令牌,则不允许发送流量。因此,如果突发门限被合理地配置并且令牌桶中有足够的令牌,那么流量就可以以峰值速率发送。</p>
<p>基于令牌桶算法改造消息中心,流程图如下:</p>
<p><img src="https://raw.githubusercontent.com/roc-wong/images/master/%E9%99%90%E6%B5%81%E6%B5%81%E7%A8%8B%E5%9B%BE.png" alt="限流方案"></p>
<h3 id="单机限流"><a href="#单机限流" class="headerlink" title="单机限流"></a>单机限流</h3><p>Google Guava RateLimiter就是令牌桶算法的实现,速率限制器会在可配置的速率下分配许可证。如果必要的话,每个acquire() 会阻塞当前线程直到许可证可用后获取该许可证。一旦获取到许可证,不需要再释放许可证。RateLimiter经常用于限制对一些物理资源或者逻辑资源的访问速率。与Semaphore 相比,Semaphore 限制了并发访问的数量而不是使用速率。</p>
<figure class="highlight gradle"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div></pre></td><td class="code"><pre><div class="line"><span class="comment">//每秒两个许可</span></div><div class="line"><span class="keyword">final</span> RateLimiter rateLimiter = RateLimiter.create(<span class="number">2.0</span>);</div><div class="line"></div><div class="line"><span class="keyword">void</span> submitTasks(List tasks, Executor executor) {</div><div class="line"> <span class="keyword">for</span> (Runnable <span class="keyword">task</span> : tasks) {</div><div class="line"> rateLimiter.acquire(); <span class="comment">// 拿不到许可就等待</span></div><div class="line"> executor.execute(<span class="keyword">task</span>);</div><div class="line"> }</div><div class="line">}</div></pre></td></tr></table></figure>
<p>通过设置许可证的速率来定义RateLimiter。在默认配置下,许可证会在固定的速率下被分配,速率单位是每秒多少个许可证。为了确保维护配置的速率,许可会被平稳地分配,许可之间的延迟会做调整。可能存在配置一个拥有预热期的RateLimiter的情况,在这段时间内,每秒分配的许可数会稳定地增长直到达到稳定的速率。</p>
<h3 id="分布式限流"><a href="#分布式限流" class="headerlink" title="分布式限流"></a>分布式限流</h3><p>Remote Dictionary Server(Redis)是一个基于 key-value 键值对的持久化数据库存储系统。支持多种数据结构,包括 string (字符串)、list (链表)、set (集合)、zset (sorted set –有序集合)和 hash(哈希类型)。这些数据类型都支持 push/pop、add/remove 及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的。</p>
<p>想实现分布式限流,非Redis莫属。Redis限流的大体思路是设置一个带有过期时间的key,每次申请令牌时,将 key 所储存的值加上增量 increment, 判断key 所存储的值是否达到上限,未达到上限,则获得许可。如有需要,亦可阻塞当前线程直到获得许可。</p>
<p>限流相关的命令:</p>
<p><strong>事务</strong></p>
<p>MULTI、EXEC、DISCARD和WATCH命令是Redis事务功能的基础,Redis事务允许在一次单独的步骤中执行一组命令,并且可以保证如下两个重要事项:</p>
<ul>
<li><p>Redis会将一个事务中的所有命令序列化,然后按顺序执行。</p>
<p> Redis不可能在一个Redis事务的执行过程中插入执行另一个客户端发出的请求。这样便能保证Redis将这些命令作为一个单独的隔离操作执行。 </p>
</li>
<li><p>在一个Redis事务中,Redis要么执行其中的所有命令,要么什么都不执行。</p>
<p> 因此,Redis事务能够保证原子性。EXEC命令会触发执行事务中的所有命令。因此,当某个客户端正在执行一次事务时,如果它在调用MULTI命令之前就从Redis服务端断开连接,那么就不会执行事务中的任何操作;相反,如果它在调用EXEC命令之后才从Redis服务端断开连接,那么就会执行事务中的所有操作。当Redis使用只增文件(AOF:Append-only File)时,Redis能够确保使用一个单独的write(2)系统调用,这样便能将事务写入磁盘。然而,如果Redis服务器宕机,或者系统管理员以某种方式停止Redis服务进程的运行,那么Redis很有可能只执行了事务中的一部分操作。Redis将会在重新启动时检查上述状态,然后退出运行,并且输出报错信息。使用redis-check-aof工具可以修复上述的只增文件,这个工具将会从上述文件中删除执行不完全的事务,这样Redis服务器才能再次启动。</p>
</li>
</ul>
<p>从2.2版本开始,除了上述两项保证之外,Redis还能够以乐观锁(Watch)的形式提供更多的保证,这种形式非常类似于”检查再设置”(CAS:Check And Set)操作。</p>
<p>从2.6版本开始提供脚本(Lua scripting)能力,一种更灵活的批量命令组织方式用于取代目前的事务机制。脚本提供了更强大和灵活的编程能力,但也是一把双刃剑,由于 Redis 需要保证脚本执行的原子性和隔离性,脚本执行期间会阻塞其他命令的执行,因此建议使用高效的脚本完成业务。</p>
<p><strong>SET</strong></p>
<p>SET key value [EX seconds] [PX milliseconds] [NX|XX]</p>
<p>将字符串值 value 关联到 key 。如果 key 已经持有其他值, SET 就覆写旧值,无视类型。对于某个原本带有生存时间(TTL)的键来说, 当 SET 命令成功在这个键上执行时, 这个键原有的 TTL 将被清除。</p>
<p>从 Redis 2.6.12 版本开始, SET 命令的行为可以通过一系列参数来修改:</p>
<p>EX second :设置键的过期时间为 second 秒。 SET key value EX second 效果等同于 SETEX key second value 。<br>PX millisecond :设置键的过期时间为 millisecond 毫秒。 SET key value PX millisecond 效果等同于 PSETEX key millisecond value 。<br>NX :只在键不存在时,才对键进行设置操作。 SET key value NX 效果等同于 SETNX key value 。<br>XX :只在键已经存在时,才对键进行设置操作。</p>
<p><strong>INCRBY</strong></p>
<p>将 key 所储存的值加上增量 increment 。如果 key 不存在,那么 key 的值会先被初始化为 0 ,然后再执行 INCRBY 命令。如果值包含错误的类型,或字符串类型的值不能表示为数字,那么返回一个错误。</p>
<p>Redis官方基于上述命令提供的限流代码:<a href="https://redis.io/commands/incr#pattern-rate-limiter-1" target="_blank" rel="external">https://redis.io/commands/incr#pattern-rate-limiter-1</a></p>
<h2 id="代码验证"><a href="#代码验证" class="headerlink" title="代码验证"></a>代码验证</h2><p>使用Jedis client进行限流方案验证:</p>
<figure class="highlight applescript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div></pre></td><td class="code"><pre><div class="line">package hbec.app.stock.ratelimiter;</div><div class="line"></div><div class="line">/**</div><div class="line"> * @author roc</div><div class="line"> * @<span class="built_in">date</span> <span class="number">2018</span>/<span class="number">01</span>/<span class="number">24</span></div><div class="line"> */</div><div class="line">public interface RateLimiter {</div><div class="line"></div><div class="line"> /**</div><div class="line"> * Acquires a permit only <span class="keyword">if</span> one <span class="keyword">is</span> available <span class="keyword">at</span> <span class="keyword">the</span></div><div class="line"> * <span class="built_in">time</span> <span class="keyword">of</span> invocation.</div><div class="line"> *</div><div class="line"> * <p>Acquires a permit, <span class="keyword">if</span> one <span class="keyword">is</span> available <span class="keyword">and</span> returns immediately,</div><div class="line"> * <span class="keyword">with</span> <span class="keyword">the</span> <span class="literal">result</span> {@code LimiterResult<span class="comment">#acquired is true},</span></div><div class="line"> * reducing <span class="keyword">the</span> <span class="built_in">number</span> <span class="keyword">of</span> available permits <span class="keyword">by</span> one.</div><div class="line"> *</div><div class="line"> * <p>If no permit <span class="keyword">is</span> available <span class="keyword">then</span> this method will <span class="literal">return</span></div><div class="line"> * immediately <span class="keyword">with</span> <span class="keyword">the</span> value {@code <span class="literal">false</span>}.</div><div class="line"> *</div><div class="line"> * @param permits <span class="keyword">the</span> <span class="built_in">number</span> <span class="keyword">of</span> permits <span class="keyword">to</span> acquire</div><div class="line"> * @<span class="literal">return</span> acquire <span class="literal">result</span> {@code <span class="literal">true</span>} <span class="keyword">if</span> a permit was acquired,</div><div class="line"> * <span class="keyword">and</span> {@code <span class="literal">false</span> <span class="keyword">is</span> <span class="literal">false</span>} otherwise</div><div class="line"> */</div><div class="line"> <span class="built_in">boolean</span> tryAcquire(int permits);</div><div class="line"></div><div class="line"> /**</div><div class="line"> * Acquires a permit <span class="keyword">from</span> this method, blocking <span class="keyword">until</span> one <span class="keyword">is</span></div><div class="line"> * available, <span class="keyword">or</span> <span class="keyword">the</span> thread <span class="keyword">is</span> {@linkplain Thread<span class="comment">#interrupt interrupted}.</span></div><div class="line"> *</div><div class="line"> * <p>Acquires a permit, <span class="keyword">if</span> one <span class="keyword">is</span> available <span class="keyword">and</span> returns immediately,</div><div class="line"> * reducing <span class="keyword">the</span> <span class="built_in">number</span> <span class="keyword">of</span> available permits <span class="keyword">by</span> one.</div><div class="line"> *</div><div class="line"> * @param permits <span class="keyword">the</span> <span class="built_in">number</span> <span class="keyword">of</span> permits <span class="keyword">to</span> acquire</div><div class="line"> */</div><div class="line"> void acquire(int permits) throws InterruptedException;</div><div class="line">}</div></pre></td></tr></table></figure>
<figure class="highlight aspectj"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div><div class="line">41</div><div class="line">42</div><div class="line">43</div><div class="line">44</div><div class="line">45</div><div class="line">46</div><div class="line">47</div><div class="line">48</div><div class="line">49</div><div class="line">50</div><div class="line">51</div><div class="line">52</div><div class="line">53</div><div class="line">54</div><div class="line">55</div><div class="line">56</div><div class="line">57</div><div class="line">58</div><div class="line">59</div><div class="line">60</div><div class="line">61</div><div class="line">62</div><div class="line">63</div><div class="line">64</div><div class="line">65</div><div class="line">66</div><div class="line">67</div><div class="line">68</div><div class="line">69</div><div class="line">70</div><div class="line">71</div><div class="line">72</div><div class="line">73</div><div class="line">74</div><div class="line">75</div><div class="line">76</div><div class="line">77</div><div class="line">78</div><div class="line">79</div><div class="line">80</div><div class="line">81</div><div class="line">82</div><div class="line">83</div><div class="line">84</div><div class="line">85</div><div class="line">86</div><div class="line">87</div><div class="line">88</div><div class="line">89</div><div class="line">90</div><div class="line">91</div><div class="line">92</div><div class="line">93</div><div class="line">94</div><div class="line">95</div><div class="line">96</div><div class="line">97</div><div class="line">98</div><div class="line">99</div><div class="line">100</div><div class="line">101</div><div class="line">102</div><div class="line">103</div><div class="line">104</div><div class="line">105</div><div class="line">106</div><div class="line">107</div><div class="line">108</div><div class="line">109</div><div class="line">110</div><div class="line">111</div><div class="line">112</div><div class="line">113</div><div class="line">114</div><div class="line">115</div><div class="line">116</div><div class="line">117</div><div class="line">118</div><div class="line">119</div><div class="line">120</div><div class="line">121</div><div class="line">122</div><div class="line">123</div><div class="line">124</div><div class="line">125</div><div class="line">126</div><div class="line">127</div><div class="line">128</div><div class="line">129</div><div class="line">130</div><div class="line">131</div><div class="line">132</div><div class="line">133</div><div class="line">134</div><div class="line">135</div><div class="line">136</div><div class="line">137</div><div class="line">138</div><div class="line">139</div><div class="line">140</div><div class="line">141</div><div class="line">142</div><div class="line">143</div><div class="line">144</div><div class="line">145</div><div class="line">146</div><div class="line">147</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">package</span> hbec.app.stock.ratelimiter;</div><div class="line"></div><div class="line"><span class="keyword">import</span> com.google.common.base.Preconditions;</div><div class="line"><span class="keyword">import</span> hbec.app.stock.commons.redis.JedisTemplate;</div><div class="line"><span class="keyword">import</span> org.apache.commons.lang3.StringUtils;</div><div class="line"><span class="keyword">import</span> org.slf4j.Logger;</div><div class="line"><span class="keyword">import</span> org.slf4j.LoggerFactory;</div><div class="line"><span class="keyword">import</span> redis.clients.jedis.Jedis;</div><div class="line"><span class="keyword">import</span> redis.clients.jedis.Response;</div><div class="line"><span class="keyword">import</span> redis.clients.jedis.Transaction;</div><div class="line"></div><div class="line"><span class="keyword">import</span> java.util.Random;</div><div class="line"><span class="keyword">import</span> java.util.concurrent.TimeUnit;</div><div class="line"></div><div class="line"><span class="comment">/**</span></div><div class="line"> * <span class="doctag">@author</span> roc</div><div class="line"> * <span class="doctag">@date</span> 2018/01/23</div><div class="line"> */</div><div class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">RedisRateLimiter</span> <span class="keyword">implements</span> <span class="title">RateLimiter</span> </span>{</div><div class="line"></div><div class="line"> <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> Logger LOGGER = LoggerFactory.getLogger(RedisRateLimiter.class);</div><div class="line"></div><div class="line"> <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> String ZERO = <span class="string">"0"</span>;</div><div class="line"></div><div class="line"> <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> String NOT_EXISTS = <span class="string">"NX"</span>;</div><div class="line"></div><div class="line"> <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> String P_EXPIRE = <span class="string">"PX"</span>;</div><div class="line"></div><div class="line"> <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="keyword">int</span> NOT_SET = <span class="number">-1</span>;</div><div class="line"></div><div class="line"> <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> Random TIME_RANDOM = <span class="keyword">new</span> Random();</div><div class="line"></div><div class="line"> <span class="comment">/**</span></div><div class="line"> * 限流标识,redis key</div><div class="line"> */</div><div class="line"> <span class="keyword">private</span> String rateLimiterName;</div><div class="line"></div><div class="line"> <span class="comment">/**</span></div><div class="line"> * 存活时间</div><div class="line"> */</div><div class="line"> <span class="keyword">private</span> <span class="keyword">int</span> timeToLive;</div><div class="line"></div><div class="line"> <span class="comment">/**</span></div><div class="line"> * 许可上限</div><div class="line"> */</div><div class="line"> <span class="keyword">private</span> <span class="keyword">int</span> upperLimitPermits;</div><div class="line"></div><div class="line"></div><div class="line"> <span class="keyword">private</span> JedisTemplate jedisTemplate;</div><div class="line"></div><div class="line"> <span class="meta">@Override</span></div><div class="line"> <span class="keyword">public</span> <span class="function"><span class="keyword">boolean</span> <span class="title">tryAcquire</span><span class="params">(<span class="keyword">final</span> <span class="keyword">int</span> permits)</span> </span>{</div><div class="line"> Preconditions.checkArgument(permits > <span class="number">0</span>, <span class="string">"The number of permits must be greater than 0."</span>);</div><div class="line"> <span class="keyword">return</span> acquireSync(permits).isAcquired();</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="meta">@Override</span></div><div class="line"> <span class="keyword">public</span> <span class="function"><span class="keyword">void</span> <span class="title">acquire</span><span class="params">(<span class="keyword">final</span> <span class="keyword">int</span> permits)</span> <span class="keyword">throws</span> InterruptedException </span>{</div><div class="line"> Preconditions.checkArgument(permits > <span class="number">0</span>, <span class="string">"The number of permits must be greater than 0."</span>);</div><div class="line"> LimiterResult limiterResult;</div><div class="line"> do {</div><div class="line"> limiterResult = acquireSync(permits);</div><div class="line"> <span class="keyword">if</span> (!limiterResult.isAcquired()) {</div><div class="line"> <span class="keyword">long</span> sleepTime = limiterResult.getRemainderTTL() + TIME_RANDOM.nextInt(<span class="number">5</span>);</div><div class="line"> Thread.sleep(sleepTime);</div><div class="line"> }</div><div class="line"> } <span class="keyword">while</span> (!limiterResult.isAcquired());</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">public</span> <span class="function">LimiterResult <span class="title">acquireSync</span><span class="params">(<span class="keyword">final</span> <span class="keyword">int</span> permits)</span> </span>{</div><div class="line"></div><div class="line"> <span class="function"><span class="keyword">return</span> jedisTemplate.<span class="title">execute</span><span class="params">(<span class="keyword">new</span> JedisTemplate.JedisAction<LimiterResult>()</span> </span>{</div><div class="line"></div><div class="line"> <span class="meta">@Override</span></div><div class="line"> <span class="keyword">public</span> <span class="function">LimiterResult <span class="title">action</span><span class="params">(Jedis jedis)</span> </span>{</div><div class="line"></div><div class="line"> Transaction transaction = jedis.multi();</div><div class="line"> transaction.set(rateLimiterName, ZERO, NOT_EXISTS, P_EXPIRE, timeToLive);</div><div class="line"> Response<Long> currentQPS = transaction.incrBy(rateLimiterName, permits);</div><div class="line"> Response<Long> keyTTL = transaction.pttl(rateLimiterName);</div><div class="line"> transaction.exec();</div><div class="line"></div><div class="line"> Long currentPermit = currentQPS.get();</div><div class="line"> Long remainderTTL = keyTTL.get();</div><div class="line"></div><div class="line"> <span class="keyword">boolean</span> acquired = currentPermit <= upperLimitPermits;</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (!acquired && remainderTTL == NOT_SET) {</div><div class="line"> LOGGER.<span class="keyword">error</span>(<span class="string">"Warning! Set ttl false, key={}, current ttl={}"</span>, rateLimiterName, remainderTTL);</div><div class="line"> jedis.expire(rateLimiterName, timeToLive);</div><div class="line"> remainderTTL = (<span class="keyword">long</span>) timeToLive;</div><div class="line"> }</div><div class="line"></div><div class="line"> LOGGER.debug(<span class="string">"rateLimiterName={}, passed={}, remainderTTL={}, time={}"</span>,</div><div class="line"> rateLimiterName, acquired ? <span class="string">"true"</span> : <span class="string">"false"</span>,</div><div class="line"> remainderTTL, currentPermit);</div><div class="line"> <span class="function"><span class="keyword">return</span> LimiterResult.<span class="title">newInstance</span><span class="params">(acquired, remainderTTL)</span></span>;</div><div class="line"> }</div><div class="line"> });</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">public</span> <span class="keyword">static</span> <span class="function">Builder <span class="title">newBuilder</span><span class="params">(JedisTemplate jedisTemplate)</span> </span>{</div><div class="line"> <span class="keyword">return</span> <span class="keyword">new</span> Builder(jedisTemplate);</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="class"><span class="keyword">class</span> <span class="title">Builder</span> </span>{</div><div class="line"> <span class="keyword">private</span> JedisTemplate jedisTemplate;</div><div class="line"> <span class="keyword">private</span> String rateLimiterName;</div><div class="line"> <span class="keyword">private</span> <span class="keyword">int</span> timeToLive;</div><div class="line"> <span class="keyword">private</span> <span class="keyword">int</span> upperLimitPermits;</div><div class="line"></div><div class="line"> <span class="function"><span class="keyword">private</span> <span class="title">Builder</span><span class="params">(JedisTemplate jedisTemplate)</span> </span>{</div><div class="line"> Preconditions.checkNotNull(jedisTemplate, <span class="string">"JedisTemplate can't be null."</span>);</div><div class="line"> <span class="keyword">this</span>.jedisTemplate = jedisTemplate;</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">public</span> <span class="function">Builder <span class="title">setRateLimiterName</span><span class="params">(String rateLimiterName)</span> </span>{</div><div class="line"></div><div class="line"> <span class="keyword">this</span>.rateLimiterName = rateLimiterName;</div><div class="line"> <span class="keyword">return</span> <span class="keyword">this</span>;</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">public</span> <span class="function">Builder <span class="title">setTimeToLive</span><span class="params">(<span class="keyword">int</span> timeToLive, TimeUnit timeUnit)</span> </span>{</div><div class="line"> <span class="keyword">this</span>.timeToLive = (<span class="keyword">int</span>) timeUnit.toMillis(timeToLive);</div><div class="line"> <span class="keyword">return</span> <span class="keyword">this</span>;</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">public</span> <span class="function">Builder <span class="title">setUpperLimitPermits</span><span class="params">(<span class="keyword">int</span> upperLimitPermits)</span> </span>{</div><div class="line"> <span class="keyword">this</span>.upperLimitPermits = upperLimitPermits;</div><div class="line"> <span class="keyword">return</span> <span class="keyword">this</span>;</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">public</span> <span class="function">RedisRateLimiter <span class="title">build</span><span class="params">()</span> </span>{</div><div class="line"> Preconditions.checkArgument(StringUtils.isNotBlank(rateLimiterName), <span class="string">"RateLimiterName can't be blank."</span>);</div><div class="line"> Preconditions.checkArgument(upperLimitPermits > <span class="number">0</span>, <span class="string">"UpperLimitPermits must be an integer greater than 0."</span>);</div><div class="line"> Preconditions.checkArgument(timeToLive > <span class="number">0</span>, <span class="string">"TimeToLive must be an integer greater than 0."</span>);</div><div class="line"></div><div class="line"> RedisRateLimiter redisRateLimiter = <span class="keyword">new</span> RedisRateLimiter();</div><div class="line"> redisRateLimiter.jedisTemplate = <span class="keyword">this</span>.jedisTemplate;</div><div class="line"> redisRateLimiter.upperLimitPermits = <span class="keyword">this</span>.upperLimitPermits;</div><div class="line"> redisRateLimiter.rateLimiterName = <span class="keyword">this</span>.rateLimiterName;</div><div class="line"> redisRateLimiter.timeToLive = <span class="keyword">this</span>.timeToLive;</div><div class="line"></div><div class="line"> <span class="keyword">return</span> redisRateLimiter;</div><div class="line"> }</div><div class="line"> }</div><div class="line">}</div></pre></td></tr></table></figure>
<figure class="highlight aspectj"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div><div class="line">41</div><div class="line">42</div><div class="line">43</div><div class="line">44</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">package</span> hbec.app.stock.ratelimiter;</div><div class="line"></div><div class="line"><span class="comment">/**</span></div><div class="line"> * <span class="doctag">@author</span> roc</div><div class="line"> * <span class="doctag">@date</span> 2018/01/24</div><div class="line"> */</div><div class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">LimiterResult</span> </span>{</div><div class="line"></div><div class="line"> <span class="keyword">private</span> <span class="keyword">boolean</span> acquired;</div><div class="line"></div><div class="line"> <span class="keyword">private</span> Long remainderTTL;</div><div class="line"></div><div class="line"> <span class="keyword">public</span> <span class="keyword">static</span> <span class="function">LimiterResult <span class="title">newInstance</span><span class="params">(<span class="keyword">boolean</span> acquired, Long remainderTTL)</span> </span>{</div><div class="line"> LimiterResult limiterResult = <span class="keyword">new</span> LimiterResult();</div><div class="line"> limiterResult.setAcquired(acquired);</div><div class="line"> limiterResult.setRemainderTTL(remainderTTL);</div><div class="line"> <span class="keyword">return</span> limiterResult;</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">public</span> <span class="function"><span class="keyword">boolean</span> <span class="title">isAcquired</span><span class="params">()</span> </span>{</div><div class="line"> <span class="keyword">return</span> acquired;</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">public</span> <span class="function">Long <span class="title">getRemainderTTL</span><span class="params">()</span> </span>{</div><div class="line"> <span class="keyword">return</span> remainderTTL;</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">public</span> <span class="function"><span class="keyword">void</span> <span class="title">setAcquired</span><span class="params">(<span class="keyword">boolean</span> acquired)</span> </span>{</div><div class="line"> <span class="keyword">this</span>.acquired = acquired;</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">public</span> <span class="function"><span class="keyword">void</span> <span class="title">setRemainderTTL</span><span class="params">(Long remainderTTL)</span> </span>{</div><div class="line"> <span class="keyword">this</span>.remainderTTL = remainderTTL;</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="meta">@Override</span></div><div class="line"> <span class="keyword">public</span> <span class="function">String <span class="title">toString</span><span class="params">()</span> </span>{</div><div class="line"> <span class="keyword">final</span> StringBuilder sb = <span class="keyword">new</span> StringBuilder(<span class="string">"LimiterResult{"</span>);</div><div class="line"> sb.append(<span class="string">"acquired="</span>).append(acquired);</div><div class="line"> sb.append(<span class="string">", remainderTTL="</span>).append(remainderTTL);</div><div class="line"> sb.append(<span class="string">'}'</span>);</div><div class="line"> <span class="function"><span class="keyword">return</span> sb.<span class="title">toString</span><span class="params">()</span></span>;</div><div class="line"> }</div><div class="line">}</div></pre></td></tr></table></figure>
<p>JedisTemplate.java<br><figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div><div class="line">41</div><div class="line">42</div><div class="line">43</div><div class="line">44</div><div class="line">45</div><div class="line">46</div><div class="line">47</div><div class="line">48</div><div class="line">49</div><div class="line">50</div><div class="line">51</div><div class="line">52</div><div class="line">53</div><div class="line">54</div><div class="line">55</div><div class="line">56</div><div class="line">57</div><div class="line">58</div><div class="line">59</div><div class="line">60</div><div class="line">61</div><div class="line">62</div><div class="line">63</div><div class="line">64</div><div class="line">65</div><div class="line">66</div><div class="line">67</div><div class="line">68</div><div class="line">69</div><div class="line">70</div><div class="line">71</div><div class="line">72</div><div class="line">73</div><div class="line">74</div><div class="line">75</div><div class="line">76</div><div class="line">77</div><div class="line">78</div><div class="line">79</div><div class="line">80</div><div class="line">81</div><div class="line">82</div><div class="line">83</div><div class="line">84</div><div class="line">85</div><div class="line">86</div><div class="line">87</div><div class="line">88</div><div class="line">89</div><div class="line">90</div><div class="line">91</div><div class="line">92</div><div class="line">93</div><div class="line">94</div><div class="line">95</div><div class="line">96</div><div class="line">97</div><div class="line">98</div><div class="line">99</div><div class="line">100</div><div class="line">101</div><div class="line">102</div><div class="line">103</div><div class="line">104</div><div class="line">105</div><div class="line">106</div><div class="line">107</div><div class="line">108</div><div class="line">109</div><div class="line">110</div><div class="line">111</div><div class="line">112</div><div class="line">113</div><div class="line">114</div><div class="line">115</div><div class="line">116</div><div class="line">117</div><div class="line">118</div><div class="line">119</div><div class="line">120</div><div class="line">121</div><div class="line">122</div><div class="line">123</div><div class="line">124</div><div class="line">125</div><div class="line">126</div><div class="line">127</div><div class="line">128</div><div class="line">129</div><div class="line">130</div><div class="line">131</div><div class="line">132</div><div class="line">133</div><div class="line">134</div><div class="line">135</div><div class="line">136</div><div class="line">137</div><div class="line">138</div><div class="line">139</div><div class="line">140</div><div class="line">141</div><div class="line">142</div><div class="line">143</div><div class="line">144</div><div class="line">145</div><div class="line">146</div><div class="line">147</div><div class="line">148</div><div class="line">149</div><div class="line">150</div><div class="line">151</div><div class="line">152</div><div class="line">153</div><div class="line">154</div><div class="line">155</div><div class="line">156</div><div class="line">157</div><div class="line">158</div><div class="line">159</div><div class="line">160</div><div class="line">161</div><div class="line">162</div><div class="line">163</div><div class="line">164</div><div class="line">165</div><div class="line">166</div><div class="line">167</div><div class="line">168</div><div class="line">169</div><div class="line">170</div><div class="line">171</div><div class="line">172</div><div class="line">173</div><div class="line">174</div><div class="line">175</div><div class="line">176</div><div class="line">177</div><div class="line">178</div><div class="line">179</div><div class="line">180</div><div class="line">181</div><div class="line">182</div><div class="line">183</div><div class="line">184</div><div class="line">185</div><div class="line">186</div><div class="line">187</div><div class="line">188</div><div class="line">189</div><div class="line">190</div><div class="line">191</div><div class="line">192</div><div class="line">193</div><div class="line">194</div><div class="line">195</div><div class="line">196</div><div class="line">197</div><div class="line">198</div><div class="line">199</div><div class="line">200</div><div class="line">201</div><div class="line">202</div><div class="line">203</div><div class="line">204</div><div class="line">205</div><div class="line">206</div><div class="line">207</div><div class="line">208</div><div class="line">209</div><div class="line">210</div><div class="line">211</div><div class="line">212</div><div class="line">213</div><div class="line">214</div><div class="line">215</div><div class="line">216</div><div class="line">217</div><div class="line">218</div><div class="line">219</div><div class="line">220</div><div class="line">221</div><div class="line">222</div><div class="line">223</div><div class="line">224</div><div class="line">225</div><div class="line">226</div><div class="line">227</div><div class="line">228</div><div class="line">229</div><div class="line">230</div><div class="line">231</div><div class="line">232</div><div class="line">233</div><div class="line">234</div><div class="line">235</div><div class="line">236</div><div class="line">237</div><div class="line">238</div><div class="line">239</div><div class="line">240</div><div class="line">241</div><div class="line">242</div><div class="line">243</div><div class="line">244</div><div class="line">245</div><div class="line">246</div><div class="line">247</div><div class="line">248</div><div class="line">249</div><div class="line">250</div><div class="line">251</div><div class="line">252</div><div class="line">253</div><div class="line">254</div><div class="line">255</div><div class="line">256</div><div class="line">257</div><div class="line">258</div><div class="line">259</div><div class="line">260</div><div class="line">261</div><div class="line">262</div><div class="line">263</div><div class="line">264</div><div class="line">265</div><div class="line">266</div><div class="line">267</div><div class="line">268</div><div class="line">269</div><div class="line">270</div><div class="line">271</div><div class="line">272</div><div class="line">273</div><div class="line">274</div><div class="line">275</div><div class="line">276</div><div class="line">277</div><div class="line">278</div><div class="line">279</div><div class="line">280</div><div class="line">281</div><div class="line">282</div><div class="line">283</div><div class="line">284</div><div class="line">285</div><div class="line">286</div><div class="line">287</div><div class="line">288</div><div class="line">289</div><div class="line">290</div><div class="line">291</div><div class="line">292</div><div class="line">293</div><div class="line">294</div><div class="line">295</div><div class="line">296</div><div class="line">297</div><div class="line">298</div><div class="line">299</div><div class="line">300</div><div class="line">301</div><div class="line">302</div><div class="line">303</div><div class="line">304</div><div class="line">305</div><div class="line">306</div><div class="line">307</div><div class="line">308</div><div class="line">309</div><div class="line">310</div><div class="line">311</div><div class="line">312</div><div class="line">313</div><div class="line">314</div><div class="line">315</div><div class="line">316</div><div class="line">317</div><div class="line">318</div><div class="line">319</div><div class="line">320</div><div class="line">321</div><div class="line">322</div><div class="line">323</div><div class="line">324</div><div class="line">325</div><div class="line">326</div><div class="line">327</div><div class="line">328</div><div class="line">329</div><div class="line">330</div><div class="line">331</div><div class="line">332</div><div class="line">333</div><div class="line">334</div><div class="line">335</div><div class="line">336</div><div class="line">337</div><div class="line">338</div><div class="line">339</div><div class="line">340</div><div class="line">341</div><div class="line">342</div><div class="line">343</div><div class="line">344</div><div class="line">345</div><div class="line">346</div><div class="line">347</div><div class="line">348</div><div class="line">349</div><div class="line">350</div><div class="line">351</div><div class="line">352</div><div class="line">353</div><div class="line">354</div><div class="line">355</div><div class="line">356</div><div class="line">357</div><div class="line">358</div><div class="line">359</div><div class="line">360</div><div class="line">361</div><div class="line">362</div><div class="line">363</div><div class="line">364</div><div class="line">365</div><div class="line">366</div><div class="line">367</div><div class="line">368</div><div class="line">369</div><div class="line">370</div><div class="line">371</div><div class="line">372</div><div class="line">373</div><div class="line">374</div><div class="line">375</div><div class="line">376</div><div class="line">377</div><div class="line">378</div><div class="line">379</div><div class="line">380</div><div class="line">381</div><div class="line">382</div><div class="line">383</div><div class="line">384</div><div class="line">385</div><div class="line">386</div><div class="line">387</div><div class="line">388</div><div class="line">389</div><div class="line">390</div><div class="line">391</div><div class="line">392</div><div class="line">393</div><div class="line">394</div><div class="line">395</div><div class="line">396</div><div class="line">397</div><div class="line">398</div><div class="line">399</div><div class="line">400</div><div class="line">401</div><div class="line">402</div><div class="line">403</div><div class="line">404</div><div class="line">405</div><div class="line">406</div><div class="line">407</div><div class="line">408</div><div class="line">409</div><div class="line">410</div><div class="line">411</div><div class="line">412</div><div class="line">413</div><div class="line">414</div><div class="line">415</div><div class="line">416</div><div class="line">417</div><div class="line">418</div><div class="line">419</div><div class="line">420</div><div class="line">421</div><div class="line">422</div><div class="line">423</div><div class="line">424</div><div class="line">425</div><div class="line">426</div><div class="line">427</div><div class="line">428</div><div class="line">429</div><div class="line">430</div><div class="line">431</div><div class="line">432</div><div class="line">433</div><div class="line">434</div><div class="line">435</div><div class="line">436</div><div class="line">437</div><div class="line">438</div><div class="line">439</div><div class="line">440</div><div class="line">441</div><div class="line">442</div><div class="line">443</div><div class="line">444</div><div class="line">445</div><div class="line">446</div><div class="line">447</div><div class="line">448</div><div class="line">449</div><div class="line">450</div><div class="line">451</div><div class="line">452</div><div class="line">453</div><div class="line">454</div><div class="line">455</div><div class="line">456</div><div class="line">457</div><div class="line">458</div><div class="line">459</div><div class="line">460</div><div class="line">461</div><div class="line">462</div><div class="line">463</div><div class="line">464</div><div class="line">465</div><div class="line">466</div><div class="line">467</div><div class="line">468</div><div class="line">469</div><div class="line">470</div><div class="line">471</div><div class="line">472</div><div class="line">473</div><div class="line">474</div><div class="line">475</div><div class="line">476</div><div class="line">477</div><div class="line">478</div><div class="line">479</div><div class="line">480</div><div class="line">481</div><div class="line">482</div><div class="line">483</div><div class="line">484</div><div class="line">485</div><div class="line">486</div><div class="line">487</div><div class="line">488</div><div class="line">489</div><div class="line">490</div><div class="line">491</div><div class="line">492</div><div class="line">493</div><div class="line">494</div><div class="line">495</div><div class="line">496</div><div class="line">497</div><div class="line">498</div><div class="line">499</div><div class="line">500</div><div class="line">501</div><div class="line">502</div><div class="line">503</div><div class="line">504</div><div class="line">505</div><div class="line">506</div><div class="line">507</div><div class="line">508</div><div class="line">509</div><div class="line">510</div><div class="line">511</div><div class="line">512</div><div class="line">513</div><div class="line">514</div><div class="line">515</div><div class="line">516</div><div class="line">517</div><div class="line">518</div><div class="line">519</div><div class="line">520</div><div class="line">521</div><div class="line">522</div><div class="line">523</div><div class="line">524</div><div class="line">525</div><div class="line">526</div><div class="line">527</div><div class="line">528</div><div class="line">529</div><div class="line">530</div><div class="line">531</div><div class="line">532</div><div class="line">533</div><div class="line">534</div><div class="line">535</div><div class="line">536</div><div class="line">537</div><div class="line">538</div><div class="line">539</div><div class="line">540</div><div class="line">541</div><div class="line">542</div><div class="line">543</div><div class="line">544</div><div class="line">545</div><div class="line">546</div><div class="line">547</div><div class="line">548</div><div class="line">549</div><div class="line">550</div><div class="line">551</div><div class="line">552</div><div class="line">553</div><div class="line">554</div><div class="line">555</div><div class="line">556</div><div class="line">557</div><div class="line">558</div><div class="line">559</div><div class="line">560</div><div class="line">561</div><div class="line">562</div><div class="line">563</div><div class="line">564</div><div class="line">565</div><div class="line">566</div><div class="line">567</div><div class="line">568</div><div class="line">569</div><div class="line">570</div><div class="line">571</div><div class="line">572</div><div class="line">573</div><div class="line">574</div><div class="line">575</div><div class="line">576</div><div class="line">577</div><div class="line">578</div><div class="line">579</div><div class="line">580</div><div class="line">581</div><div class="line">582</div><div class="line">583</div><div class="line">584</div><div class="line">585</div><div class="line">586</div><div class="line">587</div><div class="line">588</div><div class="line">589</div><div class="line">590</div><div class="line">591</div><div class="line">592</div><div class="line">593</div><div class="line">594</div><div class="line">595</div><div class="line">596</div><div class="line">597</div><div class="line">598</div><div class="line">599</div><div class="line">600</div><div class="line">601</div><div class="line">602</div><div class="line">603</div><div class="line">604</div><div class="line">605</div><div class="line">606</div><div class="line">607</div><div class="line">608</div><div class="line">609</div><div class="line">610</div><div class="line">611</div><div class="line">612</div><div class="line">613</div><div class="line">614</div><div class="line">615</div><div class="line">616</div><div class="line">617</div><div class="line">618</div><div class="line">619</div><div class="line">620</div><div class="line">621</div><div class="line">622</div><div class="line">623</div><div class="line">624</div><div class="line">625</div><div class="line">626</div><div class="line">627</div><div class="line">628</div><div class="line">629</div><div class="line">630</div><div class="line">631</div><div class="line">632</div><div class="line">633</div><div class="line">634</div><div class="line">635</div><div class="line">636</div><div class="line">637</div><div class="line">638</div><div class="line">639</div><div class="line">640</div><div class="line">641</div><div class="line">642</div><div class="line">643</div><div class="line">644</div><div class="line">645</div><div class="line">646</div><div class="line">647</div><div class="line">648</div><div class="line">649</div><div class="line">650</div><div class="line">651</div><div class="line">652</div><div class="line">653</div><div class="line">654</div><div class="line">655</div><div class="line">656</div><div class="line">657</div><div class="line">658</div><div class="line">659</div><div class="line">660</div><div class="line">661</div><div class="line">662</div><div class="line">663</div><div class="line">664</div><div class="line">665</div><div class="line">666</div><div class="line">667</div><div class="line">668</div><div class="line">669</div><div class="line">670</div><div class="line">671</div><div class="line">672</div><div class="line">673</div><div class="line">674</div><div class="line">675</div><div class="line">676</div><div class="line">677</div><div class="line">678</div><div class="line">679</div><div class="line">680</div><div class="line">681</div><div class="line">682</div><div class="line">683</div><div class="line">684</div><div class="line">685</div><div class="line">686</div><div class="line">687</div><div class="line">688</div><div class="line">689</div><div class="line">690</div><div class="line">691</div><div class="line">692</div><div class="line">693</div><div class="line">694</div><div class="line">695</div><div class="line">696</div><div class="line">697</div><div class="line">698</div><div class="line">699</div><div class="line">700</div><div class="line">701</div><div class="line">702</div><div class="line">703</div><div class="line">704</div><div class="line">705</div><div class="line">706</div><div class="line">707</div><div class="line">708</div><div class="line">709</div><div class="line">710</div><div class="line">711</div><div class="line">712</div><div class="line">713</div><div class="line">714</div><div class="line">715</div><div class="line">716</div><div class="line">717</div><div class="line">718</div><div class="line">719</div><div class="line">720</div><div class="line">721</div><div class="line">722</div><div class="line">723</div><div class="line">724</div><div class="line">725</div><div class="line">726</div><div class="line">727</div><div class="line">728</div><div class="line">729</div><div class="line">730</div><div class="line">731</div><div class="line">732</div><div class="line">733</div><div class="line">734</div><div class="line">735</div><div class="line">736</div><div class="line">737</div><div class="line">738</div><div class="line">739</div><div class="line">740</div><div class="line">741</div><div class="line">742</div><div class="line">743</div><div class="line">744</div><div class="line">745</div><div class="line">746</div><div class="line">747</div><div class="line">748</div><div class="line">749</div><div class="line">750</div><div class="line">751</div><div class="line">752</div><div class="line">753</div><div class="line">754</div><div class="line">755</div><div class="line">756</div><div class="line">757</div><div class="line">758</div><div class="line">759</div><div class="line">760</div><div class="line">761</div><div class="line">762</div><div class="line">763</div><div class="line">764</div><div class="line">765</div><div class="line">766</div><div class="line">767</div><div class="line">768</div><div class="line">769</div><div class="line">770</div><div class="line">771</div><div class="line">772</div><div class="line">773</div><div class="line">774</div><div class="line">775</div><div class="line">776</div><div class="line">777</div><div class="line">778</div><div class="line">779</div><div class="line">780</div><div class="line">781</div><div class="line">782</div><div class="line">783</div><div class="line">784</div><div class="line">785</div><div class="line">786</div><div class="line">787</div><div class="line">788</div><div class="line">789</div><div class="line">790</div><div class="line">791</div><div class="line">792</div><div class="line">793</div><div class="line">794</div><div class="line">795</div><div class="line">796</div><div class="line">797</div><div class="line">798</div><div class="line">799</div><div class="line">800</div><div class="line">801</div><div class="line">802</div><div class="line">803</div><div class="line">804</div><div class="line">805</div><div class="line">806</div><div class="line">807</div><div class="line">808</div><div class="line">809</div><div class="line">810</div><div class="line">811</div><div class="line">812</div><div class="line">813</div><div class="line">814</div><div class="line">815</div><div class="line">816</div><div class="line">817</div><div class="line">818</div><div class="line">819</div><div class="line">820</div><div class="line">821</div><div class="line">822</div><div class="line">823</div><div class="line">824</div><div class="line">825</div><div class="line">826</div><div class="line">827</div><div class="line">828</div><div class="line">829</div><div class="line">830</div><div class="line">831</div><div class="line">832</div><div class="line">833</div><div class="line">834</div><div class="line">835</div><div class="line">836</div><div class="line">837</div><div class="line">838</div><div class="line">839</div><div class="line">840</div><div class="line">841</div><div class="line">842</div><div class="line">843</div><div class="line">844</div><div class="line">845</div><div class="line">846</div><div class="line">847</div><div class="line">848</div><div class="line">849</div><div class="line">850</div><div class="line">851</div><div class="line">852</div><div class="line">853</div><div class="line">854</div><div class="line">855</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">package</span> hbec.app.stock.commons.redis;</div><div class="line"></div><div class="line"><span class="keyword">import</span> hbec.app.stock.redis.JedisUtils;</div><div class="line"></div><div class="line"><span class="keyword">import</span> java.util.List;</div><div class="line"><span class="keyword">import</span> java.util.Map;</div><div class="line"><span class="keyword">import</span> java.util.Set;</div><div class="line"></div><div class="line"><span class="keyword">import</span> org.slf4j.Logger;</div><div class="line"><span class="keyword">import</span> org.slf4j.LoggerFactory;</div><div class="line"></div><div class="line"><span class="keyword">import</span> redis.clients.jedis.Jedis;</div><div class="line"><span class="keyword">import</span> redis.clients.jedis.JedisPool;</div><div class="line"><span class="keyword">import</span> redis.clients.jedis.Pipeline;</div><div class="line"><span class="keyword">import</span> redis.clients.jedis.ScanParams;</div><div class="line"><span class="keyword">import</span> redis.clients.jedis.ScanResult;</div><div class="line"><span class="keyword">import</span> redis.clients.jedis.Tuple;</div><div class="line"><span class="keyword">import</span> redis.clients.jedis.exceptions.JedisConnectionException;</div><div class="line"><span class="keyword">import</span> redis.clients.jedis.exceptions.JedisDataException;</div><div class="line"><span class="keyword">import</span> redis.clients.jedis.exceptions.JedisException;</div><div class="line"></div><div class="line"><span class="comment">/**</span></div><div class="line"> * JedisTemplate 提供了一个template方法,负责对Jedis连接的获取与归还。</div><div class="line"> * JedisAction<T> 和 JedisActionNoResult两种回调接口,适用于有无返回值两种情况。</div><div class="line"> * PipelineAction 与 PipelineActionResult两种接口,适合于pipeline中批量传输命令的情况。</div><div class="line"> * </div><div class="line"> * 同时提供一些JedisOperation中定义的 最常用函数的封装, 如get/set/zadd等。</div><div class="line"> * </div><div class="line"> * <span class="doctag">@author</span> roc</div><div class="line"> */</div><div class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">JedisTemplate</span> </span>{</div><div class="line"></div><div class="line"> <span class="keyword">private</span> <span class="keyword">static</span> Logger logger = LoggerFactory.getLogger(JedisTemplate.class);</div><div class="line"></div><div class="line"> <span class="keyword">private</span> JedisPool jedisPool;</div><div class="line"></div><div class="line"> <span class="function"><span class="keyword">public</span> <span class="title">JedisTemplate</span><span class="params">(JedisPool jedisPool)</span> </span>{</div><div class="line"> <span class="keyword">this</span>.jedisPool = jedisPool;</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="comment">/**</span></div><div class="line"> * Callback interface for template.</div><div class="line"> */</div><div class="line"> <span class="keyword">public</span> <span class="class"><span class="keyword">interface</span> <span class="title">JedisAction</span><<span class="title">T</span>> </span>{</div><div class="line"> <span class="function">T <span class="title">action</span><span class="params">(Jedis jedis)</span></span>;</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="comment">/**</span></div><div class="line"> * Callback interface for template without result.</div><div class="line"> */</div><div class="line"> <span class="keyword">public</span> <span class="class"><span class="keyword">interface</span> <span class="title">JedisActionNoResult</span> </span>{</div><div class="line"> <span class="function"><span class="keyword">void</span> <span class="title">action</span><span class="params">(Jedis jedis)</span></span>;</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="comment">/**</span></div><div class="line"> * Callback interface for template.</div><div class="line"> */</div><div class="line"> <span class="keyword">public</span> <span class="class"><span class="keyword">interface</span> <span class="title">PipelineAction</span> </span>{</div><div class="line"> <span class="function">List<Object> <span class="title">action</span><span class="params">(Pipeline Pipeline)</span></span>;</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="comment">/**</span></div><div class="line"> * Callback interface for template without result.</div><div class="line"> */</div><div class="line"> <span class="keyword">public</span> <span class="class"><span class="keyword">interface</span> <span class="title">PipelineActionNoResult</span> </span>{</div><div class="line"> <span class="function"><span class="keyword">void</span> <span class="title">action</span><span class="params">(Pipeline Pipeline)</span></span>;</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="comment">/**</span></div><div class="line"> * Execute with a call back action with result.</div><div class="line"> */</div><div class="line"> <span class="keyword">public</span> <T> <span class="function">T <span class="title">execute</span><span class="params">(JedisAction<T> jedisAction)</span> <span class="keyword">throws</span> JedisException </span>{</div><div class="line"> Jedis jedis = <span class="keyword">null</span>;</div><div class="line"> <span class="keyword">boolean</span> broken = <span class="keyword">false</span>;</div><div class="line"> <span class="keyword">try</span> {</div><div class="line"> jedis = jedisPool.getResource();</div><div class="line"> <span class="keyword">return</span> jedisAction.action(jedis);</div><div class="line"> } <span class="keyword">catch</span> (JedisException e) {</div><div class="line"> broken = handleJedisException(e);</div><div class="line"> <span class="keyword">throw</span> e;</div><div class="line"> } <span class="keyword">finally</span> {</div><div class="line"> closeResource(jedis, broken);</div><div class="line"> }</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="comment">/**</span></div><div class="line"> * Execute with a call back action without result.</div><div class="line"> */</div><div class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">execute</span><span class="params">(JedisActionNoResult jedisAction)</span> <span class="keyword">throws</span> JedisException </span>{</div><div class="line"> Jedis jedis = <span class="keyword">null</span>;</div><div class="line"> <span class="keyword">boolean</span> broken = <span class="keyword">false</span>;</div><div class="line"> <span class="keyword">try</span> {</div><div class="line"> jedis = jedisPool.getResource();</div><div class="line"> jedisAction.action(jedis);</div><div class="line"> } <span class="keyword">catch</span> (JedisException e) {</div><div class="line"> broken = handleJedisException(e);</div><div class="line"> <span class="keyword">throw</span> e;</div><div class="line"> } <span class="keyword">finally</span> {</div><div class="line"> closeResource(jedis, broken);</div><div class="line"> }</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="comment">/**</span></div><div class="line"> * Execute with a call back action with result in pipeline.</div><div class="line"> */</div><div class="line"> <span class="function"><span class="keyword">public</span> List<Object> <span class="title">execute</span><span class="params">(PipelineAction pipelineAction)</span> <span class="keyword">throws</span> JedisException </span>{</div><div class="line"> Jedis jedis = <span class="keyword">null</span>;</div><div class="line"> <span class="keyword">boolean</span> broken = <span class="keyword">false</span>;</div><div class="line"> <span class="keyword">try</span> {</div><div class="line"> jedis = jedisPool.getResource();</div><div class="line"> Pipeline pipeline = jedis.pipelined();</div><div class="line"> pipelineAction.action(pipeline);</div><div class="line"> <span class="keyword">return</span> pipeline.syncAndReturnAll();</div><div class="line"> } <span class="keyword">catch</span> (JedisException e) {</div><div class="line"> broken = handleJedisException(e);</div><div class="line"> <span class="keyword">throw</span> e;</div><div class="line"> } <span class="keyword">finally</span> {</div><div class="line"> closeResource(jedis, broken);</div><div class="line"> }</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="comment">/**</span></div><div class="line"> * Execute with a call back action without result in pipeline.</div><div class="line"> */</div><div class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">execute</span><span class="params">(PipelineActionNoResult pipelineAction)</span> <span class="keyword">throws</span> JedisException </span>{</div><div class="line"> Jedis jedis = <span class="keyword">null</span>;</div><div class="line"> <span class="keyword">boolean</span> broken = <span class="keyword">false</span>;</div><div class="line"> <span class="keyword">try</span> {</div><div class="line"> jedis = jedisPool.getResource();</div><div class="line"> Pipeline pipeline = jedis.pipelined();</div><div class="line"> pipelineAction.action(pipeline);</div><div class="line"> pipeline.sync();</div><div class="line"> } <span class="keyword">catch</span> (JedisException e) {</div><div class="line"> broken = handleJedisException(e);</div><div class="line"> <span class="keyword">throw</span> e;</div><div class="line"> } <span class="keyword">finally</span> {</div><div class="line"> closeResource(jedis, broken);</div><div class="line"> }</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="comment">/**</span></div><div class="line"> * Handle jedisException, write log and return whether the connection is</div><div class="line"> * broken.</div><div class="line"> */</div><div class="line"> <span class="function"><span class="keyword">protected</span> <span class="keyword">boolean</span> <span class="title">handleJedisException</span><span class="params">(JedisException jedisException)</span> </span>{</div><div class="line"> <span class="keyword">if</span> (jedisException <span class="keyword">instanceof</span> JedisConnectionException) {</div><div class="line"> logger.error(<span class="string">"Redis connection lost."</span>, jedisException);</div><div class="line"> } <span class="keyword">else</span> <span class="keyword">if</span> (jedisException <span class="keyword">instanceof</span> JedisDataException) {</div><div class="line"> <span class="keyword">if</span> ((jedisException.getMessage() != <span class="keyword">null</span>) && (jedisException.getMessage().indexOf(<span class="string">"READONLY"</span>) != -<span class="number">1</span>)) {</div><div class="line"> logger.error(<span class="string">"Redis connection are read-only slave."</span>, jedisException);</div><div class="line"> } <span class="keyword">else</span> {</div><div class="line"> <span class="comment">// dataException, isBroken=false</span></div><div class="line"> <span class="keyword">return</span> <span class="keyword">false</span>;</div><div class="line"> }</div><div class="line"> } <span class="keyword">else</span> {</div><div class="line"> logger.error(<span class="string">"Jedis exception happen."</span>, jedisException);</div><div class="line"> }</div><div class="line"> <span class="keyword">return</span> <span class="keyword">true</span>;</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="comment">/**</span></div><div class="line"> * Return jedis connection to the pool, call different return methods</div><div class="line"> * depends on the conectionBroken status.</div><div class="line"> */</div><div class="line"> <span class="function"><span class="keyword">protected</span> <span class="keyword">void</span> <span class="title">closeResource</span><span class="params">(Jedis jedis, <span class="keyword">boolean</span> conectionBroken)</span> </span>{</div><div class="line"> <span class="keyword">try</span> {</div><div class="line"> <span class="keyword">if</span> (conectionBroken) {</div><div class="line"> jedisPool.returnBrokenResource(jedis);</div><div class="line"> } <span class="keyword">else</span> {</div><div class="line"> jedisPool.returnResource(jedis);</div><div class="line"> }</div><div class="line"> } <span class="keyword">catch</span> (Exception e) {</div><div class="line"> logger.error(<span class="string">"return back jedis failed, will fore close the jedis."</span>, e);</div><div class="line"> }</div><div class="line"></div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="comment">// / Common Actions ///</span></div><div class="line"></div><div class="line"> <span class="comment">/**</span></div><div class="line"> * Remove the specified keys. If a given key does not exist no operation is</div><div class="line"> * performed for this key.</div><div class="line"> * </div><div class="line"> * return false if one of the key is not exist.</div><div class="line"> */</div><div class="line"> <span class="function"><span class="keyword">public</span> Boolean <span class="title">del</span><span class="params">(<span class="keyword">final</span> String... keys)</span> </span>{</div><div class="line"> <span class="keyword">return</span> execute(<span class="keyword">new</span> JedisAction<Boolean>() {</div><div class="line"></div><div class="line"> <span class="meta">@Override</span></div><div class="line"> <span class="function"><span class="keyword">public</span> Boolean <span class="title">action</span><span class="params">(Jedis jedis)</span> </span>{</div><div class="line"> <span class="keyword">return</span> jedis.del(keys) == keys.length ? <span class="keyword">true</span> : <span class="keyword">false</span>;</div><div class="line"> }</div><div class="line"> });</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="comment">// / String Actions ///</span></div><div class="line"></div><div class="line"> <span class="comment">/**</span></div><div class="line"> * Get the value of the specified key. If the key does not exist null is</div><div class="line"> * returned. If the value stored at key is not a string an error is returned</div><div class="line"> * because GET can only handle string values.</div><div class="line"> */</div><div class="line"> <span class="function"><span class="keyword">public</span> String <span class="title">get</span><span class="params">(<span class="keyword">final</span> String key)</span> </span>{</div><div class="line"> <span class="keyword">return</span> execute(<span class="keyword">new</span> JedisAction<String>() {</div><div class="line"></div><div class="line"> <span class="meta">@Override</span></div><div class="line"> <span class="function"><span class="keyword">public</span> String <span class="title">action</span><span class="params">(Jedis jedis)</span> </span>{</div><div class="line"> <span class="keyword">return</span> jedis.get(key);</div><div class="line"> }</div><div class="line"> });</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="comment">/**</span></div><div class="line"> * Get the value of the specified key as Long.If the key does not exist null</div><div class="line"> * is returned.</div><div class="line"> */</div><div class="line"> <span class="function"><span class="keyword">public</span> Long <span class="title">getAsLong</span><span class="params">(<span class="keyword">final</span> String key)</span> </span>{</div><div class="line"> String result = get(key);</div><div class="line"> <span class="keyword">return</span> result != <span class="keyword">null</span> ? Long.valueOf(result) : <span class="keyword">null</span>;</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="comment">/**</span></div><div class="line"> * Get the value of the specified key as Integer.If the key does not exist</div><div class="line"> * null is returned.</div><div class="line"> */</div><div class="line"> <span class="function"><span class="keyword">public</span> Integer <span class="title">getAsInt</span><span class="params">(<span class="keyword">final</span> String key)</span> </span>{</div><div class="line"> String result = get(key);</div><div class="line"> <span class="keyword">return</span> result != <span class="keyword">null</span> ? Integer.valueOf(result) : <span class="keyword">null</span>;</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="comment">/**</span></div><div class="line"> * Get the value of the specified key as Boolean.If the key does not exist</div><div class="line"> * null is returned.</div><div class="line"> */</div><div class="line"> <span class="function"><span class="keyword">public</span> Boolean <span class="title">getAsBoolean</span><span class="params">(<span class="keyword">final</span> String key)</span> </span>{</div><div class="line"> String result = get(key);</div><div class="line"> <span class="keyword">return</span> result != <span class="keyword">null</span> ? Boolean.valueOf(result) : <span class="keyword">null</span>;</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="comment">/**</span></div><div class="line"> * Get the values of all the specified keys. If one or more keys dont exist</div><div class="line"> * or is not of type String, a 'nil' value is returned instead of the value</div><div class="line"> * of the specified key, but the operation never fails.</div><div class="line"> */</div><div class="line"> <span class="function"><span class="keyword">public</span> List<String> <span class="title">mget</span><span class="params">(<span class="keyword">final</span> String... keys)</span> </span>{</div><div class="line"> <span class="keyword">return</span> execute(<span class="keyword">new</span> JedisAction<List<String>>() {</div><div class="line"></div><div class="line"> <span class="meta">@Override</span></div><div class="line"> <span class="function"><span class="keyword">public</span> List<String> <span class="title">action</span><span class="params">(Jedis jedis)</span> </span>{</div><div class="line"> <span class="keyword">return</span> jedis.mget(keys);</div><div class="line"> }</div><div class="line"> });</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="comment">/**</span></div><div class="line"> * Set the string value as value of the key. The string can't be longer than</div><div class="line"> * 1073741824 bytes (1 GB).</div><div class="line"> */</div><div class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">set</span><span class="params">(<span class="keyword">final</span> String key, <span class="keyword">final</span> String value)</span> </span>{</div><div class="line"> execute(<span class="keyword">new</span> JedisActionNoResult() {</div><div class="line"></div><div class="line"> <span class="meta">@Override</span></div><div class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">action</span><span class="params">(Jedis jedis)</span> </span>{</div><div class="line"> jedis.set(key, value);</div><div class="line"> }</div><div class="line"> });</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="comment">/**</span></div><div class="line"> * The command is exactly equivalent to the following group of commands:</div><div class="line"> * {<span class="doctag">@link</span> #set(String, String) SET} + {<span class="doctag">@link</span> #expire(String, int) EXPIRE}.</div><div class="line"> * The operation is atomic.</div><div class="line"> */</div><div class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">setex</span><span class="params">(<span class="keyword">final</span> String key, <span class="keyword">final</span> String value, <span class="keyword">final</span> <span class="keyword">int</span> seconds)</span> </span>{</div><div class="line"> execute(<span class="keyword">new</span> JedisActionNoResult() {</div><div class="line"></div><div class="line"> <span class="meta">@Override</span></div><div class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">action</span><span class="params">(Jedis jedis)</span> </span>{</div><div class="line"> jedis.setex(key, seconds, value);</div><div class="line"> }</div><div class="line"> });</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="comment">/**</span></div><div class="line"> * SETNX works exactly like {<span class="doctag">@link</span> #setNX(String, String) SET} with the only</div><div class="line"> * difference that if the key already exists no operation is performed.</div><div class="line"> * SETNX actually means "SET if Not eXists".</div><div class="line"> * </div><div class="line"> * return true if the key was set.</div><div class="line"> */</div><div class="line"> <span class="function"><span class="keyword">public</span> Boolean <span class="title">setnx</span><span class="params">(<span class="keyword">final</span> String key, <span class="keyword">final</span> String value)</span> </span>{</div><div class="line"> <span class="keyword">return</span> execute(<span class="keyword">new</span> JedisAction<Boolean>() {</div><div class="line"></div><div class="line"> <span class="meta">@Override</span></div><div class="line"> <span class="function"><span class="keyword">public</span> Boolean <span class="title">action</span><span class="params">(Jedis jedis)</span> </span>{</div><div class="line"> <span class="keyword">return</span> jedis.setnx(key, value) == <span class="number">1</span> ? <span class="keyword">true</span> : <span class="keyword">false</span>;</div><div class="line"> }</div><div class="line"> });</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="comment">/**</span></div><div class="line"> * The command is exactly equivalent to the following group of commands:</div><div class="line"> * {<span class="doctag">@link</span> #setex(String, String, int) SETEX} +</div><div class="line"> * {<span class="doctag">@link</span> #sexnx(String, String) SETNX}. The operation is atomic.</div><div class="line"> */</div><div class="line"> <span class="function"><span class="keyword">public</span> Boolean <span class="title">setnxex</span><span class="params">(<span class="keyword">final</span> String key, <span class="keyword">final</span> String value, <span class="keyword">final</span> <span class="keyword">int</span> seconds)</span> </span>{</div><div class="line"> <span class="keyword">return</span> execute(<span class="keyword">new</span> JedisAction<Boolean>() {</div><div class="line"></div><div class="line"> <span class="meta">@Override</span></div><div class="line"> <span class="function"><span class="keyword">public</span> Boolean <span class="title">action</span><span class="params">(Jedis jedis)</span> </span>{</div><div class="line"> String result = jedis.set(key, value, <span class="string">"NX"</span>, <span class="string">"EX"</span>, seconds);</div><div class="line"> <span class="keyword">return</span> JedisUtils.isStatusOk(result);</div><div class="line"> }</div><div class="line"> });</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="comment">/**</span></div><div class="line"> * GETSET is an atomic set this value and return the old value command. Set</div><div class="line"> * key to the string value and return the old value stored at key. The</div><div class="line"> * string can't be longer than 1073741824 bytes (1 GB).</div><div class="line"> */</div><div class="line"> <span class="function"><span class="keyword">public</span> String <span class="title">getSet</span><span class="params">(<span class="keyword">final</span> String key, <span class="keyword">final</span> String value)</span> </span>{</div><div class="line"> <span class="keyword">return</span> execute(<span class="keyword">new</span> JedisAction<String>() {</div><div class="line"></div><div class="line"> <span class="meta">@Override</span></div><div class="line"> <span class="function"><span class="keyword">public</span> String <span class="title">action</span><span class="params">(Jedis jedis)</span> </span>{</div><div class="line"> <span class="keyword">return</span> jedis.getSet(key, value);</div><div class="line"> }</div><div class="line"> });</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="comment">/**</span></div><div class="line"> * Increment the number stored at key by one. If the key does not exist or</div><div class="line"> * contains a value of a wrong type, set the key to the value of "0" before</div><div class="line"> * to perform the increment operation.</div><div class="line"> * <p></div><div class="line"> * INCR commands are limited to 64 bit signed integers.</div><div class="line"> * <p></div><div class="line"> * Note: this is actually a string operation, that is, in Redis there are</div><div class="line"> * not "integer" types. Simply the string stored at the key is parsed as a</div><div class="line"> * base 10 64 bit signed integer, incremented, and then converted back as a</div><div class="line"> * string.</div><div class="line"> * </div><div class="line"> * <span class="doctag">@return</span> Integer reply, this commands will reply with the new value of key</div><div class="line"> * after the increment.</div><div class="line"> */</div><div class="line"> <span class="function"><span class="keyword">public</span> Long <span class="title">incr</span><span class="params">(<span class="keyword">final</span> String key)</span> </span>{</div><div class="line"> <span class="keyword">return</span> execute(<span class="keyword">new</span> JedisAction<Long>() {</div><div class="line"> <span class="meta">@Override</span></div><div class="line"> <span class="function"><span class="keyword">public</span> Long <span class="title">action</span><span class="params">(Jedis jedis)</span> </span>{</div><div class="line"> <span class="keyword">return</span> jedis.incr(key);</div><div class="line"> }</div><div class="line"> });</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="function"><span class="keyword">public</span> Long <span class="title">incrBy</span><span class="params">(<span class="keyword">final</span> String key, <span class="keyword">final</span> <span class="keyword">long</span> increment)</span> </span>{</div><div class="line"> <span class="keyword">return</span> execute(<span class="keyword">new</span> JedisAction<Long>() {</div><div class="line"> <span class="meta">@Override</span></div><div class="line"> <span class="function"><span class="keyword">public</span> Long <span class="title">action</span><span class="params">(Jedis jedis)</span> </span>{</div><div class="line"> <span class="keyword">return</span> jedis.incrBy(key, increment);</div><div class="line"> }</div><div class="line"> });</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="function"><span class="keyword">public</span> Double <span class="title">incrByFloat</span><span class="params">(<span class="keyword">final</span> String key, <span class="keyword">final</span> <span class="keyword">double</span> increment)</span> </span>{</div><div class="line"> <span class="keyword">return</span> execute(<span class="keyword">new</span> JedisAction<Double>() {</div><div class="line"> <span class="meta">@Override</span></div><div class="line"> <span class="function"><span class="keyword">public</span> Double <span class="title">action</span><span class="params">(Jedis jedis)</span> </span>{</div><div class="line"> <span class="keyword">return</span> jedis.incrByFloat(key, increment);</div><div class="line"> }</div><div class="line"> });</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="comment">/**</span></div><div class="line"> * Decrement the number stored at key by one. If the key does not exist or</div><div class="line"> * contains a value of a wrong type, set the key to the value of "0" before</div><div class="line"> * to perform the decrement operation.</div><div class="line"> */</div><div class="line"> <span class="function"><span class="keyword">public</span> Long <span class="title">decr</span><span class="params">(<span class="keyword">final</span> String key)</span> </span>{</div><div class="line"> <span class="keyword">return</span> execute(<span class="keyword">new</span> JedisAction<Long>() {</div><div class="line"> <span class="meta">@Override</span></div><div class="line"> <span class="function"><span class="keyword">public</span> Long <span class="title">action</span><span class="params">(Jedis jedis)</span> </span>{</div><div class="line"> <span class="keyword">return</span> jedis.decr(key);</div><div class="line"> }</div><div class="line"> });</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="function"><span class="keyword">public</span> Long <span class="title">decrBy</span><span class="params">(<span class="keyword">final</span> String key, <span class="keyword">final</span> <span class="keyword">long</span> decrement)</span> </span>{</div><div class="line"> <span class="keyword">return</span> execute(<span class="keyword">new</span> JedisAction<Long>() {</div><div class="line"> <span class="meta">@Override</span></div><div class="line"> <span class="function"><span class="keyword">public</span> Long <span class="title">action</span><span class="params">(Jedis jedis)</span> </span>{</div><div class="line"> <span class="keyword">return</span> jedis.decrBy(key, decrement);</div><div class="line"> }</div><div class="line"> });</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="comment">// / Hash Actions ///</span></div><div class="line"> <span class="comment">/**</span></div><div class="line"> * If key holds a hash, retrieve the value associated to the specified</div><div class="line"> * field.</div><div class="line"> * <p></div><div class="line"> * If the field is not found or the key does not exist, a special 'nil'</div><div class="line"> * value is returned.</div><div class="line"> */</div><div class="line"> <span class="function"><span class="keyword">public</span> String <span class="title">hget</span><span class="params">(<span class="keyword">final</span> String key, <span class="keyword">final</span> String fieldName)</span> </span>{</div><div class="line"> <span class="keyword">return</span> execute(<span class="keyword">new</span> JedisAction<String>() {</div><div class="line"> <span class="meta">@Override</span></div><div class="line"> <span class="function"><span class="keyword">public</span> String <span class="title">action</span><span class="params">(Jedis jedis)</span> </span>{</div><div class="line"> <span class="keyword">return</span> jedis.hget(key, fieldName);</div><div class="line"> }</div><div class="line"> });</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="function"><span class="keyword">public</span> List<String> <span class="title">hmget</span><span class="params">(<span class="keyword">final</span> String key, <span class="keyword">final</span> String... fieldsNames)</span> </span>{</div><div class="line"> <span class="keyword">return</span> execute(<span class="keyword">new</span> JedisAction<List<String>>() {</div><div class="line"> <span class="meta">@Override</span></div><div class="line"> <span class="function"><span class="keyword">public</span> List<String> <span class="title">action</span><span class="params">(Jedis jedis)</span> </span>{</div><div class="line"> <span class="keyword">return</span> jedis.hmget(key, fieldsNames);</div><div class="line"> }</div><div class="line"> });</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="function"><span class="keyword">public</span> Map<String, String> <span class="title">hgetAll</span><span class="params">(<span class="keyword">final</span> String key)</span> </span>{</div><div class="line"> <span class="keyword">return</span> execute(<span class="keyword">new</span> JedisAction<Map<String, String>>() {</div><div class="line"> <span class="meta">@Override</span></div><div class="line"> <span class="function"><span class="keyword">public</span> Map<String, String> <span class="title">action</span><span class="params">(Jedis jedis)</span> </span>{</div><div class="line"> <span class="keyword">return</span> jedis.hgetAll(key);</div><div class="line"> }</div><div class="line"> });</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">hset</span><span class="params">(<span class="keyword">final</span> String key, <span class="keyword">final</span> String fieldName, <span class="keyword">final</span> String value)</span> </span>{</div><div class="line"> execute(<span class="keyword">new</span> JedisActionNoResult() {</div><div class="line"></div><div class="line"> <span class="meta">@Override</span></div><div class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">action</span><span class="params">(Jedis jedis)</span> </span>{</div><div class="line"> jedis.hset(key, fieldName, value);</div><div class="line"> }</div><div class="line"> });</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">hmset</span><span class="params">(<span class="keyword">final</span> String key, <span class="keyword">final</span> Map<String, String> map)</span> </span>{</div><div class="line"> execute(<span class="keyword">new</span> JedisActionNoResult() {</div><div class="line"></div><div class="line"> <span class="meta">@Override</span></div><div class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">action</span><span class="params">(Jedis jedis)</span> </span>{</div><div class="line"> jedis.hmset(key, map);</div><div class="line"> }</div><div class="line"> });</div><div class="line"></div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="function"><span class="keyword">public</span> Boolean <span class="title">hsetnx</span><span class="params">(<span class="keyword">final</span> String key, <span class="keyword">final</span> String fieldName, <span class="keyword">final</span> String value)</span> </span>{</div><div class="line"> <span class="keyword">return</span> execute(<span class="keyword">new</span> JedisAction<Boolean>() {</div><div class="line"></div><div class="line"> <span class="meta">@Override</span></div><div class="line"> <span class="function"><span class="keyword">public</span> Boolean <span class="title">action</span><span class="params">(Jedis jedis)</span> </span>{</div><div class="line"> <span class="keyword">return</span> jedis.hsetnx(key, fieldName, value) == <span class="number">1</span> ? <span class="keyword">true</span> : <span class="keyword">false</span>;</div><div class="line"> }</div><div class="line"> });</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="function"><span class="keyword">public</span> Long <span class="title">hincrBy</span><span class="params">(<span class="keyword">final</span> String key, <span class="keyword">final</span> String fieldName, <span class="keyword">final</span> <span class="keyword">long</span> increment)</span> </span>{</div><div class="line"> <span class="keyword">return</span> execute(<span class="keyword">new</span> JedisAction<Long>() {</div><div class="line"> <span class="meta">@Override</span></div><div class="line"> <span class="function"><span class="keyword">public</span> Long <span class="title">action</span><span class="params">(Jedis jedis)</span> </span>{</div><div class="line"> <span class="keyword">return</span> jedis.hincrBy(key, fieldName, increment);</div><div class="line"> }</div><div class="line"> });</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="function"><span class="keyword">public</span> Double <span class="title">hincrByFloat</span><span class="params">(<span class="keyword">final</span> String key, <span class="keyword">final</span> String fieldName, <span class="keyword">final</span> <span class="keyword">double</span> increment)</span> </span>{</div><div class="line"> <span class="keyword">return</span> execute(<span class="keyword">new</span> JedisAction<Double>() {</div><div class="line"> <span class="meta">@Override</span></div><div class="line"> <span class="function"><span class="keyword">public</span> Double <span class="title">action</span><span class="params">(Jedis jedis)</span> </span>{</div><div class="line"> <span class="keyword">return</span> jedis.hincrByFloat(key, fieldName, increment);</div><div class="line"> }</div><div class="line"> });</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="function"><span class="keyword">public</span> Long <span class="title">hdel</span><span class="params">(<span class="keyword">final</span> String key, <span class="keyword">final</span> String... fieldsNames)</span> </span>{</div><div class="line"> <span class="keyword">return</span> execute(<span class="keyword">new</span> JedisAction<Long>() {</div><div class="line"> <span class="meta">@Override</span></div><div class="line"> <span class="function"><span class="keyword">public</span> Long <span class="title">action</span><span class="params">(Jedis jedis)</span> </span>{</div><div class="line"> <span class="keyword">return</span> jedis.hdel(key, fieldsNames);</div><div class="line"> }</div><div class="line"> });</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="function"><span class="keyword">public</span> Boolean <span class="title">hexists</span><span class="params">(<span class="keyword">final</span> String key, <span class="keyword">final</span> String fieldName)</span> </span>{</div><div class="line"> <span class="keyword">return</span> execute(<span class="keyword">new</span> JedisAction<Boolean>() {</div><div class="line"> <span class="meta">@Override</span></div><div class="line"> <span class="function"><span class="keyword">public</span> Boolean <span class="title">action</span><span class="params">(Jedis jedis)</span> </span>{</div><div class="line"> <span class="keyword">return</span> jedis.hexists(key, fieldName);</div><div class="line"> }</div><div class="line"> });</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="function"><span class="keyword">public</span> Set<String> <span class="title">hkeys</span><span class="params">(<span class="keyword">final</span> String key)</span> </span>{</div><div class="line"> <span class="keyword">return</span> execute(<span class="keyword">new</span> JedisAction<Set<String>>() {</div><div class="line"> <span class="meta">@Override</span></div><div class="line"> <span class="function"><span class="keyword">public</span> Set<String> <span class="title">action</span><span class="params">(Jedis jedis)</span> </span>{</div><div class="line"> <span class="keyword">return</span> jedis.hkeys(key);</div><div class="line"> }</div><div class="line"> });</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="function"><span class="keyword">public</span> Long <span class="title">hlen</span><span class="params">(<span class="keyword">final</span> String key)</span> </span>{</div><div class="line"> <span class="keyword">return</span> execute(<span class="keyword">new</span> JedisAction<Long>() {</div><div class="line"> <span class="meta">@Override</span></div><div class="line"> <span class="function"><span class="keyword">public</span> Long <span class="title">action</span><span class="params">(Jedis jedis)</span> </span>{</div><div class="line"> <span class="keyword">return</span> jedis.hlen(key);</div><div class="line"> }</div><div class="line"> });</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="comment">// / List Actions ///</span></div><div class="line"></div><div class="line"> <span class="function"><span class="keyword">public</span> Long <span class="title">lpush</span><span class="params">(<span class="keyword">final</span> String key, <span class="keyword">final</span> String... values)</span> </span>{</div><div class="line"> <span class="keyword">return</span> execute(<span class="keyword">new</span> JedisAction<Long>() {</div><div class="line"> <span class="meta">@Override</span></div><div class="line"> <span class="function"><span class="keyword">public</span> Long <span class="title">action</span><span class="params">(Jedis jedis)</span> </span>{</div><div class="line"> <span class="keyword">return</span> jedis.lpush(key, values);</div><div class="line"> }</div><div class="line"> });</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="function"><span class="keyword">public</span> String <span class="title">rpop</span><span class="params">(<span class="keyword">final</span> String key)</span> </span>{</div><div class="line"> <span class="keyword">return</span> execute(<span class="keyword">new</span> JedisAction<String>() {</div><div class="line"></div><div class="line"> <span class="meta">@Override</span></div><div class="line"> <span class="function"><span class="keyword">public</span> String <span class="title">action</span><span class="params">(Jedis jedis)</span> </span>{</div><div class="line"> <span class="keyword">return</span> jedis.rpop(key);</div><div class="line"> }</div><div class="line"> });</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="function"><span class="keyword">public</span> String <span class="title">brpop</span><span class="params">(<span class="keyword">final</span> String key)</span> </span>{</div><div class="line"> <span class="keyword">return</span> execute(<span class="keyword">new</span> JedisAction<String>() {</div><div class="line"></div><div class="line"> <span class="meta">@Override</span></div><div class="line"> <span class="function"><span class="keyword">public</span> String <span class="title">action</span><span class="params">(Jedis jedis)</span> </span>{</div><div class="line"> List<String> nameValuePair = jedis.brpop(key);</div><div class="line"> <span class="keyword">if</span> (nameValuePair != <span class="keyword">null</span>) {</div><div class="line"> <span class="keyword">return</span> nameValuePair.get(<span class="number">1</span>);</div><div class="line"> } <span class="keyword">else</span> {</div><div class="line"> <span class="keyword">return</span> <span class="keyword">null</span>;</div><div class="line"> }</div><div class="line"> }</div><div class="line"> });</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="function"><span class="keyword">public</span> String <span class="title">brpop</span><span class="params">(<span class="keyword">final</span> <span class="keyword">int</span> timeout, <span class="keyword">final</span> String key)</span> </span>{</div><div class="line"> <span class="keyword">return</span> execute(<span class="keyword">new</span> JedisAction<String>() {</div><div class="line"></div><div class="line"> <span class="meta">@Override</span></div><div class="line"> <span class="function"><span class="keyword">public</span> String <span class="title">action</span><span class="params">(Jedis jedis)</span> </span>{</div><div class="line"> List<String> nameValuePair = jedis.brpop(timeout, key);</div><div class="line"> <span class="keyword">if</span> (nameValuePair != <span class="keyword">null</span>) {</div><div class="line"> <span class="keyword">return</span> nameValuePair.get(<span class="number">1</span>);</div><div class="line"> } <span class="keyword">else</span> {</div><div class="line"> <span class="keyword">return</span> <span class="keyword">null</span>;</div><div class="line"> }</div><div class="line"> }</div><div class="line"> });</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="comment">/**</span></div><div class="line"> * Not support for sharding.</div><div class="line"> */</div><div class="line"> <span class="function"><span class="keyword">public</span> String <span class="title">rpoplpush</span><span class="params">(<span class="keyword">final</span> String sourceKey, <span class="keyword">final</span> String destinationKey)</span> </span>{</div><div class="line"> <span class="keyword">return</span> execute(<span class="keyword">new</span> JedisAction<String>() {</div><div class="line"></div><div class="line"> <span class="meta">@Override</span></div><div class="line"> <span class="function"><span class="keyword">public</span> String <span class="title">action</span><span class="params">(Jedis jedis)</span> </span>{</div><div class="line"> <span class="keyword">return</span> jedis.rpoplpush(sourceKey, destinationKey);</div><div class="line"> }</div><div class="line"> });</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="comment">/**</span></div><div class="line"> * Not support for sharding.</div><div class="line"> */</div><div class="line"> <span class="function"><span class="keyword">public</span> String <span class="title">brpoplpush</span><span class="params">(<span class="keyword">final</span> String source, <span class="keyword">final</span> String destination, <span class="keyword">final</span> <span class="keyword">int</span> timeout)</span> </span>{</div><div class="line"> <span class="keyword">return</span> execute(<span class="keyword">new</span> JedisAction<String>() {</div><div class="line"></div><div class="line"> <span class="meta">@Override</span></div><div class="line"> <span class="function"><span class="keyword">public</span> String <span class="title">action</span><span class="params">(Jedis jedis)</span> </span>{</div><div class="line"> <span class="keyword">return</span> jedis.brpoplpush(source, destination, timeout);</div><div class="line"> }</div><div class="line"> });</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="function"><span class="keyword">public</span> Long <span class="title">llen</span><span class="params">(<span class="keyword">final</span> String key)</span> </span>{</div><div class="line"> <span class="keyword">return</span> execute(<span class="keyword">new</span> JedisAction<Long>() {</div><div class="line"></div><div class="line"> <span class="meta">@Override</span></div><div class="line"> <span class="function"><span class="keyword">public</span> Long <span class="title">action</span><span class="params">(Jedis jedis)</span> </span>{</div><div class="line"> <span class="keyword">return</span> jedis.llen(key);</div><div class="line"> }</div><div class="line"> });</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="function"><span class="keyword">public</span> String <span class="title">lindex</span><span class="params">(<span class="keyword">final</span> String key, <span class="keyword">final</span> <span class="keyword">long</span> index)</span> </span>{</div><div class="line"> <span class="keyword">return</span> execute(<span class="keyword">new</span> JedisAction<String>() {</div><div class="line"></div><div class="line"> <span class="meta">@Override</span></div><div class="line"> <span class="function"><span class="keyword">public</span> String <span class="title">action</span><span class="params">(Jedis jedis)</span> </span>{</div><div class="line"> <span class="keyword">return</span> jedis.lindex(key, index);</div><div class="line"> }</div><div class="line"> });</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="function"><span class="keyword">public</span> List<String> <span class="title">lrange</span><span class="params">(<span class="keyword">final</span> String key, <span class="keyword">final</span> <span class="keyword">int</span> start, <span class="keyword">final</span> <span class="keyword">int</span> end)</span> </span>{</div><div class="line"> <span class="keyword">return</span> execute(<span class="keyword">new</span> JedisAction<List<String>>() {</div><div class="line"></div><div class="line"> <span class="meta">@Override</span></div><div class="line"> <span class="function"><span class="keyword">public</span> List<String> <span class="title">action</span><span class="params">(Jedis jedis)</span> </span>{</div><div class="line"> <span class="keyword">return</span> jedis.lrange(key, start, end);</div><div class="line"> }</div><div class="line"> });</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">ltrim</span><span class="params">(<span class="keyword">final</span> String key, <span class="keyword">final</span> <span class="keyword">int</span> start, <span class="keyword">final</span> <span class="keyword">int</span> end)</span> </span>{</div><div class="line"> execute(<span class="keyword">new</span> JedisActionNoResult() {</div><div class="line"> <span class="meta">@Override</span></div><div class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">action</span><span class="params">(Jedis jedis)</span> </span>{</div><div class="line"> jedis.ltrim(key, start, end);</div><div class="line"> }</div><div class="line"> });</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">ltrimFromLeft</span><span class="params">(<span class="keyword">final</span> String key, <span class="keyword">final</span> <span class="keyword">int</span> size)</span> </span>{</div><div class="line"> execute(<span class="keyword">new</span> JedisActionNoResult() {</div><div class="line"> <span class="meta">@Override</span></div><div class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">action</span><span class="params">(Jedis jedis)</span> </span>{</div><div class="line"> jedis.ltrim(key, <span class="number">0</span>, size - <span class="number">1</span>);</div><div class="line"> }</div><div class="line"> });</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="function"><span class="keyword">public</span> Boolean <span class="title">lremFirst</span><span class="params">(<span class="keyword">final</span> String key, <span class="keyword">final</span> String value)</span> </span>{</div><div class="line"> <span class="keyword">return</span> execute(<span class="keyword">new</span> JedisAction<Boolean>() {</div><div class="line"> <span class="meta">@Override</span></div><div class="line"> <span class="function"><span class="keyword">public</span> Boolean <span class="title">action</span><span class="params">(Jedis jedis)</span> </span>{</div><div class="line"> Long count = jedis.lrem(key, <span class="number">1</span>, value);</div><div class="line"> <span class="keyword">return</span> (count == <span class="number">1</span>);</div><div class="line"> }</div><div class="line"> });</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="function"><span class="keyword">public</span> Boolean <span class="title">lremAll</span><span class="params">(<span class="keyword">final</span> String key, <span class="keyword">final</span> String value)</span> </span>{</div><div class="line"> <span class="keyword">return</span> execute(<span class="keyword">new</span> JedisAction<Boolean>() {</div><div class="line"> <span class="meta">@Override</span></div><div class="line"> <span class="function"><span class="keyword">public</span> Boolean <span class="title">action</span><span class="params">(Jedis jedis)</span> </span>{</div><div class="line"> Long count = jedis.lrem(key, <span class="number">0</span>, value);</div><div class="line"> <span class="keyword">return</span> (count > <span class="number">0</span>);</div><div class="line"> }</div><div class="line"> });</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="comment">// / Set Actions ///</span></div><div class="line"> <span class="function"><span class="keyword">public</span> Boolean <span class="title">sadd</span><span class="params">(<span class="keyword">final</span> String key, <span class="keyword">final</span> String member)</span> </span>{</div><div class="line"> <span class="keyword">return</span> execute(<span class="keyword">new</span> JedisAction<Boolean>() {</div><div class="line"></div><div class="line"> <span class="meta">@Override</span></div><div class="line"> <span class="function"><span class="keyword">public</span> Boolean <span class="title">action</span><span class="params">(Jedis jedis)</span> </span>{</div><div class="line"> <span class="keyword">return</span> jedis.sadd(key, member) == <span class="number">1</span> ? <span class="keyword">true</span> : <span class="keyword">false</span>;</div><div class="line"> }</div><div class="line"> });</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="function"><span class="keyword">public</span> Set<String> <span class="title">smembers</span><span class="params">(<span class="keyword">final</span> String key)</span> </span>{</div><div class="line"> <span class="keyword">return</span> execute(<span class="keyword">new</span> JedisAction<Set<String>>() {</div><div class="line"></div><div class="line"> <span class="meta">@Override</span></div><div class="line"> <span class="function"><span class="keyword">public</span> Set<String> <span class="title">action</span><span class="params">(Jedis jedis)</span> </span>{</div><div class="line"> <span class="keyword">return</span> jedis.smembers(key);</div><div class="line"> }</div><div class="line"> });</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="comment">// / Ordered Set Actions ///</span></div><div class="line"> <span class="comment">/**</span></div><div class="line"> * return true for add new element, false for only update the score.</div><div class="line"> */</div><div class="line"> <span class="function"><span class="keyword">public</span> Boolean <span class="title">zadd</span><span class="params">(<span class="keyword">final</span> String key, <span class="keyword">final</span> <span class="keyword">double</span> score, <span class="keyword">final</span> String member)</span> </span>{</div><div class="line"> <span class="keyword">return</span> execute(<span class="keyword">new</span> JedisAction<Boolean>() {</div><div class="line"></div><div class="line"> <span class="meta">@Override</span></div><div class="line"> <span class="function"><span class="keyword">public</span> Boolean <span class="title">action</span><span class="params">(Jedis jedis)</span> </span>{</div><div class="line"> <span class="keyword">return</span> jedis.zadd(key, score, member) == <span class="number">1</span> ? <span class="keyword">true</span> : <span class="keyword">false</span>;</div><div class="line"> }</div><div class="line"> });</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="function"><span class="keyword">public</span> Double <span class="title">zscore</span><span class="params">(<span class="keyword">final</span> String key, <span class="keyword">final</span> String member)</span> </span>{</div><div class="line"> <span class="keyword">return</span> execute(<span class="keyword">new</span> JedisAction<Double>() {</div><div class="line"></div><div class="line"> <span class="meta">@Override</span></div><div class="line"> <span class="function"><span class="keyword">public</span> Double <span class="title">action</span><span class="params">(Jedis jedis)</span> </span>{</div><div class="line"> <span class="keyword">return</span> jedis.zscore(key, member);</div><div class="line"> }</div><div class="line"> });</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="function"><span class="keyword">public</span> Long <span class="title">zrank</span><span class="params">(<span class="keyword">final</span> String key, <span class="keyword">final</span> String member)</span> </span>{</div><div class="line"> <span class="keyword">return</span> execute(<span class="keyword">new</span> JedisAction<Long>() {</div><div class="line"></div><div class="line"> <span class="meta">@Override</span></div><div class="line"> <span class="function"><span class="keyword">public</span> Long <span class="title">action</span><span class="params">(Jedis jedis)</span> </span>{</div><div class="line"> <span class="keyword">return</span> jedis.zrank(key, member);</div><div class="line"> }</div><div class="line"> });</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="function"><span class="keyword">public</span> Long <span class="title">zrevrank</span><span class="params">(<span class="keyword">final</span> String key, <span class="keyword">final</span> String member)</span> </span>{</div><div class="line"> <span class="keyword">return</span> execute(<span class="keyword">new</span> JedisAction<Long>() {</div><div class="line"></div><div class="line"> <span class="meta">@Override</span></div><div class="line"> <span class="function"><span class="keyword">public</span> Long <span class="title">action</span><span class="params">(Jedis jedis)</span> </span>{</div><div class="line"> <span class="keyword">return</span> jedis.zrevrank(key, member);</div><div class="line"> }</div><div class="line"> });</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="function"><span class="keyword">public</span> Long <span class="title">zcount</span><span class="params">(<span class="keyword">final</span> String key, <span class="keyword">final</span> <span class="keyword">double</span> min, <span class="keyword">final</span> <span class="keyword">double</span> max)</span> </span>{</div><div class="line"> <span class="keyword">return</span> execute(<span class="keyword">new</span> JedisAction<Long>() {</div><div class="line"></div><div class="line"> <span class="meta">@Override</span></div><div class="line"> <span class="function"><span class="keyword">public</span> Long <span class="title">action</span><span class="params">(Jedis jedis)</span> </span>{</div><div class="line"> <span class="keyword">return</span> jedis.zcount(key, min, max);</div><div class="line"> }</div><div class="line"> });</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="function"><span class="keyword">public</span> Set<String> <span class="title">zrange</span><span class="params">(<span class="keyword">final</span> String key, <span class="keyword">final</span> <span class="keyword">int</span> start, <span class="keyword">final</span> <span class="keyword">int</span> end)</span> </span>{</div><div class="line"> <span class="keyword">return</span> execute(<span class="keyword">new</span> JedisAction<Set<String>>() {</div><div class="line"></div><div class="line"> <span class="meta">@Override</span></div><div class="line"> <span class="function"><span class="keyword">public</span> Set<String> <span class="title">action</span><span class="params">(Jedis jedis)</span> </span>{</div><div class="line"> <span class="keyword">return</span> jedis.zrange(key, start, end);</div><div class="line"> }</div><div class="line"> });</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="function"><span class="keyword">public</span> Set<Tuple> <span class="title">zrangeWithScores</span><span class="params">(<span class="keyword">final</span> String key, <span class="keyword">final</span> <span class="keyword">int</span> start, <span class="keyword">final</span> <span class="keyword">int</span> end)</span> </span>{</div><div class="line"> <span class="keyword">return</span> execute(<span class="keyword">new</span> JedisAction<Set<Tuple>>() {</div><div class="line"></div><div class="line"> <span class="meta">@Override</span></div><div class="line"> <span class="function"><span class="keyword">public</span> Set<Tuple> <span class="title">action</span><span class="params">(Jedis jedis)</span> </span>{</div><div class="line"> <span class="keyword">return</span> jedis.zrangeWithScores(key, start, end);</div><div class="line"> }</div><div class="line"> });</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="function"><span class="keyword">public</span> Set<String> <span class="title">zrevrange</span><span class="params">(<span class="keyword">final</span> String key, <span class="keyword">final</span> <span class="keyword">int</span> start, <span class="keyword">final</span> <span class="keyword">int</span> end)</span> </span>{</div><div class="line"> <span class="keyword">return</span> execute(<span class="keyword">new</span> JedisAction<Set<String>>() {</div><div class="line"></div><div class="line"> <span class="meta">@Override</span></div><div class="line"> <span class="function"><span class="keyword">public</span> Set<String> <span class="title">action</span><span class="params">(Jedis jedis)</span> </span>{</div><div class="line"> <span class="keyword">return</span> jedis.zrevrange(key, start, end);</div><div class="line"> }</div><div class="line"> });</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="function"><span class="keyword">public</span> Set<Tuple> <span class="title">zrevrangeWithScores</span><span class="params">(<span class="keyword">final</span> String key, <span class="keyword">final</span> <span class="keyword">int</span> start, <span class="keyword">final</span> <span class="keyword">int</span> end)</span> </span>{</div><div class="line"> <span class="keyword">return</span> execute(<span class="keyword">new</span> JedisAction<Set<Tuple>>() {</div><div class="line"></div><div class="line"> <span class="meta">@Override</span></div><div class="line"> <span class="function"><span class="keyword">public</span> Set<Tuple> <span class="title">action</span><span class="params">(Jedis jedis)</span> </span>{</div><div class="line"> <span class="keyword">return</span> jedis.zrevrangeWithScores(key, start, end);</div><div class="line"> }</div><div class="line"> });</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="function"><span class="keyword">public</span> Set<String> <span class="title">zrangeByScore</span><span class="params">(<span class="keyword">final</span> String key, <span class="keyword">final</span> <span class="keyword">double</span> min, <span class="keyword">final</span> <span class="keyword">double</span> max)</span> </span>{</div><div class="line"> <span class="keyword">return</span> execute(<span class="keyword">new</span> JedisAction<Set<String>>() {</div><div class="line"></div><div class="line"> <span class="meta">@Override</span></div><div class="line"> <span class="function"><span class="keyword">public</span> Set<String> <span class="title">action</span><span class="params">(Jedis jedis)</span> </span>{</div><div class="line"> <span class="keyword">return</span> jedis.zrangeByScore(key, min, max);</div><div class="line"> }</div><div class="line"> });</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="function"><span class="keyword">public</span> Set<Tuple> <span class="title">zrangeByScoreWithScores</span><span class="params">(<span class="keyword">final</span> String key, <span class="keyword">final</span> <span class="keyword">double</span> min, <span class="keyword">final</span> <span class="keyword">double</span> max)</span> </span>{</div><div class="line"> <span class="keyword">return</span> execute(<span class="keyword">new</span> JedisAction<Set<Tuple>>() {</div><div class="line"></div><div class="line"> <span class="meta">@Override</span></div><div class="line"> <span class="function"><span class="keyword">public</span> Set<Tuple> <span class="title">action</span><span class="params">(Jedis jedis)</span> </span>{</div><div class="line"> <span class="keyword">return</span> jedis.zrangeByScoreWithScores(key, min, max);</div><div class="line"> }</div><div class="line"> });</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="function"><span class="keyword">public</span> Set<String> <span class="title">zrevrangeByScore</span><span class="params">(<span class="keyword">final</span> String key, <span class="keyword">final</span> <span class="keyword">double</span> max, <span class="keyword">final</span> <span class="keyword">double</span> min)</span> </span>{</div><div class="line"> <span class="keyword">return</span> execute(<span class="keyword">new</span> JedisAction<Set<String>>() {</div><div class="line"></div><div class="line"> <span class="meta">@Override</span></div><div class="line"> <span class="function"><span class="keyword">public</span> Set<String> <span class="title">action</span><span class="params">(Jedis jedis)</span> </span>{</div><div class="line"> <span class="keyword">return</span> jedis.zrevrangeByScore(key, max, min);</div><div class="line"> }</div><div class="line"> });</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="function"><span class="keyword">public</span> Set<Tuple> <span class="title">zrevrangeByScoreWithScores</span><span class="params">(<span class="keyword">final</span> String key, <span class="keyword">final</span> <span class="keyword">double</span> max, <span class="keyword">final</span> <span class="keyword">double</span> min)</span> </span>{</div><div class="line"> <span class="keyword">return</span> execute(<span class="keyword">new</span> JedisAction<Set<Tuple>>() {</div><div class="line"></div><div class="line"> <span class="meta">@Override</span></div><div class="line"> <span class="function"><span class="keyword">public</span> Set<Tuple> <span class="title">action</span><span class="params">(Jedis jedis)</span> </span>{</div><div class="line"> <span class="keyword">return</span> jedis.zrevrangeByScoreWithScores(key, max, min);</div><div class="line"> }</div><div class="line"> });</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="function"><span class="keyword">public</span> Boolean <span class="title">zrem</span><span class="params">(<span class="keyword">final</span> String key, <span class="keyword">final</span> String member)</span> </span>{</div><div class="line"> <span class="keyword">return</span> execute(<span class="keyword">new</span> JedisAction<Boolean>() {</div><div class="line"></div><div class="line"> <span class="meta">@Override</span></div><div class="line"> <span class="function"><span class="keyword">public</span> Boolean <span class="title">action</span><span class="params">(Jedis jedis)</span> </span>{</div><div class="line"> <span class="keyword">return</span> jedis.zrem(key, member) == <span class="number">1</span> ? <span class="keyword">true</span> : <span class="keyword">false</span>;</div><div class="line"> }</div><div class="line"> });</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="function"><span class="keyword">public</span> Long <span class="title">zremByScore</span><span class="params">(<span class="keyword">final</span> String key, <span class="keyword">final</span> <span class="keyword">double</span> start, <span class="keyword">final</span> <span class="keyword">double</span> end)</span> </span>{</div><div class="line"> <span class="keyword">return</span> execute(<span class="keyword">new</span> JedisAction<Long>() {</div><div class="line"></div><div class="line"> <span class="meta">@Override</span></div><div class="line"> <span class="function"><span class="keyword">public</span> Long <span class="title">action</span><span class="params">(Jedis jedis)</span> </span>{</div><div class="line"> <span class="keyword">return</span> jedis.zremrangeByScore(key, start, end);</div><div class="line"> }</div><div class="line"> });</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="function"><span class="keyword">public</span> Long <span class="title">zremByRank</span><span class="params">(<span class="keyword">final</span> String key, <span class="keyword">final</span> <span class="keyword">long</span> start, <span class="keyword">final</span> <span class="keyword">long</span> end)</span> </span>{</div><div class="line"> <span class="keyword">return</span> execute(<span class="keyword">new</span> JedisAction<Long>() {</div><div class="line"></div><div class="line"> <span class="meta">@Override</span></div><div class="line"> <span class="function"><span class="keyword">public</span> Long <span class="title">action</span><span class="params">(Jedis jedis)</span> </span>{</div><div class="line"> <span class="keyword">return</span> jedis.zremrangeByRank(key, start, end);</div><div class="line"> }</div><div class="line"> });</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="function"><span class="keyword">public</span> Long <span class="title">zcard</span><span class="params">(<span class="keyword">final</span> String key)</span> </span>{</div><div class="line"> <span class="keyword">return</span> execute(<span class="keyword">new</span> JedisAction<Long>() {</div><div class="line"></div><div class="line"> <span class="meta">@Override</span></div><div class="line"> <span class="function"><span class="keyword">public</span> Long <span class="title">action</span><span class="params">(Jedis jedis)</span> </span>{</div><div class="line"> <span class="keyword">return</span> jedis.zcard(key);</div><div class="line"> }</div><div class="line"> });</div><div class="line"> }</div></pre></td></tr></table></figure></p>
<p>验证代码</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div><div class="line">41</div><div class="line">42</div><div class="line">43</div><div class="line">44</div><div class="line">45</div><div class="line">46</div><div class="line">47</div><div class="line">48</div><div class="line">49</div><div class="line">50</div><div class="line">51</div><div class="line">52</div><div class="line">53</div><div class="line">54</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">package</span> hbec.app.stock.ratelimiter;</div><div class="line"></div><div class="line"></div><div class="line"><span class="keyword">import</span> hbec.app.stock.commons.redis.JedisTemplate;</div><div class="line"><span class="keyword">import</span> org.slf4j.Logger;</div><div class="line"><span class="keyword">import</span> org.slf4j.LoggerFactory;</div><div class="line"><span class="keyword">import</span> org.testng.annotations.BeforeTest;</div><div class="line"><span class="keyword">import</span> org.testng.annotations.Test;</div><div class="line"><span class="keyword">import</span> redis.clients.jedis.JedisPool;</div><div class="line"></div><div class="line"><span class="keyword">import</span> java.util.concurrent.TimeUnit;</div><div class="line"><span class="keyword">import</span> java.util.concurrent.atomic.AtomicInteger;</div><div class="line"></div><div class="line"></div><div class="line"><span class="comment">/**</span></div><div class="line"> * <span class="doctag">@author</span> roc</div><div class="line"> * <span class="doctag">@date</span> 2018/01/26</div><div class="line"> */</div><div class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">RedisRateLimiterTest</span> </span>{</div><div class="line"></div><div class="line"></div><div class="line"> <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> Logger LOGGER = LoggerFactory.getLogger(RedisRateLimiterTest.class);</div><div class="line"></div><div class="line"> <span class="keyword">private</span> RateLimiter rateLimiter;</div><div class="line"></div><div class="line"> <span class="keyword">private</span> AtomicInteger atomicInteger = <span class="keyword">new</span> AtomicInteger(<span class="number">1</span>);</div><div class="line"></div><div class="line"> <span class="meta">@BeforeTest</span></div><div class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">init</span><span class="params">()</span> </span>{</div><div class="line"></div><div class="line"> JedisPool jedisPool = <span class="keyword">new</span> JedisPool(<span class="string">"10.0.30.66"</span>, <span class="number">6379</span>);</div><div class="line"> JedisTemplate jedisTemplate = <span class="keyword">new</span> JedisTemplate(jedisPool);</div><div class="line"> String rateLimiterName = <span class="string">"rateLimiterROC"</span>;</div><div class="line"></div><div class="line"> rateLimiter = RedisRateLimiter.newBuilder(jedisTemplate).setRateLimiterName(rateLimiterName)</div><div class="line"> .setUpperLimitPermits(<span class="number">10</span>).setTimeToLive(<span class="number">5</span>, TimeUnit.SECONDS).build();</div><div class="line"> }</div><div class="line"></div><div class="line"></div><div class="line"> <span class="meta">@Test</span>(threadPoolSize = <span class="number">10</span>, invocationCount = <span class="number">20</span>)</div><div class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">testTryAcquire</span><span class="params">()</span> <span class="keyword">throws</span> Exception </span>{</div><div class="line"> <span class="keyword">boolean</span> acquired = rateLimiter.tryAcquire(<span class="number">1</span>);</div><div class="line"> <span class="keyword">if</span> (acquired) {</div><div class="line"> LOGGER.info(<span class="string">"thread {} acquire the permit {} times."</span>, Thread.currentThread().getId(), atomicInteger.getAndIncrement());</div><div class="line"> }</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="meta">@Test</span>(threadPoolSize = <span class="number">10</span>, invocationCount = <span class="number">20</span>)</div><div class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">testAcquire</span><span class="params">()</span> <span class="keyword">throws</span> Exception </span>{</div><div class="line"> rateLimiter.acquire(<span class="number">1</span>);</div><div class="line"> LOGGER.info(<span class="string">"thread {} acquire the permit {} times."</span>, Thread.currentThread().getId(), atomicInteger.getAndIncrement());</div><div class="line"></div><div class="line"> }</div><div class="line">}</div></pre></td></tr></table></figure>
<hr>
<p><strong>测试用例</strong></p>
<p>10个线程20次请求,限制5s内10次请求。</p>
<p><strong>测试结果</strong></p>
<p>10次请求在5s内正常通过,剩下10次请求等待下个时间窗口轮询。</p>
<p><img src="https://raw.githubusercontent.com/roc-wong/images/master/%E9%99%90%E6%B5%81%E6%B5%8B%E8%AF%95.png" alt="测试结果"></p>
]]></content>
<summary type="html">
微服务限流方案,基于edis实现流速控制
</summary>
<category term="架构设计" scheme="https://roc-wong.github.io/categories/%E6%9E%B6%E6%9E%84%E8%AE%BE%E8%AE%A1/"/>
<category term="java后端" scheme="https://roc-wong.github.io/tags/java%E5%90%8E%E7%AB%AF/"/>
</entry>
<entry>
<title>极光推送java-sdk-V3.2.15堵塞BUG</title>
<link href="https://roc-wong.github.io/blog/2018/01/%E6%9E%81%E5%85%89%E6%8E%A8%E9%80%81java-sdk-V3-2-15%E5%A0%B5%E5%A1%9EBUG.html"/>
<id>https://roc-wong.github.io/blog/2018/01/极光推送java-sdk-V3-2-15堵塞BUG.html</id>
<published>2018-01-11T01:36:56.000Z</published>
<updated>2018-11-21T02:18:25.535Z</updated>
<content type="html"><![CDATA[<h2 id="案发现场"><a href="#案发现场" class="headerlink" title="案发现场"></a>案发现场</h2><ul>
<li>从RabbitMQ Server端获取消息的线程运行正常,读到数据后放到本地的BlockQueue中,等待消费者线程消费。</li>
<li>消费者线程堵塞,不再消费本地BlockQueue中的消息。</li>
<li>使用jstack进行Thread Dump分析。由于自定义消费者线程名称,所以直接筛选前缀为MessageConsumer线程,结果如下:</li>
</ul>
<figure class="highlight stylus"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div></pre></td><td class="code"><pre><div class="line"><span class="string">"MessageConsumer-1"</span> prio=<span class="number">10</span> tid=<span class="number">0</span>x00007f39309f6000 nid=<span class="number">0</span>x1047 waiting on condition [<span class="number">0</span>x00007f39052d3000]</div><div class="line"> java<span class="selector-class">.lang</span><span class="selector-class">.Thread</span><span class="selector-class">.State</span>: WAITING (parking)</div><div class="line"> at sun<span class="selector-class">.misc</span><span class="selector-class">.Unsafe</span><span class="selector-class">.park</span>(Native Method)</div><div class="line"> - parking to wait <span class="keyword">for</span> <<span class="number">0</span>x00000000a4b994d0> (<span class="selector-tag">a</span> java<span class="selector-class">.util</span><span class="selector-class">.concurrent</span><span class="selector-class">.CountDownLatch</span><span class="variable">$Sync</span>)</div><div class="line"> at java<span class="selector-class">.util</span><span class="selector-class">.concurrent</span><span class="selector-class">.locks</span><span class="selector-class">.LockSupport</span><span class="selector-class">.park</span>(LockSupport<span class="selector-class">.java</span>:<span class="number">186</span>)</div><div class="line"> at java<span class="selector-class">.util</span><span class="selector-class">.concurrent</span><span class="selector-class">.locks</span><span class="selector-class">.AbstractQueuedSynchronizer</span><span class="selector-class">.parkAndCheckInterrupt</span>(AbstractQueuedSynchronizer<span class="selector-class">.java</span>:<span class="number">834</span>)</div><div class="line"> at java<span class="selector-class">.util</span><span class="selector-class">.concurrent</span><span class="selector-class">.locks</span><span class="selector-class">.AbstractQueuedSynchronizer</span><span class="selector-class">.doAcquireSharedInterruptibly</span>(AbstractQueuedSynchronizer<span class="selector-class">.java</span>:<span class="number">994</span>)</div><div class="line"> at java<span class="selector-class">.util</span><span class="selector-class">.concurrent</span><span class="selector-class">.locks</span><span class="selector-class">.AbstractQueuedSynchronizer</span><span class="selector-class">.acquireSharedInterruptibly</span>(AbstractQueuedSynchronizer<span class="selector-class">.java</span>:<span class="number">1303</span>)</div><div class="line"> at java<span class="selector-class">.util</span><span class="selector-class">.concurrent</span><span class="selector-class">.CountDownLatch</span><span class="selector-class">.await</span>(CountDownLatch<span class="selector-class">.java</span>:<span class="number">236</span>)</div><div class="line"> at cn<span class="selector-class">.jiguang</span><span class="selector-class">.common</span><span class="selector-class">.connection</span><span class="selector-class">.NettyHttpClient</span><span class="selector-class">.sendHttpRequest</span>(NettyHttpClient<span class="selector-class">.java</span>:<span class="number">193</span>)</div><div class="line"> at cn<span class="selector-class">.jiguang</span><span class="selector-class">.common</span><span class="selector-class">.connection</span><span class="selector-class">.NettyHttpClient</span><span class="selector-class">.sendPost</span>(NettyHttpClient<span class="selector-class">.java</span>:<span class="number">134</span>)</div><div class="line"> at cn<span class="selector-class">.jpush</span><span class="selector-class">.api</span><span class="selector-class">.push</span><span class="selector-class">.PushClient</span><span class="selector-class">.sendPush</span>(PushClient<span class="selector-class">.java</span>:<span class="number">194</span>)</div><div class="line"> at cn<span class="selector-class">.jpush</span><span class="selector-class">.api</span><span class="selector-class">.JPushClient</span><span class="selector-class">.sendPush</span>(JPushClient<span class="selector-class">.java</span>:<span class="number">205</span>)</div><div class="line"> at hbec<span class="selector-class">.app</span><span class="selector-class">.platform</span><span class="selector-class">.push</span><span class="selector-class">.service</span><span class="selector-class">.impl</span><span class="selector-class">.JPushService</span><span class="selector-class">.push</span>(JPushService<span class="selector-class">.java</span>:<span class="number">66</span>)</div><div class="line"> at hbec<span class="selector-class">.app</span><span class="selector-class">.platform</span><span class="selector-class">.push</span><span class="selector-class">.service</span><span class="selector-class">.impl</span><span class="selector-class">.PushFacadeService</span><span class="selector-class">.jpush</span>(PushFacadeService<span class="selector-class">.java</span>:<span class="number">113</span>)</div><div class="line"> at sun<span class="selector-class">.reflect</span><span class="selector-class">.NativeMethodAccessorImpl</span><span class="selector-class">.invoke0</span>(Native Method)</div><div class="line"> at sun<span class="selector-class">.reflect</span><span class="selector-class">.NativeMethodAccessorImpl</span><span class="selector-class">.invoke</span>(NativeMethodAccessorImpl<span class="selector-class">.java</span>:<span class="number">57</span>)</div><div class="line"> at sun<span class="selector-class">.reflect</span><span class="selector-class">.DelegatingMethodAccessorImpl</span><span class="selector-class">.invoke</span>(DelegatingMethodAccessorImpl<span class="selector-class">.java</span>:<span class="number">43</span>)</div><div class="line"> at java<span class="selector-class">.lang</span><span class="selector-class">.reflect</span><span class="selector-class">.Method</span><span class="selector-class">.invoke</span>(Method<span class="selector-class">.java</span>:<span class="number">606</span>)</div><div class="line"> at hbec<span class="selector-class">.app</span><span class="selector-class">.mc</span><span class="selector-class">.RpcService</span><span class="selector-class">.send</span>(RpcService<span class="selector-class">.java</span>:<span class="number">38</span>)</div><div class="line"> at hbec<span class="selector-class">.app</span><span class="selector-class">.mc</span><span class="selector-class">.NotifySendService</span><span class="selector-class">.send</span>(NotifySendService<span class="selector-class">.java</span>:<span class="number">40</span>)</div><div class="line"> at hbec<span class="selector-class">.app</span><span class="selector-class">.mc</span><span class="selector-class">.NotifyService</span><span class="selector-class">.notifyPerson</span>(NotifyService<span class="selector-class">.java</span>:<span class="number">151</span>)</div><div class="line"> at hbec<span class="selector-class">.app</span><span class="selector-class">.mc</span><span class="selector-class">.NotifyService</span><span class="selector-class">.notify</span>(NotifyService<span class="selector-class">.java</span>:<span class="number">83</span>)</div><div class="line"> at hbec<span class="selector-class">.app</span><span class="selector-class">.mc</span><span class="selector-class">.rabbitmq</span><span class="selector-class">.RealTimeConsumer</span><span class="selector-class">.onMessage</span>(RealTimeConsumer<span class="selector-class">.java</span>:<span class="number">29</span>)</div><div class="line"> at org<span class="selector-class">.springframework</span><span class="selector-class">.amqp</span><span class="selector-class">.rabbit</span><span class="selector-class">.listener</span><span class="selector-class">.adapter</span><span class="selector-class">.MessageListenerAdapter</span><span class="selector-class">.onMessage</span>(MessageListenerAdapter<span class="selector-class">.java</span>:<span class="number">273</span>)</div><div class="line"> at org<span class="selector-class">.springframework</span><span class="selector-class">.amqp</span><span class="selector-class">.rabbit</span><span class="selector-class">.listener</span><span class="selector-class">.AbstractMessageListenerContainer</span><span class="selector-class">.doInvokeListener</span>(AbstractMessageListenerContainer<span class="selector-class">.java</span>:<span class="number">848</span>)</div><div class="line"> at org<span class="selector-class">.springframework</span><span class="selector-class">.amqp</span><span class="selector-class">.rabbit</span><span class="selector-class">.listener</span><span class="selector-class">.AbstractMessageListenerContainer</span><span class="selector-class">.invokeListener</span>(AbstractMessageListenerContainer<span class="selector-class">.java</span>:<span class="number">771</span>)</div><div class="line"> at org<span class="selector-class">.springframework</span><span class="selector-class">.amqp</span><span class="selector-class">.rabbit</span><span class="selector-class">.listener</span><span class="selector-class">.SimpleMessageListenerContainer</span><span class="selector-class">.access</span>$<span class="number">001</span>(SimpleMessageListenerContainer<span class="selector-class">.java</span>:<span class="number">102</span>)</div><div class="line"> at org<span class="selector-class">.springframework</span><span class="selector-class">.amqp</span><span class="selector-class">.rabbit</span><span class="selector-class">.listener</span><span class="selector-class">.SimpleMessageListenerContainer</span>$<span class="number">1</span>.invokeListener(SimpleMessageListenerContainer<span class="selector-class">.java</span>:<span class="number">198</span>)</div><div class="line"> at org<span class="selector-class">.springframework</span><span class="selector-class">.amqp</span><span class="selector-class">.rabbit</span><span class="selector-class">.listener</span><span class="selector-class">.SimpleMessageListenerContainer</span><span class="selector-class">.invokeListener</span>(SimpleMessageListenerContainer<span class="selector-class">.java</span>:<span class="number">1311</span>)</div><div class="line"> at org<span class="selector-class">.springframework</span><span class="selector-class">.amqp</span><span class="selector-class">.rabbit</span><span class="selector-class">.listener</span><span class="selector-class">.AbstractMessageListenerContainer</span><span class="selector-class">.executeListener</span>(AbstractMessageListenerContainer<span class="selector-class">.java</span>:<span class="number">752</span>)</div><div class="line"> at org<span class="selector-class">.springframework</span><span class="selector-class">.amqp</span><span class="selector-class">.rabbit</span><span class="selector-class">.listener</span><span class="selector-class">.SimpleMessageListenerContainer</span><span class="selector-class">.doReceiveAndExecute</span>(SimpleMessageListenerContainer<span class="selector-class">.java</span>:<span class="number">1254</span>)</div><div class="line"> at org<span class="selector-class">.springframework</span><span class="selector-class">.amqp</span><span class="selector-class">.rabbit</span><span class="selector-class">.listener</span><span class="selector-class">.SimpleMessageListenerContainer</span><span class="selector-class">.receiveAndExecute</span>(SimpleMessageListenerContainer<span class="selector-class">.java</span>:<span class="number">1224</span>)</div><div class="line"> at org<span class="selector-class">.springframework</span><span class="selector-class">.amqp</span><span class="selector-class">.rabbit</span><span class="selector-class">.listener</span><span class="selector-class">.SimpleMessageListenerContainer</span><span class="selector-class">.access</span>$<span class="number">1600</span>(SimpleMessageListenerContainer<span class="selector-class">.java</span>:<span class="number">102</span>)</div><div class="line"> at org<span class="selector-class">.springframework</span><span class="selector-class">.amqp</span><span class="selector-class">.rabbit</span><span class="selector-class">.listener</span><span class="selector-class">.SimpleMessageListenerContainer</span><span class="variable">$AsyncMessageProcessingConsumer</span>.run(SimpleMessageListenerContainer<span class="selector-class">.java</span>:<span class="number">1470</span>)</div><div class="line"> at java<span class="selector-class">.lang</span><span class="selector-class">.Thread</span><span class="selector-class">.run</span>(Thread<span class="selector-class">.java</span>:<span class="number">745</span>)</div><div class="line"></div><div class="line"> Locked ownable synchronizers:</div><div class="line"> - None</div><div class="line">……</div></pre></td></tr></table></figure>
<p>从上可以发现,消费者线程大都处于WAITING状态,线程阻塞在NettyHttpClient.sendHttpRequest的CountDownLatch.await()方法。<br><figure class="highlight stylus"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">at java<span class="selector-class">.util</span><span class="selector-class">.concurrent</span><span class="selector-class">.CountDownLatch</span><span class="selector-class">.await</span>(CountDownLatch<span class="selector-class">.java</span>:<span class="number">236</span>)</div><div class="line">at cn<span class="selector-class">.jiguang</span><span class="selector-class">.common</span><span class="selector-class">.connection</span><span class="selector-class">.NettyHttpClient</span><span class="selector-class">.sendHttpRequest</span>(NettyHttpClient<span class="selector-class">.java</span>:<span class="number">193</span>)</div></pre></td></tr></table></figure></p>
<h2 id="分析推理"><a href="#分析推理" class="headerlink" title="分析推理"></a>分析推理</h2><p>通过对应用中各线程运行的状态情况,推测是极光推送SDK代码BUG导致。深入源码进行问题排查:</p>
<ul>
<li><p>1> cn.jpush.api.JPushClient.java</p>
<figure class="highlight aspectj"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">public</span> <span class="function">PushResult <span class="title">sendPush</span><span class="params">(PushPayload pushPayload)</span> <span class="keyword">throws</span> APIConnectionException, APIRequestException </span>{</div><div class="line"> <span class="function"><span class="keyword">return</span> _pushClient.<span class="title">sendPush</span><span class="params">(pushPayload)</span></span>;</div><div class="line"> }</div></pre></td></tr></table></figure>
</li>
<li><p>2> cn.jpush.api.push.PushClient.java</p>
<figure class="highlight sqf"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div></pre></td><td class="code"><pre><div class="line">public PushResult sendPush(PushPayload pushPayload) throws APIConnectionException, APIRequestException {</div><div class="line"> Preconditions.checkArgument(! (null == pushPayload), <span class="string">"pushPayload should not be null"</span>);</div><div class="line"> <span class="keyword">if</span> (<span class="variable">_apnsProduction</span> > <span class="number">0</span>) {</div><div class="line"> pushPayload.resetOptionsApnsProduction(<span class="literal">true</span>);</div><div class="line"> } <span class="keyword">else</span> <span class="keyword">if</span>(<span class="variable">_apnsProduction</span> == <span class="number">0</span>) {</div><div class="line"> pushPayload.resetOptionsApnsProduction(<span class="literal">false</span>);</div><div class="line"> }</div><div class="line"> <span class="keyword">if</span> (<span class="variable">_timeToLive</span> >= <span class="number">0</span>) {</div><div class="line"> pushPayload.resetOptionsTimeToLive(<span class="variable">_timeToLive</span>);</div><div class="line"> }</div><div class="line"> <span class="comment">//该版本默认使用NettyHttpClient,进入源码</span></div><div class="line"> ResponseWrapper response = <span class="variable">_httpClient</span>.sendPost(<span class="variable">_baseUrl</span> + <span class="variable">_pushPath</span>, pushPayload.<span class="built_in">toString</span>());</div><div class="line"> return BaseResult.fromResponse(response, PushResult.class);</div><div class="line"> }</div></pre></td></tr></table></figure>
</li>
<li><p>3> cn.jiguang.common.connection.NettyHttpClient.java</p>
<figure class="highlight haxe"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div><div class="line">41</div><div class="line">42</div><div class="line">43</div><div class="line">44</div><div class="line">45</div><div class="line">46</div><div class="line">47</div><div class="line">48</div><div class="line">49</div><div class="line">50</div><div class="line">51</div><div class="line">52</div><div class="line">53</div><div class="line">54</div><div class="line">55</div></pre></td><td class="code"><pre><div class="line">@Override</div><div class="line"> <span class="keyword">public</span> ResponseWrapper sendPost(<span class="keyword">String</span> url, <span class="keyword">String</span> content) throws APIConnectionException, APIRequestException {</div><div class="line"> ResponseWrapper wrapper = <span class="keyword">new</span> <span class="type">ResponseWrapper</span>();</div><div class="line"> <span class="keyword">try</span> {</div><div class="line"> <span class="keyword">return</span> sendHttpRequest(HttpMethod.POST, url, content);</div><div class="line"> } <span class="keyword">catch</span> (Exception e) {</div><div class="line"> e.printStackTrace();</div><div class="line"> }</div><div class="line"> <span class="keyword">return</span> wrapper;</div><div class="line"> }</div><div class="line"></div><div class="line"><span class="keyword">private</span> ResponseWrapper sendHttpRequest(HttpMethod method, <span class="keyword">String</span> url, <span class="keyword">String</span> body) throws Exception {</div><div class="line"> <span class="comment">// 此处实例化CountDownLatch并传递给NettyClientInitializer, 继续跟踪 </span></div><div class="line"> CountDownLatch latch = <span class="keyword">new</span> <span class="type">CountDownLatch</span>(<span class="number">1</span>);</div><div class="line"> NettyClientInitializer initializer = <span class="keyword">new</span> <span class="type">NettyClientInitializer</span>(_sslCtx, <span class="literal">null</span>, latch);</div><div class="line"> b.handler(initializer);</div><div class="line"> ResponseWrapper wrapper = <span class="keyword">new</span> <span class="type">ResponseWrapper</span>();</div><div class="line"> URI uri = <span class="keyword">new</span> <span class="type">URI</span>(url);</div><div class="line"> <span class="keyword">String</span> scheme = uri.getScheme() == <span class="literal">null</span> ? <span class="string">"http"</span> : <span class="type">uri</span>.getScheme();</div><div class="line"> <span class="keyword">String</span> host = uri.getHost() == <span class="literal">null</span> ? <span class="string">"127.0.0.1"</span> : <span class="type">uri</span>.getHost();</div><div class="line"> int port = uri.getPort();</div><div class="line"> <span class="keyword">if</span> (port == <span class="number">-1</span>) {</div><div class="line"> <span class="keyword">if</span> (<span class="string">"http"</span>.equalsIgnoreCase(scheme)) {</div><div class="line"> port = <span class="number">80</span>;</div><div class="line"> } <span class="keyword">else</span> <span class="keyword">if</span> (<span class="string">"https"</span>.equalsIgnoreCase(scheme)) {</div><div class="line"> port = <span class="number">443</span>;</div><div class="line"> }</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">try</span> {</div><div class="line"> ChannelFuture connect = b.connect(host, port);</div><div class="line"> _channel = connect.sync().channel();</div><div class="line"> FullHttpRequest request;</div><div class="line"> <span class="keyword">if</span> (<span class="literal">null</span> != body) {</div><div class="line"> ByteBuf byteBuf = Unpooled.copiedBuffer(body.getBytes(CharsetUtil.UTF_8));</div><div class="line"> request = <span class="keyword">new</span> <span class="type">DefaultFullHttpRequest</span>(HttpVersion.HTTP_1_1, method, uri.getRawPath(), byteBuf);</div><div class="line"> request.headers().<span class="keyword">set</span>(HttpHeaderNames.CONTENT_LENGTH, (long) byteBuf.readableBytes());</div><div class="line"> } <span class="keyword">else</span> {</div><div class="line"> request = <span class="keyword">new</span> <span class="type">DefaultFullHttpRequest</span>(HTTP_1_1, method, uri.getRawPath());</div><div class="line"> }</div><div class="line"> request.headers().<span class="keyword">set</span>(HttpHeaderNames.HOST, uri.getHost());</div><div class="line"> request.headers().<span class="keyword">set</span>(HttpHeaderNames.AUTHORIZATION, _authCode);</div><div class="line"> request.headers().<span class="keyword">set</span>(<span class="string">"Content-Type"</span>,<span class="string">"application/json;charset=utf-8"</span>);</div><div class="line"> connect.awaitUninterruptibly();</div><div class="line"> LOG.info(<span class="string">"Sending request. "</span> + request);</div><div class="line"> LOG.info(<span class="string">"Send body: "</span> + body);</div><div class="line"> _channel.writeAndFlush(request);</div><div class="line"> <span class="comment">//调用latch.await()后主线程阻塞,等待netty异步网络调用。如果异步线程执行后不调用countDown(),主线程将永远阻塞,此为问题主要原因。 </span></div><div class="line"> latch.await();</div><div class="line"> wrapper = initializer.getResponse();</div><div class="line"> } <span class="keyword">catch</span> (InterruptedException e) {</div><div class="line"> e.printStackTrace();</div><div class="line"> }</div><div class="line"> <span class="keyword">return</span> wrapper;</div><div class="line"> }</div></pre></td></tr></table></figure>
</li>
<li><p>4> cn.jiguang.common.connection.NettyClientInitializer.java</p>
</li>
</ul>
<figure class="highlight aspectj"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div></pre></td><td class="code"><pre><div class="line"><span class="meta">@Override</span></div><div class="line"> <span class="keyword">protected</span> <span class="function"><span class="keyword">void</span> <span class="title">initChannel</span><span class="params">(SocketChannel socketChannel)</span> <span class="keyword">throws</span> Exception </span>{</div><div class="line"> <span class="comment">//使用_latch创建HttpResponseHandler</span></div><div class="line"> <span class="keyword">this</span>._handler = <span class="keyword">new</span> HttpResponseHandler(_callback, _latch);</div><div class="line"> socketChannel.pipeline().addLast(_sslCtx.newHandler(socketChannel.alloc()), <span class="keyword">new</span> HttpClientCodec(), _handler);</div><div class="line"> }</div></pre></td></tr></table></figure>
<ul>
<li>5> cn.jiguang.common.connection.HttpResponseHandler.java<figure class="highlight aspectj"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div><div class="line">41</div></pre></td><td class="code"><pre><div class="line"><span class="meta">@Override</span></div><div class="line"> <span class="keyword">protected</span> <span class="function"><span class="keyword">void</span> <span class="title">channelRead0</span><span class="params">(ChannelHandlerContext ctx, HttpObject msg)</span> <span class="keyword">throws</span> Exception </span>{</div><div class="line"> <span class="keyword">if</span> (msg <span class="keyword">instanceof</span> HttpResponse) {</div><div class="line"> HttpResponse response = (HttpResponse) msg;</div><div class="line"> status = response.status().code();</div><div class="line"> }</div><div class="line"> <span class="keyword">if</span> (msg <span class="keyword">instanceof</span> HttpContent) {</div><div class="line"> HttpContent content = (HttpContent) msg;</div><div class="line"> LOG.info(content.content().toString());</div><div class="line"> <span class="keyword">if</span> (content <span class="keyword">instanceof</span> LastHttpContent) {</div><div class="line"> <span class="comment">//断点跟踪发现,程序运行到该分支后,直接close,并未调用_latch.countDown(); 此为问题的主要爆发点</span></div><div class="line"> LOG.info(<span class="string">"closing connection"</span>);</div><div class="line"> ctx.close();</div><div class="line"> } <span class="keyword">else</span> {</div><div class="line"> String responseContent = content.content().toString(CharsetUtil.UTF_8);</div><div class="line"> _wrapper.responseCode = status;</div><div class="line"> _wrapper.responseContent = responseContent;</div><div class="line"> LOG.info(<span class="string">"Got Response code: "</span> + status + <span class="string">" content: "</span> + responseContent);</div><div class="line"> System.err.println(<span class="string">"Got Response code: "</span> + status + <span class="string">" content: "</span> + responseContent);</div><div class="line"> System.err.flush();</div><div class="line"> <span class="keyword">if</span> (<span class="keyword">null</span> != _callback) {</div><div class="line"> _callback.onSucceed(_wrapper);</div><div class="line"> }</div><div class="line"> <span class="keyword">if</span> (<span class="keyword">null</span> != _latch) {</div><div class="line"> <span class="comment">//正常情况下</span></div><div class="line"> _latch.countDown();</div><div class="line"> }</div><div class="line"> }</div><div class="line"> }</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="meta">@Override</span></div><div class="line"> <span class="keyword">public</span> <span class="function"><span class="keyword">void</span> <span class="title">exceptionCaught</span><span class="params">(ChannelHandlerContext ctx, Throwable cause)</span> </span>{</div><div class="line"> LOG.<span class="keyword">error</span>(<span class="string">"error:"</span>, cause);</div><div class="line"> <span class="keyword">try</span> {</div><div class="line"> <span class="comment">//模拟网络异常,发现此处也存在bug,未调用_latch.countDown(); 隐藏爆发点</span></div><div class="line"> ctx.close();</div><div class="line"> }<span class="keyword">catch</span> (Exception ex) {</div><div class="line"> LOG.<span class="keyword">error</span>(<span class="string">"close error:"</span>, ex);</div><div class="line"> }</div><div class="line"> }</div></pre></td></tr></table></figure>
</li>
</ul>
<p>翻阅源码发现HttpResponseHandler.java类内部存在两个隐患:</p>
<ul>
<li>程序运行到if (content instanceof LastHttpContent) {……}分支后,未调用_latch.countDown();</li>
<li>当出现网络异常时,exceptionCaught方法内部也未调用_latch.countDown();</li>
</ul>
<p>只要其中任意一个隐患爆发,主线程就会阻塞,进入WAITING状态。消费者线程就此堵塞,不再消费BlockQueue中的消息。</p>
<h2 id="恢复现场"><a href="#恢复现场" class="headerlink" title="恢复现场"></a>恢复现场</h2><ul>
<li>Maven pom.xml</li>
</ul>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div><div class="line">41</div><div class="line">42</div><div class="line">43</div><div class="line">44</div><div class="line">45</div><div class="line">46</div><div class="line">47</div><div class="line">48</div><div class="line">49</div><div class="line">50</div><div class="line">51</div><div class="line">52</div><div class="line">53</div><div class="line">54</div><div class="line">55</div><div class="line">56</div><div class="line">57</div><div class="line">58</div><div class="line">59</div><div class="line">60</div><div class="line">61</div><div class="line">62</div><div class="line">63</div><div class="line">64</div><div class="line">65</div><div class="line">66</div><div class="line">67</div><div class="line">68</div><div class="line">69</div><div class="line">70</div><div class="line">71</div><div class="line">72</div><div class="line">73</div><div class="line">74</div><div class="line">75</div><div class="line">76</div><div class="line">77</div><div class="line">78</div><div class="line">79</div><div class="line">80</div><div class="line">81</div><div class="line">82</div><div class="line">83</div><div class="line">84</div><div class="line">85</div><div class="line">86</div><div class="line">87</div><div class="line">88</div><div class="line">89</div></pre></td><td class="code"><pre><div class="line"><span class="php"><span class="meta"><?</span>xml version=<span class="string">"1.0"</span> encoding=<span class="string">"UTF-8"</span><span class="meta">?></span></span></div><div class="line"><span class="tag"><<span class="name">project</span> <span class="attr">xmlns</span>=<span class="string">"http://maven.apache.org/POM/4.0.0"</span></span></div><div class="line"> <span class="attr">xmlns:xsi</span>=<span class="string">"http://www.w3.org/2001/XMLSchema-instance"</span></div><div class="line"> <span class="attr">xsi:schemaLocation</span>=<span class="string">"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"</span>></div><div class="line"> <span class="tag"><<span class="name">parent</span>></span></div><div class="line"> <span class="tag"><<span class="name">artifactId</span>></span>sky-framework<span class="tag"></<span class="name">artifactId</span>></span></div><div class="line"> <span class="tag"><<span class="name">groupId</span>></span>org.sky<span class="tag"></<span class="name">groupId</span>></span></div><div class="line"> <span class="tag"><<span class="name">version</span>></span>0.0.1-SNAPSHOT<span class="tag"></<span class="name">version</span>></span></div><div class="line"> <span class="tag"></<span class="name">parent</span>></span></div><div class="line"> <span class="tag"><<span class="name">modelVersion</span>></span>4.0.0<span class="tag"></<span class="name">modelVersion</span>></span></div><div class="line"></div><div class="line"> <span class="tag"><<span class="name">artifactId</span>></span>jpush-test<span class="tag"></<span class="name">artifactId</span>></span></div><div class="line"></div><div class="line"> <span class="tag"><<span class="name">dependencies</span>></span></div><div class="line"> <span class="tag"><<span class="name">dependency</span>></span></div><div class="line"> <span class="tag"><<span class="name">groupId</span>></span>com.google.guava<span class="tag"></<span class="name">groupId</span>></span></div><div class="line"> <span class="tag"><<span class="name">artifactId</span>></span>guava<span class="tag"></<span class="name">artifactId</span>></span></div><div class="line"> <span class="tag"></<span class="name">dependency</span>></span></div><div class="line"></div><div class="line"> <span class="comment"><!-- jpush --></span></div><div class="line"> <span class="tag"><<span class="name">dependency</span>></span></div><div class="line"> <span class="tag"><<span class="name">groupId</span>></span>cn.jpush.api<span class="tag"></<span class="name">groupId</span>></span></div><div class="line"> <span class="tag"><<span class="name">artifactId</span>></span>jpush-client<span class="tag"></<span class="name">artifactId</span>></span></div><div class="line"> <span class="tag"><<span class="name">version</span>></span>3.2.15<span class="tag"></<span class="name">version</span>></span></div><div class="line"> <span class="tag"></<span class="name">dependency</span>></span></div><div class="line"> <span class="comment"><!-- utils begin --></span></div><div class="line"> <span class="tag"><<span class="name">dependency</span>></span></div><div class="line"> <span class="tag"><<span class="name">groupId</span>></span>cn.jpush.api<span class="tag"></<span class="name">groupId</span>></span></div><div class="line"> <span class="tag"><<span class="name">artifactId</span>></span>jiguang-common<span class="tag"></<span class="name">artifactId</span>></span></div><div class="line"> <span class="tag"><<span class="name">version</span>></span>1.0.1<span class="tag"></<span class="name">version</span>></span></div><div class="line"> <span class="tag"></<span class="name">dependency</span>></span></div><div class="line"> <span class="tag"><<span class="name">dependency</span>></span></div><div class="line"> <span class="tag"><<span class="name">groupId</span>></span>io.netty<span class="tag"></<span class="name">groupId</span>></span></div><div class="line"> <span class="tag"><<span class="name">artifactId</span>></span>netty-all<span class="tag"></<span class="name">artifactId</span>></span></div><div class="line"> <span class="tag"><<span class="name">version</span>></span>4.1.6.Final<span class="tag"></<span class="name">version</span>></span></div><div class="line"> <span class="tag"><<span class="name">scope</span>></span>compile<span class="tag"></<span class="name">scope</span>></span></div><div class="line"> <span class="tag"></<span class="name">dependency</span>></span></div><div class="line"> <span class="tag"><<span class="name">dependency</span>></span></div><div class="line"> <span class="tag"><<span class="name">groupId</span>></span>com.google.code.gson<span class="tag"></<span class="name">groupId</span>></span></div><div class="line"> <span class="tag"><<span class="name">artifactId</span>></span>gson<span class="tag"></<span class="name">artifactId</span>></span></div><div class="line"> <span class="tag"><<span class="name">version</span>></span>2.3<span class="tag"></<span class="name">version</span>></span></div><div class="line"> <span class="tag"></<span class="name">dependency</span>></span></div><div class="line"></div><div class="line"> <span class="comment"><!-- LOGGING begin --></span></div><div class="line"> <span class="comment"><!-- slf4j --></span></div><div class="line"> <span class="tag"><<span class="name">dependency</span>></span></div><div class="line"> <span class="tag"><<span class="name">groupId</span>></span>org.slf4j<span class="tag"></<span class="name">groupId</span>></span></div><div class="line"> <span class="tag"><<span class="name">artifactId</span>></span>slf4j-api<span class="tag"></<span class="name">artifactId</span>></span></div><div class="line"> <span class="tag"></<span class="name">dependency</span>></span></div><div class="line"></div><div class="line"> <span class="comment"><!-- logback --></span></div><div class="line"> <span class="tag"><<span class="name">dependency</span>></span></div><div class="line"> <span class="tag"><<span class="name">groupId</span>></span>ch.qos.logback<span class="tag"></<span class="name">groupId</span>></span></div><div class="line"> <span class="tag"><<span class="name">artifactId</span>></span>logback-classic<span class="tag"></<span class="name">artifactId</span>></span></div><div class="line"> <span class="tag"></<span class="name">dependency</span>></span></div><div class="line"></div><div class="line"> <span class="comment"><!-- 代码直接调用log4j会被桥接到slf4j --></span></div><div class="line"> <span class="tag"><<span class="name">dependency</span>></span></div><div class="line"> <span class="tag"><<span class="name">groupId</span>></span>org.slf4j<span class="tag"></<span class="name">groupId</span>></span></div><div class="line"> <span class="tag"><<span class="name">artifactId</span>></span>log4j-over-slf4j<span class="tag"></<span class="name">artifactId</span>></span></div><div class="line"> <span class="tag"></<span class="name">dependency</span>></span></div><div class="line"></div><div class="line"> <span class="comment"><!-- 代码直接调用commons-logging会被桥接到slf4j --></span></div><div class="line"> <span class="tag"><<span class="name">dependency</span>></span></div><div class="line"> <span class="tag"><<span class="name">groupId</span>></span>org.slf4j<span class="tag"></<span class="name">groupId</span>></span></div><div class="line"> <span class="tag"><<span class="name">artifactId</span>></span>jcl-over-slf4j<span class="tag"></<span class="name">artifactId</span>></span></div><div class="line"> <span class="tag"></<span class="name">dependency</span>></span></div><div class="line"></div><div class="line"> <span class="comment"><!-- 代码直接调用java.util.logging会被桥接到slf4j --></span></div><div class="line"> <span class="tag"><<span class="name">dependency</span>></span></div><div class="line"> <span class="tag"><<span class="name">groupId</span>></span>org.slf4j<span class="tag"></<span class="name">groupId</span>></span></div><div class="line"> <span class="tag"><<span class="name">artifactId</span>></span>jul-to-slf4j<span class="tag"></<span class="name">artifactId</span>></span></div><div class="line"> <span class="tag"></<span class="name">dependency</span>></span></div><div class="line"></div><div class="line"> <span class="comment"><!-- log4jdbc --></span></div><div class="line"> <span class="tag"><<span class="name">dependency</span>></span></div><div class="line"> <span class="tag"><<span class="name">groupId</span>></span>com.googlecode.log4jdbc<span class="tag"></<span class="name">groupId</span>></span></div><div class="line"> <span class="tag"><<span class="name">artifactId</span>></span>log4jdbc<span class="tag"></<span class="name">artifactId</span>></span></div><div class="line"> <span class="tag"><<span class="name">scope</span>></span>runtime<span class="tag"></<span class="name">scope</span>></span></div><div class="line"> <span class="tag"></<span class="name">dependency</span>></span></div><div class="line"> <span class="comment"><!-- LOGGING end --></span></div><div class="line"></div><div class="line"> <span class="tag"><<span class="name">dependency</span>></span></div><div class="line"> <span class="tag"><<span class="name">groupId</span>></span>org.testng<span class="tag"></<span class="name">groupId</span>></span></div><div class="line"> <span class="tag"><<span class="name">artifactId</span>></span>testng<span class="tag"></<span class="name">artifactId</span>></span></div><div class="line"> <span class="tag"></<span class="name">dependency</span>></span></div><div class="line"> <span class="tag"></<span class="name">dependencies</span>></span></div><div class="line"></div><div class="line"><span class="tag"></<span class="name">project</span>></span></div></pre></td></tr></table></figure>
<ul>
<li>测试代码</li>
</ul>
<figure class="highlight gradle"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div><div class="line">41</div><div class="line">42</div><div class="line">43</div><div class="line">44</div><div class="line">45</div><div class="line">46</div><div class="line">47</div><div class="line">48</div><div class="line">49</div><div class="line">50</div><div class="line">51</div><div class="line">52</div><div class="line">53</div><div class="line">54</div><div class="line">55</div><div class="line">56</div><div class="line">57</div><div class="line">58</div><div class="line">59</div><div class="line">60</div><div class="line">61</div><div class="line">62</div><div class="line">63</div><div class="line">64</div><div class="line">65</div><div class="line">66</div><div class="line">67</div><div class="line">68</div><div class="line">69</div><div class="line">70</div><div class="line">71</div><div class="line">72</div><div class="line">73</div><div class="line">74</div><div class="line">75</div><div class="line">76</div><div class="line">77</div><div class="line">78</div><div class="line">79</div><div class="line">80</div><div class="line">81</div><div class="line">82</div><div class="line">83</div><div class="line">84</div><div class="line">85</div><div class="line">86</div><div class="line">87</div><div class="line">88</div><div class="line">89</div><div class="line">90</div><div class="line">91</div><div class="line">92</div><div class="line">93</div><div class="line">94</div><div class="line">95</div><div class="line">96</div><div class="line">97</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">package</span> org.sky.jpush;</div><div class="line"></div><div class="line"><span class="keyword">import</span> cn.jiguang.common.ClientConfig;</div><div class="line"><span class="keyword">import</span> cn.jiguang.common.resp.APIConnectionException;</div><div class="line"><span class="keyword">import</span> cn.jiguang.common.resp.APIRequestException;</div><div class="line"><span class="keyword">import</span> cn.jpush.api.JPushClient;</div><div class="line"><span class="keyword">import</span> cn.jpush.api.<span class="keyword">push</span>.PushResult;</div><div class="line"><span class="keyword">import</span> cn.jpush.api.<span class="keyword">push</span>.model.<span class="keyword">Options</span>;</div><div class="line"><span class="keyword">import</span> cn.jpush.api.<span class="keyword">push</span>.model.Platform;</div><div class="line"><span class="keyword">import</span> cn.jpush.api.<span class="keyword">push</span>.model.PushPayload;</div><div class="line"><span class="keyword">import</span> cn.jpush.api.<span class="keyword">push</span>.model.audience.Audience;</div><div class="line"><span class="keyword">import</span> cn.jpush.api.<span class="keyword">push</span>.model.audience.AudienceTarget;</div><div class="line"><span class="keyword">import</span> cn.jpush.api.<span class="keyword">push</span>.model.notification.IosAlert;</div><div class="line"><span class="keyword">import</span> cn.jpush.api.<span class="keyword">push</span>.model.notification.IosNotification;</div><div class="line"><span class="keyword">import</span> cn.jpush.api.<span class="keyword">push</span>.model.notification.Notification;</div><div class="line"><span class="keyword">import</span> org.slf4j.Logger;</div><div class="line"><span class="keyword">import</span> org.slf4j.LoggerFactory;</div><div class="line"><span class="keyword">import</span> org.testng.annotations.Test;</div><div class="line"></div><div class="line"><span class="comment">/**</span></div><div class="line"> * @author roc</div><div class="line"> * @date 2018/01/09</div><div class="line"> */</div><div class="line"><span class="keyword">public</span> <span class="keyword">class</span> JPushServiceTest {</div><div class="line"></div><div class="line"> <span class="keyword">protected</span> <span class="keyword">static</span> <span class="keyword">final</span> Logger LOG = LoggerFactory.getLogger(JPushServiceTest.<span class="keyword">class</span>);</div><div class="line"></div><div class="line"> <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> String APP_KEY = <span class="string">"b11314807507e2bcfdeebe2e"</span>;</div><div class="line"> <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> String MASTER_SECRET = <span class="string">"2c88a01e073a0fe4fc7b167c"</span>;</div><div class="line"></div><div class="line"> <span class="keyword">protected</span> <span class="keyword">static</span> <span class="keyword">final</span> String GROUP_MASTER_SECRET = <span class="string">"b11314807507e2bcfdeebe2e"</span>;</div><div class="line"> <span class="keyword">protected</span> <span class="keyword">static</span> <span class="keyword">final</span> String GROUP_PUSH_KEY = <span class="string">"2c88a01e073a0fe4fc7b167c"</span>;</div><div class="line"></div><div class="line"> <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">final</span> String ALERT = <span class="string">"JPush Test - alert"</span>;</div><div class="line"> <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">final</span> String MSG_CONTENT = <span class="string">"JPush Test - msgContent"</span>;</div><div class="line"></div><div class="line"> <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">final</span> String REGISTRATION_ID1 = <span class="string">"0900e8d85ef"</span>;</div><div class="line"> <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">final</span> String REGISTRATION_ID2 = <span class="string">"0a04ad7d8b4"</span>;</div><div class="line"> <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">final</span> String REGISTRATION_ID3 = <span class="string">"18071adc030dcba91c0"</span>;</div><div class="line"></div><div class="line"> @Test</div><div class="line"> <span class="keyword">public</span> <span class="keyword">void</span> testNettyClient() {</div><div class="line"></div><div class="line"> ClientConfig clientConfig = ClientConfig.getInstance();</div><div class="line"></div><div class="line"> JPushClient jpushClient = <span class="keyword">new</span> JPushClient(MASTER_SECRET, APP_KEY, <span class="keyword">null</span>, clientConfig);</div><div class="line"> <span class="comment">/*String authCode = ServiceHelper.getBasicAuthorization(APP_KEY, MASTER_SECRET);</span></div><div class="line"> ApacheHttpClient apacheHttpClient = new (authCode, null, clientConfig);</div><div class="line"> jpushClient.getPushClient().setHttpClient(apacheHttpClienApacheHttpClientt);</div><div class="line"> */</div><div class="line"> PushPayload payload = buildTestPayload();</div><div class="line"> <span class="keyword">try</span> {</div><div class="line"> PushResult result = jpushClient.sendPush(payload);</div><div class="line"> <span class="keyword">int</span> status = result.getResponseCode();</div><div class="line"> LOG.info(<span class="string">"Got result - "</span> + result);</div><div class="line"></div><div class="line"> } <span class="keyword">catch</span> (APIConnectionException e) {</div><div class="line"> LOG.error(<span class="string">"Connection error. Should retry later. "</span>, e);</div><div class="line"> LOG.error(<span class="string">"Sendno: "</span> + payload.getSendno());</div><div class="line"></div><div class="line"> } <span class="keyword">catch</span> (APIRequestException e) {</div><div class="line"> LOG.error(<span class="string">"Error response from JPush server. Should review and fix it. "</span>, e);</div><div class="line"> LOG.info(<span class="string">"HTTP Status: "</span> + e.getStatus());</div><div class="line"> LOG.info(<span class="string">"Error Code: "</span> + e.getErrorCode());</div><div class="line"> LOG.info(<span class="string">"Error Message: "</span> + e.getErrorMessage());</div><div class="line"> LOG.info(<span class="string">"Msg ID: "</span> + e.getMsgId());</div><div class="line"> LOG.error(<span class="string">"Sendno: "</span> + payload.getSendno());</div><div class="line"> }</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">public</span> PushPayload buildTestPayload() {</div><div class="line"> String title = <span class="string">"hello world, roc"</span>;</div><div class="line"> String subTitle = <span class="string">"低头前行了这么久,我只是在找一个抬头的机会"</span>;</div><div class="line"> String body = <span class="string">"人这一生,浪费了太多的时间在毫无意义的事情上,担忧、抱怨、埋怨、比较……"</span>;</div><div class="line"></div><div class="line"> IosAlert iosAlert = IosAlert.newBuilder()</div><div class="line"> .setTitleAndBody(title, subTitle, body).build();</div><div class="line"> IosNotification iosNotification = IosNotification.newBuilder()</div><div class="line"> .setAlert(iosAlert).incrBadge(<span class="number">1</span>)</div><div class="line"> .setSound(<span class="string">"happy"</span>).build();</div><div class="line"> Notification notification = Notification.newBuilder().addPlatformNotification(iosNotification).build();</div><div class="line"></div><div class="line"> PushPayload pushPayload = PushPayload</div><div class="line"> .newBuilder()</div><div class="line"> .setPlatform(Platform.android_ios())</div><div class="line"> .setAudience(</div><div class="line"> Audience.newBuilder()</div><div class="line"> .addAudienceTarget(</div><div class="line"> AudienceTarget.alias(<span class="string">"TEST303644"</span>))</div><div class="line"> .build())</div><div class="line"> .setNotification(notification)</div><div class="line"> .setOptions(<span class="keyword">Options</span>.newBuilder().setApnsProduction(<span class="keyword">true</span>).build())</div><div class="line"> .build();</div><div class="line"> <span class="keyword">return</span> pushPayload;</div><div class="line"> }</div><div class="line"></div><div class="line">}</div></pre></td></tr></table></figure>
<ul>
<li>Thread Dump</li>
</ul>
<p>Debug跟踪,发现程序进入if分支,调用close()关闭连接后,主线程阻塞进入wait状态。使用IDEA生成thread dump:<br><img src="https://raw.githubusercontent.com/roc-wong/images/master/%E7%A8%8B%E5%BA%8F%E6%89%A7%E8%A1%8Cif%E5%88%86%E6%94%AF.png" alt="此处输入图片的描述"><br><img src="https://raw.githubusercontent.com/roc-wong/images/master/get%20thread%20dump.png" alt="此处输入图片的描述"></p>
<ul>
<li>日志输出</li>
</ul>
<figure class="highlight less"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line"><span class="selector-tag">2018-01-09</span> <span class="selector-tag">21</span><span class="selector-pseudo">:12</span><span class="selector-pseudo">:19.064</span> <span class="selector-attr">[nioEventLoopGroup-2-1]</span> <span class="selector-tag">DEBUG</span> <span class="selector-tag">io</span><span class="selector-class">.netty</span><span class="selector-class">.handler</span><span class="selector-class">.ssl</span><span class="selector-class">.SslHandler</span> <span class="selector-tag">-</span> <span class="selector-attr">[id: 0x6f019129, L:/10.0.31.70:55848 - R:api.jpush.cn/103.40.232.116:443]</span> <span class="selector-tag">HANDSHAKEN</span>: <span class="selector-tag">TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA</span></div><div class="line"><span class="selector-tag">2018-01-09</span> <span class="selector-tag">21</span><span class="selector-pseudo">:12</span><span class="selector-pseudo">:29.324</span> <span class="selector-attr">[nioEventLoopGroup-2-1]</span> <span class="selector-tag">INFO</span> <span class="selector-tag">c</span><span class="selector-class">.j</span><span class="selector-class">.c</span><span class="selector-class">.connection</span><span class="selector-class">.HttpResponseHandler</span> <span class="selector-tag">-</span> <span class="selector-tag">PooledSlicedByteBuf</span>(<span class="attribute">ridx</span>: <span class="number">0</span>, <span class="attribute">widx</span>: <span class="number">44</span>, <span class="attribute">cap</span>: <span class="number">44</span>/<span class="number">44</span>, <span class="attribute">unwrapped</span>: PooledUnsafeDirectByteBuf(<span class="attribute">ridx</span>: <span class="number">324</span>, <span class="attribute">widx</span>: <span class="number">324</span>, <span class="attribute">cap</span>: <span class="number">373</span>))</div><div class="line"><span class="comment">//此为HttpResponseHandler.java类log输出,与源代码吻合</span></div><div class="line"><span class="selector-tag">2018-01-09</span> <span class="selector-tag">21</span><span class="selector-pseudo">:12</span><span class="selector-pseudo">:49.010</span> <span class="selector-attr">[nioEventLoopGroup-2-1]</span> <span class="selector-tag">INFO</span> <span class="selector-tag">c</span><span class="selector-class">.j</span><span class="selector-class">.c</span><span class="selector-class">.connection</span><span class="selector-class">.HttpResponseHandler</span> <span class="selector-tag">-</span> <span class="selector-tag">closing</span> <span class="selector-tag">connection</span></div></pre></td></tr></table></figure>
<p>主线程处于WAIT状态,Netty异步线程已运行完毕,现场恢复成功。</p>
<h2 id="解决方案"><a href="#解决方案" class="headerlink" title="解决方案"></a>解决方案</h2><ol>
<li>升级极光SDK版本,升级后发现最新版已解决该问题。</li>
<li>增加熔断处理,调用外部服务时,使用Guava SimpleTimeLimiter设置超时熔断。</li>
</ol>
]]></content>
<summary type="html">
极光推送java-sdk-V3.2.15 CountDownLatch使用不当导致线程堵塞
</summary>
<category term="java" scheme="https://roc-wong.github.io/categories/java/"/>
<category term="java后端" scheme="https://roc-wong.github.io/tags/java%E5%90%8E%E7%AB%AF/"/>
</entry>
<entry>
<title>Notepad++-regular-expression</title>
<link href="https://roc-wong.github.io/blog/2017/08/NotePad-regular-expression.html"/>
<id>https://roc-wong.github.io/blog/2017/08/NotePad-regular-expression.html</id>
<published>2017-08-04T12:26:41.000Z</published>
<updated>2018-11-21T02:18:25.567Z</updated>
<content type="html"><![CDATA[<blockquote>
<p>低头前行了这么久,我只是在找一个抬头的机会</p>
</blockquote>
<p>Notepad++ 正则表达式用法归档</p>
<p>注意: 不支持多行表达式 (involving \n, \r, etc).</p>
<a id="more"></a>
<h2 id="基本表达式"><a href="#基本表达式" class="headerlink" title="基本表达式"></a>基本表达式</h2><table>
<thead>
<tr>
<th>符号</th>
<th>解释</th>
</tr>
</thead>
<tbody>
<tr>
<td>.</td>
<td>匹配任意字符,除了新一行(\n)。也就是说 “.”可以匹配 \r ,当文件中同时含有\r and \n时,会引起混乱。要匹配所有的字符,使用\s\S。</td>
</tr>
<tr>
<td>(…)</td>
<td>这个匹配一个标签区域. 这个标签可以被访问,通过语法 \1访问第一个标签, \2 访问第二个, 同理 \3 \4 … \9。 这些标签可以用在当前正则表达式中,或则替search和replace中的换字符串。</td>
</tr>
<tr>
<td>\1, \2, etc</td>
<td>在替换中代表1到9的标签区域(\1 to \9)。例如, 查找字符串 Fred([1-9])XXX 并替换为字符串 Sam\1YYY的方法,当在文件中找到Fred2XXX的字符串时,会替换为Sam2YYY。注意: 只有9个区域能使用,所以我们在使用时很安全,像\10\2 表示区域1和文本”0”以及区域2。</td>
</tr>
<tr>
<td>[…]</td>
<td>表示一个字符集合, 例如 [abc]表示任意字符 a, b or c.我们也可以使用范围例如[a-z] 表示所以的小写字母。</td>
</tr>
<tr>
<td>[^…]</td>
<td>表示字符补集. 例如, [^A-Za-z] 表示任意字符除了字母表。</td>
</tr>
<tr>
<td>^</td>
<td>匹配一行的开始(除非在集合中, 如下).</td>
</tr>
<tr>
<td>$</td>
<td>匹配行尾.</td>
</tr>
<tr>
<td>*</td>
<td>匹配0或多次, 例如 Sa*m 匹配 Sm, Sam, Saam, Saaam 等等.</td>
</tr>
<tr>
<td>+</td>
<td>匹配1次或多次,例如 Sa+m 匹配 Sam, Saam, Saaam 等等.</td>
</tr>
<tr>
<td>?</td>
<td>匹配0或者1次, 例如 Sa?m 匹配 Sm, Sam.</td>
</tr>
<tr>
<td>{n}</td>
<td>匹配确定的 n 次.例如, ‘Sa{2}m’ 匹配 Saam.</td>
</tr>
<tr>
<td>{m,n}</td>
<td>匹配至少m次,至多n次(如果n缺失,则任意次数).例如, ‘Sa{2,3}m’ 匹配 Saam or Saaam. ‘Sa{2,}m’ 与 ‘Saa+m’相同</td>
</tr>
<tr>
<td>*?, +?, ??, {n,m}?</td>
<td>非贪心匹配,匹配第一个有效的匹配,通常 ‘<.>’ 会匹配整个 ‘content’字符串 –但 ‘<.?>’ 只匹配 ” .这个标记一个标签区域,这些区域可以用语法\1 \2 等访问多个对应1-9区域。</td>
</tr>
</tbody>
</table>
<h2 id="标记和分组"><a href="#标记和分组" class="headerlink" title="标记和分组"></a>标记和分组</h2><table>
<thead>
<tr>
<th>符号</th>
<th>解释</th>
</tr>
</thead>
<tbody>
<tr>
<td>(…)</td>
<td>一组捕获. 可以通过\1 访问第一个组, \2 访问第二个.</td>
</tr>
<tr>
<td>(?:…)</td>
<td>非捕获组.</td>
</tr>
<tr>
<td>(?=…)</td>
<td>非捕获组 – 向前断言. 例如’(.*)(?=ton)’ 表达式,当 遇到’Appleton’字符串时,会匹配为’Apple’.</td>
</tr>
<tr>
<td>(?<=…)</td>
<td>非捕获组 – 向后断言. 例如’(?<=sir) (.*)’ 表示式,当遇到’sir William’ 字符串时,匹配为’ William’.</td>
</tr>
<tr>
<td>(?!…)</td>
<td>非捕获组 – 消极的向前断言. 例如’.(?!e)’ 表达式,当遇到’Apple’时,会找到每个字母除了 ‘l’,因为它紧跟着 ‘e’.</td>
</tr>
<tr>
<td>(?</td>
<td>非捕获组 – 消极向后断言. 例如 ‘(?</td>
</tr>
<tr>
<td>(?P…)</td>
<td>命名所捕获的组. 提交一个名称到组中供后续使用,例如’(?PA[^\s]+)\s(?P=first)’ 会找到 ‘Apple Apple’. 类似的 ‘(A[^\s]+)\s\1’ 使用组名而不是数字.</td>
</tr>
<tr>
<td>(?=name)</td>
<td>匹配名为name的组. (?P…).</td>
</tr>
<tr>
<td>(?#comment)</td>
<td>批注 –括号中的内容在匹配时将被忽略。</td>
</tr>
</tbody>
</table>
<h2 id="特殊符号"><a href="#特殊符号" class="headerlink" title="特殊符号"></a>特殊符号</h2><table>
<thead>
<tr>
<th>符号</th>
<th>解释</th>
</tr>
</thead>
<tbody>
<tr>
<td>\s</td>
<td>匹配空格. 注意,会匹配标记的末尾. 使用 [[:blank:]] 来避免匹配新一行。</td>
</tr>
<tr>
<td>\S</td>
<td>匹配非空白</td>
</tr>
<tr>
<td>\w</td>
<td>匹配单词字符</td>
</tr>
<tr>
<td>\W</td>
<td>匹配非单词字符</td>
</tr>
<tr>
<td>\d</td>
<td>匹配数字字符</td>
</tr>
<tr>
<td>\D</td>
<td>匹配非数字字符</td>
</tr>
<tr>
<td>\b</td>
<td>匹配单词边界. ‘\bW\w+’ 找到W开头的单词</td>
</tr>
<tr>
<td>\B</td>
<td>匹配非单词边界. ‘\Be\B+’ – 找到位于单子中间的字母’e’</td>
</tr>
<tr>
<td>\<</td>
<td>This matches the start of a word using Scintilla’s definitions of words.</td>
</tr>
<tr>
<td>></td>
<td>This matches the end of a word using Scintilla’s definition of words.</td>
</tr>
<tr>
<td>\x</td>
<td>运行用x来表达可能具有其他意思的字符。例如, [ 用来插入到文本中作为[ 而不是作为字符集的开始.</td>
</tr>
</tbody>
</table>
<h2 id="字符类"><a href="#字符类" class="headerlink" title="字符类"></a>字符类</h2><table>
<thead>
<tr>
<th>符号</th>
<th>解释</th>
</tr>
</thead>
<tbody>
<tr>
<td>[[:alpha:]]</td>
<td>匹配字母字符: [A-Za-z]</td>
</tr>
<tr>
<td>[[:digit:]]</td>
<td>匹配数字字符: [0-9]</td>
</tr>
<tr>
<td>[[:xdigit:]]</td>
<td>匹配16进制字符: [0-9A-Fa-f]</td>
</tr>
<tr>
<td>[[:alnum:]]</td>
<td>匹配字母数字字符: [0-9A-Za-z]</td>
</tr>
<tr>
<td>[[:lower:]]</td>
<td>匹配小写字符: [a-z]</td>
</tr>
<tr>
<td>[[:upper:]]</td>
<td>匹配大写字符: [A-Z]</td>
</tr>
<tr>
<td>[[:blank:]]</td>
<td>匹配空白 (空格 or tab):[ \t]</td>
</tr>
<tr>
<td>[[:space:]]</td>
<td>匹配空白字符:[ \t\r\n\v\f]</td>
</tr>
<tr>
<td>[[:punct:]]</td>
<td>匹配标点字符: [-!”#$%&’()*+,./:;<=>?@[]_`{</td>
</tr>
<tr>
<td>[[:graph:]]</td>
<td>匹配图形字符: [\x21-\x7E]</td>
</tr>
<tr>
<td>[[:print:]]</td>
<td>匹配可打印的字符 (graphical characters and spaces)</td>
</tr>
<tr>
<td>[[:cntrl:]]</td>
<td>匹配控制字符</td>
</tr>
</tbody>
</table>
<h2 id="替换操作"><a href="#替换操作" class="headerlink" title="替换操作"></a>替换操作</h2><p>使用正则表达式的标记,通过()来包围想要用的字符,然后用\1 来替换字符串,第一个匹配文本。</p>
<p>例如:</p>
<p>Text body Search string Replace string Result<br>Hi my name is Fred my name is (.+) my name is not \1 Hi my name is not Fred<br>The quick brown fox jumped over the fat lazy dog brown (.+) jumped over the (.+) brown \2 jumped over the \1 The quick brown fat jumped over the fox lazy dog</p>
<h2 id="限制"><a href="#限制" class="headerlink" title="限制"></a>限制</h2><p>Support for regular expressions in PN2 is currently limited, the supported patterns and syntax are a very small subset of the powerful expressions supported by perl. 最大的限制是正则表达式只能匹配单行,不能用多行匹配表达。可以用Backslash Expressions代替.</p>
<p>准备计划是使用PCRE库 library (used elsewhere in PN2) 来支持文档搜索.</p>
<p>原文:<a href="http://www.pnotepad.org/docs/search/regular_expressions/" target="_blank" rel="external">http://www.pnotepad.org/docs/search/regular_expressions/</a></p>
<h2 id="应用举例"><a href="#应用举例" class="headerlink" title="应用举例"></a>应用举例</h2><h3 id="删除空白行的方法"><a href="#删除空白行的方法" class="headerlink" title="删除空白行的方法"></a>删除空白行的方法</h3><p>选择替换,把查找模式设置为正则表达式,在查找框中输入 ^\s+ ,替换框留空,点“全部替换”,即可(先全选)。</p>
<h3 id="删除所有行s字符开始后面的所有字符"><a href="#删除所有行s字符开始后面的所有字符" class="headerlink" title="删除所有行s字符开始后面的所有字符"></a>删除所有行s字符开始后面的所有字符</h3><p>选择替换,把查找模式设置为正则表达式,在查找框中输入 ^([^:]<em>):.</em>$,替换框填写$1,点“全部替换”,即可(先全选)。</p>
]]></content>
<summary type="html">
Notepad++ regular expression 正则表达式
</summary>
<category term="IDE" scheme="https://roc-wong.github.io/categories/IDE/"/>
<category term="Notepad++" scheme="https://roc-wong.github.io/tags/Notepad/"/>
</entry>
<entry>
<title>svn-sqliteS10-disk-IO-error</title>
<link href="https://roc-wong.github.io/blog/2017/08/svn-sqliteS10-disk-IO-error.html"/>
<id>https://roc-wong.github.io/blog/2017/08/svn-sqliteS10-disk-IO-error.html</id>
<published>2017-08-04T12:23:50.000Z</published>
<updated>2018-11-21T02:18:25.531Z</updated>
<content type="html"><![CDATA[<blockquote>
<p>低头前行,莫问前程。</p>
</blockquote>
<p>在使用svn提交项目时,遇到报错:svn: E200030: sqlite[S10]: disk I/O error</p>
<a id="more"></a>
<p>在使用svn提交项目时,遇到报错:</p>
<figure class="highlight groovy"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div></pre></td><td class="code"><pre><div class="line"><span class="string">svn:</span> <span class="string">E155004:</span> Run <span class="string">'svn cleanup'</span> to remove locks (type <span class="string">'svn help cleanup'</span> <span class="keyword">for</span> details)</div><div class="line"><span class="string">svn:</span> <span class="string">E155004:</span> Failed to lock working copy <span class="string">'F:\workspace-new\idea-workspace\hbec-app-stock-project'</span>.</div><div class="line"><span class="string">svn:</span> <span class="string">E200030:</span> sqlite[S10]: disk I/O error</div><div class="line"><span class="string">svn:</span> <span class="string">E200042:</span> Additional <span class="string">errors:</span></div><div class="line"><span class="string">svn:</span> <span class="string">E200030:</span> sqlite[S10]: disk I/O error</div><div class="line"><span class="string">svn:</span> <span class="string">E200030:</span> sqlite[S1]: no such <span class="string">savepoint:</span> svn</div><div class="line"><span class="string">svn:</span> <span class="string">E200030:</span> sqlite[S1]: no such <span class="string">savepoint:</span> svn</div><div class="line"><span class="string">svn:</span> <span class="string">E200030:</span> sqlite[S1]: no such <span class="string">savepoint:</span> svn</div><div class="line"><span class="string">svn:</span> <span class="string">E200030:</span> sqlite[S1]: no such <span class="string">savepoint:</span> svn</div></pre></td></tr></table></figure>
<p>此时可通过sqlite3工具来修复,具体步骤为:</p>
<ul>
<li>下载sqlite3工具,下载地址为:<a href="http://www.sqlite.org/download.html" target="_blank" rel="external">http://www.sqlite.org/download.html</a></li>
<li>将sqlite3.exe文件解压缩到.svn目录的同级目录</li>
<li>打开命令行工具,切换到.svn的同级目录<br> 执行命令:<br> sqlite3.exe .svn/wc.db “reindex nodes”<br> sqlite3.exe .svn/wc.db “reindex pristine”</li>
</ul>
]]></content>
<summary type="html">
svn E200030 sqlite[S10] disk I/O error
</summary>
<category term="SVN" scheme="https://roc-wong.github.io/categories/SVN/"/>
<category term="SVN" scheme="https://roc-wong.github.io/tags/SVN/"/>
</entry>
<entry>
<title>deadlock-found-when-trying-to-get-lock</title>
<link href="https://roc-wong.github.io/blog/2017/07/deadlock-found-when-trying-to-get-lock.html"/>
<id>https://roc-wong.github.io/blog/2017/07/deadlock-found-when-trying-to-get-lock.html</id>
<published>2017-07-24T04:33:22.000Z</published>
<updated>2018-11-21T02:18:25.572Z</updated>
<content type="html"><![CDATA[<p>mysql锁机制分为表级锁和行级锁:</p>
<p>共享锁又称为读锁,简称S锁,顾名思义,共享锁就是多个事务对于同一数据可以共享一把锁,都能访问到数据,但是只能读不能修改。</p>
<p>排他锁又称为写锁,简称X锁,顾名思义,排他锁就是不能与其他所并存,如一个事务获取了一个数据行的排他锁,其他事务就不能再获取该行的其他锁,包括共享锁和排他锁,但是获取排他锁的事务是可以对数据就行读取和修改。</p>
<a id="more"></a>
<p>对于共享锁大家可能很好理解,就是多个事务只能读数据不能改数据,对于排他锁大家的理解可能就有些差别,我当初就犯了一个错误,以为排他锁锁住一行数据后,其他事务就不能读取和修改该行数据,其实不是这样的。排他锁指的是一个事务在一行数据加上排他锁后,其他事务不能再在其上加其他的锁。mysql InnoDB引擎默认的修改数据语句,update,delete,insert都会自动给涉及到的数据加上排他锁,select语句默认不会加任何锁类型,如果加排他锁可以使用select …for update语句,加共享锁可以使用select … lock in share mode语句。所以加过排他锁的数据行在其他事务种是不能修改数据的,也不能通过for update和lock in share mode锁的方式查询数据,但可以直接通过select …from…查询数据,因为普通查询没有任何锁机制。</p>
<p><img src="https://raw.githubusercontent.com/roc-wong/images/master/mysql-lock.png" alt="死锁"></p>
<h2 id="案发现场"><a href="#案发现场" class="headerlink" title="案发现场"></a>案发现场</h2><p>API网关在30ms内收到6次相同请求,错误日志:</p>
<figure class="highlight stylus"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div></pre></td><td class="code"><pre><div class="line">Jul <span class="number">23</span> <span class="number">17</span>:<span class="number">12</span>:<span class="number">50</span> iZ23qpg65e4Z api_qianqian1 <span class="number">2017</span>-<span class="number">07</span>-<span class="number">23</span> <span class="number">17</span>:<span class="number">12</span>:<span class="number">50.754</span> [http-apr-<span class="number">8080</span>-exec-<span class="number">1379</span>] INFO h<span class="selector-class">.a</span><span class="selector-class">.a</span><span class="selector-class">.f</span><span class="selector-class">.AppPlatformRateLimiterFilter</span> - parameter=_appCrypt_=VDzT76Hdrp9QAO4lSbQuJeIaKnQ8VZnqljK+YmN2W1tyBSv1JqIhTrDHrBlWM9K8yg3kcLOUmENr1OUc+<span class="number">6</span>xWSL13Z2jaBhCJDrMYWad/H971ilDd4eQMrakZP84dCbXC&_t_=HBStockWarningIos_3.<span class="number">6.4</span>&ticket=<span class="number">7</span>.BdzpPOeP2_7JV6IYArPBIOC36NO2PoCMhVPHiISIEM_tAo7-unTlp_baBhZ79TZskD-HBIBmSnk-<span class="number">7</span>y_tv24wD2IiSgTHlj7x5DTHEV7CacwVdw9jmTCuVdePd4mUaM11k5XGRSsPzqzQmomKMu7aGm8R48Nq-ECE7WpSNtQmExU&</div><div class="line">Jul <span class="number">23</span> <span class="number">17</span>:<span class="number">12</span>:<span class="number">50</span> iZ23qpg65e4Z api_qianqian1 <span class="number">2017</span>-<span class="number">07</span>-<span class="number">23</span> <span class="number">17</span>:<span class="number">12</span>:<span class="number">50.756</span> [http-apr-<span class="number">8080</span>-exec-<span class="number">1379</span>] INFO sky<span class="selector-class">.app</span><span class="selector-class">.api</span><span class="selector-class">.filter</span><span class="selector-class">.RateLimiter</span> - userId:<span class="number">3245964</span>, 在 <span class="number">5s</span> 内第<span class="number">1</span>次 执行操作 http:<span class="comment">//api.*.com/followStockService.follow, 通过流速控制器, 阀值(5s最高40次)</span></div><div class="line"></div><div class="line"></div><div class="line">Jul <span class="number">23</span> <span class="number">17</span>:<span class="number">12</span>:<span class="number">50</span> iZ23qpg65e4Z api_qianqian1 <span class="number">2017</span>-<span class="number">07</span>-<span class="number">23</span> <span class="number">17</span>:<span class="number">12</span>:<span class="number">50.756</span> [http-apr-<span class="number">8080</span>-exec-<span class="number">1319</span>] INFO sky<span class="selector-class">.app</span><span class="selector-class">.api</span><span class="selector-class">.filter</span><span class="selector-class">.RateLimiter</span> - userId:<span class="number">3245964</span>, 在 <span class="number">5s</span> 内第<span class="number">2</span>次 执行操作 http:<span class="comment">//api.*.com/followStockService.follow, 通过流速控制器, 阀值(5s最高40次)</span></div><div class="line">Jul <span class="number">23</span> <span class="number">17</span>:<span class="number">12</span>:<span class="number">50</span> iZ23qpg65e4Z api_qianqian1 <span class="number">2017</span>-<span class="number">07</span>-<span class="number">23</span> <span class="number">17</span>:<span class="number">12</span>:<span class="number">50.757</span> [http-apr-<span class="number">8080</span>-exec-<span class="number">1319</span>] DEBUG h<span class="selector-class">.p</span><span class="selector-class">.commons</span><span class="selector-class">.web</span><span class="selector-class">.HbecApiHandleAdapter</span> - param-sha1 : null, appCrypt<<span class="number">1</span>> : VDzT76Hdrp9QAO4lSbQuJeIaKnQ8VZnqljK+YmN2W1tyBSv1JqIhTrDHrBlWM9K8yg3kcLOUmENr1OUc+<span class="number">6</span>xWSL13Z2jaBhCJDrMYWad/H971ilDd4eQMrakZP84dCbXC, dataKey=l7g19q1<span class="variable">$g</span>#*o9v-<span class="number">1</span></div><div class="line"></div><div class="line"></div><div class="line">Jul <span class="number">23</span> <span class="number">17</span>:<span class="number">12</span>:<span class="number">50</span> iZ23qpg65e4Z api_qianqian1 <span class="number">2017</span>-<span class="number">07</span>-<span class="number">23</span> <span class="number">17</span>:<span class="number">12</span>:<span class="number">50.755</span> [http-apr-<span class="number">8080</span>-exec-<span class="number">1414</span>] INFO h<span class="selector-class">.a</span><span class="selector-class">.a</span><span class="selector-class">.f</span><span class="selector-class">.AppPlatformRateLimiterFilter</span> - http request=http:<span class="comment">//api.*.com/followStockService.follow</span></div><div class="line">Jul <span class="number">23</span> <span class="number">17</span>:<span class="number">12</span>:<span class="number">50</span> iZ23qpg65e4Z api_qianqian1 <span class="number">2017</span>-<span class="number">07</span>-<span class="number">23</span> <span class="number">17</span>:<span class="number">12</span>:<span class="number">50.755</span> [http-apr-<span class="number">8080</span>-exec-<span class="number">1414</span>] INFO h<span class="selector-class">.a</span><span class="selector-class">.a</span><span class="selector-class">.f</span><span class="selector-class">.AppPlatformRateLimiterFilter</span> - </div><div class="line">Jul <span class="number">23</span> <span class="number">17</span>:<span class="number">12</span>:<span class="number">50</span> iZ23qpg65e4Z api_qianqian1 <span class="number">2017</span>-<span class="number">07</span>-<span class="number">23</span> <span class="number">17</span>:<span class="number">12</span>:<span class="number">50.757</span> [http-apr-<span class="number">8080</span>-exec-<span class="number">1414</span>] INFO sky<span class="selector-class">.app</span><span class="selector-class">.api</span><span class="selector-class">.filter</span><span class="selector-class">.RateLimiter</span> - userId:<span class="number">3245964</span>, 在 <span class="number">5s</span> 内第<span class="number">3</span>次 执行操作 http:<span class="comment">//api.*.com/followStockService.follow, 通过流速控制器, 阀值(5s最高40次)</span></div><div class="line"></div><div class="line">Jul <span class="number">23</span> <span class="number">17</span>:<span class="number">12</span>:<span class="number">50</span> iZ23qpg65e4Z api_qianqian1 <span class="number">2017</span>-<span class="number">07</span>-<span class="number">23</span> <span class="number">17</span>:<span class="number">12</span>:<span class="number">50.756</span> [http-apr-<span class="number">8080</span>-exec-<span class="number">1457</span>] INFO h<span class="selector-class">.a</span><span class="selector-class">.a</span><span class="selector-class">.f</span><span class="selector-class">.AppPlatformRateLimiterFilter</span> - http request=http:<span class="comment">//api.*.com/followStockService.follow</span></div><div class="line">Jul <span class="number">23</span> <span class="number">17</span>:<span class="number">12</span>:<span class="number">50</span> iZ23qpg65e4Z api_qianqian1 <span class="number">2017</span>-<span class="number">07</span>-<span class="number">23</span> <span class="number">17</span>:<span class="number">12</span>:<span class="number">50.756</span> [http-apr-<span class="number">8080</span>-exec-<span class="number">1457</span>] INFO h<span class="selector-class">.a</span><span class="selector-class">.a</span><span class="selector-class">.f</span><span class="selector-class">.AppPlatformRateLimiterFilter</span> - </div><div class="line">Jul <span class="number">23</span> <span class="number">17</span>:<span class="number">12</span>:<span class="number">50</span> iZ23qpg65e4Z api_qianqian1 <span class="number">2017</span>-<span class="number">07</span>-<span class="number">23</span> <span class="number">17</span>:<span class="number">12</span>:<span class="number">50.757</span> [http-apr-<span class="number">8080</span>-exec-<span class="number">1457</span>] INFO sky<span class="selector-class">.app</span><span class="selector-class">.api</span><span class="selector-class">.filter</span><span class="selector-class">.RateLimiter</span> - userId:<span class="number">3245964</span>, 在 <span class="number">5s</span> 内第<span class="number">4</span>次 执行操作 http:<span class="comment">//api.*.com/followStockService.follow, 通过流速控制器, 阀值(5s最高40次)</span></div><div class="line"></div><div class="line">Jul <span class="number">23</span> <span class="number">17</span>:<span class="number">12</span>:<span class="number">50</span> iZ23qpg65e4Z api_qianqian1 <span class="number">2017</span>-<span class="number">07</span>-<span class="number">23</span> <span class="number">17</span>:<span class="number">12</span>:<span class="number">50.757</span> [http-apr-<span class="number">8080</span>-exec-<span class="number">1334</span>] INFO h<span class="selector-class">.a</span><span class="selector-class">.a</span><span class="selector-class">.f</span><span class="selector-class">.AppPlatformRateLimiterFilter</span> - http request=http:<span class="comment">//api.*.com/followStockService.follow</span></div><div class="line">Jul <span class="number">23</span> <span class="number">17</span>:<span class="number">12</span>:<span class="number">50</span> iZ23qpg65e4Z api_qianqian1 <span class="number">2017</span>-<span class="number">07</span>-<span class="number">23</span> <span class="number">17</span>:<span class="number">12</span>:<span class="number">50.757</span> [http-apr-<span class="number">8080</span>-exec-<span class="number">1334</span>] INFO h<span class="selector-class">.a</span><span class="selector-class">.a</span><span class="selector-class">.f</span><span class="selector-class">.AppPlatformRateLimiterFilter</span> - parameter=_appCrypt_=VDzT76Hdrp9QAO4lSbQuJeIaKnQ8VZnqljK+YmN2W1tyBSv1JqIhTrDHrBlWM9K8yg3kcLOUmENr1OUc+<span class="number">6</span>xWSL13Z2jaBhCJDrMYWad/H971ilDd4eQMrakZP84dCbXC&_t_=HBStockWarningIos_3.<span class="number">6.4</span>&ticket=<span class="number">7</span>.BdzpPOeP2_7JV6IYArPBIOC36NO2PoCMhVPHiISIEM_tAo7-unTlp_baBhZ79TZskD-HBIBmSnk-<span class="number">7</span>y_tv24wD2IiSgTHlj7x5DTHEV7CacwVdw9jmTCuVdePd4mUaM11k5XGRSsPzqzQmomKMu7aGm8R48Nq-ECE7WpSNtQmExU&</div><div class="line">Jul <span class="number">23</span> <span class="number">17</span>:<span class="number">12</span>:<span class="number">50</span> iZ23qpg65e4Z api_qianqian1 <span class="number">2017</span>-<span class="number">07</span>-<span class="number">23</span> <span class="number">17</span>:<span class="number">12</span>:<span class="number">50.759</span> [http-apr-<span class="number">8080</span>-exec-<span class="number">1334</span>] INFO sky<span class="selector-class">.app</span><span class="selector-class">.api</span><span class="selector-class">.filter</span><span class="selector-class">.RateLimiter</span> - userId:<span class="number">3245964</span>, 在 <span class="number">5s</span> 内第<span class="number">5</span>次 执行操作 http:<span class="comment">//api.*.com/followStockService.follow, 通过流速控制器, 阀值(5s最高40次)</span></div></pre></td></tr></table></figure>
<p>业务日志</p>
<p>追踪到业务节点后,发现mysql出现死锁问题:Deadlock found when trying to get lock; try restarting transaction</p>
<figure class="highlight mipsasm"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div><div class="line">41</div><div class="line">42</div><div class="line">43</div><div class="line">44</div><div class="line">45</div><div class="line">46</div><div class="line">47</div><div class="line">48</div><div class="line">49</div><div class="line">50</div><div class="line">51</div><div class="line">52</div><div class="line">53</div><div class="line">54</div><div class="line">55</div><div class="line">56</div><div class="line">57</div><div class="line">58</div><div class="line">59</div><div class="line">60</div><div class="line">61</div><div class="line">62</div><div class="line">63</div><div class="line">64</div><div class="line">65</div><div class="line">66</div><div class="line">67</div><div class="line">68</div><div class="line">69</div><div class="line">70</div><div class="line">71</div><div class="line">72</div><div class="line">73</div><div class="line">74</div><div class="line">75</div><div class="line">76</div><div class="line">77</div><div class="line">78</div><div class="line">79</div><div class="line">80</div><div class="line">81</div><div class="line">82</div><div class="line">83</div><div class="line">84</div><div class="line">85</div><div class="line">86</div><div class="line">87</div><div class="line">88</div><div class="line">89</div><div class="line">90</div><div class="line">91</div><div class="line">92</div><div class="line">93</div><div class="line">94</div><div class="line">95</div><div class="line">96</div><div class="line">97</div><div class="line">98</div><div class="line">99</div><div class="line">100</div><div class="line">101</div><div class="line">102</div><div class="line">103</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">Jul </span><span class="number">23</span> <span class="number">17</span>:<span class="number">12</span>:<span class="number">50</span> iZ2360o6lpyZ warn1 <span class="number">17</span>-07-23 <span class="number">17</span>:<span class="number">12</span>:<span class="number">50</span>.<span class="number">779</span> ERROR[DubboServerHandler-10.<span class="number">253</span>.<span class="number">17</span>.<span class="number">105</span>:<span class="number">20880</span>-thread-193 DbService.execute:<span class="number">1247</span>] {}</div><div class="line"><span class="keyword">Jul </span><span class="number">23</span> <span class="number">17</span>:<span class="number">12</span>:<span class="number">50</span> iZ2360o6lpyZ warn1 sky.platform.commons.exceptions.HbecDbServiceException: service=db,message=sky.platform.commons.exceptions.HbecDbServiceException: service=db,message=</div><div class="line"><span class="keyword">Jul </span><span class="number">23</span> <span class="number">17</span>:<span class="number">12</span>:<span class="number">50</span> iZ2360o6lpyZ warn1 <span class="comment">### Error updating database. Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException: Deadlock found when trying to get lock; try restarting transaction</span></div><div class="line"><span class="keyword">Jul </span><span class="number">23</span> <span class="number">17</span>:<span class="number">12</span>:<span class="number">50</span> iZ2360o6lpyZ warn1 <span class="comment">### The error may involve WarnFollowMapper.follow-Inline</span></div><div class="line"><span class="keyword">Jul </span><span class="number">23</span> <span class="number">17</span>:<span class="number">12</span>:<span class="number">50</span> iZ2360o6lpyZ warn1 <span class="comment">### The error occurred while setting parameters</span></div><div class="line"><span class="keyword">Jul </span><span class="number">23</span> <span class="number">17</span>:<span class="number">12</span>:<span class="number">50</span> iZ2360o6lpyZ warn1 <span class="comment">### SQL: insert into test_follow (user_id, security_type, stock_code, exchange, stock_name, sub_fund_type, sort) values (?, ?, ?, ?,?, ?, (select max(IFNULL(t1.sort,0)) + 1 from test_FOLLOW t1 where t1.user_id = ?) ) on duplicate key update sort= (select max(IFNULL(t2.sort,0)) + 1 from test_follow t2 where t2.user_id= ?)</span></div><div class="line"><span class="keyword">Jul </span><span class="number">23</span> <span class="number">17</span>:<span class="number">12</span>:<span class="number">50</span> iZ2360o6lpyZ warn1 <span class="comment">### Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException: Deadlock found when trying to get lock; try restarting transaction</span></div><div class="line"><span class="keyword">Jul </span><span class="number">23</span> <span class="number">17</span>:<span class="number">12</span>:<span class="number">50</span> iZ2360o6lpyZ warn1 <span class="built_in">at</span> sky.platform.runtime.DbServiceInterceptor$<span class="number">1</span>.execute(DbServiceInterceptor.<span class="keyword">java:39) </span>~[hbec-platform-commons-0.<span class="number">0</span>.<span class="number">32</span>-SNAPSHOT.<span class="keyword">jar:na]</span></div><div class="line"><span class="keyword">Jul </span><span class="number">23</span> <span class="number">17</span>:<span class="number">12</span>:<span class="number">50</span> iZ2360o6lpyZ warn1 <span class="built_in">at</span> sky.platform.runtime.DbService.execute(DbService.<span class="keyword">java:1242) </span>~[hbec-platform-commons-0.<span class="number">0</span>.<span class="number">32</span>-SNAPSHOT.<span class="keyword">jar:na]</span></div><div class="line"><span class="keyword">Jul </span><span class="number">23</span> <span class="number">17</span>:<span class="number">12</span>:<span class="number">50</span> iZ2360o6lpyZ warn1 <span class="built_in">at</span> sky.platform.runtime.DbServiceInterceptor.intercept(DbServiceInterceptor.<span class="keyword">java:33) </span>[hbec-platform-commons-0.<span class="number">0</span>.<span class="number">32</span>-SNAPSHOT.<span class="keyword">jar:na]</span></div><div class="line"><span class="keyword">Jul </span><span class="number">23</span> <span class="number">17</span>:<span class="number">12</span>:<span class="number">50</span> iZ2360o6lpyZ warn1 <span class="built_in">at</span> sky.app.stock.follow.service.impl.WarnFollowServiceImpl$$EnhancerByCGLIB$$<span class="number">41</span>e28e09.follow(<generated>) [spring-core-4.<span class="number">0</span>.<span class="number">2</span>.RELEASE.<span class="keyword">jar:na]</span></div><div class="line"><span class="keyword">Jul </span><span class="number">23</span> <span class="number">17</span>:<span class="number">12</span>:<span class="number">50</span> iZ2360o6lpyZ warn1 <span class="built_in">at</span> sky.app.stock.follow.controller.impl.FollowStockControllerImpl.follow(FollowStockControllerImpl.<span class="keyword">java:304) </span>[hbec-app-stock-follow-1.<span class="number">0</span>.<span class="number">2</span>-SNAPSHOT.<span class="keyword">jar:na]</span></div><div class="line"><span class="keyword">Jul </span><span class="number">23</span> <span class="number">17</span>:<span class="number">12</span>:<span class="number">50</span> iZ2360o6lpyZ warn1 <span class="built_in">at</span> com.alibaba.dubbo.common.<span class="keyword">bytecode.Wrapper94.invokeMethod(Wrapper94.java) </span>[na:<span class="number">2</span>.<span class="number">5</span>.<span class="number">3</span>]</div><div class="line"><span class="keyword">Jul </span><span class="number">23</span> <span class="number">17</span>:<span class="number">12</span>:<span class="number">50</span> iZ2360o6lpyZ warn1 <span class="built_in">at</span> com.alibaba.dubbo.rpc.proxy.<span class="keyword">javassist.JavassistProxyFactory$1.doInvoke(JavassistProxyFactory.java:46) </span>[dubbo-2.<span class="number">5</span>.<span class="number">3</span>.<span class="keyword">jar:2.5.3]</span></div><div class="line"><span class="keyword">Jul </span><span class="number">23</span> <span class="number">17</span>:<span class="number">12</span>:<span class="number">50</span> iZ2360o6lpyZ warn1 <span class="built_in">at</span> com.alibaba.dubbo.rpc.proxy.AbstractProxyInvoker.invoke(AbstractProxyInvoker.<span class="keyword">java:72) </span>[dubbo-2.<span class="number">5</span>.<span class="number">3</span>.<span class="keyword">jar:2.5.3]</span></div><div class="line"><span class="keyword">Jul </span><span class="number">23</span> <span class="number">17</span>:<span class="number">12</span>:<span class="number">50</span> iZ2360o6lpyZ warn1 <span class="built_in">at</span> com.alibaba.dubbo.rpc.protocol.InvokerWrapper.invoke(InvokerWrapper.<span class="keyword">java:53) </span>[dubbo-2.<span class="number">5</span>.<span class="number">3</span>.<span class="keyword">jar:2.5.3]</span></div><div class="line"><span class="keyword">Jul </span><span class="number">23</span> <span class="number">17</span>:<span class="number">12</span>:<span class="number">50</span> iZ2360o6lpyZ warn1 <span class="built_in">at</span> com.alibaba.dubbo.rpc.filter.ExceptionFilter.invoke(ExceptionFilter.<span class="keyword">java:64) </span>[dubbo-2.<span class="number">5</span>.<span class="number">3</span>.<span class="keyword">jar:2.5.3]</span></div><div class="line"><span class="keyword">Jul </span><span class="number">23</span> <span class="number">17</span>:<span class="number">12</span>:<span class="number">50</span> iZ2360o6lpyZ warn1 <span class="built_in">at</span> com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper$<span class="number">1</span>.invoke(ProtocolFilterWrapper.<span class="keyword">java:91) </span>[dubbo-2.<span class="number">5</span>.<span class="number">3</span>.<span class="keyword">jar:2.5.3]</span></div><div class="line"><span class="keyword">Jul </span><span class="number">23</span> <span class="number">17</span>:<span class="number">12</span>:<span class="number">50</span> iZ2360o6lpyZ warn1 <span class="built_in">at</span> com.alibaba.dubbo.rpc.filter.TimeoutFilter.invoke(TimeoutFilter.<span class="keyword">java:42) </span>[dubbo-2.<span class="number">5</span>.<span class="number">3</span>.<span class="keyword">jar:2.5.3]</span></div><div class="line"><span class="keyword">Jul </span><span class="number">23</span> <span class="number">17</span>:<span class="number">12</span>:<span class="number">50</span> iZ2360o6lpyZ warn1 <span class="built_in">at</span> com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper$<span class="number">1</span>.invoke(ProtocolFilterWrapper.<span class="keyword">java:91) </span>[dubbo-2.<span class="number">5</span>.<span class="number">3</span>.<span class="keyword">jar:2.5.3]</span></div><div class="line"><span class="keyword">Jul </span><span class="number">23</span> <span class="number">17</span>:<span class="number">12</span>:<span class="number">50</span> iZ2360o6lpyZ warn1 <span class="built_in">at</span> com.alibaba.dubbo.monitor.support.MonitorFilter.invoke(MonitorFilter.<span class="keyword">java:75) </span>[dubbo-2.<span class="number">5</span>.<span class="number">3</span>.<span class="keyword">jar:2.5.3]</span></div><div class="line"><span class="keyword">Jul </span><span class="number">23</span> <span class="number">17</span>:<span class="number">12</span>:<span class="number">50</span> iZ2360o6lpyZ warn1 <span class="built_in">at</span> com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper$<span class="number">1</span>.invoke(ProtocolFilterWrapper.<span class="keyword">java:91) </span>[dubbo-2.<span class="number">5</span>.<span class="number">3</span>.<span class="keyword">jar:2.5.3]</span></div><div class="line"><span class="keyword">Jul </span><span class="number">23</span> <span class="number">17</span>:<span class="number">12</span>:<span class="number">50</span> iZ2360o6lpyZ warn1 <span class="built_in">at</span> com.alibaba.dubbo.rpc.protocol.dubbo.filter.TraceFilter.invoke(TraceFilter.<span class="keyword">java:78) </span>[dubbo-2.<span class="number">5</span>.<span class="number">3</span>.<span class="keyword">jar:2.5.3]</span></div><div class="line"><span class="keyword">Jul </span><span class="number">23</span> <span class="number">17</span>:<span class="number">12</span>:<span class="number">50</span> iZ2360o6lpyZ warn1 <span class="built_in">at</span> com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper$<span class="number">1</span>.invoke(ProtocolFilterWrapper.<span class="keyword">java:91) </span>[dubbo-2.<span class="number">5</span>.<span class="number">3</span>.<span class="keyword">jar:2.5.3]</span></div><div class="line"><span class="keyword">Jul </span><span class="number">23</span> <span class="number">17</span>:<span class="number">12</span>:<span class="number">50</span> iZ2360o6lpyZ warn1 <span class="built_in">at</span> sky.app.eagleeye.dubbo.EagleeyeFilter.invoke(EagleeyeFilter.<span class="keyword">java:155) </span>[hbec-platform-runtime-app-0.<span class="number">0</span>.<span class="number">32</span>-SNAPSHOT.<span class="keyword">jar:na]</span></div><div class="line"><span class="keyword">Jul </span><span class="number">23</span> <span class="number">17</span>:<span class="number">12</span>:<span class="number">50</span> iZ2360o6lpyZ warn1 <span class="built_in">at</span> com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper$<span class="number">1</span>.invoke(ProtocolFilterWrapper.<span class="keyword">java:91) </span>[dubbo-2.<span class="number">5</span>.<span class="number">3</span>.<span class="keyword">jar:2.5.3]</span></div><div class="line"><span class="keyword">Jul </span><span class="number">23</span> <span class="number">17</span>:<span class="number">12</span>:<span class="number">50</span> iZ2360o6lpyZ warn1 <span class="built_in">at</span> com.alibaba.dubbo.rpc.filter.ContextFilter.invoke(ContextFilter.<span class="keyword">java:60) </span>[dubbo-2.<span class="number">5</span>.<span class="number">3</span>.<span class="keyword">jar:2.5.3]</span></div><div class="line"><span class="keyword">Jul </span><span class="number">23</span> <span class="number">17</span>:<span class="number">12</span>:<span class="number">50</span> iZ2360o6lpyZ warn1 <span class="built_in">at</span> com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper$<span class="number">1</span>.invoke(ProtocolFilterWrapper.<span class="keyword">java:91) </span>[dubbo-2.<span class="number">5</span>.<span class="number">3</span>.<span class="keyword">jar:2.5.3]</span></div><div class="line"><span class="keyword">Jul </span><span class="number">23</span> <span class="number">17</span>:<span class="number">12</span>:<span class="number">50</span> iZ2360o6lpyZ warn1 <span class="built_in">at</span> com.alibaba.dubbo.rpc.filter.GenericFilter.invoke(GenericFilter.<span class="keyword">java:112) </span>[dubbo-2.<span class="number">5</span>.<span class="number">3</span>.<span class="keyword">jar:2.5.3]</span></div><div class="line"><span class="keyword">Jul </span><span class="number">23</span> <span class="number">17</span>:<span class="number">12</span>:<span class="number">50</span> iZ2360o6lpyZ warn1 <span class="built_in">at</span> com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper$<span class="number">1</span>.invoke(ProtocolFilterWrapper.<span class="keyword">java:91) </span>[dubbo-2.<span class="number">5</span>.<span class="number">3</span>.<span class="keyword">jar:2.5.3]</span></div><div class="line"><span class="keyword">Jul </span><span class="number">23</span> <span class="number">17</span>:<span class="number">12</span>:<span class="number">50</span> iZ2360o6lpyZ warn1 <span class="built_in">at</span> com.alibaba.dubbo.rpc.filter.ClassLoaderFilter.invoke(ClassLoaderFilter.<span class="keyword">java:38) </span>[dubbo-2.<span class="number">5</span>.<span class="number">3</span>.<span class="keyword">jar:2.5.3]</span></div><div class="line"><span class="keyword">Jul </span><span class="number">23</span> <span class="number">17</span>:<span class="number">12</span>:<span class="number">50</span> iZ2360o6lpyZ warn1 <span class="built_in">at</span> com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper$<span class="number">1</span>.invoke(ProtocolFilterWrapper.<span class="keyword">java:91) </span>[dubbo-2.<span class="number">5</span>.<span class="number">3</span>.<span class="keyword">jar:2.5.3]</span></div><div class="line"><span class="keyword">Jul </span><span class="number">23</span> <span class="number">17</span>:<span class="number">12</span>:<span class="number">50</span> iZ2360o6lpyZ warn1 <span class="built_in">at</span> com.alibaba.dubbo.rpc.filter.EchoFilter.invoke(EchoFilter.<span class="keyword">java:38) </span>[dubbo-2.<span class="number">5</span>.<span class="number">3</span>.<span class="keyword">jar:2.5.3]</span></div><div class="line"><span class="keyword">Jul </span><span class="number">23</span> <span class="number">17</span>:<span class="number">12</span>:<span class="number">50</span> iZ2360o6lpyZ warn1 <span class="built_in">at</span> com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper$<span class="number">1</span>.invoke(ProtocolFilterWrapper.<span class="keyword">java:91) </span>[dubbo-2.<span class="number">5</span>.<span class="number">3</span>.<span class="keyword">jar:2.5.3]</span></div><div class="line"><span class="keyword">Jul </span><span class="number">23</span> <span class="number">17</span>:<span class="number">12</span>:<span class="number">50</span> iZ2360o6lpyZ warn1 <span class="built_in">at</span> com.alibaba.dubbo.rpc.protocol.dubbo.DubboProtocol$<span class="number">1</span>.reply(DubboProtocol.<span class="keyword">java:108) </span>[dubbo-2.<span class="number">5</span>.<span class="number">3</span>.<span class="keyword">jar:2.5.3]</span></div><div class="line"><span class="keyword">Jul </span><span class="number">23</span> <span class="number">17</span>:<span class="number">12</span>:<span class="number">50</span> iZ2360o6lpyZ warn1 <span class="built_in">at</span> com.alibaba.dubbo.remoting.exchange.support.header.HeaderExchangeHandler.handleRequest(HeaderExchangeHandler.<span class="keyword">java:84) </span>[dubbo-2.<span class="number">5</span>.<span class="number">3</span>.<span class="keyword">jar:2.5.3]</span></div><div class="line"><span class="keyword">Jul </span><span class="number">23</span> <span class="number">17</span>:<span class="number">12</span>:<span class="number">50</span> iZ2360o6lpyZ warn1 <span class="built_in">at</span> com.alibaba.dubbo.remoting.exchange.support.header.HeaderExchangeHandler.received(HeaderExchangeHandler.<span class="keyword">java:170) </span>[dubbo-2.<span class="number">5</span>.<span class="number">3</span>.<span class="keyword">jar:2.5.3]</span></div><div class="line"><span class="keyword">Jul </span><span class="number">23</span> <span class="number">17</span>:<span class="number">12</span>:<span class="number">50</span> iZ2360o6lpyZ warn1 <span class="built_in">at</span> com.alibaba.dubbo.remoting.transport.DecodeHandler.received(DecodeHandler.<span class="keyword">java:52) </span>[dubbo-2.<span class="number">5</span>.<span class="number">3</span>.<span class="keyword">jar:2.5.3]</span></div><div class="line"><span class="keyword">Jul </span><span class="number">23</span> <span class="number">17</span>:<span class="number">12</span>:<span class="number">50</span> iZ2360o6lpyZ warn1 <span class="built_in">at</span> com.alibaba.dubbo.remoting.transport.<span class="keyword">dispatcher.ChannelEventRunnable.run(ChannelEventRunnable.java:82) </span>[dubbo-2.<span class="number">5</span>.<span class="number">3</span>.<span class="keyword">jar:2.5.3]</span></div><div class="line"><span class="keyword">Jul </span><span class="number">23</span> <span class="number">17</span>:<span class="number">12</span>:<span class="number">50</span> iZ2360o6lpyZ warn1 <span class="built_in">at</span> <span class="keyword">java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) </span>[na:<span class="number">1</span>.<span class="number">7</span>.<span class="number">0</span>_55]</div><div class="line"><span class="keyword">Jul </span><span class="number">23</span> <span class="number">17</span>:<span class="number">12</span>:<span class="number">50</span> iZ2360o6lpyZ warn1 <span class="built_in">at</span> <span class="keyword">java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) </span>[na:<span class="number">1</span>.<span class="number">7</span>.<span class="number">0</span>_55]</div><div class="line"><span class="keyword">Jul </span><span class="number">23</span> <span class="number">17</span>:<span class="number">12</span>:<span class="number">50</span> iZ2360o6lpyZ warn1 <span class="built_in">at</span> <span class="keyword">java.lang.Thread.run(Thread.java:745) </span>[na:<span class="number">1</span>.<span class="number">7</span>.<span class="number">0</span>_55]</div><div class="line"><span class="keyword">Jul </span><span class="number">23</span> <span class="number">17</span>:<span class="number">12</span>:<span class="number">50</span> iZ2360o6lpyZ warn1 Caused <span class="keyword">by: </span><span class="keyword">java.lang.RuntimeException: </span>sky.platform.commons.exceptions.HbecDbServiceException: service=db,message=</div><div class="line"><span class="keyword">Jul </span><span class="number">23</span> <span class="number">17</span>:<span class="number">12</span>:<span class="number">50</span> iZ2360o6lpyZ warn1 <span class="comment">### Error updating database. Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException: Deadlock found when trying to get lock; try restarting transaction</span></div><div class="line"><span class="keyword">Jul </span><span class="number">23</span> <span class="number">17</span>:<span class="number">12</span>:<span class="number">50</span> iZ2360o6lpyZ warn1 <span class="comment">### The error may involve WarnFollowMapper.follow-Inline</span></div><div class="line"><span class="keyword">Jul </span><span class="number">23</span> <span class="number">17</span>:<span class="number">12</span>:<span class="number">50</span> iZ2360o6lpyZ warn1 <span class="comment">### The error occurred while setting parameters</span></div><div class="line"><span class="keyword">Jul </span><span class="number">23</span> <span class="number">17</span>:<span class="number">12</span>:<span class="number">50</span> iZ2360o6lpyZ warn1 <span class="comment">### SQL: insert into test_follow (user_id, security_type, stock_code, exchange, stock_name, sub_fund_type, sort) values (?, ?, ?, ?,?, ?, (select max(IFNULL(t1.sort,0)) + 1 from test_FOLLOW t1 where t1.user_id = ?) ) on duplicate key update sort= (select max(IFNULL(t2.sort,0)) + 1 from test_follow t2 where t2.user_id= ?)</span></div><div class="line"><span class="keyword">Jul </span><span class="number">23</span> <span class="number">17</span>:<span class="number">12</span>:<span class="number">50</span> iZ2360o6lpyZ warn1 <span class="comment">### Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException: Deadlock found when trying to get lock; try restarting transaction</span></div><div class="line"><span class="keyword">Jul </span><span class="number">23</span> <span class="number">17</span>:<span class="number">12</span>:<span class="number">50</span> iZ2360o6lpyZ warn1 <span class="built_in">at</span> sky.app.stock.follow.repository.impl.WarnFollowRepository.follow(WarnFollowRepository.<span class="keyword">java:238) </span>~[hbec-app-stock-follow-1.<span class="number">0</span>.<span class="number">2</span>-SNAPSHOT.<span class="keyword">jar:na]</span></div><div class="line"><span class="keyword">Jul </span><span class="number">23</span> <span class="number">17</span>:<span class="number">12</span>:<span class="number">50</span> iZ2360o6lpyZ warn1 <span class="built_in">at</span> sky.app.stock.follow.service.impl.WarnFollowServiceImpl.follow(WarnFollowServiceImpl.<span class="keyword">java:87) </span>~[hbec-app-stock-follow-1.<span class="number">0</span>.<span class="number">2</span>-SNAPSHOT.<span class="keyword">jar:na]</span></div><div class="line"><span class="keyword">Jul </span><span class="number">23</span> <span class="number">17</span>:<span class="number">12</span>:<span class="number">50</span> iZ2360o6lpyZ warn1 <span class="built_in">at</span> sky.app.stock.follow.service.impl.WarnFollowServiceImpl$$EnhancerByCGLIB$$<span class="number">41</span>e28e09.CGLIB$follow$<span class="number">0</span>(<generated>) [spring-core-4.<span class="number">0</span>.<span class="number">2</span>.RELEASE.<span class="keyword">jar:na]</span></div><div class="line"><span class="keyword">Jul </span><span class="number">23</span> <span class="number">17</span>:<span class="number">12</span>:<span class="number">50</span> iZ2360o6lpyZ warn1 <span class="built_in">at</span> sky.app.stock.follow.service.impl.WarnFollowServiceImpl$$EnhancerByCGLIB$$<span class="number">41</span>e28e09$$FastClassByCGLIB$$cf<span class="number">1f</span>7d<span class="number">1b</span>.invoke(<generated>) ~[spring-core-4.<span class="number">0</span>.<span class="number">2</span>.RELEASE.<span class="keyword">jar:na]</span></div><div class="line"><span class="keyword">Jul </span><span class="number">23</span> <span class="number">17</span>:<span class="number">12</span>:<span class="number">50</span> iZ2360o6lpyZ warn1 <span class="built_in">at</span> <span class="keyword">org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228) </span>~[spring-core-4.<span class="number">0</span>.<span class="number">2</span>.RELEASE.<span class="keyword">jar:4.0.2.RELEASE]</span></div><div class="line"><span class="keyword">Jul </span><span class="number">23</span> <span class="number">17</span>:<span class="number">12</span>:<span class="number">50</span> iZ2360o6lpyZ warn1 <span class="built_in">at</span> sky.platform.runtime.DbServiceInterceptor$<span class="number">1</span>.execute(DbServiceInterceptor.<span class="keyword">java:37) </span>~[hbec-platform-commons-0.<span class="number">0</span>.<span class="number">32</span>-SNAPSHOT.<span class="keyword">jar:na]</span></div><div class="line"><span class="keyword">Jul </span><span class="number">23</span> <span class="number">17</span>:<span class="number">12</span>:<span class="number">50</span> iZ2360o6lpyZ warn1 ... <span class="number">34</span> common frames omitted</div><div class="line"><span class="keyword">Jul </span><span class="number">23</span> <span class="number">17</span>:<span class="number">12</span>:<span class="number">50</span> iZ2360o6lpyZ warn1 Caused <span class="keyword">by: </span>sky.platform.commons.exceptions.HbecDbServiceException: service=db,message=</div><div class="line"><span class="keyword">Jul </span><span class="number">23</span> <span class="number">17</span>:<span class="number">12</span>:<span class="number">50</span> iZ2360o6lpyZ warn1 <span class="comment">### Error updating database. Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException: Deadlock found when trying to get lock; try restarting transaction</span></div><div class="line"><span class="keyword">Jul </span><span class="number">23</span> <span class="number">17</span>:<span class="number">12</span>:<span class="number">50</span> iZ2360o6lpyZ warn1 <span class="comment">### The error may involve WarnFollowMapper.follow-Inline</span></div><div class="line"><span class="keyword">Jul </span><span class="number">23</span> <span class="number">17</span>:<span class="number">12</span>:<span class="number">50</span> iZ2360o6lpyZ warn1 <span class="comment">### The error occurred while setting parameters</span></div><div class="line"><span class="keyword">Jul </span><span class="number">23</span> <span class="number">17</span>:<span class="number">12</span>:<span class="number">50</span> iZ2360o6lpyZ warn1 <span class="comment">### SQL: insert into test_follow (user_id, security_type, stock_code, exchange, stock_name, sub_fund_type, sort) values (?, ?, ?, ?,?, ?, (select max(IFNULL(t1.sort,0)) + 1 from test_FOLLOW t1 where t1.user_id = ?) ) on duplicate key update sort= (select max(IFNULL(t2.sort,0)) + 1 from test_follow t2 where t2.user_id= ?)</span></div><div class="line"><span class="keyword">Jul </span><span class="number">23</span> <span class="number">17</span>:<span class="number">12</span>:<span class="number">50</span> iZ2360o6lpyZ warn1 <span class="comment">### Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException: Deadlock found when trying to get lock; try restarting transaction</span></div><div class="line"><span class="keyword">Jul </span><span class="number">23</span> <span class="number">17</span>:<span class="number">12</span>:<span class="number">50</span> iZ2360o6lpyZ warn1 <span class="built_in">at</span> sky.platform.runtime.DbService.myInsert(DbService.<span class="keyword">java:2345) </span>~[hbec-platform-commons-0.<span class="number">0</span>.<span class="number">32</span>-SNAPSHOT.<span class="keyword">jar:na]</span></div><div class="line"><span class="keyword">Jul </span><span class="number">23</span> <span class="number">17</span>:<span class="number">12</span>:<span class="number">50</span> iZ2360o6lpyZ warn1 <span class="built_in">at</span> sky.app.stock.follow.repository.impl.WarnFollowRepository.follow(WarnFollowRepository.<span class="keyword">java:236) </span>~[hbec-app-stock-follow-1.<span class="number">0</span>.<span class="number">2</span>-SNAPSHOT.<span class="keyword">jar:na]</span></div><div class="line"><span class="keyword">Jul </span><span class="number">23</span> <span class="number">17</span>:<span class="number">12</span>:<span class="number">50</span> iZ2360o6lpyZ warn1 ... <span class="number">39</span> common frames omitted</div><div class="line"><span class="keyword">Jul </span><span class="number">23</span> <span class="number">17</span>:<span class="number">12</span>:<span class="number">50</span> iZ2360o6lpyZ warn1 Caused <span class="keyword">by: </span><span class="keyword">org.apache.ibatis.exceptions.PersistenceException: </span></div><div class="line"><span class="keyword">Jul </span><span class="number">23</span> <span class="number">17</span>:<span class="number">12</span>:<span class="number">50</span> iZ2360o6lpyZ warn1 <span class="comment">### Error updating database. Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException: Deadlock found when trying to get lock; try restarting transaction</span></div><div class="line"><span class="keyword">Jul </span><span class="number">23</span> <span class="number">17</span>:<span class="number">12</span>:<span class="number">50</span> iZ2360o6lpyZ warn1 <span class="comment">### The error may involve WarnFollowMapper.follow-Inline</span></div><div class="line"><span class="keyword">Jul </span><span class="number">23</span> <span class="number">17</span>:<span class="number">12</span>:<span class="number">50</span> iZ2360o6lpyZ warn1 <span class="comment">### The error occurred while setting parameters</span></div><div class="line"><span class="keyword">Jul </span><span class="number">23</span> <span class="number">17</span>:<span class="number">12</span>:<span class="number">50</span> iZ2360o6lpyZ warn1 <span class="comment">### SQL: insert into test_follow (user_id, security_type, stock_code, exchange, stock_name, sub_fund_type, sort) values (?, ?, ?, ?,?, ?, (select max(IFNULL(t1.sort,0)) + 1 from test_FOLLOW t1 where t1.user_id = ?) ) on duplicate key update sort= (select max(IFNULL(t2.sort,0)) + 1 from test_follow t2 where t2.user_id= ?)</span></div><div class="line"><span class="keyword">Jul </span><span class="number">23</span> <span class="number">17</span>:<span class="number">12</span>:<span class="number">50</span> iZ2360o6lpyZ warn1 <span class="comment">### Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException: Deadlock found when trying to get lock; try restarting transaction</span></div><div class="line"><span class="keyword">Jul </span><span class="number">23</span> <span class="number">17</span>:<span class="number">12</span>:<span class="number">50</span> iZ2360o6lpyZ warn1 <span class="built_in">at</span> <span class="keyword">org.apache.ibatis.exceptions.ExceptionFactory.wrapException(ExceptionFactory.java:26) </span>~[mybatis-3.<span class="number">2</span>.<span class="number">8</span>.<span class="keyword">jar:3.2.8]</span></div><div class="line"><span class="keyword">Jul </span><span class="number">23</span> <span class="number">17</span>:<span class="number">12</span>:<span class="number">50</span> iZ2360o6lpyZ warn1 <span class="built_in">at</span> <span class="keyword">org.apache.ibatis.session.defaults.DefaultSqlSession.update(DefaultSqlSession.java:154) </span>~[mybatis-3.<span class="number">2</span>.<span class="number">8</span>.<span class="keyword">jar:3.2.8]</span></div><div class="line"><span class="keyword">Jul </span><span class="number">23</span> <span class="number">17</span>:<span class="number">12</span>:<span class="number">50</span> iZ2360o6lpyZ warn1 <span class="built_in">at</span> <span class="keyword">org.apache.ibatis.session.defaults.DefaultSqlSession.insert(DefaultSqlSession.java:141) </span>~[mybatis-3.<span class="number">2</span>.<span class="number">8</span>.<span class="keyword">jar:3.2.8]</span></div><div class="line"><span class="keyword">Jul </span><span class="number">23</span> <span class="number">17</span>:<span class="number">12</span>:<span class="number">50</span> iZ2360o6lpyZ warn1 <span class="built_in">at</span> sky.platform.runtime.DbService.myInsert(DbService.<span class="keyword">java:2331) </span>~[hbec-platform-commons-0.<span class="number">0</span>.<span class="number">32</span>-SNAPSHOT.<span class="keyword">jar:na]</span></div><div class="line"><span class="keyword">Jul </span><span class="number">23</span> <span class="number">17</span>:<span class="number">12</span>:<span class="number">50</span> iZ2360o6lpyZ warn1 ... <span class="number">40</span> common frames omitted</div><div class="line"><span class="keyword">Jul </span><span class="number">23</span> <span class="number">17</span>:<span class="number">12</span>:<span class="number">50</span> iZ2360o6lpyZ warn1 Caused <span class="keyword">by: </span>com.mysql.<span class="keyword">jdbc.exceptions.jdbc4.MySQLTransactionRollbackException: </span>Deadlock found when trying to get lock<span class="comment">; try restarting transaction</span></div><div class="line"><span class="keyword">Jul </span><span class="number">23</span> <span class="number">17</span>:<span class="number">12</span>:<span class="number">50</span> iZ2360o6lpyZ warn1 <span class="built_in">at</span> sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) ~[na:<span class="number">1</span>.<span class="number">7</span>.<span class="number">0</span>_55]</div><div class="line"><span class="keyword">Jul </span><span class="number">23</span> <span class="number">17</span>:<span class="number">12</span>:<span class="number">50</span> iZ2360o6lpyZ warn1 <span class="built_in">at</span> sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.<span class="keyword">java:57) </span>~[na:<span class="number">1</span>.<span class="number">7</span>.<span class="number">0</span>_55]</div><div class="line"><span class="keyword">Jul </span><span class="number">23</span> <span class="number">17</span>:<span class="number">12</span>:<span class="number">50</span> iZ2360o6lpyZ warn1 <span class="built_in">at</span> sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.<span class="keyword">java:45) </span>~[na:<span class="number">1</span>.<span class="number">7</span>.<span class="number">0</span>_55]</div><div class="line"><span class="keyword">Jul </span><span class="number">23</span> <span class="number">17</span>:<span class="number">12</span>:<span class="number">50</span> iZ2360o6lpyZ warn1 <span class="built_in">at</span> <span class="keyword">java.lang.reflect.Constructor.newInstance(Constructor.java:526) </span>~[na:<span class="number">1</span>.<span class="number">7</span>.<span class="number">0</span>_55]</div><div class="line"><span class="keyword">Jul </span><span class="number">23</span> <span class="number">17</span>:<span class="number">12</span>:<span class="number">50</span> iZ2360o6lpyZ warn1 <span class="built_in">at</span> com.mysql.<span class="keyword">jdbc.Util.handleNewInstance(Util.java:411) </span>~[mysql-connector-<span class="keyword">java-5.1.28.jar:na]</span></div><div class="line"><span class="keyword">Jul </span><span class="number">23</span> <span class="number">17</span>:<span class="number">12</span>:<span class="number">50</span> iZ2360o6lpyZ warn1 <span class="built_in">at</span> com.mysql.<span class="keyword">jdbc.Util.getInstance(Util.java:386) </span>~[mysql-connector-<span class="keyword">java-5.1.28.jar:na]</span></div><div class="line"><span class="keyword">Jul </span><span class="number">23</span> <span class="number">17</span>:<span class="number">12</span>:<span class="number">50</span> iZ2360o6lpyZ warn1 <span class="built_in">at</span> com.mysql.<span class="keyword">jdbc.SQLError.createSQLException(SQLError.java:1066) </span>~[mysql-connector-<span class="keyword">java-5.1.28.jar:na]</span></div><div class="line"><span class="keyword">Jul </span><span class="number">23</span> <span class="number">17</span>:<span class="number">12</span>:<span class="number">50</span> iZ2360o6lpyZ warn1 <span class="built_in">at</span> com.mysql.<span class="keyword">jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4237) </span>~[mysql-connector-<span class="keyword">java-5.1.28.jar:na]</span></div><div class="line"><span class="keyword">Jul </span><span class="number">23</span> <span class="number">17</span>:<span class="number">12</span>:<span class="number">50</span> iZ2360o6lpyZ warn1 <span class="built_in">at</span> com.mysql.<span class="keyword">jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4169) </span>~[mysql-connector-<span class="keyword">java-5.1.28.jar:na]</span></div><div class="line"><span class="keyword">Jul </span><span class="number">23</span> <span class="number">17</span>:<span class="number">12</span>:<span class="number">50</span> iZ2360o6lpyZ warn1 <span class="built_in">at</span> com.mysql.<span class="keyword">jdbc.MysqlIO.sendCommand(MysqlIO.java:2617) </span>~[mysql-connector-<span class="keyword">java-5.1.28.jar:na]</span></div><div class="line"><span class="keyword">Jul </span><span class="number">23</span> <span class="number">17</span>:<span class="number">12</span>:<span class="number">50</span> iZ2360o6lpyZ warn1 <span class="built_in">at</span> com.mysql.<span class="keyword">jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2778) </span>~[mysql-connector-<span class="keyword">java-5.1.28.jar:na]</span></div><div class="line"><span class="keyword">Jul </span><span class="number">23</span> <span class="number">17</span>:<span class="number">12</span>:<span class="number">50</span> iZ2360o6lpyZ warn1 <span class="built_in">at</span> com.mysql.<span class="keyword">jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2825) </span>~[mysql-connector-<span class="keyword">java-5.1.28.jar:na]</span></div><div class="line"><span class="keyword">Jul </span><span class="number">23</span> <span class="number">17</span>:<span class="number">12</span>:<span class="number">50</span> iZ2360o6lpyZ warn1 <span class="built_in">at</span> com.mysql.<span class="keyword">jdbc.PreparedStatement.executeInternal(PreparedStatement.java:2156) </span>~[mysql-connector-<span class="keyword">java-5.1.28.jar:na]</span></div><div class="line"><span class="keyword">Jul </span><span class="number">23</span> <span class="number">17</span>:<span class="number">12</span>:<span class="number">50</span> iZ2360o6lpyZ warn1 <span class="built_in">at</span> com.mysql.<span class="keyword">jdbc.PreparedStatement.execute(PreparedStatement.java:1379) </span>~[mysql-connector-<span class="keyword">java-5.1.28.jar:na]</span></div><div class="line"><span class="keyword">Jul </span><span class="number">23</span> <span class="number">17</span>:<span class="number">12</span>:<span class="number">50</span> iZ2360o6lpyZ warn1 <span class="built_in">at</span> sun.reflect.GeneratedMethodAccessor199.invoke(Unknown Source) ~[na:na]</div><div class="line"><span class="keyword">Jul </span><span class="number">23</span> <span class="number">17</span>:<span class="number">12</span>:<span class="number">50</span> iZ2360o6lpyZ warn1 <span class="built_in">at</span> sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.<span class="keyword">java:43) </span>~[na:<span class="number">1</span>.<span class="number">7</span>.<span class="number">0</span>_55]</div><div class="line"><span class="keyword">Jul </span><span class="number">23</span> <span class="number">17</span>:<span class="number">12</span>:<span class="number">50</span> iZ2360o6lpyZ warn1 <span class="built_in">at</span> <span class="keyword">java.lang.reflect.Method.invoke(Method.java:606) </span>~[na:<span class="number">1</span>.<span class="number">7</span>.<span class="number">0</span>_55]</div><div class="line"><span class="keyword">Jul </span><span class="number">23</span> <span class="number">17</span>:<span class="number">12</span>:<span class="number">50</span> iZ2360o6lpyZ warn1 <span class="built_in">at</span> <span class="keyword">org.apache.ibatis.logging.jdbc.PreparedStatementLogger.invoke(PreparedStatementLogger.java:62) </span>~[mybatis-3.<span class="number">2</span>.<span class="number">8</span>.<span class="keyword">jar:3.2.8]</span></div><div class="line"><span class="keyword">Jul </span><span class="number">23</span> <span class="number">17</span>:<span class="number">12</span>:<span class="number">50</span> iZ2360o6lpyZ warn1 <span class="built_in">at</span> com.sun.proxy.$Proxy28.execute(Unknown Source) ~[na:na]</div><div class="line"><span class="keyword">Jul </span><span class="number">23</span> <span class="number">17</span>:<span class="number">12</span>:<span class="number">50</span> iZ2360o6lpyZ warn1 <span class="built_in">at</span> <span class="keyword">org.apache.ibatis.executor.statement.PreparedStatementHandler.update(PreparedStatementHandler.java:44) </span>~[mybatis-3.<span class="number">2</span>.<span class="number">8</span>.<span class="keyword">jar:3.2.8]</span></div><div class="line"><span class="keyword">Jul </span><span class="number">23</span> <span class="number">17</span>:<span class="number">12</span>:<span class="number">50</span> iZ2360o6lpyZ warn1 <span class="built_in">at</span> <span class="keyword">org.apache.ibatis.executor.statement.RoutingStatementHandler.update(RoutingStatementHandler.java:69) </span>~[mybatis-3.<span class="number">2</span>.<span class="number">8</span>.<span class="keyword">jar:3.2.8]</span></div><div class="line"><span class="keyword">Jul </span><span class="number">23</span> <span class="number">17</span>:<span class="number">12</span>:<span class="number">50</span> iZ2360o6lpyZ warn1 <span class="built_in">at</span> <span class="keyword">org.apache.ibatis.executor.SimpleExecutor.doUpdate(SimpleExecutor.java:48) </span>~[mybatis-3.<span class="number">2</span>.<span class="number">8</span>.<span class="keyword">jar:3.2.8]</span></div><div class="line"><span class="keyword">Jul </span><span class="number">23</span> <span class="number">17</span>:<span class="number">12</span>:<span class="number">50</span> iZ2360o6lpyZ warn1 <span class="built_in">at</span> <span class="keyword">org.apache.ibatis.executor.BaseExecutor.update(BaseExecutor.java:105) </span>~[mybatis-3.<span class="number">2</span>.<span class="number">8</span>.<span class="keyword">jar:3.2.8]</span></div><div class="line"><span class="keyword">Jul </span><span class="number">23</span> <span class="number">17</span>:<span class="number">12</span>:<span class="number">50</span> iZ2360o6lpyZ warn1 <span class="built_in">at</span> <span class="keyword">org.apache.ibatis.executor.CachingExecutor.update(CachingExecutor.java:71) </span>~[mybatis-3.<span class="number">2</span>.<span class="number">8</span>.<span class="keyword">jar:3.2.8]</span></div><div class="line"><span class="keyword">Jul </span><span class="number">23</span> <span class="number">17</span>:<span class="number">12</span>:<span class="number">50</span> iZ2360o6lpyZ warn1 <span class="built_in">at</span> <span class="keyword">org.apache.ibatis.session.defaults.DefaultSqlSession.update(DefaultSqlSession.java:152) </span>~[mybatis-3.<span class="number">2</span>.<span class="number">8</span>.<span class="keyword">jar:3.2.8]</span></div><div class="line"><span class="keyword">Jul </span><span class="number">23</span> <span class="number">17</span>:<span class="number">12</span>:<span class="number">50</span> iZ2360o6lpyZ warn1 ... <span class="number">42</span> common frames omitted</div><div class="line"><span class="keyword">Jul </span><span class="number">23</span> <span class="number">17</span>:<span class="number">12</span>:<span class="number">50</span> iZ2360o6lpyZ warn1 <span class="number">17</span>-07-23 <span class="number">17</span>:<span class="number">12</span>:<span class="number">50</span>.<span class="number">780</span> <span class="built_in">DEBUG</span>[DubboServerHandler-10.<span class="number">253</span>.<span class="number">17</span>.<span class="number">105</span>:<span class="number">20880</span>-thread-192 follow.debug:<span class="number">139</span>]MYBATIS <== Updates: <span class="number">2</span></div></pre></td></tr></table></figure>
<p>查看数据库引擎状态</p>
<figure class="highlight sql"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">show</span> <span class="keyword">engine</span> <span class="keyword">innodb</span> <span class="keyword">status</span></div></pre></td></tr></table></figure>
<figure class="highlight oxygene"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div><div class="line">41</div><div class="line">42</div><div class="line">43</div><div class="line">44</div><div class="line">45</div><div class="line">46</div><div class="line">47</div><div class="line">48</div><div class="line">49</div><div class="line">50</div></pre></td><td class="code"><pre><div class="line">------------------------</div><div class="line">LATEST DETECTED DEADLOCK</div><div class="line">------------------------</div><div class="line"><span class="number">2017</span>-<span class="number">07</span>-<span class="number">23</span> <span class="number">17</span>:<span class="number">13</span>:<span class="number">58</span> <span class="number">2</span>afc664c2700</div><div class="line">*** (<span class="number">1</span>) TRANSACTION:</div><div class="line">TRANSACTION <span class="number">730441984</span>, ACTIVE <span class="number">0.003</span> sec inserting</div><div class="line">mysql tables <span class="keyword">in</span> use <span class="number">3</span>, <span class="keyword">locked</span> <span class="number">3</span></div><div class="line">LOCK WAIT <span class="number">8</span> lock struct(s), heap size <span class="number">2936</span>, <span class="number">37</span> row lock(s), undo log entries <span class="number">1</span></div><div class="line">LOCK BLOCKING MySQL thread id: <span class="number">12246957</span> <span class="keyword">block</span> <span class="number">12256080</span></div><div class="line">MySQL thread id <span class="number">12256080</span>, OS thread handle <span class="number">0</span>x2afc48c40700, query id <span class="number">3543571324</span> <span class="number">10.253</span>.<span class="number">17.105</span> test_app Sending data</div><div class="line">insert <span class="keyword">into</span> test_follow (user_id, security_type, stock_code, exchange, stock_name, sub_fund_type, sort)</div><div class="line"> values (<span class="number">3245964</span>, <span class="number">4</span>, <span class="string">'601318'</span>,</div><div class="line"> <span class="string">'SH'</span>,<span class="string">'中国平安'</span>, null,</div><div class="line"> (<span class="keyword">select</span> max(IFNULL(t1.sort,<span class="number">0</span>)) + <span class="number">1</span> <span class="keyword">from</span> test_FOLLOW t1 <span class="keyword">where</span> t1.user_id = <span class="number">3245964</span>) )</div><div class="line"> <span class="keyword">on</span> duplicate key update sort= (<span class="keyword">select</span> max(IFNULL(t2.sort,<span class="number">0</span>)) + <span class="number">1</span> <span class="keyword">from</span> test_follow t2 <span class="keyword">where</span> t2.user_id= <span class="number">3245964</span>)</div><div class="line">*** (<span class="number">1</span>) WAITING <span class="keyword">FOR</span> THIS LOCK <span class="keyword">TO</span> BE GRANTED:</div><div class="line"><span class="keyword">RECORD</span> LOCKS space id <span class="number">1198</span> page no <span class="number">842</span> n bits <span class="number">696</span> <span class="keyword">index</span> `unique_index` <span class="keyword">of</span> table `wndb`.`test_follow` trx id <span class="number">730441984</span> lock_mode X waiting</div><div class="line"><span class="keyword">Record</span> lock, heap no <span class="number">624</span> PHYSICAL <span class="keyword">RECORD</span>: n_fields <span class="number">4</span>; compact format; info bits <span class="number">0</span></div><div class="line"> <span class="number">0</span>: len <span class="number">4</span>; hex <span class="number">8031878</span>c; <span class="keyword">asc</span> <span class="number">1</span> ;;</div><div class="line"> <span class="number">1</span>: len <span class="number">1</span>; hex <span class="number">84</span>; <span class="keyword">asc</span> ;;</div><div class="line"> <span class="number">2</span>: len <span class="number">6</span>; hex <span class="number">363031333138</span>; <span class="keyword">asc</span> <span class="number">601318</span>;;</div><div class="line"> <span class="number">3</span>: len <span class="number">4</span>; hex <span class="number">800399</span>cb; <span class="keyword">asc</span> ;;</div><div class="line"></div><div class="line">*** (<span class="number">2</span>) TRANSACTION:</div><div class="line">TRANSACTION <span class="number">730441985</span>, ACTIVE <span class="number">0.001</span> sec inserting</div><div class="line">mysql tables <span class="keyword">in</span> use <span class="number">3</span>, <span class="keyword">locked</span> <span class="number">3</span></div><div class="line"><span class="number">8</span> lock struct(s), heap size <span class="number">2936</span>, <span class="number">37</span> row lock(s), undo log entries <span class="number">1</span></div><div class="line">MySQL thread id <span class="number">12246957</span>, OS thread handle <span class="number">0</span>x2afc664c2700, query id <span class="number">3543571329</span> <span class="number">10.253</span>.<span class="number">17.105</span> test_app Sending data</div><div class="line">insert <span class="keyword">into</span> test_follow (user_id, security_type, stock_code, exchange, stock_name, sub_fund_type, sort)</div><div class="line"> values (<span class="number">3245964</span>, <span class="number">4</span>, <span class="string">'601318'</span>,</div><div class="line"> <span class="string">'SH'</span>,<span class="string">'中国平安'</span>, null,</div><div class="line"> (<span class="keyword">select</span> max(IFNULL(t1.sort,<span class="number">0</span>)) + <span class="number">1</span> <span class="keyword">from</span> test_FOLLOW t1 <span class="keyword">where</span> t1.user_id = <span class="number">3245964</span>) )</div><div class="line"> <span class="keyword">on</span> duplicate key update sort= (<span class="keyword">select</span> max(IFNULL(t2.sort,<span class="number">0</span>)) + <span class="number">1</span> <span class="keyword">from</span> test_follow t2 <span class="keyword">where</span> t2.user_id= <span class="number">3245964</span>)</div><div class="line">*** (<span class="number">2</span>) HOLDS THE LOCK(S):</div><div class="line"><span class="keyword">RECORD</span> LOCKS space id <span class="number">1198</span> page no <span class="number">842</span> n bits <span class="number">696</span> <span class="keyword">index</span> `unique_index` <span class="keyword">of</span> table `wndb`.`test_follow` trx id <span class="number">730441985</span> lock mode S locks rec but <span class="keyword">not</span> gap</div><div class="line"><span class="keyword">Record</span> lock, heap no <span class="number">624</span> PHYSICAL <span class="keyword">RECORD</span>: n_fields <span class="number">4</span>; compact format; info bits <span class="number">0</span></div><div class="line"> <span class="number">0</span>: len <span class="number">4</span>; hex <span class="number">8031878</span>c; <span class="keyword">asc</span> <span class="number">1</span> ;;</div><div class="line"> <span class="number">1</span>: len <span class="number">1</span>; hex <span class="number">84</span>; <span class="keyword">asc</span> ;;</div><div class="line"> <span class="number">2</span>: len <span class="number">6</span>; hex <span class="number">363031333138</span>; <span class="keyword">asc</span> <span class="number">601318</span>;;</div><div class="line"> <span class="number">3</span>: len <span class="number">4</span>; hex <span class="number">800399</span>cb; <span class="keyword">asc</span> ;;</div><div class="line"></div><div class="line">*** (<span class="number">2</span>) WAITING <span class="keyword">FOR</span> THIS LOCK <span class="keyword">TO</span> BE GRANTED:</div><div class="line"><span class="keyword">RECORD</span> LOCKS space id <span class="number">1198</span> page no <span class="number">842</span> n bits <span class="number">696</span> <span class="keyword">index</span> `unique_index` <span class="keyword">of</span> table `wndb`.`test_follow` trx id <span class="number">730441985</span> lock_mode X waiting</div><div class="line"><span class="keyword">Record</span> lock, heap no <span class="number">624</span> PHYSICAL <span class="keyword">RECORD</span>: n_fields <span class="number">4</span>; compact format; info bits <span class="number">0</span></div><div class="line"> <span class="number">0</span>: len <span class="number">4</span>; hex <span class="number">8031878</span>c; <span class="keyword">asc</span> <span class="number">1</span> ;;</div><div class="line"> <span class="number">1</span>: len <span class="number">1</span>; hex <span class="number">84</span>; <span class="keyword">asc</span> ;;</div><div class="line"> <span class="number">2</span>: len <span class="number">6</span>; hex <span class="number">363031333138</span>; <span class="keyword">asc</span> <span class="number">601318</span>;;</div><div class="line"> <span class="number">3</span>: len <span class="number">4</span>; hex <span class="number">800399</span>cb; <span class="keyword">asc</span> ;;</div><div class="line"></div><div class="line">*** WE ROLL BACK TRANSACTION (<span class="number">2</span>)</div></pre></td></tr></table></figure>
<p>从中可以看到两个事务在等待X锁<br><figure class="highlight sql"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div></pre></td><td class="code"><pre><div class="line">WAITING FOR THIS <span class="keyword">LOCK</span> <span class="keyword">TO</span> BE GRANTED:</div><div class="line"><span class="built_in">RECORD</span> LOCKS <span class="keyword">space</span> <span class="keyword">id</span> <span class="number">1198</span> page <span class="keyword">no</span> <span class="number">842</span> n bits <span class="number">696</span> <span class="keyword">index</span> <span class="string">`unique_index`</span> <span class="keyword">of</span> <span class="keyword">table</span> <span class="string">`wndb`</span>.<span class="string">`test_follow`</span> trx <span class="keyword">id</span> <span class="number">730441984</span> lock_mode X waiting</div><div class="line"><span class="built_in">Record</span> <span class="keyword">lock</span></div><div class="line"></div><div class="line">(<span class="number">2</span>) HOLDS THE <span class="keyword">LOCK</span>(S):</div><div class="line"><span class="built_in">RECORD</span> LOCKS <span class="keyword">space</span> <span class="keyword">id</span> <span class="number">1198</span> page <span class="keyword">no</span> <span class="number">842</span> n bits <span class="number">696</span> <span class="keyword">index</span> <span class="string">`unique_index`</span> <span class="keyword">of</span> <span class="keyword">table</span> <span class="string">`wndb`</span>.<span class="string">`test_follow`</span> trx <span class="keyword">id</span> <span class="number">730441985</span> <span class="keyword">lock</span> <span class="keyword">mode</span> S locks rec but <span class="keyword">not</span> gap</div><div class="line"><span class="built_in">Record</span> <span class="keyword">lock</span>, <span class="keyword">heap</span> <span class="keyword">no</span> <span class="number">624</span> <span class="keyword">PHYSICAL</span> <span class="built_in">RECORD</span></div><div class="line"></div><div class="line">(<span class="number">2</span>) WAITING <span class="keyword">FOR</span> THIS <span class="keyword">LOCK</span> <span class="keyword">TO</span> BE GRANTED:</div><div class="line"><span class="built_in">RECORD</span> LOCKS <span class="keyword">space</span> <span class="keyword">id</span> <span class="number">1198</span> page <span class="keyword">no</span> <span class="number">842</span> n bits <span class="number">696</span> <span class="keyword">index</span> <span class="string">`unique_index`</span> <span class="keyword">of</span> <span class="keyword">table</span> <span class="string">`wndb`</span>.<span class="string">`test_follow`</span> trx <span class="keyword">id</span> <span class="number">730441985</span> lock_mode X waiting</div><div class="line"><span class="built_in">Record</span> <span class="keyword">lock</span>, <span class="keyword">heap</span> <span class="keyword">no</span> <span class="number">624</span> <span class="keyword">PHYSICAL</span> <span class="built_in">RECORD</span></div></pre></td></tr></table></figure></p>
<h2 id="重现"><a href="#重现" class="headerlink" title="重现"></a>重现</h2><h3 id="1-准备工作"><a href="#1-准备工作" class="headerlink" title="1.准备工作"></a>1.准备工作</h3><ul>
<li>同时开启三个command prompt,远程连接mysql服务器:mysql -uroc -proc -h10.0.30.59 wndb</li>
<li>关闭自动提交:set autocommit=0</li>
</ul>
<h3 id="2-模拟请求"><a href="#2-模拟请求" class="headerlink" title="2.模拟请求"></a>2.模拟请求</h3><p>Session A<br><figure class="highlight sql"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">begin</span>;</div><div class="line"></div><div class="line"><span class="keyword">insert</span> <span class="keyword">into</span> test_follow (user_id, security_type, stock_code, <span class="keyword">exchange</span>, stock_name, sub_fund_type, <span class="keyword">sort</span>) <span class="keyword">values</span> (<span class="number">3245964</span>, <span class="number">4</span>, <span class="string">'600628'</span>, <span class="string">'SH'</span>,<span class="string">'新世界'</span>, <span class="literal">null</span>, (<span class="keyword">select</span> <span class="keyword">max</span>(<span class="keyword">IFNULL</span>(t1.sort,<span class="number">0</span>)) + <span class="number">1</span> <span class="keyword">from</span> test_FOLLOW t1 <span class="keyword">where</span> t1.user_id = <span class="number">3245964</span>) ) <span class="keyword">on</span> <span class="keyword">duplicate</span> <span class="keyword">key</span> <span class="keyword">update</span> <span class="keyword">sort</span>= (<span class="keyword">select</span> <span class="keyword">max</span>(<span class="keyword">IFNULL</span>(t2.sort,<span class="number">0</span>)) + <span class="number">1</span> <span class="keyword">from</span> test_follow t2 <span class="keyword">where</span> t2.user_id= <span class="number">3245964</span>);</div></pre></td></tr></table></figure></p>
<p>Session B<br><figure class="highlight sql"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">begin</span>;</div><div class="line"></div><div class="line"><span class="keyword">insert</span> <span class="keyword">into</span> test_follow (user_id, security_type, stock_code, <span class="keyword">exchange</span>, stock_name, sub_fund_type, <span class="keyword">sort</span>) <span class="keyword">values</span> (<span class="number">3245964</span>, <span class="number">4</span>, <span class="string">'600628'</span>, <span class="string">'SH'</span>,<span class="string">'新世界'</span>, <span class="literal">null</span>, (<span class="keyword">select</span> <span class="keyword">max</span>(<span class="keyword">IFNULL</span>(t1.sort,<span class="number">0</span>)) + <span class="number">1</span> <span class="keyword">from</span> test_FOLLOW t1 <span class="keyword">where</span> t1.user_id = <span class="number">3245964</span>) ) <span class="keyword">on</span> <span class="keyword">duplicate</span> <span class="keyword">key</span> <span class="keyword">update</span> <span class="keyword">sort</span>= (<span class="keyword">select</span> <span class="keyword">max</span>(<span class="keyword">IFNULL</span>(t2.sort,<span class="number">0</span>)) + <span class="number">1</span> <span class="keyword">from</span> test_follow t2 <span class="keyword">where</span> t2.user_id= <span class="number">3245964</span>);</div></pre></td></tr></table></figure></p>
<p>Session C<br><figure class="highlight sql"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">begin</span>;</div><div class="line"></div><div class="line"><span class="keyword">insert</span> <span class="keyword">into</span> test_follow (user_id, security_type, stock_code, <span class="keyword">exchange</span>, stock_name, sub_fund_type, <span class="keyword">sort</span>) <span class="keyword">values</span> (<span class="number">3245964</span>, <span class="number">4</span>, <span class="string">'600628'</span>, <span class="string">'SH'</span>,<span class="string">'新世界'</span>, <span class="literal">null</span>, (<span class="keyword">select</span> <span class="keyword">max</span>(<span class="keyword">IFNULL</span>(t1.sort,<span class="number">0</span>)) + <span class="number">1</span> <span class="keyword">from</span> test_FOLLOW t1 <span class="keyword">where</span> t1.user_id = <span class="number">3245964</span>) ) <span class="keyword">on</span> <span class="keyword">duplicate</span> <span class="keyword">key</span> <span class="keyword">update</span> <span class="keyword">sort</span>= (<span class="keyword">select</span> <span class="keyword">max</span>(<span class="keyword">IFNULL</span>(t2.sort,<span class="number">0</span>)) + <span class="number">1</span> <span class="keyword">from</span> test_follow t2 <span class="keyword">where</span> t2.user_id= <span class="number">3245964</span>);</div></pre></td></tr></table></figure></p>
<p>commit Session A,session B与session C竞争X锁,直接报错:</p>
<p><img src="https://raw.githubusercontent.com/roc-wong/images/master/%E6%AD%BB%E9%94%81%E9%97%AE%E9%A2%98.png" alt="死锁"></p>
<h2 id="解决"><a href="#解决" class="headerlink" title="解决"></a>解决</h2><p>首先这是个添加操作,APP端不应该对同一用户、同一只股票执行多次并发添加操作<br>,APP端需要解决单设备、多并发问题。后台针对同一用户、同一股票的添加操作,需要使用分布式锁控制并发。</p>
]]></content>
<summary type="html">
Deadlock found when trying to get lock; try restarting transaction
</summary>
<category term="Mysql" scheme="https://roc-wong.github.io/categories/Mysql/"/>