-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathatom.xml
More file actions
547 lines (261 loc) · 189 KB
/
atom.xml
File metadata and controls
547 lines (261 loc) · 189 KB
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
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title>eastFu</title>
<link href="http://xiaodongzi.cn/atom.xml" rel="self"/>
<link href="http://xiaodongzi.cn/"/>
<updated>2020-12-19T04:04:04.518Z</updated>
<id>http://xiaodongzi.cn/</id>
<author>
<name>eastFu</name>
</author>
<generator uri="https://hexo.io/">Hexo</generator>
<entry>
<title>storm 安装部署</title>
<link href="http://xiaodongzi.cn/2019/02/26/storm%E5%AE%89%E8%A3%85/"/>
<id>http://xiaodongzi.cn/2019/02/26/storm%E5%AE%89%E8%A3%85/</id>
<published>2019-02-26T10:24:57.000Z</published>
<updated>2020-12-19T04:04:04.518Z</updated>
<content type="html"><![CDATA[<h1 id="storm-安装部署"><a href="#storm-安装部署" class="headerlink" title="storm 安装部署"></a>storm 安装部署</h1><h2 id="1-关于Storm"><a href="#1-关于Storm" class="headerlink" title="1.关于Storm"></a>1.关于Storm</h2><blockquote><p>Storm是Twitter开源的分布式实时大数据处理框架,被业界称为实时版Hadoop。随着越来越多的场景对Hadoop的MapReduce高延迟无法容忍,比如网站统计、推荐系统、预警系统、金融系统(高频交易、股票)等等,大数据实时处理解决方案(流计算)的应用日趋广泛,目前已是分布式技术领域最新爆发点,而Storm更是流计算技术中的佼佼者和主流。</p></blockquote><blockquote><p>按照storm作者的说法,Storm对于实时计算的意义类似于Hadoop对于批处理的意义。Hadoop提供了map、reduce原语,使我们的批处理程序变得简单和高效。同样,Storm也为实时计算提供了一些简单高效的原语,而且Storm的Trident是基于Storm原语更高级的抽象框架,类似于基于Hadoop的Pig框架,让开发更加便利和高效。</p></blockquote><blockquote><p>Storm 目前版本更新到2.x,这里我们选用经典版本1.1.0进行安装部署,storm+kafka+zookeeper 实现流式计算。</p></blockquote><p>官方下载地址:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">https://archive.apache.org/dist/storm/</span><br></pre></td></tr></table></figure><h2 id="2-单节点安装部署"><a href="#2-单节点安装部署" class="headerlink" title="2.单节点安装部署"></a>2.单节点安装部署</h2><h3 id="修改配置文件conf-storm-yaml"><a href="#修改配置文件conf-storm-yaml" class="headerlink" title="修改配置文件conf/storm.yaml"></a>修改配置文件conf/storm.yaml</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">storm.zookeeper.servers:</span><br><span class="line"> - "zk001.test.com"</span><br><span class="line">nimbus.seeds: ["storm001.test.com"]</span><br><span class="line">storm.log.dir: "/data/storm/logs"</span><br><span class="line">storm.local.dir: "/data/storm/db"</span><br><span class="line">storm.zookeeper.root: "/storm-1.1.0"</span><br><span class="line">ui.port: 18888</span><br><span class="line">supervisor.slots.ports:</span><br><span class="line"> - 19527</span><br><span class="line"> - 19528</span><br><span class="line"> - 19529</span><br></pre></td></tr></table></figure><h3 id="启动storm"><a href="#启动storm" class="headerlink" title="启动storm"></a>启动storm</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">nohup bin/storm nimbus >/data/storm/logs/storm_start.log 2>&1 &</span><br><span class="line">nohup bin/storm supervisor >/data/storm/logs/storm_supervisor.log 2>&1 &</span><br><span class="line">nohup bin/storm ui >/data/storm/logs/storm_ui.log 2>&1 &</span><br></pre></td></tr></table></figure><h3 id="访问UI-web"><a href="#访问UI-web" class="headerlink" title="访问UI web"></a>访问UI web</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">http://ip:18888</span><br><span class="line"></span><br></pre></td></tr></table></figure><h2 id="3-集群部署"><a href="#3-集群部署" class="headerlink" title="3.集群部署"></a>3.集群部署</h2><h2 id="4-应用程序编写和打包发布"><a href="#4-应用程序编写和打包发布" class="headerlink" title="4.应用程序编写和打包发布"></a>4.应用程序编写和打包发布</h2>]]></content>
<summary type="html"><h1 id="storm-安装部署"><a href="#storm-安装部署" class="headerlink" title="storm 安装部署"></a>storm 安装部署</h1><h2 id="1-关于Storm"><a href="#1-关于Storm" c</summary>
<category term="storm" scheme="http://xiaodongzi.cn/categories/storm/"/>
<category term="编程" scheme="http://xiaodongzi.cn/tags/%E7%BC%96%E7%A8%8B/"/>
</entry>
<entry>
<title>kafka的安装</title>
<link href="http://xiaodongzi.cn/2018/10/20/kafka%E5%AE%89%E8%A3%85/"/>
<id>http://xiaodongzi.cn/2018/10/20/kafka%E5%AE%89%E8%A3%85/</id>
<published>2018-10-20T11:26:08.000Z</published>
<updated>2020-12-19T04:04:52.704Z</updated>
<content type="html"><![CDATA[<h1 id="kafka的安装"><a href="#kafka的安装" class="headerlink" title="kafka的安装"></a>kafka的安装</h1><h2 id="1-下载安装"><a href="#1-下载安装" class="headerlink" title="1.下载安装"></a>1.下载安装</h2><blockquote><p>kafka的安装需要依赖zookeeper,虽然kafka自带了zookeeper,但是为了方便维护,推荐自己安装zookeeper</p></blockquote><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br></pre></td><td class="code"><pre><span class="line">#zookeeper下载地址:</span><br><span class="line">https://zookeeper.apache.org/releases.html</span><br><span class="line"></span><br><span class="line">#解压缩zookeeper</span><br><span class="line">tar -zxvf apache-zookeeper-3.6.2-bin.tar.gz</span><br><span class="line"></span><br><span class="line">##修改配置 conf/zoo.cfg</span><br><span class="line">dataDir=/data/zk/node1/data</span><br><span class="line">clientPort=2181</span><br><span class="line"></span><br><span class="line">server.1=localhost:2287:3387</span><br><span class="line">server.2=localhost:2288:3388</span><br><span class="line">server.3=localhost:2289:3389</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">echo 1 >> /data/zk/node1/data/myid</span><br><span class="line">echo 2 >> /data/zk/node2/data/myid</span><br><span class="line">echo 3 >> /data/zk/node3/data/myid</span><br><span class="line"></span><br><span class="line">##启动zookeeper</span><br><span class="line">./zkServer.sh start ../conf/zoo1.cfg</span><br><span class="line">./zkServer.sh start ../conf/zoo2.cfg</span><br><span class="line">./zkServer.sh start ../conf/zoo3.cfg</span><br><span class="line"></span><br><span class="line">#kafka下载地址:</span><br><span class="line">http://kafka.apache.org/downloads</span><br><span class="line"></span><br><span class="line"># 解压缩</span><br><span class="line">tar -zxvf kafka_2.11-2.2.2.tgz</span><br><span class="line"></span><br><span class="line">#修改 conf/server.properties</span><br><span class="line">broker.id=0</span><br><span class="line">listeners=PLAINTEXT://hostname:9092</span><br><span class="line">log.dirs=/data/kafka-logs/kafka3</span><br><span class="line">zookeeper.connect=zk1:2181,zk3:2181,zk3:2181</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">#启动</span><br><span class="line">./kafka-server-start.sh -daemon ../config/server.properties</span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure><h2 id="2-配置文件修改"><a href="#2-配置文件修改" class="headerlink" title="2.配置文件修改"></a>2.配置文件修改</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">broker.id=0 #当前机器在集群中的唯一标识,和zookeeper的myid性质一样</span><br><span class="line"></span><br><span class="line">port=19092 #当前kafka对外提供服务的端口默认是9092</span><br><span class="line"></span><br><span class="line">host.name=192.168.7.100 #这个参数默认是关闭的,在0.8.1有个bug,DNS解析问题,失败率的问题。</span><br><span class="line"></span><br><span class="line">num.network.threads=3 #这个是borker进行网络处理的线程数</span><br><span class="line"></span><br><span class="line">num.io.threads=8 #这个是borker进行I/O处理的线程数</span><br><span class="line"></span><br><span class="line">log.dirs=/opt/kafka/kafkalogs/ #消息存放的目录,这个目录可以配置为“,”逗号分割的表达式,上面的num.io.threads要大于这个目录的个数这个目录,如果配置多个目录,新创建的topic他把消息持久化的地方是,当前以逗号分割的目录中,那个分区数最少就放那一个</span><br><span class="line"></span><br><span class="line">socket.send.buffer.bytes=102400 #发送缓冲区buffer大小,数据不是一下子就发送的,先回存储到缓冲区了到达一定的大小后在发送,能提高性能</span><br><span class="line"></span><br><span class="line">socket.receive.buffer.bytes=102400 #kafka接收缓冲区大小,当数据到达一定大小后在序列化到磁盘</span><br><span class="line"></span><br><span class="line">socket.request.max.bytes=104857600 #这个参数是向kafka请求消息或者向kafka发送消息的请请求的最大数,这个值不能超过java的堆栈大小</span><br><span class="line"></span><br><span class="line">num.partitions=1 #默认的分区数,一个topic默认1个分区数</span><br><span class="line"></span><br><span class="line">log.retention.hours=168 #默认消息的最大持久化时间,168小时,7天</span><br><span class="line"></span><br><span class="line">message.max.byte=5242880 #消息保存的最大值5M</span><br><span class="line"></span><br><span class="line">default.replication.factor=2 #kafka保存消息的副本数,如果一个副本失效了,另一个还可以继续提供服务</span><br><span class="line"></span><br><span class="line">replica.fetch.max.bytes=5242880 #取消息的最大直接数</span><br><span class="line"></span><br><span class="line">log.segment.bytes=1073741824 #这个参数是:因为kafka的消息是以追加的形式落地到文件,当超过这个值的时候,kafka会新起一个文件</span><br><span class="line"></span><br><span class="line">log.retention.check.interval.ms=300000 #每隔300000毫秒去检查上面配置的log失效时间(log.retention.hours=168 ),到目录查看是否有过期的消息如果有,删除</span><br><span class="line"></span><br><span class="line">log.cleaner.enable=false #是否启用log压缩,一般不用启用,启用的话可以提高性能</span><br><span class="line"></span><br><span class="line">zookeeper.connect=192.168.7.100:12181,192.168.7.101:12181,192.168.7.107:1218 #设置zookeeper的连接端口</span><br><span class="line"></span><br></pre></td></tr></table></figure><h2 id="3-启动命令"><a href="#3-启动命令" class="headerlink" title="3.启动命令"></a>3.启动命令</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">#启动</span><br><span class="line"></span><br><span class="line">./kafka-server-start.sh -daemon ../config/server.properties</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">kafka1/bin/kafka-server-start.sh -daemon kafka1/config/server.properties</span><br><span class="line">kafka2/bin/kafka-server-start.sh -daemon kafka2/config/server.properties</span><br><span class="line">kafka3/bin/kafka-server-start.sh -daemon kafka3/config/server.properties</span><br><span class="line"></span><br><span class="line">#暂停</span><br><span class="line">kafka1/bin/kafka-server-stop.sh</span><br><span class="line">kafka2/bin/kafka-server-stop.sh</span><br><span class="line">kafka3/bin/kafka-server-stop.sh</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">#创建Topic</span><br><span class="line"></span><br><span class="line">./kafka-topics.sh --create --zookeeper 192.168.7.100:12181 --replication-factor 2 --partitions 1 --topic shuaige</span><br><span class="line"></span><br><span class="line">#解释</span><br><span class="line"></span><br><span class="line">--replication-factor 2 #复制两份</span><br><span class="line"></span><br><span class="line">--partitions 1 #创建1个分区</span><br><span class="line"></span><br><span class="line">--topic #主题为shuaige</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">'''在一台服务器上创建一个发布者'''</span><br><span class="line"></span><br><span class="line">#创建一个broker,发布者</span><br><span class="line"></span><br><span class="line">./kafka-console-producer.sh --broker-list 192.168.7.100:19092 --topic shuaige</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">#在一台服务器上创建一个订阅者</span><br><span class="line"></span><br><span class="line">./kafka-console-consumer.sh --zookeeper localhost:12181 --topic shuaige --from-beginning</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">#查看topic</span><br><span class="line"></span><br><span class="line">./kafka-topics.sh --list --zookeeper localhost:12181</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">#查看topic状态</span><br><span class="line"></span><br><span class="line">/kafka-topics.sh --describe --zookeeper localhost:12181 --topic shuaige</span><br><span class="line"></span><br><span class="line">#下面是显示信息</span><br><span class="line"></span><br><span class="line">Topic:ssports PartitionCount:1 ReplicationFactor:2 Configs:</span><br><span class="line"></span><br><span class="line"> Topic: shuaige Partition: 0 Leader: 1 Replicas: 0,1 Isr: 1</span><br><span class="line"></span><br><span class="line">#分区为为1 复制因子为2 他的 shuaige的分区为0 </span><br><span class="line"></span><br><span class="line">#Replicas: 0,1 复制的为0,1</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure><h2 id="4-kafka日志"><a href="#4-kafka日志" class="headerlink" title="4.kafka日志"></a>4.kafka日志</h2><blockquote><p>可以通过配置server.properties文件中配置log.dirs参数来指定kafka的日志地址</p></blockquote><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">server.log #kafka的运行日志</span><br><span class="line"></span><br><span class="line">state-change.log #kafka他是用zookeeper来保存状态,所以他可能会进行切换,切换的日志就保存在这里</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">controller.log #kafka选择一个节点作为“controller”,当发现有节点down掉的时候它负责在游泳分区的所有节点中选择新的leader,这使得Kafka可以批量的高效的管理所有分区节点的主从关系。如果controller down掉了,活着的节点中的一个会备切换为新的controller.</span><br><span class="line"></span><br></pre></td></tr></table></figure><h2 id="5-kafka的一些基本概念"><a href="#5-kafka的一些基本概念" class="headerlink" title="5.kafka的一些基本概念"></a>5.kafka的一些基本概念</h2><ul><li><p>consumer 消费者:从消息队列中请求消息的客户端应用程序</p></li><li><p>producer 生产者:向broker发布消息的应用程序</p></li><li><p>broker AMQP服务端:用来接收生产者发送的消息并将这些消息路由给服务器中的队列,便于kfafka将生产者发送的消息,动态的添加到磁盘并给每一条消息一个偏移量,所以对于kafka一个broker就是一个应用程序的实例,即一个kafka节点。</p></li><li><p>partition 分区:一个Topic中的消息数据按照多个分区组织,分区是kafka消息队列组织的最小单位,一个分区可以看作是一个FIFO( First Input First Output的缩写,先入先出队列)的队列。</p></li><li><p>topic 主题:一个主题类似新闻中的体育、娱乐、教育等分类概念,在实际工程中通常一个业务一个主题</p></li><li><p>replication factor 副本因子:推送到kafka的消息都进行了持久化,集群模式为了防止数据丢失,需要将消息数据进行复制,副本因子即为消息数据的复制个数,类比hadoop。</p></li><li><p>controller 控制器:类似于hadoop的hdfs中的namenode,负责消息副本和分区leader的管理,一套kafka集群启动后选举出一个broker节点作为controller。</p></li></ul>]]></content>
<summary type="html"><h1 id="kafka的安装"><a href="#kafka的安装" class="headerlink" title="kafka的安装"></a>kafka的安装</h1><h2 id="1-下载安装"><a href="#1-下载安装" class="headerli</summary>
<category term="编程" scheme="http://xiaodongzi.cn/categories/%E7%BC%96%E7%A8%8B/"/>
<category term="kafka" scheme="http://xiaodongzi.cn/categories/%E7%BC%96%E7%A8%8B/kafka/"/>
<category term="编程" scheme="http://xiaodongzi.cn/tags/%E7%BC%96%E7%A8%8B/"/>
</entry>
<entry>
<title>正则表达式的那些事儿</title>
<link href="http://xiaodongzi.cn/2018/10/15/%E6%AD%A3%E5%88%99%E8%A1%A8%E8%BE%BE%E5%BC%8F%E7%9A%84%E9%82%A3%E4%BA%9B%E4%BA%8B%E5%84%BF/"/>
<id>http://xiaodongzi.cn/2018/10/15/%E6%AD%A3%E5%88%99%E8%A1%A8%E8%BE%BE%E5%BC%8F%E7%9A%84%E9%82%A3%E4%BA%9B%E4%BA%8B%E5%84%BF/</id>
<published>2018-10-15T14:10:55.000Z</published>
<updated>2020-12-05T08:55:25.552Z</updated>
<content type="html"><![CDATA[<h2 id="正则表达式引擎"><a href="#正则表达式引擎" class="headerlink" title="正则表达式引擎"></a>正则表达式引擎</h2><p>正则表达式是一个很方便的匹配符号,但要实现这么复杂,功能如此强大的匹配语法,就必须要有一套算法来实现,而实现这套算法的东西就叫做正则表达式引擎。简单地说,实现正则表达式引擎的有两种方式:DFA 自动机(Deterministic Final Automata 确定型有穷自动机)和 NFA 自动机(Non deterministic Finite Automaton 不确定型有穷自动机)。</p><p>对于这两种自动机,他们有各自的区别,这里并不打算深入将它们的原理。简单地说,DFA 自动机的时间复杂度是线性的,更加稳定,但是功能有限。而 NFA 的时间复杂度比较不稳定,有时候很好,有时候不怎么好,好不好取决于你写的正则表达式。但是胜在 NFA 的功能更加强大,所以包括 Java 、.NET、Perl、Python、Ruby、PHP 等语言都使用了 NFA 去实现其正则表达式。</p><h2 id="NFA自动机的回溯"><a href="#NFA自动机的回溯" class="headerlink" title="NFA自动机的回溯"></a>NFA自动机的回溯</h2><p>了解了 NFA 是如何进行字符串匹配的,接下来我们就可以讲讲这篇文章的重点了:回溯。为了更好地解释回溯,我们同样以下面的例子来讲解。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">text="abbc"regex="ab{1,3}c"</span><br></pre></td></tr></table></figure><p>上面的这个例子的目的比较简单,匹配以 a 开头,以 c 结尾,中间有 1-3 个 b 字符的字符串。NFA 对其解析的过程是这样子的:</p><ul><li>首先,读取正则表达式第一个匹配符 a 和 字符串第一个字符 a 比较,匹配了。于是读取正则表达式第二个字符。</li><li>读取正则表达式第二个匹配符 b{1,3} 和字符串的第二个字符 b 比较,匹配了。但因为 b{1,3} 表示 1-3 个 b 字符串,以及 NFA 自动机的贪婪特性(也就是说要尽可能多地匹配),所以此时并不会再去读取下一个正则表达式的匹配符,而是依旧使用 b{1,3} 和字符串的第三个字符 b 比较,发现还是匹配。于是继续使用 b{1,3} 和字符串的第四个字符 c 比较,发现不匹配了。此时就会发生回溯。</li><li>发生回溯是怎么操作呢?发生回溯后,我们已经读取的字符串第四个字符 c 将被吐出去,指针回到第三个字符串的位置。之后,程序读取正则表达式的下一个操作符 c,读取当前指针的下一个字符 c 进行对比,发现匹配。于是读取下一个操作符,但这里已经结束了。</li></ul>]]></content>
<summary type="html"><h2 id="正则表达式引擎"><a href="#正则表达式引擎" class="headerlink" title="正则表达式引擎"></a>正则表达式引擎</h2><p>正则表达式是一个很方便的匹配符号,但要实现这么复杂,功能如此强大的匹配语法,就必须要有一套算法来实现</summary>
<category term="编程" scheme="http://xiaodongzi.cn/categories/%E7%BC%96%E7%A8%8B/"/>
<category term="正则表达式" scheme="http://xiaodongzi.cn/categories/%E7%BC%96%E7%A8%8B/%E6%AD%A3%E5%88%99%E8%A1%A8%E8%BE%BE%E5%BC%8F/"/>
<category term="编程" scheme="http://xiaodongzi.cn/tags/%E7%BC%96%E7%A8%8B/"/>
</entry>
<entry>
<title>深入浅出Http和WebSocket</title>
<link href="http://xiaodongzi.cn/2018/10/12/%E6%B7%B1%E5%85%A5%E6%B5%85%E5%87%BAHTTP%E5%92%8CWebSocket/"/>
<id>http://xiaodongzi.cn/2018/10/12/%E6%B7%B1%E5%85%A5%E6%B5%85%E5%87%BAHTTP%E5%92%8CWebSocket/</id>
<published>2018-10-12T14:46:19.000Z</published>
<updated>2020-12-05T08:55:25.556Z</updated>
<content type="html"><![CDATA[<h2 id="关于http协议"><a href="#关于http协议" class="headerlink" title="关于http协议"></a>关于http协议</h2><blockquote><p>超文本传输协议(英文:HyperText Transfer Protocol,缩写:HTTP)是一种用于分布式、协作式和超媒体信息系统的应用层协议[1]。HTTP是万维网的数据通信的基础。</p></blockquote><p>设计HTTP最初的目的是为了提供一种发布和接收HTML页面的方法。通过HTTP或者HTTPS协议请求的资源由统一资源标识符(Uniform Resource Identifiers,URI)来标识</p><p>HTTP是一个客户端终端(用户)和服务器端(网站)请求和应答的标准(TCP)。通过使用网页浏览器、网络爬虫或者其它的工具,客户端发起一个HTTP请求到服务器上指定端口(默认端口为80)。我们称这个客户端为用户代理程序(user agent)。应答的服务器上存储着一些资源,比如HTML文件和图像。我们称这个应答服务器为源服务器(origin server)。在用户代理和源服务器中间可能存在多个“中间层”,比如代理服务器、网关或者隧道(tunnel)。</p><p>尽管TCP/IP协议是互联网上最流行的应用,HTTP协议中,并没有规定必须使用它或它支持的层。事实上,HTTP可以在任何互联网协议上,或其他网络上实现。HTTP假定其下层协议提供可靠的传输。因此,任何能够提供这种保证的协议都可以被其使用。因此也就是其在TCP/IP协议族使用TCP作为其传输层。</p><p>通常,由HTTP客户端发起一个请求,创建一个到服务器指定端口(默认是80端口)的TCP连接。HTTP服务器则在那个端口监听客户端的请求。一旦收到请求,服务器会向客户端返回一个状态,比如”HTTP/1.1 200 OK”,以及返回的内容,如请求的文件、错误消息、或者其它信息。</p><h2 id="http协议的弊端"><a href="#http协议的弊端" class="headerlink" title="http协议的弊端"></a>http协议的弊端</h2><ul><li>http协议是半双开工协议。半双开工协议指数据可以在客户端和服务端两个方向上传输,但是不能同时传输。它意味着在同一时刻,只有一个方向上的数据传送;</li><li>http消息冗长而繁琐。http消息包含消息头、消息体、换行符等,通常情况下采用文本方式传送,相比于其他的二进制通讯协议,冗长而繁琐;</li><li>针对服务器推送的黑客攻击。 例如长时间轮询;</li></ul><h2 id="关于websocket"><a href="#关于websocket" class="headerlink" title="关于websocket"></a>关于websocket</h2><blockquote><p>websocket 是 html5 开始提供的一种浏览器和服务器间进行全双工通讯的网络技术,websocket通讯协议于2011年被IETF定为标准 RFC6455,websocket API 被W3C 定为标准。</p></blockquote><h2 id="websocket的特点"><a href="#websocket的特点" class="headerlink" title="websocket的特点"></a>websocket的特点</h2><ul><li>单一的TCP连接,采用全双工模式通讯</li><li>对代理、防火墙和路由器透明</li><li>无头部信息、cookie和身份验证</li><li>无安全开销</li><li>通过“ping/pong” 帧保持链路激活</li><li>服务器可以主动传递消息给客户端,不再需要客户端轮询。</li></ul>]]></content>
<summary type="html"><h2 id="关于http协议"><a href="#关于http协议" class="headerlink" title="关于http协议"></a>关于http协议</h2><blockquote>
<p>超文本传输协议(英文:HyperText Transfer Pro</summary>
<category term="编程" scheme="http://xiaodongzi.cn/categories/%E7%BC%96%E7%A8%8B/"/>
<category term="网络" scheme="http://xiaodongzi.cn/categories/%E7%BC%96%E7%A8%8B/%E7%BD%91%E7%BB%9C/"/>
<category term="编程" scheme="http://xiaodongzi.cn/tags/%E7%BC%96%E7%A8%8B/"/>
</entry>
<entry>
<title>初识RabbitMQ</title>
<link href="http://xiaodongzi.cn/2018/10/10/%E5%88%9D%E8%AF%86RabbitMQ/"/>
<id>http://xiaodongzi.cn/2018/10/10/%E5%88%9D%E8%AF%86RabbitMQ/</id>
<published>2018-10-10T11:33:24.000Z</published>
<updated>2020-12-05T08:55:25.554Z</updated>
<content type="html"><![CDATA[<h2 id="参考资料"><a href="#参考资料" class="headerlink" title="参考资料"></a>参考资料</h2><blockquote><ul><li><a href=""></a></li><li><a href=""></a></li></ul></blockquote>]]></content>
<summary type="html"><h2 id="参考资料"><a href="#参考资料" class="headerlink" title="参考资料"></a>参考资料</h2><blockquote>
<ul>
<li><a href=""></a></li>
<li><a href=""></a></l</summary>
<category term="编程" scheme="http://xiaodongzi.cn/categories/%E7%BC%96%E7%A8%8B/"/>
<category term="RabbitMQ" scheme="http://xiaodongzi.cn/categories/%E7%BC%96%E7%A8%8B/RabbitMQ/"/>
<category term="编程" scheme="http://xiaodongzi.cn/tags/%E7%BC%96%E7%A8%8B/"/>
</entry>
<entry>
<title>聊一聊常用的登录认证方式</title>
<link href="http://xiaodongzi.cn/2018/09/30/%E8%81%8A%E4%B8%80%E8%81%8A%E5%B8%B8%E7%94%A8%E7%9A%84%E7%99%BB%E5%BD%95%E8%AE%A4%E8%AF%81%E6%96%B9%E5%BC%8F/"/>
<id>http://xiaodongzi.cn/2018/09/30/%E8%81%8A%E4%B8%80%E8%81%8A%E5%B8%B8%E7%94%A8%E7%9A%84%E7%99%BB%E5%BD%95%E8%AE%A4%E8%AF%81%E6%96%B9%E5%BC%8F/</id>
<published>2018-09-30T11:26:08.000Z</published>
<updated>2020-12-05T08:55:25.559Z</updated>
<content type="html"><![CDATA[<h2 id="介绍"><a href="#介绍" class="headerlink" title="介绍"></a>介绍</h2><blockquote><p>登录认证几乎是任何一个系统的标配,web 系统、APP、PC 客户端等,好多都需要注册、登录、授权认证。</p></blockquote><p>以一个电商系统,假设淘宝为例,如果我们想要下单,首先需要注册一个账号。拥有了账号之后,我们需要输入用户名(比如手机号或邮箱)、密码完成登录过程。之后如果你在一段时间内再次进入系统,是不需要输入用户名和密码的,只有在连续长时间不登录的情况下(例如一个月没登录过)访问系统,再次需要输入用户名和密码。如果使用频率很频繁,通常是一年都不用再输一次密码,所以经常在换了一台电脑或者一部手机之后,一些经常使用的网站或 APP 不记得密码了。</p><p>提炼出来整个过程大概就是如下几步:</p><blockquote><p>首次使用,需要通过邮箱或手机号注册;<br>注册完成后,需要提供用户名和密码完成登录;<br>下次再使用,通常不会再次输入用户名和密码即可直接进入系统并使用其功能(除非连续长时间未使用);</p></blockquote><h2 id="常用的认证方式"><a href="#常用的认证方式" class="headerlink" title="常用的认证方式"></a>常用的认证方式</h2><h3 id="OAuth-认证"><a href="#OAuth-认证" class="headerlink" title="OAuth 认证"></a>OAuth 认证</h3><p>OAuth 认证比较常见的就是微信登录、微博登录、qq登录等,简单来说就是利用这些比较权威的网站或应用开放的 API 来实现用户登录,用户可以不用在你的网站或应用上注册账号,直接用已有的微信、微博、qq 等账号登录。</p><p>这一样一来,即省了用户注册的时间,又简化了你的系统的账号体系。从而既可以提高用户注册率可以节省开发时间,同时,安全性也有了保障。</p><p>维基百科对它的解释摘要如下:</p><blockquote><p>OAuth允许用户提供一个令牌,而不是用户名和密码来访问他们存放在特定服务提供者的数据。每一个令牌>授权一个特定的网站(例如,视频编辑网站)在特定的时段(例如,接下来的2小时内)内访问特定的资源(例如仅仅是某一相册中的视频)。这样,OAuth让用户可以授权第三方网站访问他们存储在另外服务提供者的某些特定信息,而非所有内容。</p></blockquote><p>假设我们开发了一个电商平台,并集成了微信登录,以这个场景为例,说一下 OAuth 的工作原理。</p><p>讲之前需要了解其中涉及到的几个角色:</p><ul><li>用户:即使用我们平台的用户</li><li>用户终端:即最终用户使用的 APP 端或 web 端</li><li>应用服务器端:即我们的服务器端</li><li>授权服务器端:这里就是微信处理授权请求的服务器</li></ul><p>好的,接下来开始在我们的电商平台web端实现微信登录功能。微信网页授权是授权码模式(authorization code)的 OAuth 授权模式。</p><ul><li>我们电商平台的用户过来登录,常用场景是点击“微信登录”按钮;</li><li>接下来,用户终端将用户引导到微信授权页面;</li><li>用户同意授权,应用服务器重定向到之前设置好的 redirect_uri (应用服务器所在的地址),并附带上授权码(code);</li><li>应用服务器用上一步获取的 code 向微信授权服务器发送请求,获取 access_token,也就是上面说的令牌;</li><li>之后应用服务器用上一步获取的 access_token 去请求微信授权服务器获取用户的基本信息,例如头像、昵称等;</li></ul><h3 id="Cookie-Session认证"><a href="#Cookie-Session认证" class="headerlink" title="Cookie-Session认证"></a>Cookie-Session认证</h3><p>早期互联网以 web 为主,客户端是浏览器,所以 Cookie-Session 方式最那时候最常用的方式,直到现在,一些 web 网站依然用这种方式做认证。</p><p>认证过程大致如下:</p><ul><li>用户输入用户名、密码或者用短信验证码方式登录系统;</li><li>服务端验证后,创建一个 Session 信息,并且将 SessionID 存到 cookie,发送回浏览器;</li><li>下次客户端再发起请求,自动带上 cookie 信息,服务端通过 cookie 获取 Session 信息进行校验;</li></ul><p>弊端:</p><ul><li>只能在 web 场景下使用,如果是 APP 中,不能使用 cookie 的情况下就不能用了;</li><li>即使能在 web 场景下使用,也要考虑跨域问题,因为 cookie 不能跨域;</li><li>cookie 存在 CSRF(跨站请求伪造)的风险;</li><li>如果是分布式服务,需要考虑 Session 同步问题;</li></ul><h3 id="Cookie-Session改造版"><a href="#Cookie-Session改造版" class="headerlink" title="Cookie-Session改造版"></a>Cookie-Session改造版</h3><p>由于传统的 Cookie-Session 认证存在诸多问题,可以把上面的方案改造一下。改动的地方如下:</p><ul><li><p>不用 cookie 做客户端存储,改用其他方式,web 下使用 local storage,APP 中使用客户端数据库,这样就实现了跨域,并且避免了 CSRF ;</p></li><li><p>服务端也不存 Session 了,把 Session 信息拿出来存到 Redis 等内存数据库中,这样即提高了速度,又避免了 Session 同步问题;<br>经过改造之后变成了如下的认证过程:</p></li><li><p>用户输入用户名、密码或者用短信验证码方式登录系统;</p></li><li><p>服务端经过验证,将认证信息构造好的数据结构存储到 Redis 中,并将 key 值返回给客户端;</p></li><li><p>客户端拿到返回的 key,存储到 local storage 或本地数据库;</p></li><li><p>下次客户端再次请求,把 key 值附加到 header 或者 请求体中;</p></li><li><p>服务端根据获取的 key,到 Redis 中获取认证信息;</p></li></ul><h3 id="基于JWT的Token认证"><a href="#基于JWT的Token认证" class="headerlink" title="基于JWT的Token认证"></a>基于JWT的Token认证</h3><p>上面的方案虽然经过了改版,但还是需要客户端和服务器端维持一个状态信息,比如用 cookie 换 session ,或者用 key 换 Redis 的 value 信息,基于 JWT 的 Token 认证方案可以省去这个过程。</p><p>JSON Web Token(JWT)是一个非常轻巧的规范。这个规范允许我们使用JWT在用户和服务器之间传递安全可靠的信息。</p><p>认证过程</p><ul><li>依然是用户登录系统;</li><li>服务端验证,将认证信息通过指定的算法(例如HS256)进行加密,例如对用户名和用户所属角色进行加密,加密私钥是保存在服务器端的,将加密后的结果发送给客户端,加密的字符串格式为三个”.” 分隔的字符串 Token,分别对应头部、载荷与签名,头部和载荷都可以通过 base64 解码出来,签名部分不可以;</li><li>客户端拿到返回的 Token,存储到 local storage 或本地数据库;</li><li>下次客户端再次发起请求,将 Token 附加到 header 中;</li><li>服务端获取 header 中的 Token ,通过相同的算法对 Token 中的用户名和所属角色进行相同的加密验证,如果验证结果相同,则说明这个请求是正常的,没有被篡改。这个过程可以完全不涉及到查询 Redis 或其他存储;</li></ul><p>优点:</p><ul><li>使用 json 作为数据传输,有广泛的通用型,并且体积小,便于传输;</li><li>不需要在服务器端保存相关信息;</li><li>jwt 载荷部分可以存储业务相关的信息(非敏感的),例如用户信息、角色等;</li></ul><h2 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h2><p>综上所述,JWT 可以作为首选的认证方案。当然,具体的情况具体分析,还要看是不是适合真实的应用场景。除了上述的这些,涉及到信息安全的,建议全部采用 https 方式部署,采用 https 方式,信息很难被嗅探破解,对应用的安全性很重要。</p><h2 id="参考资料"><a href="#参考资料" class="headerlink" title="参考资料"></a>参考资料</h2><blockquote><p>OAuth - <a href="http://www.ruanyifeng.com/blog/2014/05/oauth_2_0.html">http://www.ruanyifeng.com/blog/2014/05/oauth_2_0.html</a></p></blockquote><blockquote><p>JWT- [<a href="https://jwt.io/introduction/">https://jwt.io/introduction/</a> <a href="http://blog.leapoahead.com/2015/09/06/understanding-jwt]">http://blog.leapoahead.com/2015/09/06/understanding-jwt]</a>(<a href="https://jwt.io/introduction/">https://jwt.io/introduction/</a> <a href="http://blog.leapoahead.com/2015/09/06/understanding-jwt">http://blog.leapoahead.com/2015/09/06/understanding-jwt</a>)</p></blockquote><blockquote><p>JWT Java 库- <a href="https://github.com/jwtk/jjwt">https://github.com/jwtk/jjwt</a></p></blockquote>]]></content>
<summary type="html"><h2 id="介绍"><a href="#介绍" class="headerlink" title="介绍"></a>介绍</h2><blockquote>
<p>登录认证几乎是任何一个系统的标配,web 系统、APP、PC 客户端等,好多都需要注册、登录、授权认证。</p>
</summary>
<category term="编程" scheme="http://xiaodongzi.cn/categories/%E7%BC%96%E7%A8%8B/"/>
<category term="安全" scheme="http://xiaodongzi.cn/categories/%E7%BC%96%E7%A8%8B/%E5%AE%89%E5%85%A8/"/>
<category term="编程" scheme="http://xiaodongzi.cn/tags/%E7%BC%96%E7%A8%8B/"/>
</entry>
<entry>
<title>OAuth 2.0介绍[转]</title>
<link href="http://xiaodongzi.cn/2018/09/26/OAuth-2-0%E4%BB%8B%E7%BB%8D-%E8%BD%AC/"/>
<id>http://xiaodongzi.cn/2018/09/26/OAuth-2-0%E4%BB%8B%E7%BB%8D-%E8%BD%AC/</id>
<published>2018-09-26T12:55:51.000Z</published>
<updated>2020-12-07T05:38:44.387Z</updated>
<content type="html"><![CDATA[<h2 id="OAuth"><a href="#OAuth" class="headerlink" title="OAuth"></a>OAuth</h2><blockquote><p>OAuth 是一个关于授权(authorization)的开放网络标准,在全世界得到广泛应用,目前的版本是2.0版。</p></blockquote><blockquote><p>本文对OAuth 2.0的设计思路和运行流程,做一个简明通俗的解释,主要参考材料为 RFC 6749。</p></blockquote><p><img src="https://raw.githubusercontent.com/eastFu/docs/master/blog/oauth/oauth-logo.png" alt="OAuth Logo"></p><h2 id="应用场景"><a href="#应用场景" class="headerlink" title="应用场景"></a>应用场景</h2><p>为了理解OAuth的适用场合,让我举一个假设的例子。</p><p>有一个”云冲印”的网站,可以将用户储存在Google的照片,冲印出来。用户为了使用该服务,必须让”云冲印”读取自己储存在Google上的照片。</p><p><img src="https://raw.githubusercontent.com/eastFu/docs/master/blog/oauth/%E4%BA%91%E5%86%B2%E6%B4%97.png" alt="云冲印"></p><p>问题是只有得到用户的授权,Google才会同意”云冲印”读取这些照片。那么,”云冲印”怎样获得用户的授权呢?</p><p>传统方法是,用户将自己的Google用户名和密码,告诉”云冲印”,后者就可以读取用户的照片了。这样的做法有以下几个严重的缺点。</p><ol><li><p>”云冲印”为了后续的服务,会保存用户的密码,这样很不安全。</p></li><li><p>Google不得不部署密码登录,而我们知道,单纯的密码登录并不安全。</p></li><li><p>”云冲印”拥有了获取用户储存在Google所有资料的权力,用户没法限制”云冲印”获得授权的范围和有效期。</p></li><li><p>用户只有修改密码,才能收回赋予”云冲印”的权力。但是这样做,会使得其他所有获得用户授权的第三方应用程序全部失效。</p></li><li><p>只要有一个第三方应用程序被破解,就会导致用户密码泄漏,以及所有被密码保护的数据泄漏。</p></li></ol><p>OAuth就是为了解决上面这些问题而诞生的。</p><h2 id="名词定义"><a href="#名词定义" class="headerlink" title="名词定义"></a>名词定义</h2><p>在详细讲解OAuth 2.0之前,需要了解几个专用名词。它们对读懂后面的讲解,尤其是几张图,至关重要。</p><ol><li><p>Third-party application:第三方应用程序,本文中又称”客户端”(client),即上一节例子中的”云冲印”。</p></li><li><p>HTTP service:HTTP服务提供商,本文中简称”服务提供商”,即上一节例子中的Google。</p></li><li><p>Resource Owner:资源所有者,本文中又称”用户”(user)。</p></li><li><p>User Agent:用户代理,本文中就是指浏览器。</p></li><li><p>Authorization server:认证服务器,即服务提供商专门用来处理认证的服务器。</p></li><li><p>Resource server:资源服务器,即服务提供商存放用户生成的资源的服务器。它与认证服务器,可以是同一台服务器,也可以是不同的服务器。</p></li></ol><p>知道了上面这些名词,就不难理解,OAuth的作用就是让”客户端”安全可控地获取”用户”的授权,与”服务商提供商”进行互动。</p><h2 id="OAuth的思路"><a href="#OAuth的思路" class="headerlink" title="OAuth的思路"></a>OAuth的思路</h2><p>OAuth在”客户端”与”服务提供商”之间,设置了一个授权层(authorization layer)。”客户端”不能直接登录”服务提供商”,只能登录授权层,以此将用户与客户端区分开来。”客户端”登录授权层所用的令牌(token),与用户的密码不同。用户可以在登录的时候,指定授权层令牌的权限范围和有效期。</p><p>“客户端”登录授权层以后,”服务提供商”根据令牌的权限范围和有效期,向”客户端”开放用户储存的资料。</p><h2 id="运行流程"><a href="#运行流程" class="headerlink" title="运行流程"></a>运行流程</h2><p>OAuth 2.0的运行流程如下图,摘自RFC 6749。</p><p>OAuth运行流程</p><ol><li><p>用户打开客户端以后,客户端要求用户给予授权。</p></li><li><p>用户同意给予客户端授权。</p></li><li><p>客户端使用上一步获得的授权,向认证服务器申请令牌。</p></li><li><p>认证服务器对客户端进行认证以后,确认无误,同意发放令牌。</p></li><li><p>客户端使用令牌,向资源服务器申请获取资源。</p></li><li><p>资源服务器确认令牌无误,同意向客户端开放资源。</p></li></ol><p>不难看出来,上面六个步骤之中,B是关键,即用户怎样才能给于客户端授权。有了这个授权以后,客户端就可以获取令牌,进而凭令牌获取资源。</p><p>下面一一讲解客户端获取授权的四种模式。</p><h2 id="客户端的授权模式"><a href="#客户端的授权模式" class="headerlink" title="客户端的授权模式"></a>客户端的授权模式</h2><p>客户端必须得到用户的授权(authorization grant),才能获得令牌(access token)。OAuth 2.0定义了四种授权方式。</p><p>授权码模式(authorization code)</p><p>简化模式(implicit)</p><p>密码模式(resource owner password credentials)</p><p>客户端模式(client credentials)</p><h2 id="授权码模式"><a href="#授权码模式" class="headerlink" title="授权码模式"></a>授权码模式</h2><p>授权码模式(authorization code)是功能最完整、流程最严密的授权模式。它的特点就是通过客户端的后台服务器,与”服务提供商”的认证服务器进行互动。</p><p>授权码模式</p><p>它的步骤如下:</p><ol><li><p>用户访问客户端,后者将前者导向认证服务器。</p></li><li><p>用户选择是否给予客户端授权。</p></li><li><p>假设用户给予授权,认证服务器将用户导向客户端事先指定的”重定向URI”(redirection URI),同时附上一个授权码。</p></li><li><p>客户端收到授权码,附上早先的”重定向URI”,向认证服务器申请令牌。这一步是在客户端的后台的服务器上完成的,对用户不可见。</p></li><li><p>认证服务器核对了授权码和重定向URI,确认无误后,向客户端发送访问令牌(access token)和更新令牌(refresh token)。</p></li></ol><p>下面是上面这些步骤所需要的参数。</p><p>1步骤中,客户端申请认证的URI,包含以下参数:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">response_type:表示授权类型,必选项,此处的值固定为"code"</span><br><span class="line">client_id:表示客户端的ID,必选项</span><br><span class="line">redirect_uri:表示重定向URI,可选项</span><br><span class="line">scope:表示申请的权限范围,可选项</span><br><span class="line">state:表示</span><br></pre></td></tr></table></figure><p>客户端的当前状态,可以指定任意值,认证服务器会原封不动地返回这个值。</p><p>下面是一个例子。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">GET /authorize?response_type=code&client_id=s6BhdRkqt3&state=xyz</span><br><span class="line"> &redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb HTTP/1.1</span><br><span class="line">Host: server.example.com</span><br></pre></td></tr></table></figure><p>3步骤中,服务器回应客户端的URI,包含以下参数:</p><p>code:表示授权码,必选项。该码的有效期应该很短,通常设为10分钟,客户端只能使用该码一次,否则会被授权服务器拒绝。该码与客户端ID和重定向URI,是一一对应关系。<br>state:如果客户端的请求中包含这个参数,认证服务器的回应也必须一模一样包含这个参数。<br>下面是一个例子。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">HTTP/1.1 302 Found</span><br><span class="line">Location: https://client.example.com/cb?code=SplxlOBeZQQYbYS6WxSbIA</span><br><span class="line"> &state=xyz</span><br></pre></td></tr></table></figure><p>4步骤中,客户端向认证服务器申请令牌的HTTP请求,包含以下参数:</p><p>grant_type:表示使用的授权模式,必选项,此处的值固定为”authorization_code”。<br>code:表示上一步获得的授权码,必选项。<br>redirect_uri:表示重定向URI,必选项,且必须与A步骤中的该参数值保持一致。<br>client_id:表示客户端ID,必选项。<br>下面是一个例子。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">POST /token HTTP/1.1</span><br><span class="line">Host: server.example.com</span><br><span class="line">Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW</span><br><span class="line">Content-Type: application/x-www-form-urlencoded</span><br><span class="line"></span><br><span class="line">grant_type=authorization_code&code=SplxlOBeZQQYbYS6WxSbIA</span><br><span class="line">&redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb</span><br></pre></td></tr></table></figure><p>5步骤中,认证服务器发送的HTTP回复,包含以下参数:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">access_token:表示访问令牌,必选项。</span><br><span class="line">token_type:表示令牌类型,该值大小写不敏感,必选项,可以是bearer类型或mac类型。</span><br><span class="line">expires_in:表示过期时间,单位为秒。如果省略该参数,必须其他方式设置过期时间。</span><br><span class="line">refresh_token:表示更新令牌,用来获取下一次的访问令牌,可选项。</span><br><span class="line">scope:表示权限范围,如果与客户端申请的范围一致,此项可省略。</span><br></pre></td></tr></table></figure><p>下面是一个例子。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">HTTP/1.1 200 OK</span><br><span class="line"> Content-Type: application/json;charset=UTF-8</span><br><span class="line"> Cache-Control: no-store</span><br><span class="line"> Pragma: no-cache</span><br><span class="line"></span><br><span class="line"> {</span><br><span class="line"> "access_token":"2YotnFZFEjr1zCsicMWpAA",</span><br><span class="line"> "token_type":"example",</span><br><span class="line"> "expires_in":3600,</span><br><span class="line"> "refresh_token":"tGzv3JOkF0XG5Qx2TlKWIA",</span><br><span class="line"> "example_parameter":"example_value"</span><br><span class="line"> }</span><br></pre></td></tr></table></figure><p>从上面代码可以看到,相关参数使用JSON格式发送(Content-Type: application/json)。此外,HTTP头信息中明确指定不得缓存。</p><h2 id="简化模式"><a href="#简化模式" class="headerlink" title="简化模式"></a>简化模式</h2><p>简化模式(implicit grant type)不通过第三方应用程序的服务器,直接在浏览器中向认证服务器申请令牌,跳过了”授权码”这个步骤,因此得名。所有步骤在浏览器中完成,令牌对访问者是可见的,且客户端不需要认证。</p><p>简化模式</p><p>它的步骤如下:</p><ol><li><p>客户端将用户导向认证服务器。</p></li><li><p>用户决定是否给于客户端授权。</p></li><li><p>假设用户给予授权,认证服务器将用户导向客户端指定的”重定向URI”,并在URI的Hash部分包含了访问令牌。</p></li><li><p>浏览器向资源服务器发出请求,其中不包括上一步收到的Hash值。</p></li><li><p>资源服务器返回一个网页,其中包含的代码可以获取Hash值中的令牌。</p></li><li><p>浏览器执行上一步获得的脚本,提取出令牌。</p></li><li><p>浏览器将令牌发给客户端。</p></li></ol><p>下面是上面这些步骤所需要的参数。</p><p>1步骤中,客户端发出的HTTP请求,包含以下参数:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">response_type:表示授权类型,此处的值固定为"token",必选项。</span><br><span class="line">client_id:表示客户端的ID,必选项。</span><br><span class="line">redirect_uri:表示重定向的URI,可选项。</span><br><span class="line">scope:表示权限范围,可选项。</span><br><span class="line">state:表示客户端的当前状态,可以指定任意值,认证服务器会原封不动地返回这个值。</span><br></pre></td></tr></table></figure><p>下面是一个例子。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">GET /authorize?response_type=token&client_id=s6BhdRkqt3&state=xyz</span><br><span class="line"> &redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb HTTP/1.1</span><br><span class="line">Host: server.example.com</span><br></pre></td></tr></table></figure><p>3步骤中,认证服务器回应客户端的URI,包含以下参数:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">access_token:表示访问令牌,必选项。</span><br><span class="line">token_type:表示令牌类型,该值大小写不敏感,必选项。</span><br><span class="line">expires_in:表示过期时间,单位为秒。如果省略该参数,必须其他方式设置过期时间。</span><br><span class="line">scope:表示权限范围,如果与客户端申请的范围一致,此项可省略。</span><br><span class="line">state:如果客户端的请求中包含这个参数,认证服务器的回应也必须一模一样包含这个参数。</span><br></pre></td></tr></table></figure><p>下面是一个例子。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">HTTP/1.1 302 Found</span><br><span class="line"> Location: http://example.com/cb#access_token=2YotnFZFEjr1zCsicMWpAA</span><br><span class="line"> &state=xyz&token_type=example&expires_in=3600</span><br></pre></td></tr></table></figure><p>在上面的例子中,认证服务器用HTTP头信息的Location栏,指定浏览器重定向的网址。注意,在这个网址的Hash部分包含了令牌。</p><p>根据上面的D步骤,下一步浏览器会访问Location指定的网址,但是Hash部分不会发送。接下来的E步骤,服务提供商的资源服务器发送过来的代码,会提取出Hash中的令牌。</p><h2 id="密码模式"><a href="#密码模式" class="headerlink" title="密码模式"></a>密码模式</h2><p>密码模式(Resource Owner Password Credentials Grant)中,用户向客户端提供自己的用户名和密码。客户端使用这些信息,向”服务商提供商”索要授权。</p><p>在这种模式中,用户必须把自己的密码给客户端,但是客户端不得储存密码。这通常用在用户对客户端高度信任的情况下,比如客户端是操作系统的一部分,或者由一个著名公司出品。而认证服务器只有在其他授权模式无法执行的情况下,才能考虑使用这种模式。</p><p>密码模式</p><p>它的步骤如下:</p><ol><li><p>用户向客户端提供用户名和密码。</p></li><li><p>客户端将用户名和密码发给认证服务器,向后者请求令牌。</p></li><li><p>认证服务器确认无误后,向客户端提供访问令牌。</p></li></ol><p>2步骤中,客户端发出的HTTP请求,包含以下参数:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">grant_type:表示授权类型,此处的值固定为"password",必选项。</span><br><span class="line">username:表示用户名,必选项。</span><br><span class="line">password:表示用户的密码,必选项。</span><br><span class="line">scope:表示权限范围,可选项。</span><br></pre></td></tr></table></figure><p>下面是一个例子。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">POST /token HTTP/1.1</span><br><span class="line"> Host: server.example.com</span><br><span class="line"> Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW</span><br><span class="line"> Content-Type: application/x-www-form-urlencoded</span><br><span class="line"></span><br><span class="line"> grant_type=password&username=johndoe&password=A3ddj3w</span><br></pre></td></tr></table></figure><p>3步骤中,认证服务器向客户端发送访问令牌,下面是一个例子。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">HTTP/1.1 200 OK</span><br><span class="line"> Content-Type: application/json;charset=UTF-8</span><br><span class="line"> Cache-Control: no-store</span><br><span class="line"> Pragma: no-cache</span><br><span class="line"></span><br><span class="line"> {</span><br><span class="line"> "access_token":"2YotnFZFEjr1zCsicMWpAA",</span><br><span class="line"> "token_type":"example",</span><br><span class="line"> "expires_in":3600,</span><br><span class="line"> "refresh_token":"tGzv3JOkF0XG5Qx2TlKWIA",</span><br><span class="line"> "example_parameter":"example_value"</span><br><span class="line"> }</span><br></pre></td></tr></table></figure><p>上面代码中,各个参数的含义参见《授权码模式》一节。</p><p>整个过程中,客户端不得保存用户的密码。</p><h2 id="客户端模式"><a href="#客户端模式" class="headerlink" title="客户端模式"></a>客户端模式</h2><p>客户端模式(Client Credentials Grant)指客户端以自己的名义,而不是以用户的名义,向”服务提供商”进行认证。严格地说,客户端模式并不属于OAuth框架所要解决的问题。在这种模式中,用户直接向客户端注册,客户端以自己的名义要求”服务提供商”提供服务,其实不存在授权问题。</p><p>客户端模式</p><p>它的步骤如下:</p><ol><li><p>客户端向认证服务器进行身份认证,并要求一个访问令牌。</p></li><li><p>认证服务器确认无误后,向客户端提供访问令牌。</p></li></ol><p>1步骤中,客户端发出的HTTP请求,包含以下参数:</p><p>granttype:表示授权类型,此处的值固定为”clientcredentials”,必选项。<br>scope:表示权限范围,可选项。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">POST /token HTTP/1.1</span><br><span class="line"> Host: server.example.com</span><br><span class="line"> Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW</span><br><span class="line"> Content-Type: application/x-www-form-urlencoded</span><br><span class="line"></span><br><span class="line"> grant_type=client_credentials</span><br></pre></td></tr></table></figure><p>认证服务器必须以某种方式,验证客户端身份。</p><p>2步骤中,认证服务器向客户端发送访问令牌,下面是一个例子。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">HTTP/1.1 200 OK</span><br><span class="line"> Content-Type: application/json;charset=UTF-8</span><br><span class="line"> Cache-Control: no-store</span><br><span class="line"> Pragma: no-cache</span><br><span class="line"></span><br><span class="line"> {</span><br><span class="line"> "access_token":"2YotnFZFEjr1zCsicMWpAA",</span><br><span class="line"> "token_type":"example",</span><br><span class="line"> "expires_in":3600,</span><br><span class="line"> "example_parameter":"example_value"</span><br><span class="line"> }</span><br></pre></td></tr></table></figure><p>上面代码中,各个参数的含义参见《授权码模式》一节。</p><h2 id="更新令牌"><a href="#更新令牌" class="headerlink" title="更新令牌"></a>更新令牌</h2><p>如果用户访问的时候,客户端的”访问令牌”已经过期,则需要使用”更新令牌”申请一个新的访问令牌。</p><p>客户端发出更新令牌的HTTP请求,包含以下参数:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">granttype:表示使用的授权模式,此处的值固定为"refreshtoken",必选项。</span><br><span class="line">refresh_token:表示早前收到的更新令牌,必选项。</span><br><span class="line">scope:表示申请的授权范围,不可以超出上一次申请的范围,如果省略该参数,则表示与上一次一致。</span><br></pre></td></tr></table></figure><p>下面是一个例子。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">POST /token HTTP/1.1</span><br><span class="line"> Host: server.example.com</span><br><span class="line"> Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW</span><br><span class="line"> Content-Type: application/x-www-form-urlencoded</span><br><span class="line"></span><br><span class="line"> grant_type=refresh_token&refresh_token=tGzv3JOkF0XG5Qx2TlKWIA</span><br></pre></td></tr></table></figure><p>(完)</p><p>原文转载地址: <a href="http://www.ruanyifeng.com/blog/2014/05/oauth_2_0.html">http://www.ruanyifeng.com/blog/2014/05/oauth_2_0.html</a></p>]]></content>
<summary type="html"><h2 id="OAuth"><a href="#OAuth" class="headerlink" title="OAuth"></a>OAuth</h2><blockquote>
<p>OAuth 是一个关于授权(authorization)的开放网络标准,在全世界得到广泛应</summary>
<category term="编程" scheme="http://xiaodongzi.cn/categories/%E7%BC%96%E7%A8%8B/"/>
<category term="OAuth" scheme="http://xiaodongzi.cn/categories/%E7%BC%96%E7%A8%8B/OAuth/"/>
<category term="编程" scheme="http://xiaodongzi.cn/tags/%E7%BC%96%E7%A8%8B/"/>
</entry>
<entry>
<title>spring boot中的banner.txt</title>
<link href="http://xiaodongzi.cn/2018/09/25/Spring-Boot%E4%B8%AD%E7%9A%84banner-txt/"/>
<id>http://xiaodongzi.cn/2018/09/25/Spring-Boot%E4%B8%AD%E7%9A%84banner-txt/</id>
<published>2018-09-25T11:19:25.000Z</published>
<updated>2020-12-05T08:55:25.561Z</updated>
<content type="html"><![CDATA[<h2 id="关于banneer"><a href="#关于banneer" class="headerlink" title="关于banneer"></a>关于banneer</h2><p>banner是spring boot 应用启动时打印在控制台的彩蛋信息,默认是这样的</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">. ____ _ __ _ _</span><br><span class="line"> /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \</span><br><span class="line">( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \</span><br><span class="line"> \\/ ___)| |_)| | | | | || (_| | ) ) ) )</span><br><span class="line"> ' |____| .__|_| |_|_| |_\__, | / / / /</span><br><span class="line"> =========|_|==============|___/=/_/_/_/</span><br><span class="line"> :: Spring Boot :: (v1.4.3.RELEASE)</span><br></pre></td></tr></table></figure><h2 id="DIY"><a href="#DIY" class="headerlink" title="DIY"></a>DIY</h2><p>想要修改这个文本的话,只需要在resources下新建banner.txt即可。这里可以自定义banner: <a href="http://patorjk.com/software/taag">http://patorjk.com/software/taag</a></p><h2 id="看这里"><a href="#看这里" class="headerlink" title="看这里"></a>看这里</h2><p>闲来无事收集了一些有趣的注释,各式各样的都有,程序员真是一群有趣的人,喜欢哪一款拿走不谢,还可以用到bannner文件中</p><h3 id="第一款:佛祖保佑,永无BUG"><a href="#第一款:佛祖保佑,永无BUG" class="headerlink" title="第一款:佛祖保佑,永无BUG"></a>第一款:佛祖保佑,永无BUG</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line">// _ooOoo_</span><br><span class="line">// o8888888o</span><br><span class="line">// 88" . "88</span><br><span class="line">// (| -_- |)</span><br><span class="line">// O\ = /O</span><br><span class="line">// ____/`---'\____</span><br><span class="line">// . ' \\| |// `.</span><br><span class="line">// / \\||| : |||// \</span><br><span class="line">// / _||||| -:- |||||- \</span><br><span class="line">// | | \\\ - /// | |</span><br><span class="line">// | \_| ''\---/'' | |</span><br><span class="line">// \ .-\__ `-` ___/-. /</span><br><span class="line">// ___`. .' /--.--\ `. . __</span><br><span class="line">// ."" '< `.___\_<|>_/___.' >'"".</span><br><span class="line">// | | : `- \`.;`\ _ /`;.`/ - ` : | |</span><br><span class="line">// \ \ `-. \_ __\ /__ _/ .-` / /</span><br><span class="line">// ======`-.____`-.___\_____/___.-`____.-'======</span><br><span class="line">// `=---='</span><br><span class="line">//</span><br><span class="line">// .............................................</span><br><span class="line">// 佛祖保佑 永无BUG</span><br></pre></td></tr></table></figure><h3 id="第二款:神兽护体,永无BUG"><a href="#第二款:神兽护体,永无BUG" class="headerlink" title="第二款:神兽护体,永无BUG"></a>第二款:神兽护体,永无BUG</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br></pre></td><td class="code"><pre><span class="line">// ┏┓ ┏┓</span><br><span class="line">// ┏┛┻━━━┛┻┓</span><br><span class="line">// ┃ ┃</span><br><span class="line">// ┃ ━ ┃</span><br><span class="line">// ┃ ┳┛ ┗┳ ┃</span><br><span class="line">// ┃ ┃</span><br><span class="line">// ┃ ┻ ┃</span><br><span class="line">// ┃ ┃</span><br><span class="line">// ┗━┓ ┏━┛</span><br><span class="line">// ┃ ┃ Code is far away from bug with the animal protecting</span><br><span class="line">// ┃ ┃ 神兽保护,永无BUG!</span><br><span class="line">// ┃ ┗━━━┓</span><br><span class="line">// ┃ ┣┓</span><br><span class="line">// ┃ ┏┛</span><br><span class="line">// ┗┓┓┏━┳┓┏┛</span><br><span class="line">// ┃┫┫ ┃┫┫</span><br><span class="line">// ┗┻┛ ┗┻┛</span><br><span class="line">/**</span><br><span class="line"> * ┏┓ ┏┓+ +</span><br><span class="line"> * ┏┛┻━━━┛┻┓ + +</span><br><span class="line"> * ┃ ┃</span><br><span class="line"> * ┃ ━ ┃ ++ + + +</span><br><span class="line"> * ████━████ ┃+</span><br><span class="line"> * ┃ ┃ +</span><br><span class="line"> * ┃ ┻ ┃</span><br><span class="line"> * ┃ ┃ + +</span><br><span class="line"> * ┗━┓ ┏━┛</span><br><span class="line"> * ┃ ┃</span><br><span class="line"> * ┃ ┃ + + + +</span><br><span class="line"> * ┃ ┃ Code is far away from bug with the animal protecting</span><br><span class="line"> * ┃ ┃ + 神兽保佑,永无bug</span><br><span class="line"> * ┃ ┃</span><br><span class="line"> * ┃ ┃ +</span><br><span class="line"> * ┃ ┗━━━┓ + +</span><br><span class="line"> * ┃ ┣┓</span><br><span class="line"> * ┃ ┏┛</span><br><span class="line"> * ┗┓┓┏━┳┓┏┛ + + + +</span><br><span class="line"> * ┃┫┫ ┃┫┫</span><br><span class="line"> * ┗┻┛ ┗┻┛+ + + +</span><br><span class="line"> */</span><br></pre></td></tr></table></figure><h3 id="第三款:来首程序员打油诗,笑"><a href="#第三款:来首程序员打油诗,笑" class="headerlink" title="第三款:来首程序员打油诗,笑"></a>第三款:来首程序员打油诗,笑</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line">/**</span><br><span class="line"> * 江城子 . 程序员之歌</span><br><span class="line"> *</span><br><span class="line"> * 十年生死两茫茫,写程序,到天亮。</span><br><span class="line"> * 千行代码,Bug何处藏。</span><br><span class="line"> * 纵使上线又怎样,朝令改,夕断肠。</span><br><span class="line"> *</span><br><span class="line"> * 领导每天新想法,天天改,日日忙。</span><br><span class="line"> * 相顾无言,惟有泪千行。</span><br><span class="line"> * 每晚灯火阑珊处,夜难寐,加班狂。</span><br><span class="line">*/</span><br><span class="line">/**</span><br><span class="line"> * 写字楼里写字间,写字间里程序员;</span><br><span class="line"> * 程序人员写程序,又拿程序换酒钱。</span><br><span class="line"> * 酒醒只在网上坐,酒醉还来网下眠;</span><br><span class="line"> * 酒醉酒醒日复日,网上网下年复年。</span><br><span class="line"> * 但愿老死电脑间,不愿鞠躬老板前;</span><br><span class="line"> * 奔驰宝马贵者趣,公交自行程序员。</span><br><span class="line"> * 别人笑我忒疯癫,我笑自己命太贱;</span><br><span class="line"> * 不见满街漂亮妹,哪个归得程序员?</span><br><span class="line"> */</span><br></pre></td></tr></table></figure><h3 id="第四款:无尽诱惑"><a href="#第四款:无尽诱惑" class="headerlink" title="第四款:无尽诱惑"></a>第四款:无尽诱惑</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br></pre></td><td class="code"><pre><span class="line">//</span><br><span class="line">// .::::.</span><br><span class="line">// .::::::::.</span><br><span class="line">// :::::::::::</span><br><span class="line">// ..:::::::::::'</span><br><span class="line">// '::::::::::::'</span><br><span class="line">// .::::::::::</span><br><span class="line">// '::::::::::::::..</span><br><span class="line">// ..::::::::::::.</span><br><span class="line">// ``::::::::::::::::</span><br><span class="line">// ::::``:::::::::' .:::.</span><br><span class="line">// ::::' ':::::' .::::::::.</span><br><span class="line">// .::::' :::: .:::::::'::::.</span><br><span class="line">// .:::' ::::: .:::::::::' ':::::.</span><br><span class="line">// .::' :::::.:::::::::' ':::::.</span><br><span class="line">// .::' ::::::::::::::' ``::::.</span><br><span class="line">// ...::: ::::::::::::' ``::.</span><br><span class="line">// ```` ':. ':::::::::' ::::..</span><br><span class="line">// '.:::::' ':'````..</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">/**</span><br><span class="line"> * _.._ ,------------.</span><br><span class="line"> * ,' `. ( We want you! )</span><br><span class="line"> * / __) __` \ `-,----------'</span><br><span class="line"> * ( (`-`(-') ) _.-'</span><br><span class="line"> * /) \ = / (</span><br><span class="line"> * /' |--' . \</span><br><span class="line"> * ( ,---| `-.)__`</span><br><span class="line"> * )( `-.,--' _`-.</span><br><span class="line"> * '/,' ( Uu",</span><br><span class="line"> * (_ , `/,-' )</span><br><span class="line"> * `.__, : `-'/ /`--'</span><br><span class="line"> * | `--' |</span><br><span class="line"> * ` `-._ /</span><br><span class="line"> * \ (</span><br><span class="line"> * /\ . \. </span><br><span class="line"> * / |` \ ,-\</span><br><span class="line"> * / \| .) / \</span><br><span class="line"> * ( ,'|\ ,' :</span><br><span class="line"> * | \,`.`--"/ }</span><br><span class="line"> * `,' \ |,' /</span><br><span class="line"> * / "-._ `-/ |</span><br><span class="line"> * "-. "-.,'| ;</span><br><span class="line"> * / _/["---'""]</span><br><span class="line"> * : / |"- '</span><br><span class="line"> * ' | /</span><br><span class="line"> * ` |</span><br><span class="line"> */</span><br></pre></td></tr></table></figure><h3 id="第五款:单身狗专用"><a href="#第五款:单身狗专用" class="headerlink" title="第五款:单身狗专用"></a>第五款:单身狗专用</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br></pre></td><td class="code"><pre><span class="line"><!--</span><br><span class="line"> ::</span><br><span class="line"> :;J7, :, ::;7:</span><br><span class="line"> ,ivYi, , ;LLLFS:</span><br><span class="line"> :iv7Yi :7ri;j5PL</span><br><span class="line"> ,:ivYLvr ,ivrrirrY2X,</span><br><span class="line"> :;r@Wwz.7r: :ivu@kexianli.</span><br><span class="line"> :iL7::,:::iiirii:ii;::::,,irvF7rvvLujL7ur</span><br><span class="line"> ri::,:,::i:iiiiiii:i:irrv177JX7rYXqZEkvv17</span><br><span class="line"> ;i:, , ::::iirrririi:i:::iiir2XXvii;L8OGJr71i</span><br><span class="line"> :,, ,,: ,::ir@mingyi.irii:i:::j1jri7ZBOS7ivv,</span><br><span class="line"> ,::, ::rv77iiiriii:iii:i::,rvLq@huhao.Li</span><br><span class="line"> ,, ,, ,:ir7ir::,:::i;ir:::i:i::rSGGYri712:</span><br><span class="line"> ::: ,v7r:: ::rrv77:, ,, ,:i7rrii:::::, ir7ri7Lri</span><br><span class="line"> , 2OBBOi,iiir;r:: ,irriiii::,, ,iv7Luur:</span><br><span class="line"> ,, i78MBBi,:,:::,:, :7FSL: ,iriii:::i::,,:rLqXv::</span><br><span class="line"> : iuMMP: :,:::,:ii;2GY7OBB0viiii:i:iii:i:::iJqL;::</span><br><span class="line"> , ::::i ,,,,, ::LuBBu BBBBBErii:i:i:i:i:i:i:r77ii</span><br><span class="line"> , : , ,,:::rruBZ1MBBqi, :,,,:::,::::::iiriri:</span><br><span class="line"> , ,,,,::::i: @arqiao. ,:,, ,:::ii;i7:</span><br><span class="line"> :, rjujLYLi ,,:::::,:::::::::,, ,:i,:,,,,,::i:iii</span><br><span class="line"> :: BBBBBBBBB0, ,,::: , ,:::::: , ,,,, ,,:::::::</span><br><span class="line"> i, , ,8BMMBBBBBBi ,,:,, ,,, , , , , , :,::ii::i::</span><br><span class="line"> : iZMOMOMBBM2::::::::::,,,, ,,,,,,:,,,::::i:irr:i:::,</span><br><span class="line"> i ,,:;u0MBMOG1L:::i:::::: ,,,::, ,,, ::::::i:i:iirii:i:i:</span><br><span class="line"> : ,iuUuuXUkFu7i:iii:i:::, :,:,: ::::::::i:i:::::iirr7iiri::</span><br><span class="line"> : :rk@Yizero.i:::::, ,:ii:::::::i:::::i::,::::iirrriiiri::,</span><br><span class="line"> : 5BMBBBBBBSr:,::rv2kuii:::iii::,:i:,, , ,,:,:i@petermu.,</span><br><span class="line"> , :r50EZ8MBBBBGOBBBZP7::::i::,:::::,: :,:,::i;rrririiii::</span><br><span class="line"> :jujYY7LS0ujJL7r::,::i::,::::::::::::::iirirrrrrrr:ii:</span><br><span class="line"> ,: :@kevensun.:,:,,,::::i:i:::::,,::::::iir;ii;7v77;ii;i,</span><br><span class="line"> ,,, ,,:,::::::i:iiiii:i::::,, ::::iiiir@xingjief.r;7:i,</span><br><span class="line"> , , ,,,:,,::::::::iiiiiiiiii:,:,:::::::::iiir;ri7vL77rrirri::</span><br><span class="line"> :,, , ::::::::i:::i:::i:i::,,,,,:,::i:i:::iir;@Secbone.ii:::</span><br><span class="line">--></span><br></pre></td></tr></table></figure><h3 id="第六款:骷髅头"><a href="#第六款:骷髅头" class="headerlink" title="第六款:骷髅头"></a>第六款:骷髅头</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line">/**</span><br><span class="line"> **************************************************************</span><br><span class="line"> * *</span><br><span class="line"> * .=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-. *</span><br><span class="line"> * | ______ | *</span><br><span class="line"> * | .-" "-. | *</span><br><span class="line"> * | / \ | *</span><br><span class="line"> * | _ | | _ | *</span><br><span class="line"> * | ( \ |, .-. .-. ,| / ) | *</span><br><span class="line"> * | > "=._ | )(__/ \__)( | _.=" < | *</span><br><span class="line"> * | (_/"=._"=._ |/ /\ \| _.="_.="\_) | *</span><br><span class="line"> * | "=._"(_ ^^ _)"_.=" | *</span><br><span class="line"> * | "=\__|IIIIII|__/=" | *</span><br><span class="line"> * | _.="| \IIIIII/ |"=._ | *</span><br><span class="line"> * | _ _.="_.="\ /"=._"=._ _ | *</span><br><span class="line"> * | ( \_.="_.=" `--------` "=._"=._/ ) | *</span><br><span class="line"> * | > _.=" "=._ < | *</span><br><span class="line"> * | (_/ \_) | *</span><br><span class="line"> * | | *</span><br><span class="line"> * '-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=' *</span><br><span class="line"> * *</span><br><span class="line"> * LASCIATE OGNI SPERANZA, VOI CH'ENTRATE *</span><br><span class="line"> **************************************************************</span><br><span class="line"> */</span><br></pre></td></tr></table></figure><h3 id="第七款:标准键盘"><a href="#第七款:标准键盘" class="headerlink" title="第七款:标准键盘"></a>第七款:标准键盘</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line">/**</span><br><span class="line"> * ┌───┐ ┌───┬───┬───┬───┐ ┌───┬───┬───┬───┐ ┌───┬───┬───┬───┐ ┌───┬───┬───┐</span><br><span class="line"> * │Esc│ │ F1│ F2│ F3│ F4│ │ F5│ F6│ F7│ F8│ │ F9│F10│F11│F12│ │P/S│S L│P/B│ ┌┐ ┌┐ ┌┐</span><br><span class="line"> * └───┘ └───┴───┴───┴───┘ └───┴───┴───┴───┘ └───┴───┴───┴───┘ └───┴───┴───┘ └┘ └┘ └┘</span><br><span class="line"> * ┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───────┐ ┌───┬───┬───┐ ┌───┬───┬───┬───┐</span><br><span class="line"> * │~ `│! 1│@ 2│# 3│$ 4│% 5│^ 6│& 7│* 8│( 9│) 0│_ -│+ =│ BacSp │ │Ins│Hom│PUp│ │N L│ / │ * │ - │</span><br><span class="line"> * ├───┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─────┤ ├───┼───┼───┤ ├───┼───┼───┼───┤</span><br><span class="line"> * │ Tab │ Q │ W │ E │ R │ T │ Y │ U │ I │ O │ P │{ [│} ]│ | \ │ │Del│End│PDn│ │ 7 │ 8 │ 9 │ │</span><br><span class="line"> * ├─────┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴─────┤ └───┴───┴───┘ ├───┼───┼───┤ + │</span><br><span class="line"> * │ Caps │ A │ S │ D │ F │ G │ H │ J │ K │ L │: ;│" '│ Enter │ │ 4 │ 5 │ 6 │ │</span><br><span class="line"> * ├──────┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴────────┤ ┌───┐ ├───┼───┼───┼───┤</span><br><span class="line"> * │ Shift │ Z │ X │ C │ V │ B │ N │ M │< ,│> .│? /│ Shift │ │ ↑ │ │ 1 │ 2 │ 3 │ │</span><br><span class="line"> * ├─────┬──┴─┬─┴──┬┴───┴───┴───┴───┴───┴──┬┴───┼───┴┬────┬────┤ ┌───┼───┼───┐ ├───┴───┼───┤ E││</span><br><span class="line"> * │ Ctrl│ │Alt │ Space │ Alt│ │ │Ctrl│ │ ← │ ↓ │ → │ │ 0 │ . │←─┘│</span><br><span class="line"> * └─────┴────┴────┴───────────────────────┴────┴────┴────┴────┘ └───┴───┴───┘ └───────┴───┴───┘</span><br><span class="line"> */</span><br></pre></td></tr></table></figure><h3 id="第八款:顶"><a href="#第八款:顶" class="headerlink" title="第八款:顶"></a>第八款:顶</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">/**</span><br><span class="line"> * 頂頂頂頂頂頂頂頂頂 頂頂頂頂頂頂頂頂頂</span><br><span class="line"> * 頂頂頂頂頂頂頂 頂頂</span><br><span class="line"> * 頂頂 頂頂頂頂頂頂頂頂頂頂頂</span><br><span class="line"> * 頂頂 頂頂頂頂頂頂頂頂頂頂頂</span><br><span class="line"> * 頂頂 頂頂 頂頂</span><br><span class="line"> * 頂頂 頂頂 頂頂頂 頂頂</span><br><span class="line"> * 頂頂 頂頂 頂頂頂 頂頂</span><br><span class="line"> * 頂頂 頂頂 頂頂頂 頂頂</span><br><span class="line"> * 頂頂 頂頂 頂頂頂 頂頂</span><br><span class="line"> * 頂頂 頂頂頂</span><br><span class="line"> * 頂頂 頂頂 頂頂 頂頂</span><br><span class="line"> * 頂頂頂頂 頂頂頂頂頂 頂頂頂頂頂</span><br><span class="line"> * 頂頂頂頂 頂頂頂頂 頂頂頂頂</span><br><span class="line"> */</span><br></pre></td></tr></table></figure><h2 id="还有一些其他有趣搞怪的注释"><a href="#还有一些其他有趣搞怪的注释" class="headerlink" title="还有一些其他有趣搞怪的注释"></a>还有一些其他有趣搞怪的注释</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br></pre></td><td class="code"><pre><span class="line">/**</span><br><span class="line"> * _ooOoo_</span><br><span class="line"> * o8888888o</span><br><span class="line"> * 88" . "88</span><br><span class="line"> * (| -_- |)</span><br><span class="line"> * O\ = /O</span><br><span class="line"> * ___/`---'\____</span><br><span class="line"> * . ' \\| |// `.</span><br><span class="line"> * / \\||| : |||// \</span><br><span class="line"> * / _||||| -:- |||||- \</span><br><span class="line"> * | | \\\ - /// | |</span><br><span class="line"> * | \_| ''\---/'' | |</span><br><span class="line"> * \ .-\__ `-` ___/-. /</span><br><span class="line"> * ___`. .' /--.--\ `. . __</span><br><span class="line"> * ."" '< `.___\_<|>_/___.' >'"".</span><br><span class="line"> * | | : `- \`.;`\ _ /`;.`/ - ` : | |</span><br><span class="line"> * \ \ `-. \_ __\ /__ _/ .-` / /</span><br><span class="line"> * ======`-.____`-.___\_____/___.-`____.-'======</span><br><span class="line"> * `=---='</span><br><span class="line"> * .............................................</span><br><span class="line"> * 佛曰:bug泛滥,我已瘫痪!</span><br><span class="line"> */</span><br><span class="line"></span><br><span class="line">/**</span><br><span class="line"> * ,s555SB@@&</span><br><span class="line"> * :9H####@@@@@Xi</span><br><span class="line"> * 1@@@@@@@@@@@@@@8</span><br><span class="line"> * ,8@@@@@@@@@B@@@@@@8</span><br><span class="line"> * :B@@@@X3hi8Bs;B@@@@@Ah,</span><br><span class="line"> * ,8i r@@@B: 1S ,M@@@@@@#8;</span><br><span class="line"> * 1AB35.i: X@@8 . SGhr ,A@@@@@@@@S</span><br><span class="line"> * 1@h31MX8 18Hhh3i .i3r ,A@@@@@@@@@5</span><br><span class="line"> * ;@&i,58r5 rGSS: :B@@@@@@@@@@A</span><br><span class="line"> * 1#i . 9i hX. .: .5@@@@@@@@@@@1</span><br><span class="line"> * sG1, ,G53s. 9#Xi;hS5 3B@@@@@@@B1</span><br><span class="line"> * .h8h.,A@@@MXSs, #@H1: 3ssSSX@1</span><br><span class="line"> * s ,@@@@@@@@@@@@Xhi, r#@@X1s9M8 .GA981</span><br><span class="line"> * ,. rS8H#@@@@@@@@@@#HG51;. .h31i;9@r .8@@@@BS;i;</span><br><span class="line"> * .19AXXXAB@@@@@@@@@@@@@@#MHXG893hrX#XGGXM@@@@@@@@@@MS</span><br><span class="line"> * s@@MM@@@hsX#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@&,</span><br><span class="line"> * :GB@#3G@@Brs ,1GM@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@B,</span><br><span class="line"> * .hM@@@#@@#MX 51 r;iSGAM@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@8</span><br><span class="line"> * :3B@@@@@@@@@@@&9@h :Gs .;sSXH@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@:</span><br><span class="line"> * s&HA#@@@@@@@@@@@@@@M89A;.8S. ,r3@@@@@@@@@@@@@@@@@@@@@@@@@@@r</span><br><span class="line"> * ,13B@@@@@@@@@@@@@@@@@@@5 5B3 ;. ;@@@@@@@@@@@@@@@@@@@@@@@@@@@i</span><br><span class="line"> * 5#@@#&@@@@@@@@@@@@@@@@@@9 .39: ;@@@@@@@@@@@@@@@@@@@@@@@@@@@;</span><br><span class="line"> * 9@@@X:MM@@@@@@@@@@@@@@@#; ;31. H@@@@@@@@@@@@@@@@@@@@@@@@@@:</span><br><span class="line"> * SH#@B9.rM@@@@@@@@@@@@@B :. 3@@@@@@@@@@@@@@@@@@@@@@@@@@5</span><br><span class="line"> * ,:. 9@@@@@@@@@@@#HB5 .M@@@@@@@@@@@@@@@@@@@@@@@@@B</span><br><span class="line"> * ,ssirhSM@&1;i19911i,. s@@@@@@@@@@@@@@@@@@@@@@@@@@S</span><br><span class="line"> * ,,,rHAri1h1rh&@#353Sh: 8@@@@@@@@@@@@@@@@@@@@@@@@@#:</span><br><span class="line"> * .A3hH@#5S553&@@#h i:i9S #@@@@@@@@@@@@@@@@@@@@@@@@@A.</span><br><span class="line"> *</span><br><span class="line"> *</span><br><span class="line"> *</span><br><span class="line"> */</span><br></pre></td></tr></table></figure><h2 id="注意"><a href="#注意" class="headerlink" title="注意"></a>注意</h2><p>什么?上面这些都不能满足你,想要找更多的ascii图在这里 : <a href="http://www.asciiworld.com/">http://www.asciiworld.com/</a></p>]]></content>
<summary type="html"><h2 id="关于banneer"><a href="#关于banneer" class="headerlink" title="关于banneer"></a>关于banneer</h2><p>banner是spring boot 应用启动时打印在控制台的彩蛋信息,默认是这样的</summary>
<category term="编程" scheme="http://xiaodongzi.cn/categories/%E7%BC%96%E7%A8%8B/"/>
<category term="spring" scheme="http://xiaodongzi.cn/categories/%E7%BC%96%E7%A8%8B/spring/"/>
<category term="编程" scheme="http://xiaodongzi.cn/tags/%E7%BC%96%E7%A8%8B/"/>
</entry>
<entry>
<title>markdown编辑器:Haroopad</title>
<link href="http://xiaodongzi.cn/2018/09/02/markdown%E7%BC%96%E8%BE%91%E5%99%A8-Haroopad/"/>
<id>http://xiaodongzi.cn/2018/09/02/markdown%E7%BC%96%E8%BE%91%E5%99%A8-Haroopad/</id>
<published>2018-09-02T10:19:53.000Z</published>
<updated>2020-12-07T05:38:03.940Z</updated>
<content type="html"><![CDATA[<h2 id="haroopad"><a href="#haroopad" class="headerlink" title="haroopad"></a>haroopad</h2><p>经常写Markdown 文件,需要一款趁手的“兵器”,用的的编辑器很多: StackEdit、EpicEditor、Markable、Dillinger、Markdown Pad等。<br>但都或多或少有点不舒服,尤其最近用Markdown在预览界面一直出不来,果断卸载,这里推荐一款很简单安装和操作简单的markdown编辑器: haroopad 。</p><p>操作界面:</p><p><img src="https://raw.githubusercontent.com/eastFu/docs/master/blog/haroopad/haroopad.jpg" alt="界面"></p><p>功能:可以快捷插入标题、图标、超链接等等,而且很方便的切换主题。你值得拥有!</p><p>官网地址:<a href="http://http//pad.haroopress.com/">http://http://pad.haroopress.com/</a></p><h2 id="注意事项"><a href="#注意事项" class="headerlink" title="注意事项"></a>注意事项</h2><p>因为这款软件比较小众,所以坐着应该很久没有维护了,官网放出的下载连接是v0.13.1 , 但是这款软件有bug ,中文不现实的问题,如图:</p><p><img src="https://raw.githubusercontent.com/eastFu/docs/master/blog/haroopad/haroopad-error.png" alt="错误页面"></p><p>所以请下载v0.13 之前的版本,下面是下载地址:</p><p><a href="https://bitbucket.org/rhiokim/haroopad-download/downloads/?tab=downloads">https://bitbucket.org/rhiokim/haroopad-download/downloads/?tab=downloads</a></p>]]></content>
<summary type="html"><h2 id="haroopad"><a href="#haroopad" class="headerlink" title="haroopad"></a>haroopad</h2><p>经常写Markdown 文件,需要一款趁手的“兵器”,用的的编辑器很多: StackEdit</summary>
<category term="编程" scheme="http://xiaodongzi.cn/categories/%E7%BC%96%E7%A8%8B/"/>
<category term="IDE" scheme="http://xiaodongzi.cn/categories/%E7%BC%96%E7%A8%8B/IDE/"/>
<category term="编程" scheme="http://xiaodongzi.cn/tags/%E7%BC%96%E7%A8%8B/"/>
</entry>
<entry>
<title>踩坑:python base64</title>
<link href="http://xiaodongzi.cn/2018/04/11/%E8%B8%A9%E5%9D%91-python-base64/"/>
<id>http://xiaodongzi.cn/2018/04/11/%E8%B8%A9%E5%9D%91-python-base64/</id>
<published>2018-04-11T13:46:08.000Z</published>
<updated>2020-12-05T08:55:25.560Z</updated>
<content type="html"><![CDATA[<h2 id="需求"><a href="#需求" class="headerlink" title="需求"></a>需求</h2><p>读取文本内容,对字符串进行base64加密</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">>>> str = 'aaaaaaaaaaaaaaaaaaa\nbbbbbbbbbbbbbbbbbbbbbbbbbbb\ncccccccccccccccccccccccccc'</span><br><span class="line">>>> encodeStr = base64.encodestring(str)</span><br><span class="line">>>> encodeStr</span><br><span class="line"> 'YWFhYWFhYWFhYWFhYWFhYWFhYQpiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmIKY2NjY2NjY2Nj\nY2NjY2NjY2NjY2NjY2NjY2M=\n'</span><br></pre></td></tr></table></figure><p>使用到了 base64 模块的 base64.encodestring()</p><h2 id="采坑"><a href="#采坑" class="headerlink" title="采坑"></a>采坑</h2><p>返回的字符串默认结尾带”\n”,而且产生的base64编码字符串每76个字符就会用”\n”隔开</p><h2 id="解决"><a href="#解决" class="headerlink" title="解决"></a>解决</h2><p>使用replace() 替换吊所有的\n</p><p>base64.ecodestring每76字符就换行,这个是mime协议的规定,用于email发送,感兴趣的话自己去了解一下mime协议</p>]]></content>
<summary type="html"><h2 id="需求"><a href="#需求" class="headerlink" title="需求"></a>需求</h2><p>读取文本内容,对字符串进行base64加密</p>
<figure class="highlight plain"><table><tr><</summary>
<category term="编程" scheme="http://xiaodongzi.cn/categories/%E7%BC%96%E7%A8%8B/"/>
<category term="Python" scheme="http://xiaodongzi.cn/categories/%E7%BC%96%E7%A8%8B/Python/"/>
<category term="编程" scheme="http://xiaodongzi.cn/tags/%E7%BC%96%E7%A8%8B/"/>
</entry>
<entry>
<title>解决npm安装速度慢的问题</title>
<link href="http://xiaodongzi.cn/2017/11/30/%E8%A7%A3%E5%86%B3npm%E5%AE%89%E8%A3%85%E9%80%9F%E5%BA%A6%E6%85%A2%E7%9A%84%E9%97%AE%E9%A2%98/"/>
<id>http://xiaodongzi.cn/2017/11/30/%E8%A7%A3%E5%86%B3npm%E5%AE%89%E8%A3%85%E9%80%9F%E5%BA%A6%E6%85%A2%E7%9A%84%E9%97%AE%E9%A2%98/</id>
<published>2017-11-30T11:42:34.000Z</published>
<updated>2020-12-05T08:55:25.557Z</updated>
<content type="html"><![CDATA[<h2 id="问题"><a href="#问题" class="headerlink" title="问题"></a>问题</h2><p>不知道各位是否遇到这种情况,使用NPM(Node.js包管理工具)安装依赖时速度特别慢,为了安装Express,执行命令后两个多小时都没安装成功,最后只能取消安装,笔者20M带宽,应该不是我网络的原因,后来在网上找了好久才找到一种最佳解决办法,在安装时可以手动指定从哪个镜像服务器获取资源,我们可以使用阿里巴巴在国内的镜像服务器。</p><h2 id="方法"><a href="#方法" class="headerlink" title="方法"></a>方法</h2><p>命令如下:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm install -gd express --registry=http://registry.npm.taobao.org</span><br></pre></td></tr></table></figure><p>只需要使用–registry参数指定镜像服务器地址,为了避免每次安装都需要–registry参数,可以使用如下命令进行永久设置:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm config set registry http://registry.npm.taobao.org</span><br></pre></td></tr></table></figure><p>换了国内镜像,安装速度就很快了,特写篇博客分享这种方法,希望对大家有帮助</p>]]></content>
<summary type="html"><h2 id="问题"><a href="#问题" class="headerlink" title="问题"></a>问题</h2><p>不知道各位是否遇到这种情况,使用NPM(Node.js包管理工具)安装依赖时速度特别慢,为了安装Express,执行命令后两个多小时都没安装</summary>
<category term="编程" scheme="http://xiaodongzi.cn/categories/%E7%BC%96%E7%A8%8B/"/>
<category term="Node.js" scheme="http://xiaodongzi.cn/categories/%E7%BC%96%E7%A8%8B/Node-js/"/>
<category term="编程" scheme="http://xiaodongzi.cn/tags/%E7%BC%96%E7%A8%8B/"/>
</entry>
<entry>
<title>cmd命令右键菜单</title>
<link href="http://xiaodongzi.cn/2017/11/26/cmd%E5%91%BD%E4%BB%A4%E5%8F%B3%E9%94%AE%E8%8F%9C%E5%8D%95/"/>
<id>http://xiaodongzi.cn/2017/11/26/cmd%E5%91%BD%E4%BB%A4%E5%8F%B3%E9%94%AE%E8%8F%9C%E5%8D%95/</id>
<published>2017-11-26T10:40:07.000Z</published>
<updated>2020-12-06T09:21:44.442Z</updated>
<content type="html"><![CDATA[<h2 id="使用方法"><a href="#使用方法" class="headerlink" title="使用方法"></a>使用方法</h2><p>新建一个xx.reg,将下面的命令粘贴进去,直接双击运行即可</p><h2 id="添加cmd"><a href="#添加cmd" class="headerlink" title="添加cmd"></a>添加cmd</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line">Windows Registry Editor Version 5.00</span><br><span class="line"></span><br><span class="line">[HKEY_CLASSES_ROOT\*\shell\mycmd]</span><br><span class="line">@="在此处打开CMD"</span><br><span class="line"></span><br><span class="line">[HKEY_CLASSES_ROOT\*\shell\mycmd\command]</span><br><span class="line">@="cmd.exe /k pushd \"%L\\..\""[HKEY_CLASSES_ROOT\Folder\shell\mycmd]</span><br><span class="line">@="在此处打开CMD"</span><br><span class="line"></span><br><span class="line">[HKEY_CLASSES_ROOT\Folder\shell\mycmd\command]</span><br><span class="line">@="cmd.exe /k pushd \"%L\""[HKEY_CLASSES_ROOT\DesktopBackground\shell\mycmd]</span><br><span class="line">@="在此处打开CMD"</span><br><span class="line"></span><br><span class="line">[HKEY_CLASSES_ROOT\DesktopBackground\shell\mycmd\command]</span><br><span class="line">@="cmd.exe /k pushd \"%V\""[HKEY_CLASSES_ROOT\Directory\Background\shell\mycmd]</span><br><span class="line">@="在此处打开CMD"</span><br><span class="line"></span><br><span class="line">[HKEY_CLASSES_ROOT\Directory\Background\shell\mycmd\command]</span><br><span class="line">@="cmd.exe /k pushd \"%V\""</span><br></pre></td></tr></table></figure><h2 id="删除cmd"><a href="#删除cmd" class="headerlink" title="删除cmd"></a>删除cmd</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">Windows Registry Editor Version 5.00</span><br><span class="line"></span><br><span class="line">[-HKEY_CLASSES_ROOT\*\shell\mycmd]</span><br><span class="line">[-HKEY_CLASSES_ROOT\Folder\shell\mycmd]</span><br><span class="line">[-HKEY_CLASSES_ROOT\DesktopBackground\shell\mycmd]</span><br><span class="line">[-HKEY_CLASSES_ROOT\Directory\Background\shell\mycmd]</span><br></pre></td></tr></table></figure>]]></content>
<summary type="html"><h2 id="使用方法"><a href="#使用方法" class="headerlink" title="使用方法"></a>使用方法</h2><p>新建一个xx.reg,将下面的命令粘贴进去,直接双击运行即可</p>
<h2 id="添加cmd"><a href="#添加</summary>
<category term="编程" scheme="http://xiaodongzi.cn/categories/%E7%BC%96%E7%A8%8B/"/>
<category term="其它" scheme="http://xiaodongzi.cn/categories/%E7%BC%96%E7%A8%8B/%E5%85%B6%E5%AE%83/"/>
<category term="编程" scheme="http://xiaodongzi.cn/tags/%E7%BC%96%E7%A8%8B/"/>
</entry>
<entry>
<title>精简JRE</title>
<link href="http://xiaodongzi.cn/2016/07/18/%E7%B2%BE%E7%AE%80JRE/"/>
<id>http://xiaodongzi.cn/2016/07/18/%E7%B2%BE%E7%AE%80JRE/</id>
<published>2016-07-18T12:34:23.000Z</published>
<updated>2020-12-05T08:55:25.555Z</updated>
<content type="html"><![CDATA[<h2 id="需求场景"><a href="#需求场景" class="headerlink" title="需求场景"></a>需求场景</h2><p>最近手头上的有个项目发布是以jar包来发布运行的,由于部署的服务器很多,不能保证每台机器上都安装同一版本的Java环境。 需要 发布包中内置jre,但是原始的jre太大,所以进行了手动的精简(这个精简包有可能会不能通用你们的项目,原因是不同的项目使用到jre中的class不同 ,精简包主要是将一些没有用到的class删除)。</p><p>下面我们看一下jre的目录结构:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br></pre></td><td class="code"><pre><span class="line">jre7</span><br><span class="line"> ├─bin</span><br><span class="line"> │ ├─dtplugin</span><br><span class="line"> │ ├─plugin2</span><br><span class="line"> │ └─server</span><br><span class="line"> └─lib</span><br><span class="line"> ├─amd64</span><br><span class="line"> ├─applet</span><br><span class="line"> ├─cmm</span><br><span class="line"> ├─deploy</span><br><span class="line"> ├─ext</span><br><span class="line"> ├─fonts</span><br><span class="line"> ├─images</span><br><span class="line"> │ └─cursors</span><br><span class="line"> ├─management</span><br><span class="line"> ├─security</span><br><span class="line"> ├─servicetag</span><br><span class="line"> └─zi</span><br><span class="line"> ├─Africa</span><br><span class="line"> ├─America</span><br><span class="line"> │ ├─Argentina</span><br><span class="line"> │ ├─Indiana</span><br><span class="line"> │ ├─Kentucky</span><br><span class="line"> │ └─North_Dakota</span><br><span class="line"> ├─Antarctica</span><br><span class="line"> ├─Asia</span><br><span class="line"> ├─Atlantic</span><br><span class="line"> ├─Australia</span><br><span class="line"> ├─Etc</span><br><span class="line"> ├─Europe</span><br><span class="line"> ├─Indian</span><br><span class="line"> ├─Pacific</span><br><span class="line"> └─SystemV</span><br></pre></td></tr></table></figure><h2 id="瘦身"><a href="#瘦身" class="headerlink" title="瘦身"></a>瘦身</h2><p>jre bin目录下 我们要保留的 是 jvm 虚拟机的配置文件。</p><p>之后就是精简lib包, lib包中我们仅仅需要三个jar包:charsets.jar,resources.jar,rt.jar (32位的系统会多几个jar包)<br>我们使用最核心的jar包是 rt.jar ,需要根据自己的需求删除其中没用的class文件。</p><p>最后附上,jre7 Linux和Windows ,32和 64 位 的精简包,希望可以解决你们的问题。</p><p>地址:<a href="https://pan.baidu.com/s/1c1RfxxY">https://pan.baidu.com/s/1c1RfxxY</a></p>]]></content>
<summary type="html"><h2 id="需求场景"><a href="#需求场景" class="headerlink" title="需求场景"></a>需求场景</h2><p>最近手头上的有个项目发布是以jar包来发布运行的,由于部署的服务器很多,不能保证每台机器上都安装同一版本的Java环境。 需</summary>
<category term="编程" scheme="http://xiaodongzi.cn/categories/%E7%BC%96%E7%A8%8B/"/>
<category term="Java" scheme="http://xiaodongzi.cn/categories/%E7%BC%96%E7%A8%8B/Java/"/>
<category term="编程" scheme="http://xiaodongzi.cn/tags/%E7%BC%96%E7%A8%8B/"/>
</entry>
<entry>
<title>zookeeper的断线重连实现</title>
<link href="http://xiaodongzi.cn/2016/06/18/zookeeper%E7%9A%84%E6%96%AD%E7%BA%BF%E9%87%8D%E8%BF%9E%E5%AE%9E%E7%8E%B0/"/>
<id>http://xiaodongzi.cn/2016/06/18/zookeeper%E7%9A%84%E6%96%AD%E7%BA%BF%E9%87%8D%E8%BF%9E%E5%AE%9E%E7%8E%B0/</id>
<published>2016-06-18T02:31:48.000Z</published>
<updated>2020-12-05T08:55:25.543Z</updated>
<content type="html"><![CDATA[<h2 id="zookeeper简介"><a href="#zookeeper简介" class="headerlink" title="zookeeper简介"></a>zookeeper简介</h2><p>ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,是Google的Chubby一个开源的实现,是Hadoop和Hbase的重要组件。<br>我们可以使用zookeeper做程序的健康监测(EPHEMERAL 临时节点)、公共配置文件、集群管理(leader 选举)等等。<br>但是zookeeper并没有提供断线重连的功能,必须我们手动实现,这里使用 Curator来实现了zookeeper的断线重连功能,代码如下:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br></pre></td><td class="code"><pre><span class="line">import java.io.UnsupportedEncodingException;</span><br><span class="line"></span><br><span class="line">import org.apache.curator.framework.CuratorFramework;</span><br><span class="line">import org.apache.curator.framework.CuratorFrameworkFactory;</span><br><span class="line">import org.apache.curator.framework.listen.ListenerContainer;</span><br><span class="line">import org.apache.curator.framework.state.ConnectionState;</span><br><span class="line">import org.apache.curator.framework.state.ConnectionStateListener;</span><br><span class="line">import org.apache.curator.retry.ExponentialBackoffRetry;</span><br><span class="line">import org.apache.zookeeper.CreateMode;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">/**</span><br><span class="line"> * @ClassName: ZookeeperExcutor</span><br><span class="line"> * @Description: zookeeper连接处理器</span><br><span class="line"> */</span><br><span class="line">public class ZookeeperExcutor {</span><br><span class="line"></span><br><span class="line"> private CuratorFramework client;</span><br><span class="line"></span><br><span class="line"> public ZookeeperExcutor(String zklist,int sessionTimeout,int connectTimeout){</span><br><span class="line"> client = CuratorFrameworkFactory.builder()</span><br><span class="line"> .connectString(zklist).sessionTimeoutMs(sessionTimeout)</span><br><span class="line"> .connectionTimeoutMs(connectTimeout)</span><br><span class="line"> .retryPolicy(new ExponentialBackoffRetry(1000, 3)).build();</span><br><span class="line"> client.start();</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> public CuratorFramework getClient() {</span><br><span class="line"> return client;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> /**</span><br><span class="line"> * @Title: createNodeAddListener</span><br><span class="line"> * @Description: 添加node节点</span><br><span class="line"> * @param nodePath</span><br><span class="line"> * @param nodeData 设定文件</span><br><span class="line"> * @return void 返回类型</span><br><span class="line"> */</span><br><span class="line"> public String createNode(String nodePath,String nodeData){</span><br><span class="line"> if(client!=null){</span><br><span class="line"> try {</span><br><span class="line"> String nodeName=client.create().creatingParentsIfNeeded()</span><br><span class="line"> .withMode(CreateMode.EPHEMERAL_SEQUENTIAL)</span><br><span class="line"> .forPath(nodePath, nodeData.getBytes("UTF-8"));</span><br><span class="line"> return nodeName;</span><br><span class="line"> } catch (UnsupportedEncodingException e) {</span><br><span class="line"> e.printStackTrace();</span><br><span class="line"> return null;</span><br><span class="line"> } catch (Exception e) {</span><br><span class="line"> e.printStackTrace();</span><br><span class="line"> return null;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> return null;</span><br><span class="line"> }</span><br><span class="line"> /**</span><br><span class="line"> * @Title: getListener</span><br><span class="line"> * @Description: 为节点添加 connectState 监听器,实现断线重连,然后添加上节点</span><br><span class="line"> * @param nodePath 节点路径</span><br><span class="line"> * @param nodeData 节点数据</span><br><span class="line"> * @return void 返回类型</span><br><span class="line"> */</span><br><span class="line"> public ConnectionStateListener getListener(final String nodePath,final String nodeData){</span><br><span class="line"> if(null!=client){</span><br><span class="line"> ConnectionStateListener connectListener = new ConnectionStateListener() {</span><br><span class="line"> @Override</span><br><span class="line"> public void stateChanged(CuratorFramework curatorFramework, ConnectionState connectionState) {</span><br><span class="line"> if (connectionState == ConnectionState.LOST) {</span><br><span class="line"> while (true) {</span><br><span class="line"> try {</span><br><span class="line"> //手动重连</span><br><span class="line"> boolean flag=curatorFramework.getZookeeperClient().blockUntilConnectedOrTimedOut();</span><br><span class="line"> if (flag){</span><br><span class="line"> //重新添加节点</span><br><span class="line"> clearListener();</span><br><span class="line"> createNode(nodePath, nodeData);</span><br><span class="line"> client.getConnectionStateListenable().addListener(getListener(nodePath, nodeData));</span><br><span class="line"> break;</span><br><span class="line"> }</span><br><span class="line"> } catch (InterruptedException e) {</span><br><span class="line"> e.printStackTrace();</span><br><span class="line"> } catch (Exception e) {</span><br><span class="line"> e.printStackTrace();</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> }else if(connectionState==ConnectionState.RECONNECTED){</span><br><span class="line"> //重新连接成功</span><br><span class="line"> }else if(connectionState==ConnectionState.SUSPENDED){</span><br><span class="line"> //自动重连,自动新建 schedular的临时节点</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> };</span><br><span class="line"> return connectListener;</span><br><span class="line"> }</span><br><span class="line"> return null;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> public void clearListener(){</span><br><span class="line"> ListenerContainer<ConnectionStateListener> list=(ListenerContainer<ConnectionStateListener>) client.getConnectionStateListenable();</span><br><span class="line"> list.clear();</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> public void addListener(String nodePath,String nodeData){</span><br><span class="line"> client.getConnectionStateListenable().addListener(getListener(nodePath, nodeData));</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> public static void main(String[] args) {</span><br><span class="line"> ZookeeperExcutor zke=new ZookeeperExcutor("127.0.0.1:2181",10000, 10000);</span><br><span class="line"> String nodeName=zke.createNode("/Test", "test");</span><br><span class="line"> if(null!=nodeName){</span><br><span class="line"> zke.addListener("/Test", "test");</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h2 id="关于curator"><a href="#关于curator" class="headerlink" title="关于curator"></a>关于curator</h2><p>Curator是Netflix公司开源的一个Zookeeper客户端,与Zookeeper提供的原生客户端相比,Curator的抽象层次更高,简化了Zookeeper客户端的开发量,原生的zookeeper实现起来稍微麻烦一点。<br>下面是Curator的maven配置:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><dependency></span><br><span class="line"> <groupId>org.apache.curator</groupId></span><br><span class="line"> <artifactId>curator-framework</artifactId></span><br><span class="line"> <version>2.4.2</version></span><br><span class="line"></dependency></span><br><span class="line"><dependency></span><br><span class="line"> <groupId>org.apache.curator</groupId></span><br><span class="line"> <artifactId>curator-client</artifactId></span><br><span class="line"> <version>2.4.2</version></span><br><span class="line"></dependency></span><br><span class="line"><dependency></span><br><span class="line"> <groupId>org.apache.curator</groupId></span><br><span class="line"> <artifactId>curator-recipes</artifactId></span><br><span class="line"> <version>2.4.2</version></span><br><span class="line"></dependency></span><br></pre></td></tr></table></figure>]]></content>
<summary type="html"><h2 id="zookeeper简介"><a href="#zookeeper简介" class="headerlink" title="zookeeper简介"></a>zookeeper简介</h2><p>ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,</summary>
<category term="编程" scheme="http://xiaodongzi.cn/categories/%E7%BC%96%E7%A8%8B/"/>
<category term="Zookeeper" scheme="http://xiaodongzi.cn/categories/%E7%BC%96%E7%A8%8B/Zookeeper/"/>
<category term="编程" scheme="http://xiaodongzi.cn/tags/%E7%BC%96%E7%A8%8B/"/>
</entry>
<entry>
<title>IDEA版本: Ultimate、Community、EAP</title>
<link href="http://xiaodongzi.cn/2016/04/11/IDEA%E7%89%88%E6%9C%AC-Ultimate%E3%80%81Community%E3%80%81EAP/"/>
<id>http://xiaodongzi.cn/2016/04/11/IDEA%E7%89%88%E6%9C%AC-Ultimate%E3%80%81Community%E3%80%81EAP/</id>
<published>2016-04-11T13:11:17.000Z</published>
<updated>2020-12-05T08:55:25.526Z</updated>
<content type="html"><![CDATA[<h2 id="Community"><a href="#Community" class="headerlink" title="Community"></a>Community</h2><p>社区版,免费,但是功能有限制,Android Studio就是基于这个版本定制的。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">http://idea-intellij.com/intellij-community/</span><br></pre></td></tr></table></figure><h2 id="Ultimate"><a href="#Ultimate" class="headerlink" title="Ultimate"></a>Ultimate</h2><p>终极版,收费,功能无限制。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">http://idea-intellij.com/intellij-ultimate/</span><br></pre></td></tr></table></figure><h2 id="EAP"><a href="#EAP" class="headerlink" title="EAP"></a>EAP</h2><p>终极版的免费版,免费,功能无限制,但是每隔30天要重装一次。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">http://idea-intellij.com/intellij-eap/</span><br></pre></td></tr></table></figure>]]></content>
<summary type="html"><h2 id="Community"><a href="#Community" class="headerlink" title="Community"></a>Community</h2><p>社区版,免费,但是功能有限制,Android Studio就是基于这个版本定制的。<</summary>
<category term="编程" scheme="http://xiaodongzi.cn/categories/%E7%BC%96%E7%A8%8B/"/>
<category term="IDE" scheme="http://xiaodongzi.cn/categories/%E7%BC%96%E7%A8%8B/IDE/"/>
<category term="编程" scheme="http://xiaodongzi.cn/tags/%E7%BC%96%E7%A8%8B/"/>
</entry>
<entry>
<title>关于spring mvc请求乱码问题分析</title>
<link href="http://xiaodongzi.cn/2015/04/26/%E5%85%B3%E4%BA%8Espring-mvc%E8%AF%B7%E6%B1%82%E4%B9%B1%E7%A0%81%E9%97%AE%E9%A2%98%E5%88%86%E6%9E%90/"/>
<id>http://xiaodongzi.cn/2015/04/26/%E5%85%B3%E4%BA%8Espring-mvc%E8%AF%B7%E6%B1%82%E4%B9%B1%E7%A0%81%E9%97%AE%E9%A2%98%E5%88%86%E6%9E%90/</id>
<published>2015-04-26T11:46:07.000Z</published>
<updated>2020-12-05T08:55:25.548Z</updated>
<content type="html"><![CDATA[<h2 id="spring乱码"><a href="#spring乱码" class="headerlink" title="spring乱码"></a>spring乱码</h2><p>spring mvc 在请求参数乱码的时候可以使用 CharacterEncodingFilter来做处理,配置如下:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><filter></span><br><span class="line"> <filter-name>characterEncodingFilter</filter-name></span><br><span class="line"> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class></span><br><span class="line"> <init-param></span><br><span class="line"> <param-name>encoding</param-name></span><br><span class="line"> <param-value>UTF-8</param-value></span><br><span class="line"> </init-param></span><br><span class="line"> <init-param></span><br><span class="line"> <param-name>forceEncoding</param-name></span><br><span class="line"> <param-value>true</param-value></span><br><span class="line"> </init-param></span><br><span class="line"></filter></span><br><span class="line"><filter-mapping></span><br><span class="line"> <filter-name>characterEncodingFilter</filter-name></span><br><span class="line"> <url-pattern>/*</url-pattern></span><br><span class="line"></filter-mapping></span><br></pre></td></tr></table></figure><h2 id="原理"><a href="#原理" class="headerlink" title="原理"></a>原理</h2><p>很简单,就是拦截所有/*的请求,并将request和response的编码设置为UTF-8,关键的源代码如下:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">@Override</span><br><span class="line">protected void doFilterInternal(</span><br><span class="line"> HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)</span><br><span class="line"> throws ServletException, IOException {</span><br><span class="line"></span><br><span class="line"> if (this.encoding != null && (this.forceEncoding || request.getCharacterEncoding() == null)) {</span><br><span class="line"> request.setCharacterEncoding(this.encoding);</span><br><span class="line"> if (this.forceEncoding) {</span><br><span class="line"> response.setCharacterEncoding(this.encoding);</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> filterChain.doFilter(request, response);</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h2 id="get请求"><a href="#get请求" class="headerlink" title="get请求"></a>get请求</h2><p>但是这只能解决post的请求,对于get请求传递的参数,这种方法是不起作用的。最简单的办法就是修改tomcat的配置文件,新增配置项: useBodyEncodingForURI=”true”</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><Connector connectionTimeout="20000" port="80" protocol="HTTP/1.1" redirectPort="8443" useBodyEncodingForURI="true"/></span><br></pre></td></tr></table></figure><h2 id="原因"><a href="#原因" class="headerlink" title="原因"></a>原因</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">tomcat 默认按ISO-8859-1进行URL解码,如果请求方式为get,参数包含中文字符,则会出现乱码的问题,按ISO-8859-1进行URL解码,useBodyEncodingForURI的作用是根据响应该请求的页面的request.setCharacterEncoding参数对数据进行的重新编码,不同的页面可以有不同的重新编码的编码,默认:false 不启用,设置为 true,那么我们上面配置的filter就生效了。</span><br></pre></td></tr></table></figure><h2 id="其它方式"><a href="#其它方式" class="headerlink" title="其它方式"></a>其它方式</h2><p>tomcat还有一个URIEncoding的配置项,它的作用是对所有GET方式的请求的数据进行统一的重新编码,简单暴力,如果尝试过多次还未解决乱码问题,可以添加这样一个配置项:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><Connector connectionTimeout="20000" port="80" protocol="HTTP/1.1" redirectPort="8443" URIEncoding="utf-8"/></span><br></pre></td></tr></table></figure>]]></content>
<summary type="html"><h2 id="spring乱码"><a href="#spring乱码" class="headerlink" title="spring乱码"></a>spring乱码</h2><p>spring mvc 在请求参数乱码的时候可以使用 CharacterEncodingFil</summary>
<category term="编程" scheme="http://xiaodongzi.cn/categories/%E7%BC%96%E7%A8%8B/"/>
<category term="Java" scheme="http://xiaodongzi.cn/categories/%E7%BC%96%E7%A8%8B/Java/"/>
<category term="编程" scheme="http://xiaodongzi.cn/tags/%E7%BC%96%E7%A8%8B/"/>
</entry>
<entry>
<title>hibernate插入mysql中文乱码问题</title>
<link href="http://xiaodongzi.cn/2014/08/26/hibernate%E6%8F%92%E5%85%A5mysql%E4%B8%AD%E6%96%87%E4%B9%B1%E7%A0%81%E9%97%AE%E9%A2%98/"/>
<id>http://xiaodongzi.cn/2014/08/26/hibernate%E6%8F%92%E5%85%A5mysql%E4%B8%AD%E6%96%87%E4%B9%B1%E7%A0%81%E9%97%AE%E9%A2%98/</id>
<published>2014-08-26T01:41:23.000Z</published>
<updated>2020-12-05T08:55:25.535Z</updated>
<content type="html"><![CDATA[<h2 id="mysql配置问题"><a href="#mysql配置问题" class="headerlink" title="mysql配置问题"></a>mysql配置问题</h2><p>首先需要修改mysql数据库的配置文件my.ini,此文件放在mysql根目录下。在此文件下查找default-character-set属性,并将其值更改为utf8(注意:不是utf-8,也要注意大小写),这里需要将default-character-set属性全部属性的值修改为utf8。示例:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">default-character-set= utf8</span><br></pre></td></tr></table></figure><p>提示:default-character-set属性有两个,一个在[mysql]下面,另外一个在[mysqld]下面。</p><h2 id="sql问题"><a href="#sql问题" class="headerlink" title="sql问题"></a>sql问题</h2><p>同时创建hibernate数据库时需要显示设置数据库的编码方式为utf8。示例:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">create database daycode default charset=utf8;</span><br></pre></td></tr></table></figure><h2 id="hibernate配置问题"><a href="#hibernate配置问题" class="headerlink" title="hibernate配置问题"></a>hibernate配置问题</h2><p>做完这两步还是不行,需要修改hibernate的配置文件hibernate.cfg.xml,在配置文件配置hibernate.connection.url属性。示例:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><property name="hibernate.connection.url"></span><br><span class="line"><![CDATA[jdbc:mysql://localhost:3306/daycode?useUnicode=true&characterEncoding=utf8]]></span><br><span class="line"></property></span><br><span class="line">设置这些之后乱码问题就解决了。</span><br></pre></td></tr></table></figure>]]></content>
<summary type="html"><h2 id="mysql配置问题"><a href="#mysql配置问题" class="headerlink" title="mysql配置问题"></a>mysql配置问题</h2><p>首先需要修改mysql数据库的配置文件my.ini,此文件放在mysql根目录下。在</summary>
<category term="编程" scheme="http://xiaodongzi.cn/categories/%E7%BC%96%E7%A8%8B/"/>
<category term="Java" scheme="http://xiaodongzi.cn/categories/%E7%BC%96%E7%A8%8B/Java/"/>
<category term="编程" scheme="http://xiaodongzi.cn/tags/%E7%BC%96%E7%A8%8B/"/>
</entry>
<entry>
<title>入门(三)详解redis配置文件</title>
<link href="http://xiaodongzi.cn/2014/06/08/%E5%85%A5%E9%97%A8-%E4%B8%89-%E8%AF%A6%E8%A7%A3redis%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6/"/>
<id>http://xiaodongzi.cn/2014/06/08/%E5%85%A5%E9%97%A8-%E4%B8%89-%E8%AF%A6%E8%A7%A3redis%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6/</id>
<published>2014-06-08T05:15:34.000Z</published>
<updated>2020-12-05T08:55:25.547Z</updated>
<content type="html"><![CDATA[<h2 id="redis脚本简介"><a href="#redis脚本简介" class="headerlink" title="redis脚本简介"></a>redis脚本简介</h2><p>在我们介绍redis的配置文件之前,我们先来说一下Redis安装完成后生成的几个可执行文件: redis-server 、redis-cli 、redis-benchmark 、redis-stat 、redis-check-dump、redis-check-aof :</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">redis-server:Redis 服务器的daemon启动程序。</span><br><span class="line"></span><br><span class="line">redis-cli:Redis 命令行执行工具。当然,你也可以用telnet根据其纯文本协议来操作。</span><br><span class="line"></span><br><span class="line">redis-benchmark:Redis 性能检测工具,测试Redis在你的系统及你的配置下的读写性能。</span><br><span class="line"></span><br><span class="line">redis-stat:Redis 状态检测工具,可以检测 Redis 当前状态参数及延迟状况(高版本的Redis将没有这个脚本)。</span><br><span class="line"></span><br><span class="line">redis-check-dump:Redis dump 数据文件的修复工具。</span><br><span class="line"></span><br><span class="line">redis-check-aof:Redis aof 日志文件修复工具。</span><br></pre></td></tr></table></figure><h2 id="redis配置详解"><a href="#redis配置详解" class="headerlink" title="redis配置详解"></a>redis配置详解</h2><p>redis 的配置 定义在 redis.conf 文件中,下面我们介绍一下各个配置项的含义:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br></pre></td><td class="code"><pre><span class="line">1. Redis默认不是以守护进程的方式运行,可以通过该配置项修改,使用yes启用守护进程</span><br><span class="line"></span><br><span class="line"> daemonize no</span><br><span class="line"></span><br><span class="line">2. 当Redis以守护进程方式运行时,Redis默认会把pid写入/var/run/redis.pid文件,可以通过pidfile指定</span><br><span class="line"></span><br><span class="line"> pidfile /var/run/redis.pid</span><br><span class="line"></span><br><span class="line">3. 指定Redis监听端口,默认端口为6379,作者在自己的一篇博文中解释了为什么选用6379作为默认端口,因为6379在手机按键上MERZ对应的号码,而MERZ取自意大利歌女Alessia Merz的名字</span><br><span class="line"></span><br><span class="line"> port 6379</span><br><span class="line"></span><br><span class="line">4. 绑定的主机地址</span><br><span class="line"></span><br><span class="line"> bind 127.0.0.1</span><br><span class="line"></span><br><span class="line">5.当 客户端闲置多长时间后关闭连接,如果指定为0,表示关闭该功能</span><br><span class="line"></span><br><span class="line"> timeout 300</span><br><span class="line"></span><br><span class="line">6. 指定日志记录级别,Redis总共支持四个级别:debug、verbose、notice、warning,默认为verbose</span><br><span class="line"></span><br><span class="line"> loglevel verbose</span><br><span class="line"></span><br><span class="line">7. 日志记录方式,默认为标准输出,如果配置Redis为守护进程方式运行,而这里又配置为日志记录方式为标准输出,则日志将会发送给/dev/null</span><br><span class="line"></span><br><span class="line"> logfile stdout</span><br><span class="line"></span><br><span class="line">8. 设置数据库的数量,默认数据库为0,可以使用SELECT <dbid>命令在连接上指定数据库id</span><br><span class="line"></span><br><span class="line"> databases 16</span><br><span class="line"></span><br><span class="line">9. 指定在多长时间内,有多少次更新操作,就将数据同步到数据文件,可以多个条件配合</span><br><span class="line"></span><br><span class="line"> save <seconds> <changes></span><br><span class="line"></span><br><span class="line"> Redis默认配置文件中提供了三个条件:</span><br><span class="line"></span><br><span class="line"> save 900 1</span><br><span class="line"></span><br><span class="line"> save 300 10</span><br><span class="line"></span><br><span class="line"> save 60 10000</span><br><span class="line"></span><br><span class="line"> 分别表示900秒(15分钟)内有1个更改,300秒(5分钟)内有10个更改以及60秒内有10000个更改。</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">10. 指定存储至本地数据库时是否压缩数据,默认为yes,Redis采用LZF压缩,如果为了节省CPU时间,可以关闭该选项,但会导致数据库文件变的巨大</span><br><span class="line"></span><br><span class="line"> rdbcompression yes</span><br><span class="line"></span><br><span class="line">11. 指定本地数据库文件名,默认值为dump.rdb</span><br><span class="line"></span><br><span class="line"> dbfilename dump.rdb</span><br><span class="line"></span><br><span class="line">12. 指定本地数据库存放目录</span><br><span class="line"></span><br><span class="line"> dir ./</span><br><span class="line"></span><br><span class="line">13. 设置当本机为slav服务时,设置master服务的IP地址及端口,在Redis启动时,它会自动从master进行数据同步</span><br><span class="line"></span><br><span class="line"> slaveof <masterip> <masterport></span><br><span class="line"></span><br><span class="line">14. 当master服务设置了密码保护时,slav服务连接master的密码</span><br><span class="line"></span><br><span class="line"> masterauth <master-password></span><br><span class="line"></span><br><span class="line">15. 设置Redis连接密码,如果配置了连接密码,客户端在连接Redis时需要通过AUTH <password>命令提供密码,默认关闭</span><br><span class="line"></span><br><span class="line"> requirepass foobared</span><br><span class="line"></span><br><span class="line">16. 设置同一时间最大客户端连接数,默认无限制,Redis可以同时打开的客户端连接数为Redis进程可以打开的最大文件描述符数,如果设置 maxclients 0,表示不作限制。当客户端连接数到达限制时,Redis会关闭新的连接并向客户端返回max number of clients reached错误信息</span><br><span class="line"></span><br><span class="line"> maxclients 128</span><br><span class="line"></span><br><span class="line">17. 指定Redis最大内存限制,Redis在启动时会把数据加载到内存中,达到最大内存后,Redis会先尝试清除已到期或即将到期的Key,当此方法处理 后,仍然到达最大内存设置,将无法再进行写入操作,但仍然可以进行读取操作。Redis新的vm机制,会把Key存放内存,Value会存放在swap区</span><br><span class="line"></span><br><span class="line"> maxmemory <bytes></span><br><span class="line"></span><br><span class="line">18. 指定是否在每次更新操作后进行日志记录,Redis在默认情况下是异步的把数据写入磁盘,如果不开启,可能会在断电时导致一段时间内的数据丢失。因为 redis本身同步数据文件是按上面save条件来同步的,所以有的数据会在一段时间内只存在于内存中。默认为no</span><br><span class="line"></span><br><span class="line"> appendonly no</span><br><span class="line"></span><br><span class="line">19. 指定更新日志文件名,默认为appendonly.aof</span><br><span class="line"></span><br><span class="line"> appendfilename appendonly.aof</span><br><span class="line"></span><br><span class="line">20. 指定更新日志条件,共有3个可选值: </span><br><span class="line"> no:表示等操作系统进行数据缓存同步到磁盘(快) </span><br><span class="line"> always:表示每次更新操作后手动调用fsync()将数据写到磁盘(慢,安全) </span><br><span class="line"> everysec:表示每秒同步一次(折衷,默认值)</span><br><span class="line"></span><br><span class="line"> appendfsync everysec</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">21. 指定是否启用虚拟内存机制,默认值为no,简单的介绍一下,VM机制将数据分页存放,由Redis将访问量较少的页即冷数据swap到磁盘上,访问多的页面由磁盘自动换出到内存中(在后面的文章我会仔细分析Redis的VM机制)</span><br><span class="line"></span><br><span class="line"> vm-enabled no</span><br><span class="line"></span><br><span class="line">22. 虚拟内存文件路径,默认值为/tmp/redis.swap,不可多个Redis实例共享</span><br><span class="line"></span><br><span class="line"> vm-swap-file /tmp/redis.swap</span><br><span class="line"></span><br><span class="line">23. 将所有大于vm-max-memory的数据存入虚拟内存,无论vm-max-memory设置多小,所有索引数据都是内存存储的(Redis的索引数据 就是keys),也就是说,当vm-max-memory设置为0的时候,其实是所有value都存在于磁盘。默认值为0</span><br><span class="line"></span><br><span class="line"> vm-max-memory 0</span><br><span class="line"></span><br><span class="line">24. Redis swap文件分成了很多的page,一个对象可以保存在多个page上面,但一个page上不能被多个对象共享,vm-page-size是要根据存储的 数据大小来设定的,作者建议如果存储很多小对象,page大小最好设置为32或者64bytes;如果存储很大大对象,则可以使用更大的page,如果不 确定,就使用默认值</span><br><span class="line"></span><br><span class="line"> vm-page-size 32</span><br><span class="line"></span><br><span class="line">25. 设置swap文件中的page数量,由于页表(一种表示页面空闲或使用的bitmap)是在放在内存中的,,在磁盘上每8个pages将消耗1byte的内存。</span><br><span class="line"></span><br><span class="line"> vm-pages 134217728</span><br><span class="line"></span><br><span class="line">26. 设置访问swap文件的线程数,最好不要超过机器的核数,如果设置为0,那么所有对swap文件的操作都是串行的,可能会造成比较长时间的延迟。默认值为4</span><br><span class="line"></span><br><span class="line"> vm-max-threads 4</span><br><span class="line"></span><br><span class="line">27. 设置在向客户端应答时,是否把较小的包合并为一个包发送,默认为开启</span><br><span class="line"></span><br><span class="line"> glueoutputbuf yes</span><br><span class="line"></span><br><span class="line">28. 指定在超过一定的数量或者最大的元素超过某一临界值时,采用一种特殊的哈希算法</span><br><span class="line"></span><br><span class="line"> hash-max-zipmap-entries 64</span><br><span class="line"></span><br><span class="line"> hash-max-zipmap-value 512</span><br><span class="line"></span><br><span class="line">29. 指定是否激活重置哈希,默认为开启(后面在介绍Redis的哈希算法时具体介绍)</span><br><span class="line"></span><br><span class="line"> activerehashing yes</span><br><span class="line"></span><br><span class="line">30. 指定包含其它的配置文件,可以在同一主机上多个Redis实例之间使用同一份配置文件,而同时各个实例又拥有自己的特定配置文件</span><br><span class="line"></span><br><span class="line"> include /path/to/local.conf</span><br><span class="line"><<<<<<< HEAD</span><br></pre></td></tr></table></figure><p>=======</p><pre><code>>>>>>>> origin/master</code></pre>]]></content>
<summary type="html"><h2 id="redis脚本简介"><a href="#redis脚本简介" class="headerlink" title="redis脚本简介"></a>redis脚本简介</h2><p>在我们介绍redis的配置文件之前,我们先来说一下Redis安装完成后生成的几个可执</summary>
<category term="编程" scheme="http://xiaodongzi.cn/categories/%E7%BC%96%E7%A8%8B/"/>
<category term="Redis" scheme="http://xiaodongzi.cn/categories/%E7%BC%96%E7%A8%8B/Redis/"/>
<category term="编程" scheme="http://xiaodongzi.cn/tags/%E7%BC%96%E7%A8%8B/"/>
</entry>
<entry>
<title>入门(二)Windows环境下redis的安装</title>
<link href="http://xiaodongzi.cn/2014/06/07/%E5%85%A5%E9%97%A8-%E4%BA%8C-Windows%E7%8E%AF%E5%A2%83%E4%B8%8Bredis%E7%9A%84%E5%AE%89%E8%A3%85/"/>
<id>http://xiaodongzi.cn/2014/06/07/%E5%85%A5%E9%97%A8-%E4%BA%8C-Windows%E7%8E%AF%E5%A2%83%E4%B8%8Bredis%E7%9A%84%E5%AE%89%E8%A3%85/</id>
<published>2014-06-07T11:05:10.000Z</published>
<updated>2020-12-07T05:41:13.939Z</updated>
<content type="html"><![CDATA[<h2 id="说明"><a href="#说明" class="headerlink" title="说明"></a>说明</h2><p>之前介绍了Linux环境下Redis的安装,这次介绍一下Windows环境下Redis的安装,首先要讲的是,Redis官方只支持Linux,还好 Microsoft Open Tech group 开发了windows版本的Redis,github地址: <a href="https://github.com/MicrosoftArchive/redis">https://github.com/MicrosoftArchive/redis</a></p><p>已经发布了很多个release版本,截至目前已经发布到了 v-3.2.100 。</p><p>官网截图:</p><p><img src="https://raw.githubusercontent.com/eastFu/docs/master/blog/redis-win/redis-win.png" alt="官网"></p><p>github截图:</p><p><img src="https://raw.githubusercontent.com/eastFu/docs/master/blog/redis-win/redis-win-github.png" alt="github"></p><h2 id="下载与安装"><a href="#下载与安装" class="headerlink" title="下载与安装"></a>下载与安装</h2><p>截至到目前最新版本是3.2.100 ,这里就使用这个版本来进行安装,下载 Redis-x64-3.2.100.msi ,双击开始安装:</p><p><img src="https://raw.githubusercontent.com/eastFu/docs/master/blog/redis-win/redis-win-1.png" alt="步骤1"></p><p><img src="https://raw.githubusercontent.com/eastFu/docs/master/blog/redis-win/redis-win-2.png" alt="步骤2"></p><p><img src="https://raw.githubusercontent.com/eastFu/docs/master/blog/redis-win/redis-win-3.png" alt="步骤3"></p><p><img src="https://raw.githubusercontent.com/eastFu/docs/master/blog/redis-win/redis-win-4.png" alt="步骤4"></p><p><img src="https://raw.githubusercontent.com/eastFu/docs/master/blog/redis-win/redis-win-5.png" alt="步骤5"></p><p><img src="https://raw.githubusercontent.com/eastFu/docs/master/blog/redis-win/redis-win-6.png" alt="步骤6"></p><p><img src="https://raw.githubusercontent.com/eastFu/docs/master/blog/redis-win/redis-win-7.png" alt="步骤7"></p><p><img src="https://raw.githubusercontent.com/eastFu/docs/master/blog/redis-win/redis-win-8.png" alt="步骤8"></p><p>安装完毕,我们看一下目录文件:</p><p><img src="https://raw.githubusercontent.com/eastFu/docs/master/blog/redis-win/redis-win-9.png" alt="目录"></p><h2 id="redis启动"><a href="#redis启动" class="headerlink" title="redis启动"></a>redis启动</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">redis-server redis.windows.conf</span><br></pre></td></tr></table></figure><p><img src="https://raw.githubusercontent.com/eastFu/docs/master/blog/redis-win/redis-win-10.png" alt="启动效果图"></p><h2 id="redis-cli的使用"><a href="#redis-cli的使用" class="headerlink" title="redis-cli的使用"></a>redis-cli的使用</h2><p>双击打开 redis-cli.exe,我们可以在命令行使用redis命令来进行操作:</p><p><img src="https://raw.githubusercontent.com/eastFu/docs/master/blog/redis-win/redis-win-11.png" alt="命令"></p>]]></content>
<summary type="html"><h2 id="说明"><a href="#说明" class="headerlink" title="说明"></a>说明</h2><p>之前介绍了Linux环境下Redis的安装,这次介绍一下Windows环境下Redis的安装,首先要讲的是,Redis官方只支持Linux,</summary>
<category term="编程" scheme="http://xiaodongzi.cn/categories/%E7%BC%96%E7%A8%8B/"/>
<category term="Redis" scheme="http://xiaodongzi.cn/categories/%E7%BC%96%E7%A8%8B/Redis/"/>
<category term="编程" scheme="http://xiaodongzi.cn/tags/%E7%BC%96%E7%A8%8B/"/>
</entry>
<entry>
<title>入门(一)Linux环境下redis的安装</title>
<link href="http://xiaodongzi.cn/2014/06/06/%E5%85%A5%E9%97%A8-%E4%B8%80-Linux%E7%8E%AF%E5%A2%83%E4%B8%8Bredis%E7%9A%84%E5%AE%89%E8%A3%85/"/>
<id>http://xiaodongzi.cn/2014/06/06/%E5%85%A5%E9%97%A8-%E4%B8%80-Linux%E7%8E%AF%E5%A2%83%E4%B8%8Bredis%E7%9A%84%E5%AE%89%E8%A3%85/</id>
<published>2014-06-06T08:52:03.000Z</published>
<updated>2020-12-07T05:41:52.097Z</updated>
<content type="html"><![CDATA[<h2 id="关于redis"><a href="#关于redis" class="headerlink" title="关于redis"></a>关于redis</h2><blockquote><p>Redis最为一款开源的key-value存储系统,自推出到现在一直受到编程人员的喜爱。它支持存储多种value类型,String 、List 、Set 、Zset 、Hash。这些数据类型都支持push/pop、add/remove 及取交集、并集、差集等操作,这些操作都是原子性的,而且Redis还有各种不同的排序方式。</p></blockquote><p>Redis 的数据都是缓存在内存中,这样做是为了保证效率,而且也支持数据的磁盘持久化,目前Redis 不仅可以部署Linux 而且Windows 同样可以进行部署。</p><h2 id="下载与安装"><a href="#下载与安装" class="headerlink" title="下载与安装"></a>下载与安装</h2><p>Redis的下载地址:<a href="http://download.redis.io/releases/">http://download.redis.io/releases/</a> 版本很多,请自己下载想要安装的版本,这里 介绍 3.2.8的安装过程:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">$ wget http://download.redis.io/releases/redis-3.2.8.tar.gz</span><br><span class="line">$ tar xzf redis-3.2.8.tar.gz</span><br><span class="line">$ cd redis-3.2.8</span><br><span class="line">$ make</span><br><span class="line">$ make install</span><br></pre></td></tr></table></figure><h2 id="启动"><a href="#启动" class="headerlink" title="启动"></a>启动</h2><p>安装完成之后,进入src文件夹,你会发现脚本文件很多,为了操作方便我们将我们一会要使用到的脚本文件拷贝到一个目录同一进行管理:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"># 1. 创建两个文件夹 bin 、etc</span><br><span class="line"></span><br><span class="line">$ mkdir -p /usr/local/redis/bin</span><br><span class="line">$ mkdir -p /usr/local/redis/ect</span><br><span class="line"></span><br><span class="line"># 2. copy 脚本和配置文件</span><br><span class="line"></span><br><span class="line">$ mv /lamp/redis-3.2.8/redis.conf /usr/local/redis/etc</span><br><span class="line">$ cd /lamp/redis-3.2.8/src</span><br><span class="line">$ mv mkreleasehdr.sh redis-benchmark redis-check-aof redis-check-dump redis-cli redis-server /usr/local/redis/bin</span><br><span class="line"></span><br><span class="line">#3. 启动Redis</span><br><span class="line"></span><br><span class="line">$ cd /usr/local/redis/bin</span><br><span class="line">$ ./redis-server</span><br></pre></td></tr></table></figure><p>下面是启动后的截图(redis 默认端口 6379):<br><img src="https://raw.githubusercontent.com/eastFu/docs/master/blog/redis-linux/redis-linux.png" alt="启动效果图"></p><h2 id="问题分析"><a href="#问题分析" class="headerlink" title="问题分析"></a>问题分析</h2><p>如上图所示,redis已经成功启动,但是这里有三个WARNING 警告项,请不要忽略,下面介绍一下解决方法:</p><ul><li>第一个错误大概是说somaxconn的值128设置过小,从/proc/sys/net/core/somaxconn这个路径也可大概知道这个值的设置是关于网络连接中某个最大值的限定设置,此值表示网络连接的队列大小,在配置文件redis.conf中的“tcp-backlog 511”就配置在高并发环境下的最大队列大小,此值受限于系统的somaxconn与tcp_max_syn_backlog这两个值,所以应该把这两个内核参数值调大,具体解决方法如下:</li></ul><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">$ vim /etc/sysctl.conf</span><br><span class="line">$ net.core.somaxconn = 20480 #最大队列长度,应付突发的大并发连接请求,默认为128</span><br><span class="line">$ net.ipv4.tcp_max_syn_backlog = 20480 #半连接队列长度,此值受限于内存大小,默认为1024</span><br><span class="line">$ sysctl -p #使参数生效</span><br></pre></td></tr></table></figure><ul><li>报错解释</li></ul><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line">警告:过量使用内存设置为0!在低内存环境下,后台保存可能失败。为了修正这个问题,</span><br><span class="line">请在/etc/sysctl.conf 添加一项 'vm.overcommit_memory = 1' ,</span><br><span class="line">然后重启(或者运行命令'sysctl vm.overcommit_memory=1' )使其生效。</span><br><span class="line"></span><br><span class="line">vm.overcommit_memory不同的值说明:</span><br><span class="line"></span><br><span class="line">0 表示检查是否有足够的内存可用,如果是,允许分配;如果内存不够,拒绝该请求,并返回一个错误给应用程序。</span><br><span class="line">1 允许分配超出物理内存加上交换内存的请求</span><br><span class="line">2 内核总是返回true</span><br><span class="line">redis的数据回写机制分为两种</span><br><span class="line"></span><br><span class="line">同步回写即SAVE命令。redis主进程直接写数据到磁盘。当数据量大时,这个命令将阻塞,响应时间长</span><br><span class="line">异步回写即BGSAVE命令。redis 主进程fork一个子进程,复制主进程的内存并通过子进程回写数据到磁盘。</span><br><span class="line">由于RDB文件写的时候fork一个子进程。相当于复制了一个内存镜像。当时系统的内存是4G,而redis占用了</span><br><span class="line">近3G的内存,因此肯定会报内存无法分配。如果 「vm.overcommit_memory」设置为0,在可用内存不足的情况</span><br><span class="line">下,就无法分配新的内存。如果 「vm.overcommit_memory」设置为1。 那么redis将使用交换内存。</span><br></pre></td></tr></table></figure><p>解决方法:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">$ vim /etc/sysctl.conf</span><br><span class="line">$ vm.overcommit_memory = 1 #末尾追加</span><br><span class="line">$ sysctl -p #参数生效</span><br><span class="line">注:使用交换内存并不是一个完美的方案。最好的办法是扩大物理内存。</span><br></pre></td></tr></table></figure><ul><li>关闭THP透明内存</li></ul><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">`Transparent Huge Pages (THP)`告警,这是一个关于透明内存巨页的话题。简单来说内存可管理的最小</span><br><span class="line">单位是page,一个page通常是4kb,那1M内存就会有256个page,CPU通过内置的内存管理单元管理page表</span><br><span class="line">记录。Huge Pages就是表示page的大小已超过4kb了,一般是2M到1G,它的出现主要是为了管理超大内存。</span><br><span class="line">个人理解上TB的内存。而THP就是管理Huge Pages的一个抽象层次,根据一些资料显示THP会导致内存锁</span><br><span class="line">影响性能,所以一般建议关闭此功能。</span><br><span class="line"></span><br><span class="line">"/sys/kernel/mm/transparent_hugepage/enabled”有三个值,如下:</span><br><span class="line">$ cat /sys/kernel/mm/transparent_hugepage/enabled</span><br><span class="line"></span><br><span class="line">always [madvise] never</span><br><span class="line">####</span><br><span class="line"># always 尽量使用透明内存,扫描内存,有512个 4k页面可以整合,就整合成一个2M的页面</span><br><span class="line"># never 关闭,不使用透明内存</span><br><span class="line"># madvise 避免改变内存占用</span><br></pre></td></tr></table></figure><p>解决方法:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"># 临时解决</span><br><span class="line">$ echo never > /sys/kernel/mm/transparent_hugepage/enabled</span><br><span class="line"></span><br><span class="line"># 永久解决</span><br><span class="line">$ vim /etc/rc.local</span><br><span class="line">$ echo never > /sys/kernel/mm/transparent_hugepage/enabled #在开机脚本里追加此命令</span><br></pre></td></tr></table></figure><h2 id="redis的启动和暂停"><a href="#redis的启动和暂停" class="headerlink" title="redis的启动和暂停"></a>redis的启动和暂停</h2><p>刚刚我们使用 ./redis-server 来启动了Redis ,但是Redis默认是前台启动的,后台启动Redis设置:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"># 修改配置文件,将 daemonize 设置为 yes</span><br><span class="line"></span><br><span class="line">$ cd /usr/local/redis/etc</span><br><span class="line">$ vim redis.conf</span><br><span class="line">$ daemonize yes</span><br><span class="line"></span><br><span class="line"># 调用启动脚本</span><br><span class="line"></span><br><span class="line">$ cd /usr/local/redis/bin</span><br><span class="line">$ ./redis-server /usr/local/redis/etc/redis.conf</span><br><span class="line">复制代码</span><br><span class="line">停止Redis 两种方式:</span><br><span class="line"></span><br><span class="line">$ cd /usr/local/redis/bin</span><br><span class="line">$ ./redis-cli shutdown</span><br><span class="line"></span><br><span class="line"># 或者关闭端口为 6379 的 redis-server</span><br><span class="line">$ ./redis-cli -p 6379 shutdown</span><br></pre></td></tr></table></figure><p>到此我们对Redis有了初步的了解,后面我们将继续了解Redis的其他内容。</p>]]></content>
<summary type="html"><h2 id="关于redis"><a href="#关于redis" class="headerlink" title="关于redis"></a>关于redis</h2><blockquote>
<p>Redis最为一款开源的key-value存储系统,自推出到现在一直受到编</summary>
<category term="编程" scheme="http://xiaodongzi.cn/categories/%E7%BC%96%E7%A8%8B/"/>
<category term="Redis" scheme="http://xiaodongzi.cn/categories/%E7%BC%96%E7%A8%8B/Redis/"/>
<category term="编程" scheme="http://xiaodongzi.cn/tags/%E7%BC%96%E7%A8%8B/"/>
</entry>
</feed>