-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.html
719 lines (400 loc) · 39.9 KB
/
index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
<!DOCTYPE html>
<!--[if IEMobile 7 ]><html class="no-js iem7"><![endif]-->
<!--[if lt IE 9]><html class="no-js lte-ie8"><![endif]-->
<!--[if (gt IE 8)|(gt IEMobile 7)|!(IEMobile)|!(IE)]><!--><html class="no-js" lang="en"><!--<![endif]-->
<head>
<meta charset="utf-8">
<title>Trade Off</title>
<meta name="author" content="dawncold">
<meta name="description" content="先说结果,如果你需要构建一个中国大陆地区的省市区数据库,请只参考这里:http://www.stats.gov.cn/tjsj/tjbz/xzqhdm/,目前没有比这里更加准确的数据了,但若你又和某些电商网站集成了订单信息,那很可能还会遇到问题,可以看后面。 region问题说大不大说小不小, …">
<!-- http://t.co/dKP3o1e -->
<meta name="HandheldFriendly" content="True">
<meta name="MobileOptimized" content="320">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="canonical" href="http://www.youth2009.org/www.youth2009.org/">
<link href="/favicon.png" rel="icon">
<link href="/stylesheets/screen.css" media="screen, projection" rel="stylesheet" type="text/css">
<link href="/atom.xml" rel="alternate" title="Trade Off" type="application/atom+xml">
<script src="/javascripts/modernizr-2.0.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script>!window.jQuery && document.write(unescape('%3Cscript src="/javascripts/libs/jquery.min.js"%3E%3C/script%3E'))</script>
<script src="/javascripts/octopress.js" type="text/javascript"></script>
<!--Fonts from Google"s Web font directory at http://google.com/webfonts -->
<link href="//fonts.googleapis.com/css?family=PT+Serif:regular,italic,bold,bolditalic" rel="stylesheet" type="text/css">
<link href="//fonts.googleapis.com/css?family=PT+Sans:regular,italic,bold,bolditalic" rel="stylesheet" type="text/css">
<script type="text/javascript">
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-8650400-5']);
_gaq.push(['_trackPageview']);
(function() {
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();
</script>
</head>
<body >
<header role="banner"><hgroup>
<h1><a href="/">Trade Off</a></h1>
<h2>supercalifragilisticexpialidocious</h2>
</hgroup>
</header>
<nav role="navigation"><ul class="subscription" data-subscription="rss">
<li><a href="/atom.xml" rel="subscribe-rss" title="subscribe via RSS">RSS</a></li>
</ul>
<form action="http://google.com/search" method="get">
<fieldset role="search">
<input type="hidden" name="sitesearch" value="www.youth2009.org/www.youth2009.org">
<input class="search" type="text" name="q" results="0" placeholder="Search"/>
</fieldset>
</form>
<ul class="main-navigation">
<li><a href="/">Blog</a></li>
<li><a href="/blog/archives">Archives</a></li>
</ul>
</nav>
<div id="main">
<div id="content">
<div class="blog-index">
<article>
<header>
<h1 class="entry-title"><a href="/blog/2015/11/30/region/">Region</a></h1>
<p class="meta">
<time class='entry-date' datetime='2015-11-30T22:27:11+08:00'><span class='date'><span class='date-month'>Nov</span> <span class='date-day'>30</span><span class='date-suffix'>th</span>, <span class='date-year'>2015</span></span> <span class='time'>10:27 pm</span></time>
</p>
</header>
<div class="entry-content"><p><strong>先说结果,如果你需要构建一个中国大陆地区的省市区数据库,请只参考这里:<a href="http://www.stats.gov.cn/tjsj/tjbz/xzqhdm/">http://www.stats.gov.cn/tjsj/tjbz/xzqhdm/</a>,目前没有比这里更加准确的数据了,但若你又和某些电商网站集成了订单信息,那很可能还会遇到问题,可以看后面。</strong></p>
<p>region问题说大不大说小不小,如果你需要精确的规划物流(或者以后有可能的话)从而降低配送成本,那么region的问题就躲不过。</p>
<p>我国的行政规划编码挺简单,具体编码规则不谈(如果想了解请搜索相关GB开头的文件),某GB文件提到规则中的一条就是作废了的code不会再被是使用,也许有这一条规则就够用一阵子了。行政规划结构很清晰——三级结构,第一层是省及直辖市,第二层一般是“市”、“县”或“xxx市”这样的,第三级是“区”。但根据精简行政规划或者发展的需要,有些地区没有第三级,例如广东省中山市,这样的情况不算多但若要构建一个精确的region表的话,这点知识必不可少。</p>
<p>如果你是一个电商网站,用户只能在你的网站下单,那没问题,但这个时代如果你做的稍微大一些的话,势必要和其他电商网站或平台集成,简单说就是在人家那里开了个店,订单会被导入到你的系统中去(如果不需要导入到你的系统中的话可以不用往下看了,你基本不会遇到region的问题)很可惜现在大家都在拼命收集数据,会员啊、订单啊、用户的个人隐私啊等等,怎么能错过订单这么重要的信息,既然如此,别的平台的订单信息势必会导入到自己系统中来,其中订单中的一个重要的信息就是收货地址。</p>
<p>此时就会遇到一个问题,其他平台的region和我们用的是一样的吗?基本是不一样的,好的developer也许会找一份统计局的数据,但一般的也就从网上搜一个出来,搜到哪个格式看着顺眼的就拿来用了,不对比的话你还看不出大的疏漏,因为省区市的数据变化都不太大。</p>
<p>每年统计局都会更新这个库(除了数据的格式乱七八糟外都还好),有的时候你能看到一次新发布,有的时候你看到的是更新原来的发布时间,但变动都不大,可能有某几个市改名啦、合并啦、降级到区啦、区升级到市啦等等。就是因为改动不会很大所以从网上随便找来一个数据库还真的可以用一阵子,出来混早晚是要还的。</p>
<p>就是由于很多标准不统一,你用A版本的region,我用B版本的,他用C版本的,到底以谁的为准?一般情况下谁都不会改自己的region,因为有历史数据的负担,所以region的集成方式是“不集成”,也就是说直接拼好省市区和详细地址,这样看起来是没问题的,用起来可能也凑合,但这些数据就不再是格式化的了,起码不是符合规范的了,因为有的数据在你这边可能不存在,等你需要用这些数据的时候会很痛苦。</p>
<p>我遇到的问题是,已有系统中的region不知道是哪个版本,和X猫等平台集成的订单没有格式化的省市区数据。更新自己平台的region数据库工作量并不算大,抓取最新数据按照三级的结构存储好,再和已有数据对比,新增、删除(标记删除)、改名就好了,这里用的主键是code,code的编码很简单,前两位是省,中间两位是市,最后的是区,如果是省,那么后面的市区位置都是0,因为我们知道<strong>用过的code不会被重新使用</strong>,所以可以用作主键。</p>
<p>这样可以解决自己数据与最新数据不一致的问题,但仍无法解决多平台region不一致问题,除了大家使用统一标准外没有轻松解决的办法,这里只能吐槽X宝的网站和手机版,他们使用的region都是不一样的,更有甚者手机版的每个城市下面都能找到一个万能的区——“其他区”,PC版的还好,看起来准确,不过因为他们有对地址更加精细的管理,会添加一些本身并不存在区以方便用户的地址添加?例如某些工业园区、开发区、新区等等,最终的解决只能是我们处理这样的地址,看是归到某个区下还是怎样,总之这样的处理规则很多,一切都是为了数据的真实性。</p>
<p><strong>希望有能力可以让这个世界变得更加美好一点的企业能从这些方面出发做一点让人感受得到的改进,有一批人会感受到专业和幸福。</strong></p>
</div>
</article>
<article>
<header>
<h1 class="entry-title"><a href="/blog/2015/10/30/push-notification/">Push Notification</a></h1>
<p class="meta">
<time class='entry-date' datetime='2015-10-30T00:30:44+08:00'><span class='date'><span class='date-month'>Oct</span> <span class='date-day'>30</span><span class='date-suffix'>th</span>, <span class='date-year'>2015</span></span> <span class='time'>12:30 am</span></time>
</p>
</header>
<div class="entry-content"><p>最近App工作接近尾声,还有几个接口没有完成,其中之一就是需要在某些事件发生的时候通知App的后台,继而由App后台通知App,比如“订单即将被关闭,请尽快付款”、“优惠券即将到期”这样的消息。因为这些消息最终是要在用户的App上出现的,一般的做法是以Push notification的形式出现,主流平台android和iOS都是在屏幕最上方出现一些提示,点击后可以进入App的某个地方。</p>
<p>既然这样我们就直接集成第三方平台发送相应的消息好了,不过App做得实在很遗憾,用户点击消息后总会进入到App的消息中心,再点击某条消息才能看到具体内容,这样做可能是比较快,但体验不太好,至少和现有的主流App做法都不太一样,像上个时代的做法。</p>
<p>以上是背景,基于此我们希望能够把App作为推送会员消息的渠道,因为短信渠道现在变得越来越不可用,仅限于发送验证码等transactional消息,其实以上说的消息都是transactional消息,区别于marketing消息,这些消息一般是由用户自主激活的或满足一定条件触发,最终是区别于用户的,一般不是群发性的,例如营销类信息就属于marketing。将用户的App作为消息推送渠道的前提是能够较准确地获取这个用户的App渠道是否可用,如果不可用还是得选择短信等。</p>
<p>对于不同手机平台使用的技术差不多,但机制不太一样,不过这是有原因的。例如iOS上的推送机制:设备连接APNs,商户后端推送消息给APNs,再由APNs推送到最终用户的设备上;但android在国内不大一样,由于某些特殊的原因,android的GCM服务(类似APNs)无法使用,继而诞生了很多第三方推送服务商,这些服务商一方面做android的推送,另一方面也接管了到APNs的这块,其实接管APNs这块也不错,因为向APNs推送也并不容易实现——socket长连接,二进制消息等都增加了用户的开发成本,对于一般规模的App开发,使用第三方消息服务商几乎是没得选。</p>
<p><strong>iOS的推送</strong>:在成功推送到APNs时服务商得不到任何响应,也不保证给你送达,用户不在线可以给你保留一段时间等用户上线了再推送,但长时间不在线的话推送消息也会被删除。除非消息格式有错等语法性的错误会得到响应,再就是如果APNs发现用户设备上没有这个App(被用户删除或被用户禁用了推送)会将该设备的ID记录下来,服务商可以通过APNs提供的反馈接口得到这些信息,也就是说只有再次给App推送消息后才有可能知道这条渠道还是不是可用。</p>
<p><strong>android的推送</strong>:目前第三方服务商的做法是做出SDK,让开发App的人集成到App中,这个App安装到系统中后会出现一个Push Service在运行,当然不知道他们哪里来的智慧,如果多个App都用了某一家提供商,并不会启动多个Push Service,一般是一两个,这一两个服务所有App,从而实现了他们所描绘的多App共享长连接很省电什么的。某个设备后台的Push Service会自动和服务商的后端连接,等有消息过来时这些Service会知道该送给哪个App,到了具体的App再由用户的代码处理。由于机制的作用,android的消息服务商是可以实时知道某条消息能不能推送到设备上的,但这毕竟是一个不太常用的功能,所以服务商们一般不会公开这种API,我们用的这家在邮件中才告诉我们是有类似的API,但是VIP级别的,详情需要联系商务部门了解。</p>
</div>
</article>
<article>
<header>
<h1 class="entry-title"><a href="/blog/2015/10/27/build-hybla-for-ubuntu-14-dot-04/">Build Hybla for Ubuntu 14.04</a></h1>
<p class="meta">
<time class='entry-date' datetime='2015-10-27T00:42:28+08:00'><span class='date'><span class='date-month'>Oct</span> <span class='date-day'>27</span><span class='date-suffix'>th</span>, <span class='date-year'>2015</span></span> <span class='time'>12:42 am</span></time>
</p>
</header>
<div class="entry-content"><p>When I modify some ipv4 config for system I got an error like this: <code>sysctl: setting key "net.ipv4.tcp_congestion_control": No such file or directory</code>, so I followed <a href="http://v2ex.com/t/114788">this post</a> to build a kernel module for ubuntu 14.04</p>
<p>The net/ipv4 hybla Makefile(bad script format in original post):</p>
<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
</pre></td><td class='code'><pre><code class=''><span class='line'># Makefile for tcp_hybla.ko
</span><span class='line'>obj-m := tcp_hybla.o
</span><span class='line'>KDIR := /home/dejavu/linux-4.1.5
</span><span class='line'>PWD := $(shell pwd)
</span><span class='line'>default:
</span><span class='line'> $(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules</span></code></pre></td></tr></table></div></figure>
<p>I also got a warning during build modules: <code>No X.509 certificates found</code>, but it doesn’t matter I think, I can build the <code>tcp_hybla.ko</code> and load in kernel.</p>
</div>
</article>
<article>
<header>
<h1 class="entry-title"><a href="/blog/2015/10/26/save-red-status-elasticsearch/">Save Red Status Elasticsearch</a></h1>
<p class="meta">
<time class='entry-date' datetime='2015-10-26T22:49:13+08:00'><span class='date'><span class='date-month'>Oct</span> <span class='date-day'>26</span><span class='date-suffix'>th</span>, <span class='date-year'>2015</span></span> <span class='time'>10:49 pm</span></time>
</p>
</header>
<div class="entry-content"><p>Someday when I use Kibana, I got an error all shards failed, so I look through office guide and some posts on the Internet.</p>
<p>Maybe the memory limit results in some primary shards can not be loaded by elasticsearch. If one or all primary shards are unsigned, your elasticsearch cluster will be in red status, if all primary shards are loaded, your cluster status will be yellow, if all shards are loaded, the green status you will be get.</p>
<p>The data is stored in <code>index</code> in elasticsearch, the <code>index</code> will be divided into some shards, the shards are <code>primary</code> and <code>replica</code> kind, you can have no replica, but you can have no primary. replica shards will be stored on the other nodes in cluster, but in default setting, you have only two nodes, one is data store node, another one is a client node, and the default setting of index is 2 or 3 replicas for each primary shard, you can update all index setting to disabling this config.</p>
</div>
</article>
<article>
<header>
<h1 class="entry-title"><a href="/blog/2015/08/29/msa-thoughts/">MSA Thoughts</a></h1>
<p class="meta">
<time class='entry-date' datetime='2015-08-29T21:51:24+08:00'><span class='date'><span class='date-month'>Aug</span> <span class='date-day'>29</span><span class='date-suffix'>th</span>, <span class='date-year'>2015</span></span> <span class='time'>9:51 pm</span></time>
</p>
</header>
<div class="entry-content"><p>MSA (Micro Service Architecture) is a methodology of dependencies management. Its core thought is divided a large application into some independent small applications, these small applications can be deployed independent and use different programming language, etc.</p>
<p>I think it’s not a new methodology, but a new concept.</p>
<p>We can think you make an application, used some libraries written by others, these libraries are some independent application, they expose some APIs for you, your application import them and call some APIs to fullfill some functions. Generally they will keep same APIs during update and fix bugs, so you can upgrade them and use latest version. You can also copy their codes to your application code base, just like you write all codes, but if they updated, you must copy new codes to your code base, that likes the development without MSA.</p>
<p>So, MSA is a methodology of dependencies management, the example is a small scope of MSA, the real MSA means some independent application, for instance an order service, an logistics service, etc. We may name these order module, logistics module before, but now we name these xxx service.</p>
</div>
</article>
<article>
<header>
<h1 class="entry-title"><a href="/blog/2015/08/27/sort-and-uniq-count/">Sort and Uniq Count</a></h1>
<p class="meta">
<time class='entry-date' datetime='2015-08-27T19:41:46+08:00'><span class='date'><span class='date-month'>Aug</span> <span class='date-day'>27</span><span class='date-suffix'>th</span>, <span class='date-year'>2015</span></span> <span class='time'>7:41 pm</span></time>
</p>
</header>
<div class="entry-content"><p>I got some logs which recorded someone IP address and the URL it requests, I want to summary how many unique IP addresses request some specified URL, and request counts for one IP address.</p>
<p>so I filter out specified URL rows:</p>
<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>grep URL_PATH *.log</span></code></pre></td></tr></table></div></figure>
<p>then I got these rows:</p>
<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>...
</span><span class='line'>[ 2015-08-26T23:59:59+08:00 ] 14.219.202.241 /xx
</span><span class='line'>[ 2015-08-26T23:59:59+08:00 ] 14.219.202.241 /xx
</span><span class='line'>[ 2015-08-26T23:59:59+08:00 ] 14.219.202.241 /xx
</span><span class='line'>[ 2015-08-26T23:59:59+08:00 ] 14.219.202.241 /xx
</span><span class='line'>[ 2015-08-26T23:59:59+08:00 ] 14.219.202.241 /xx
</span><span class='line'>[ 2015-08-26T23:59:59+08:00 ] 14.219.202.241 /xx
</span><span class='line'>...</span></code></pre></td></tr></table></div></figure>
<p>then I use <code>awk</code> print the fourth column:</p>
<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>grep URL_PATH *.log | awk '{print $4}'</span></code></pre></td></tr></table></div></figure>
<p>then I got these IPs, I stored these IPs to a file, then <code>sort</code> and <code>uniq</code>, the <code>uniq</code> excepts a sorted file, the <code>-c</code> option means count these rows:</p>
<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>sort ips | uniq -c</span></code></pre></td></tr></table></div></figure>
<p>then I got some unique rows with counts, but I want sort these rows order by counts desc:</p>
<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>sort ips | uniq -c | sort -k1nr -k2</span></code></pre></td></tr></table></div></figure>
<p>the <code>-k1nr</code> means the KEY starts with first field, and as (n)umber, and ®everse, the <code>-k2</code> means ends with second field. The <code>field</code> means the column in your data.</p>
</div>
</article>
<article>
<header>
<h1 class="entry-title"><a href="/blog/2015/08/21/tornado-2/">Tornado-2</a></h1>
<p class="meta">
<time class='entry-date' datetime='2015-08-21T22:17:23+08:00'><span class='date'><span class='date-month'>Aug</span> <span class='date-day'>21</span><span class='date-suffix'>st</span>, <span class='date-year'>2015</span></span> <span class='time'>10:17 pm</span></time>
</p>
</header>
<div class="entry-content"><p>write some subclasses of <code>RequestHandler</code> and mapped these with routers, pass these routers to <code>Application</code>, run <code>Application</code>.</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'><span class="kn">from</span> <span class="nn">tornado.ioloop</span> <span class="kn">import</span> <span class="n">IOLoop</span>
</span><span class='line'><span class="kn">from</span> <span class="nn">tornado.web</span> <span class="kn">import</span> <span class="n">RequestHandler</span><span class="p">,</span> <span class="n">Application</span><span class="p">,</span> <span class="n">url</span>
</span><span class='line'>
</span><span class='line'><span class="k">class</span> <span class="nc">HelloHandler</span><span class="p">(</span><span class="n">RequestHandler</span><span class="p">):</span>
</span><span class='line'> <span class="k">def</span> <span class="nf">get</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
</span><span class='line'> <span class="bp">self</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="s">"Hello, world"</span><span class="p">)</span>
</span><span class='line'>
</span><span class='line'><span class="k">def</span> <span class="nf">make_app</span><span class="p">():</span>
</span><span class='line'> <span class="k">return</span> <span class="n">Application</span><span class="p">([</span>
</span><span class='line'> <span class="n">url</span><span class="p">(</span><span class="s">r"/"</span><span class="p">,</span> <span class="n">HelloHandler</span><span class="p">),</span>
</span><span class='line'> <span class="p">])</span>
</span><span class='line'>
</span><span class='line'><span class="k">def</span> <span class="nf">main</span><span class="p">():</span>
</span><span class='line'> <span class="n">app</span> <span class="o">=</span> <span class="n">make_app</span><span class="p">()</span>
</span><span class='line'> <span class="n">app</span><span class="o">.</span><span class="n">listen</span><span class="p">(</span><span class="mi">8888</span><span class="p">)</span>
</span><span class='line'> <span class="n">IOLoop</span><span class="o">.</span><span class="n">current</span><span class="p">()</span><span class="o">.</span><span class="n">start</span><span class="p">()</span>
</span></code></pre></td></tr></table></div></figure>
<p>Tornado supports strings, bytes, and dictionaries as response, you can use Template to building strings and bytes, also you can write response by hand. If you pass a dictionary to response, it will be encoded as JSON.</p>
<p>Tornado will not parse other types request arguments, e.g. Tornado will not parse JSON request bodies, you need to parse these by yourself(override <code>prepare</code> method)</p>
<p>CSRF/XSRF prevent: the session cookie from SiteA is not expired, there is a form in SiteB, the form aims doing something to SiteA, if SiteA don’t support XSRF prevent, it will allow submitting if you constructed valid form arguments. If SiteA supports XSRF prevent, it will set a cookie with token to user, and that token will filled in any action form(POST,PUT,DELETE), if these two values are not equal, that request will be prevented, because SiteB can’t retrive SiteA’s cookie, so that form can’t submit with valid cookie value.</p>
<p>Due to the Python GIL (Global Interpreter Lock), it is necessary to run multiple Python processes to take full advantage of multi-CPU machines. Typically it is best to run one process per CPU.</p>
</div>
</article>
<article>
<header>
<h1 class="entry-title"><a href="/blog/2015/08/16/tornado-1/">Tornado-1</a></h1>
<p class="meta">
<time class='entry-date' datetime='2015-08-16T16:16:51+08:00'><span class='date'><span class='date-month'>Aug</span> <span class='date-day'>16</span><span class='date-suffix'>th</span>, <span class='date-year'>2015</span></span> <span class='time'>4:16 pm</span></time>
</p>
</header>
<div class="entry-content"><p>This is the first part of Tornado studying project.</p>
<p>Tornado can be roughly divided into four major components:</p>
<ul>
<li>A web framework (including RequestHandler which is subclassed to create web applications, and various supporting classes).</li>
<li>Client- and server-side implementions of HTTP (HTTPServer and AsyncHTTPClient).</li>
<li>An asynchronous networking library (IOLoop and IOStream), which serve as the building blocks for the HTTP components and can also be used to implement other protocols.</li>
<li>A coroutine library (tornado.gen) which allows asynchronous code to be written in a more straightforward way than chaining callbacks.</li>
</ul>
<p>Tornado uses a signle-threaded event loop.This means that all application code should aim to be asynchronous and non-blocking because only one operation can be active at a time.</p>
<p>There are many styles of asynchronous interfaces:</p>
<ul>
<li>Callback argument</li>
<li>Return a placeholder (Future, Promise, Deferred)</li>
<li>Deliver to a queue</li>
<li>Callback registry (e.g. POSIX signals)</li>
</ul>
<p>There is no free way to make a synchronous function asynchronous in a way that is transparent to its callers.</p>
<p>Coroutines are the recommended way to write asynchronous code in Tornado</p>
<p>A function containing yield is a generator. All generators are asynchronous; when called they return a generator object instead of running to completion.</p>
</div>
</article>
<article>
<header>
<h1 class="entry-title"><a href="/blog/2015/08/16/checksums-function-in-macos/">Checksum Functions in MacOs</a></h1>
<p class="meta">
<time class='entry-date' datetime='2015-08-16T15:22:06+08:00'><span class='date'><span class='date-month'>Aug</span> <span class='date-day'>16</span><span class='date-suffix'>th</span>, <span class='date-year'>2015</span></span> <span class='time'>3:22 pm</span></time>
</p>
</header>
<div class="entry-content"><p>It’s better to calculate checksum for your downloaded files, it can make sure you download that real file from server, not from the ISP proxy server.</p>
<p>In MacOS, you can use <code>md5</code> and <code>shasum</code> to calculate file checksums.</p>
<ul>
<li>calculate a MD5 checksum</li>
</ul>
<p><code>md5 xxx.data</code></p>
<ul>
<li>calculate a SHA-1 checksum</li>
</ul>
<p><code>shasum -a 1 xxx.data</code></p>
<ul>
<li>calcuate a SHA-256 checksum</li>
</ul>
<p><code>shasum -a 256 xxx.data</code></p>
<p>Thanks for <a href="http://notepad2.blogspot.jp/2012/07/mac-os-x-how-to-generate-md5-sha1.html">here</a></p>
</div>
</article>
<article>
<header>
<h1 class="entry-title"><a href="/blog/2015/04/19/exception-in-python/">Exception in Python</a></h1>
<p class="meta">
<time class='entry-date' datetime='2015-04-19T17:05:31+08:00'><span class='date'><span class='date-month'>Apr</span> <span class='date-day'>19</span><span class='date-suffix'>th</span>, <span class='date-year'>2015</span></span> <span class='time'>5:05 pm</span></time>
</p>
</header>
<div class="entry-content"><p>My colleague remembered that if you pass some <code>kwargs</code> to an <code>Exception</code> subclass e.g. <code>class MyException(Exception): pass</code>, you will get a composed message when you catch the exception and call <code>e.message</code>. Unitil we got nothing from one place which it should display exception’s message, python language part is implemented by C, so we downloaded python source code(2.7.9), and find these lines.</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
</pre></td><td class='code'><pre><code class='c'><span class='line'><span class="k">static</span> <span class="kt">int</span>
</span><span class='line'><span class="nf">BaseException_init</span><span class="p">(</span><span class="n">PyBaseExceptionObject</span> <span class="o">*</span><span class="n">self</span><span class="p">,</span> <span class="n">PyObject</span> <span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="n">PyObject</span> <span class="o">*</span><span class="n">kwds</span><span class="p">)</span>
</span><span class='line'><span class="p">{</span>
</span><span class='line'> <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">_PyArg_NoKeywords</span><span class="p">(</span><span class="n">Py_TYPE</span><span class="p">(</span><span class="n">self</span><span class="p">)</span><span class="o">-></span><span class="n">tp_name</span><span class="p">,</span> <span class="n">kwds</span><span class="p">))</span>
</span><span class='line'> <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'> <span class="n">Py_DECREF</span><span class="p">(</span><span class="n">self</span><span class="o">-></span><span class="n">args</span><span class="p">);</span>
</span><span class='line'> <span class="n">self</span><span class="o">-></span><span class="n">args</span> <span class="o">=</span> <span class="n">args</span><span class="p">;</span>
</span><span class='line'> <span class="n">Py_INCREF</span><span class="p">(</span><span class="n">self</span><span class="o">-></span><span class="n">args</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'> <span class="k">if</span> <span class="p">(</span><span class="n">PyTuple_GET_SIZE</span><span class="p">(</span><span class="n">self</span><span class="o">-></span><span class="n">args</span><span class="p">)</span> <span class="o">==</span> <span class="mi">1</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'> <span class="n">Py_CLEAR</span><span class="p">(</span><span class="n">self</span><span class="o">-></span><span class="n">message</span><span class="p">);</span>
</span><span class='line'> <span class="n">self</span><span class="o">-></span><span class="n">message</span> <span class="o">=</span> <span class="n">PyTuple_GET_ITEM</span><span class="p">(</span><span class="n">self</span><span class="o">-></span><span class="n">args</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>
</span><span class='line'> <span class="n">Py_INCREF</span><span class="p">(</span><span class="n">self</span><span class="o">-></span><span class="n">message</span><span class="p">);</span>
</span><span class='line'> <span class="p">}</span>
</span><span class='line'> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>
<p>This is python BaseException’s C implementation, I can understand logic but C syntax. The BaseException accepts <code>kwargs</code>, but if you pass a <code>kwargs</code> to Exception, you will get a warning, because of <code>_PyArg_NoKeywords</code>, maybe it needs compatibility with old code, but now, you can’t use <code>kwargs</code>.</p>
<p>Another notice, if you pass one argument to it, this argument will be the <code>e.message</code> value, if not, your args will be placed in <code>e.args</code>.</p>
<p>We finally implemented <code>__str__</code> and <code>__unicode__</code> methods, because of we imported <code>unicode_literals</code>, so we think this is the best practice, we just use <code>str(e)</code> in those places.</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'><span class="k">class</span> <span class="nc">TmallAPIException</span><span class="p">(</span><span class="ne">Exception</span><span class="p">):</span>
</span><span class='line'> <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">code</span><span class="p">,</span> <span class="n">msg</span><span class="p">,</span> <span class="n">sub_code</span><span class="p">,</span> <span class="n">sub_msg</span><span class="p">):</span>
</span><span class='line'> <span class="nb">super</span><span class="p">(</span><span class="n">TmallAPIException</span><span class="p">,</span> <span class="bp">self</span><span class="p">)</span><span class="o">.</span><span class="n">__init__</span><span class="p">(</span><span class="n">code</span><span class="p">,</span> <span class="n">msg</span><span class="p">,</span> <span class="n">sub_code</span><span class="p">,</span> <span class="n">sub_msg</span><span class="p">)</span>
</span><span class='line'> <span class="bp">self</span><span class="o">.</span><span class="n">code</span> <span class="o">=</span> <span class="n">code</span>
</span><span class='line'> <span class="bp">self</span><span class="o">.</span><span class="n">msg</span> <span class="o">=</span> <span class="n">msg</span>
</span><span class='line'> <span class="bp">self</span><span class="o">.</span><span class="n">sub_code</span> <span class="o">=</span> <span class="n">sub_code</span>
</span><span class='line'> <span class="bp">self</span><span class="o">.</span><span class="n">sub_msg</span> <span class="o">=</span> <span class="n">sub_msg</span>
</span><span class='line'>
</span><span class='line'> <span class="k">def</span> <span class="nf">__unicode__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="c"># TODO: not necessary under python3</span>
</span><span class='line'> <span class="k">return</span> <span class="s">'code: {}, msg: {}, sub_code: {}, sub_msg: {}'</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">code</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">msg</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">sub_code</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">sub_msg</span><span class="p">)</span>
</span><span class='line'>
</span><span class='line'> <span class="k">def</span> <span class="nf">__str__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
</span><span class='line'> <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">__unicode__</span><span class="p">()</span><span class="o">.</span><span class="n">encode</span><span class="p">(</span><span class="s">'utf-8'</span><span class="p">)</span>
</span></code></pre></td></tr></table></div></figure>
</div>
</article>
<div class="pagination">
<a class="prev" href="/posts/2">← Older</a>
<a href="/blog/archives">Blog Archives</a>
</div>
</div>
<aside class="sidebar">
<section>
<h1>Recent Posts</h1>
<ul id="recent_posts">
<li class="post">
<a href="/blog/2015/11/30/region/">Region</a>
</li>
<li class="post">
<a href="/blog/2015/10/30/push-notification/">Push Notification</a>
</li>
<li class="post">
<a href="/blog/2015/10/27/build-hybla-for-ubuntu-14-dot-04/">Build Hybla for Ubuntu 14.04</a>
</li>
<li class="post">
<a href="/blog/2015/10/26/save-red-status-elasticsearch/">Save Red Status Elasticsearch</a>
</li>
<li class="post">
<a href="/blog/2015/08/29/msa-thoughts/">MSA Thoughts</a>
</li>
</ul>
</section>
</aside>
</div>
</div>
<footer role="contentinfo"><p>
Copyright © 2015 - dawncold -
<span class="credit">Powered by <a href="http://octopress.org">Octopress</a></span>
</p>
</footer>
<script type="text/javascript">
var disqus_shortname = 'dawncoldtechblog';
var disqus_script = 'count.js';
(function () {
var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true;
dsq.src = '//' + disqus_shortname + '.disqus.com/' + disqus_script;
(document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
}());
</script>
</body>
</html>