-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathatom.xml
More file actions
532 lines (301 loc) · 208 KB
/
atom.xml
File metadata and controls
532 lines (301 loc) · 208 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
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title>Hello 橙子</title>
<link href="/atom.xml" rel="self"/>
<link href="https://0rainge.github.io/"/>
<updated>2019-02-22T05:11:21.711Z</updated>
<id>https://0rainge.github.io/</id>
<author>
<name>John Doe</name>
</author>
<generator uri="http://hexo.io/">Hexo</generator>
<entry>
<title>react/既简单又可以做假账的小账本</title>
<link href="https://0rainge.github.io/2019/02/22/react-%E7%AE%80%E5%8D%95%E7%9A%84%E8%B4%A2%E5%8A%A1%E7%AE%A1%E7%90%86%E7%B3%BB%E7%BB%9F/"/>
<id>https://0rainge.github.io/2019/02/22/react-简单的财务管理系统/</id>
<published>2019-02-21T16:00:00.000Z</published>
<updated>2019-02-22T05:11:21.711Z</updated>
<content type="html"><![CDATA[<h1 id="accounts-app"><a href="#accounts-app" class="headerlink" title="accounts-app"></a>accounts-app</h1><p>simple account app<br>react/一个功能简单的小账本,记录现金的流入流出/可以做假账(随时编辑历史记录)</p><p>GitHub源地址:<a href="https://github.com/0rainge/accounts-app" target="_blank" rel="noopener">https://github.com/0rainge/accounts-app</a></p><h2 id="0-项目总结"><a href="#0-项目总结" class="headerlink" title="0. 项目总结"></a>0. 项目总结</h2><h3 id="0-1-展示"><a href="#0-1-展示" class="headerlink" title="0-1. 展示"></a>0-1. 展示</h3><p><img src="https://github.com/0rainge/accounts-app/blob/master/imgDoc/demo.png?raw=true" alt="image"></p><h3 id="0-2-功能点"><a href="#0-2-功能点" class="headerlink" title="0-2. 功能点"></a>0-2. 功能点</h3><ol><li>展示记录(设置表格,展示每条记录)</li><li>创建记录(设置表单,输入记录:时间,事项,收支金额)</li><li>计算并展示总金额(设置数据展示卡片,计算收入、支出、总金额并展示)</li><li>更新/删除记录(在表单中实现数据的更新和删除)</li></ol><a id="more"></a><h2 id="1-思路"><a href="#1-思路" class="headerlink" title="1. 思路"></a>1. 思路</h2><h3 id="1-0-搭建项目"><a href="#1-0-搭建项目" class="headerlink" title="1-0 搭建项目"></a>1-0 搭建项目</h3><ol><li>搭建脚手架:create-react-app</li><li>引入样式bootstrap样式库,从bootCDN中找一个css复制link标签 <a href="https://www.bootcdn.cn/twitter-bootstrap/" target="_blank" rel="noopener">https://www.bootcdn.cn/twitter-bootstrap/</a></li><li>新建文件夹component,实现组件</li></ol><h3 id="1-1-records列表和record行记录"><a href="#1-1-records列表和record行记录" class="headerlink" title="1-1 records列表和record行记录"></a>1-1 records列表和record行记录</h3><ol><li>实现Records组件,渲染一个记账表格</li><li>实现Record组件,渲染一行表格内容用来存一条数据内容,通过<record>调用数据</record></li><li>设置Records的state,通过map传递给Record(之后会从API里取)(设置数据静态类型)</li></ol><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">{<span class="keyword">this</span>.state.records.map(<span class="function">(<span class="params">record</span>) =></span> <Record record={record} / >)}</span><br></pre></td></tr></table></figure><h3 id="1-2-页面组件载入后的请求数据"><a href="#1-2-页面组件载入后的请求数据" class="headerlink" title="1-2 页面组件载入后的请求数据"></a>1-2 页面组件载入后的请求数据</h3><ol><li>利用组件生命周期:componentDidMount</li><li>通过jquery创建ajax发送请求,加载数据(通过then返回成功的结果response或失败的结果error),设置状态error和isLoaded</li><li>或通过axios(基于promise的http请求库)创建ajax发送请求,(链式调用then和catch处理返回数据或捕获错误),设置状态同上</li><li>根据状态(加载中、加载失败、加载成功)显示不同结果:取值、判断、返回html或{}包含的动态数据</li></ol><h3 id="1-3-设置API"><a href="#1-3-设置API" class="headerlink" title="1-3 设置API"></a>1-3 设置API</h3><ol><li>建立文件夹utils/RecordsAPI.js 设置API</li><li>定义常量 api = process.env.NAMEE || XXXXXX</li><li>导出api,在其他地方引入</li><li>package.json的start中设置全局变量NAMEE;或者在根目录新建文件.env.development.local</li><li>定义NAMEE = API_URL</li><li>npm start时默认找.env.development.local等其他几个文件设置环境变量</li><li>注意字符串的拼接:嵌套模版<code>`</code>${api}/records`</li><li>封装axios的ajax方法(get,post,put,delete)</li></ol><h3 id="1-4-设置Record表单输入数据"><a href="#1-4-设置Record表单输入数据" class="headerlink" title="1-4 设置Record表单输入数据"></a>1-4 设置Record表单输入数据</h3><ol><li>设置表单组件</li><li>render return中定义表单from,包含3个input(type,name,value,placeholder, onChange),1个btn(type),input的传入name,样式用bootstrap</li><li>设置开启规则:三个表单全有值,开启按钮,通过{}传入函数动态赋值disable属性;执行方法和传入方法的区别:是否有()</li><li>监听表单内容操作state:设置onchange方法</li><li>event.target.name 和 event.target.value 分别代表事件发生的组件和事件发生组件内的值(event是this)</li></ol><h3 id="1-5-增加记录"><a href="#1-5-增加记录" class="headerlink" title="1-5 增加记录"></a>1-5 增加记录</h3><ul><li>思路:</li></ul><ol><li>提交数据,发起请求,到API中</li><li>服务器收到请求返回一个id,</li><li>id再加上其他数据(date,title,amount)到table组件中,重新渲染<br>(只要发起一条请求用来创建数据,创建完不用发送请求)做法:组件之间传递消息如form组件向table组件传递信息</li></ol><ul><li>步骤:</li></ul><ol><li>在表单中设置监听函数</li><li>绑定事件句柄</li><li>在API文档中创建create方法的API:调用axios的post方法,传入body和api地址</li><li>事件句柄调用api</li><li>调用api后设置链式调用的then和catch,使用response和error(此处测试)</li><li>子组件和父组件传递数据:实现发送数据后更新表单</li><li>点击btn清空input——设置状态</li><li>table添加数据:通过扩展运算法,把原来的状态和传入参数混合,更新状态</li></ol><h3 id="1-6-更新记录"><a href="#1-6-更新记录" class="headerlink" title="1-6 更新记录"></a>1-6 更新记录</h3><ol><li>添加编辑/更新/取消按钮(点击编辑进入编辑状态,点击更新发送请求,点击取消返回(新增状态edit进行控制)</li><li>根据当前edit设置显示逻辑:从td返回不同内容(不可编辑——返回值,编辑状态——返回input,注意设置defaultValue),编辑按钮和返回按钮调用同一个函数(布尔)进行状态切换</li><li>设置api发送put请求(需要传个id和需要更新的内容refs过去)</li><li>更新table(仿照redux——在数组中更新元素:找到数据中那个数据,替换,返回新的数组,render更新)</li><li>table和record之间共享数据</li><li>更新table的方法:传入的全部数据和更新过的数据,通过map更新</li></ol><h3 id="1-7-删除记录"><a href="#1-7-删除记录" class="headerlink" title="1-7 删除记录"></a>1-7 删除记录</h3><ul><li>思路:</li></ul><ol><li>绑定监听函数</li><li>发送请求把记录删除</li><li>更新父组件</li></ol><ul><li>实现:</li></ul><ol><li>按钮:上绑定监听函数</li><li>子组件函数:在组件中设置监听函数</li><li>API:添加deleteAPI</li><li>子组件函数:通过监听函数调用api函数</li><li>父组件函数:由子组件调用——参数是子组件的,参数更新了父组件的状态,实现删除</li><li>子组件:调用父组件传来的函数更新页面</li></ol><h3 id="1-7-计算金额"><a href="#1-7-计算金额" class="headerlink" title="1-7 计算金额"></a>1-7 计算金额</h3><p>统计收入(正数amount相加),支出(负数amount相加),余额(收入和支出相加)</p><ul><li>思路:</li></ul><ol><li>显示卡片</li><li>计算数字</li></ol><ul><li>实现:</li></ul><ol><li>设置组件,返回html代码,传入数值</li><li>父组件中设置计算函数返回给子组件</li></ol><h2 id="问题记录:"><a href="#问题记录:" class="headerlink" title="问题记录:"></a>问题记录:</h2><h4 id="1-vs-code-react如何自动补全标签"><a href="#1-vs-code-react如何自动补全标签" class="headerlink" title="1. vs code react如何自动补全标签"></a>1. vs code react如何自动补全标签</h4><p><a href="https://blog.csdn.net/shaleilei/article/details/82984228" target="_blank" rel="noopener">https://blog.csdn.net/shaleilei/article/details/82984228</a></p><h4 id="2-chrome安装react调试插件"><a href="#2-chrome安装react调试插件" class="headerlink" title="2. chrome安装react调试插件"></a>2. chrome安装react调试插件</h4><p><a href="https://github.com/facebook/react-devtools/blob/master/README.md#the-react-tab-doesnt-show-up" target="_blank" rel="noopener">https://github.com/facebook/react-devtools/blob/master/README.md#the-react-tab-doesnt-show-up</a></p><h4 id="3-报错"><a href="#3-报错" class="headerlink" title="3. 报错"></a>3. 报错</h4><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">index.js:1446 Warning: Each child in an array or iterator should have a unique "key" prop.</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">key应该放在Records里面,而不是Record中</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><tr key ={this.props.record.id}> 改成 <Record key ={record.id} record={record} / ></span><br></pre></td></tr></table></figure><h4 id="4-mock模拟服务器端数据"><a href="#4-mock模拟服务器端数据" class="headerlink" title="4. mock模拟服务器端数据"></a>4. mock模拟服务器端数据</h4><ol><li>通过API创建数据 <a href="https://www.mockapi.io/" target="_blank" rel="noopener">https://www.mockapi.io/</a></li><li>json server:<a href="https://github.com/typicode/json-server" target="_blank" rel="noopener">https://github.com/typicode/json-server</a></li></ol><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">1. 项目根目录创建一个json</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">2. Yo:accounts-app 0range$ json-server --watch db.json --port 3004</span><br><span class="line"></span><br><span class="line"> \{^_^}/ hi!</span><br><span class="line"></span><br><span class="line"> Loading db.json</span><br><span class="line"> Done</span><br><span class="line"></span><br><span class="line"> Resources</span><br><span class="line"> http://localhost:3004/records</span><br><span class="line"></span><br><span class="line"> Home</span><br><span class="line"> http://localhost:3004</span><br></pre></td></tr></table></figure><h4 id="5-mock模拟收到数据"><a href="#5-mock模拟收到数据" class="headerlink" title="5. mock模拟收到数据"></a>5. mock模拟收到数据</h4><ol><li>在终端进行curl</li></ol><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">curl http://5c544a2ea659410014eeeb2c.mockapi.io/api/v1/records </span><br><span class="line"></span><br><span class="line"> [{"id":"1","date":"2019-02-01","title":"title 1","amount":91},{"id":"2","date":"2019-02-01","title":"title 2","amount":73},{"id":"3","date":"2019-02-01","title":"title 3","amount":71},{"id":"4","date":"2019-02-01","title":"title 4","amount":16}]Yo:accounts-app</span><br></pre></td></tr></table></figure><ol start="2"><li>postman使用get方法</li></ol><p><img src="https://github.com/0rainge/accounts-app/blob/master/imgDoc/getM.png?raw=true" alt="image"></p><ol start="3"><li>浏览器自带fetch方法</li></ol><p>参考:<a href="https://developer.mozilla.org/zh-CN/docs/Web/API/Fetch_API/Using_Fetch" target="_blank" rel="noopener">https://developer.mozilla.org/zh-CN/docs/Web/API/Fetch_API/Using_Fetch</a><br><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">fetch('http://localhost:3004/records ')</span><br><span class="line"> .then(response => response.json())</span><br><span class="line"> .then(data => {</span><br><span class="line"> console.log(data)</span><br><span class="line"> });</span><br><span class="line"></span><br><span class="line">分析这个函数:接url接then函数返回一个promise,后面跟一个json,最后输出</span><br><span class="line"></span><br><span class="line">只有当网络故障或请求阻止才会被标记为reject</span><br></pre></td></tr></table></figure></p><h4 id="6-mock模拟发送数据"><a href="#6-mock模拟发送数据" class="headerlink" title="6. mock模拟发送数据"></a>6. mock模拟发送数据</h4><ol><li><p>向远程API发送数据<br><img src="https://github.com/0rainge/accounts-app/blob/master/imgDoc/postR.png?raw=true" alt="image"></p></li><li><p>向本地json server发送数据<br><img src="https://github.com/0rainge/accounts-app/blob/master/imgDoc/postL.png?raw=true" alt="image"></p></li></ol><h4 id="7-父组件向字组件传递数据"><a href="#7-父组件向字组件传递数据" class="headerlink" title="7. 父组件向字组件传递数据"></a>7. 父组件向字组件传递数据</h4><p>通过map枚举,把值赋给另一个组件:有几条数据,调用几次组件,组件的内容通过父组件传入</p><p>子组件用this.props.record.date等来调用父组件的值</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"></span><br><span class="line"> {</span><br><span class="line"> this.state.records.map( (record) => </Record record = {record} >)</span><br><span class="line"> }</span><br><span class="line"> </span><br><span class="line">更复杂一点:</span><br><span class="line"> {records.map((record) => (</span><br><span class="line"> <Record </span><br><span class="line"> key ={record.id} </span><br><span class="line"> record = {record} </span><br><span class="line"> handleEditRecord = {this.updateRecord.bind(this)}</span><br><span class="line"> handleDeleteRecord = {this.deleteRecord.bind(this)}</span><br><span class="line"> /></span><br></pre></td></tr></table></figure><h4 id="8-扩展运算法-…"><a href="#8-扩展运算法-…" class="headerlink" title="8. 扩展运算法: …"></a>8. 扩展运算法: …</h4><p>扩展运算符用于扩展一个哈希或数组,ES6的写法</p><figure class="highlight js"><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"><span class="number">1.</span> {...record} = {<span class="attr">id</span>:record.id} {<span class="attr">date</span>:record:date}</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="number">2.</span> 把数据混在一起:</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> a = [{<span class="string">"a"</span>:<span class="number">1</span>},{<span class="string">"b"</span>:<span class="number">2</span>}]</span><br><span class="line"><span class="keyword">const</span> b = [{<span class="string">"c"</span>:<span class="number">3</span>}]</span><br><span class="line"><span class="keyword">const</span> c = [...a,b]</span><br><span class="line">等价于</span><br><span class="line"><span class="keyword">const</span> c = [{<span class="string">"a"</span>:<span class="number">1</span>},{<span class="string">"b"</span>:<span class="number">2</span>},{<span class="string">"c"</span>:<span class="number">3</span>}]</span><br></pre></td></tr></table></figure><h4 id="9-组件分析:"><a href="#9-组件分析:" class="headerlink" title="9. 组件分析:"></a>9. 组件分析:</h4><p>组件:可以看成是一个函数/类,可以继承自Component,也可以自定义不继承</p><p>看成函数:不继承自Component,通过函数传递数据</p><ol><li>声明:扩展自Component</li><li>构造器:执行父组件构造函数,设置状态state</li><li>方法:自定义各种方式,实现增删改查、调接口、计算数值</li><li>render函数:定义变量和代码逻辑,变量可以是css样式{},html代码(),state改变就会重新render</li><li>return:返回html代码</li><li>导出组件:export default + 组件名(或者在定义组件时就导出)</li></ol><h4 id="10-ES6解构赋值"><a href="#10-ES6解构赋值" class="headerlink" title="10. ES6解构赋值"></a>10. ES6解构赋值</h4><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">const {err,isLoaded,records} = this.state</span><br></pre></td></tr></table></figure><h4 id="11-库的按需导入"><a href="#11-库的按需导入" class="headerlink" title="11. 库的按需导入"></a>11. 库的按需导入</h4><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">import {getJson} from 'jquery'</span><br></pre></td></tr></table></figure><p>到时候就直接用getJson方法</p><h4 id="12-静态类型的检查机制"><a href="#12-静态类型的检查机制" class="headerlink" title="12. 静态类型的检查机制"></a>12. 静态类型的检查机制</h4><p>导入静态类型检查库:propTypes,设置组件的proptypes对象,key是state/porps;value是proptypes的数据类型</p><h4 id="13-使用环境变量代替API地址"><a href="#13-使用环境变量代替API地址" class="headerlink" title="13. 使用环境变量代替API地址"></a>13. 使用环境变量代替API地址</h4><p>重构API变量,放入统一的文件中,把环境变量(URL)单独放入一个文件中</p><p>环境变量:‘REACT_APP_’开头,‘’</p><h4 id="14-bootstrap常用类名"><a href="#14-bootstrap常用类名" class="headerlink" title="14. bootstrap常用类名"></a>14. bootstrap常用类名</h4><p>外边距/内填充</p><ol><li>第一位 </li></ol><ul><li>m:margin </li><li>p:padding</li></ul><ol start="2"><li>第二位 </li></ol><ul><li>t:top, </li><li>b:bottom </li><li>l:left </li><li>r:right </li><li>a:all </li><li>x:left和right</li></ul><ol start="3"><li>第三位 </li></ol><ul><li>auto:auto </li><li>md:1.5rem </li><li>lg :3rem</li><li>1:$spacer-x</li><li>2:$spacer-x * 1.5</li><li>3:$spacer-y * 3</li></ul><p>还有:网格,排版,表格,表单,按钮,图片,下拉菜单,按钮组,输入框,导航栏,面包屑,分页,标签,缩略图,进度条,多媒体列表,面板等</p><p>更多常用类名参考:<a href="https://www.cnblogs.com/sunxirui00/p/7580850.html" target="_blank" rel="noopener">https://www.cnblogs.com/sunxirui00/p/7580850.html</a></p><p><a href="https://v4.bootcss.com/docs/4.0/getting-started/introduction/" target="_blank" rel="noopener">https://v4.bootcss.com/docs/4.0/getting-started/introduction/</a></p><h4 id="15-组件的监听方法:on-动作"><a href="#15-组件的监听方法:on-动作" class="headerlink" title="15. 组件的监听方法:on+动作"></a>15. 组件的监听方法:on+动作</h4><ol><li><p>创建事件句柄:自定义方法重写形如:handleAction(event)</p></li><li><p>默认监听方法形如:onAction</p></li></ol><ul><li>onSubmit:表单提交</li><li>onChange:input内容改变</li></ul><p>默认监听方法onAction通常会绑定自定义方法handleAction:<br><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">onAction = <span class="keyword">this</span>.handleAction.bind(<span class="keyword">this</span>)</span><br></pre></td></tr></table></figure></p><h4 id="16-阻止默认事件"><a href="#16-阻止默认事件" class="headerlink" title="16. 阻止默认事件"></a>16. 阻止默认事件</h4><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">event.preventDefault();</span><br></pre></td></tr></table></figure><h4 id="17-发送数据的数据类型"><a href="#17-发送数据的数据类型" class="headerlink" title="17. 发送数据的数据类型"></a>17. 发送数据的数据类型</h4><p>把字符串类型转换为整形<br>xx:Number.parseInt(this.state.xx,0)</p><h4 id="18-父组件向子组件传值-函数"><a href="#18-父组件向子组件传值-函数" class="headerlink" title="18. 父组件向子组件传值/函数"></a>18. 父组件向子组件传值/函数</h4><p>目的:实现发送数据后更新表单的功能(当子组件form向API发出post请求后收到response,后调用父组件函数更新table,只有发送一次请求),将父组件函数传递给子组件,通过子组件调用父组件函数改变父组件状态。</p><ol><li>创建父组件方法Action</li><li><p>把父组件方法Action赋值给子组件句柄handleAction,类似把handleChange赋值给onChange</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">handleAction = <span class="keyword">this</span>.Action.bind(<span class="keyword">this</span>)</span><br></pre></td></tr></table></figure></li><li><p>子组件触发条件,通过this.props.handleAction调用这个函数(传入参数是子组件状态,方法内数据为父组件状态)</p></li><li>父组件的状态得到更新</li></ol><h4 id="19-更新数据:获取input的内容"><a href="#19-更新数据:获取input的内容" class="headerlink" title="19. 更新数据:获取input的内容"></a>19. 更新数据:获取input的内容</h4><ul><li><p>获取:使用input框的3个值,在input中设置ref属性:ref = “date/value/amount”</p></li><li><p>使用:在自定义方法中使用this.refs.date.value</p></li></ul><h4 id="20-关于api发送请求的疑问"><a href="#20-关于api发送请求的疑问" class="headerlink" title="20. 关于api发送请求的疑问"></a>20. 关于api发送请求的疑问</h4><p>向api发送数据,为什么会返回这个发送过去的数据以及id呢?</p><h4 id="21-关于map"><a href="#21-关于map" class="headerlink" title="21. 关于map"></a>21. 关于map</h4><figure class="highlight js"><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">anArray.map(aFun):数组里的每项执行这个函数,可以用于更新数组中的某项 </span><br><span class="line"></span><br><span class="line">例子:</span><br><span class="line"></span><br><span class="line">updateRecord(record,data){</span><br><span class="line"> <span class="comment">// console.log(record);</span></span><br><span class="line"> <span class="keyword">const</span> recordIndex = <span class="keyword">this</span>.state.records.indexOf(record);</span><br><span class="line"> <span class="keyword">const</span> newRecords = <span class="keyword">this</span>.state.records.map(<span class="function">(<span class="params">item,index</span>) =></span>{</span><br><span class="line"> <span class="keyword">if</span>(index!==recordIndex){</span><br><span class="line"> <span class="keyword">return</span> item;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span>{</span><br><span class="line"> ...item,</span><br><span class="line"> ...data</span><br><span class="line"> };</span><br><span class="line"> })</span><br><span class="line"> <span class="keyword">this</span>.setState({</span><br><span class="line"> records: newRecords</span><br><span class="line"> })</span><br><span class="line"> }</span><br></pre></td></tr></table></figure><p>如果是不需要改的记录就把它和更新的data放在一起,item是每一项,index是该项的索引</p><h4 id="22-关于key"><a href="#22-关于key" class="headerlink" title="22. 关于key"></a>22. 关于key</h4><p>用于记录多个相同组件</p><figure class="highlight js"><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"><Record </span><br><span class="line"> key ={record.id} </span><br><span class="line"> record = {record} </span><br><span class="line"> handleEditRecord = {<span class="keyword">this</span>.updateRecord.bind(<span class="keyword">this</span>)}</span><br><span class="line"> handleDeleteRecord = {<span class="keyword">this</span>.deleteRecord.bind(<span class="keyword">this</span>)}</span><br><span class="line"> /></span><br></pre></td></tr></table></figure><h4 id="23-关于filter"><a href="#23-关于filter" class="headerlink" title="23. 关于filter"></a>23. 关于filter</h4><figure class="highlight js"><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"></span><br><span class="line">anArray.filter(aFun) :返回数组中满足条件的项,取出要的东西</span><br><span class="line"></span><br><span class="line">举例<span class="number">1</span>——在数组中移除元素:</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> newRecords = <span class="keyword">this</span>.state.records.filter(<span class="function">(<span class="params">item,index</span>) =></span>index!==recordIndex);</span><br><span class="line"></span><br><span class="line">举例<span class="number">2</span>——选出数组中所有的正数和负数:</span><br><span class="line"></span><br><span class="line"> <span class="keyword">let</span> credits = <span class="keyword">this</span>.state.records.filter(<span class="function">(<span class="params">record</span>)=></span>{</span><br><span class="line"> <span class="keyword">return</span> record.amount<<span class="number">0</span>;</span><br><span class="line"> })</span><br></pre></td></tr></table></figure><h4 id="24-动态设置组件样式"><a href="#24-动态设置组件样式" class="headerlink" title="24. 动态设置组件样式"></a>24. 动态设置组件样式</h4><p>传入参数bg-${type}改变样式</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><div className={<span class="string">`card-header bg-<span class="subst">${type}</span> text-white`</span>} ></span><br></pre></td></tr></table></figure>]]></content>
<summary type="html">
<h1 id="accounts-app"><a href="#accounts-app" class="headerlink" title="accounts-app"></a>accounts-app</h1><p>simple account app<br>react/一个功能简单的小账本,记录现金的流入流出/可以做假账(随时编辑历史记录)</p>
<p>GitHub源地址:<a href="https://github.com/0rainge/accounts-app" target="_blank" rel="noopener">https://github.com/0rainge/accounts-app</a></p>
<h2 id="0-项目总结"><a href="#0-项目总结" class="headerlink" title="0. 项目总结"></a>0. 项目总结</h2><h3 id="0-1-展示"><a href="#0-1-展示" class="headerlink" title="0-1. 展示"></a>0-1. 展示</h3><p><img src="https://github.com/0rainge/accounts-app/blob/master/imgDoc/demo.png?raw=true" alt="image"></p>
<h3 id="0-2-功能点"><a href="#0-2-功能点" class="headerlink" title="0-2. 功能点"></a>0-2. 功能点</h3><ol>
<li>展示记录(设置表格,展示每条记录)</li>
<li>创建记录(设置表单,输入记录:时间,事项,收支金额)</li>
<li>计算并展示总金额(设置数据展示卡片,计算收入、支出、总金额并展示)</li>
<li>更新/删除记录(在表单中实现数据的更新和删除)</li>
</ol>
</summary>
<category term="缓慢的前端学习-练手项目记录" scheme="https://0rainge.github.io/categories/%E7%BC%93%E6%85%A2%E7%9A%84%E5%89%8D%E7%AB%AF%E5%AD%A6%E4%B9%A0-%E7%BB%83%E6%89%8B%E9%A1%B9%E7%9B%AE%E8%AE%B0%E5%BD%95/"/>
<category term="JavaScript" scheme="https://0rainge.github.io/tags/JavaScript/"/>
<category term="react" scheme="https://0rainge.github.io/tags/react/"/>
<category term="bootstrap" scheme="https://0rainge.github.io/tags/bootstrap/"/>
<category term="axios" scheme="https://0rainge.github.io/tags/axios/"/>
</entry>
<entry>
<title>NodeJs/Flag清单</title>
<link href="https://0rainge.github.io/2019/01/31/nodeJs-Flag%E6%B8%85%E5%8D%95/"/>
<id>https://0rainge.github.io/2019/01/31/nodeJs-Flag清单/</id>
<published>2019-01-30T16:00:00.000Z</published>
<updated>2019-02-22T05:12:16.686Z</updated>
<content type="html"><![CDATA[<h1 id="也可以看成一个ToDoList"><a href="#也可以看成一个ToDoList" class="headerlink" title="也可以看成一个ToDoList"></a>也可以看成一个ToDoList</h1><p>a To-Do-List using jQuery, nodejs, Express, mongoDB</p><p>实现一个flag清单,添加或删除flag</p><p>前端使用模版引擎EJS,引用jQuery库,后端使用nodejs,采用express框架,数据储存在mongoDB上</p><p>GitHub源地址:<a href="https://github.com/0rainge/myToDoList" target="_blank" rel="noopener">https://github.com/0rainge/myToDoList</a></p><h2 id="界面展示:"><a href="#界面展示:" class="headerlink" title="界面展示:"></a>界面展示:</h2><p>前端:<br><img src="https://github.com/0rainge/myToDoList/blob/master/img/demo.png?raw=true" alt="image"></p><p>后端:<br><img src="https://github.com/0rainge/myToDoList/blob/master/img/db.png?raw=true" alt="image"><br><a id="more"></a></p><h2 id="0-安装:"><a href="#0-安装:" class="headerlink" title="0. 安装:"></a>0. 安装:</h2><ul><li>express:后端框架</li><li>body-parser:处理表单</li><li>ejs:模版引擎</li><li>mongoose:连接数据库</li></ul><h2 id="1-定义入口文件,实现web服务器"><a href="#1-定义入口文件,实现web服务器" class="headerlink" title="1. 定义入口文件,实现web服务器"></a>1. 定义入口文件,实现web服务器</h2><p>导入express变量(导入进来是一个函数)<br>实例化变量<br>引入模版引擎<br>使用静态文件,中间件写法,设置一个文件夹做为根目录<br>监听3000端口</p><p>安装插件nodemon,默认找server.js </p><h2 id="2-定义路由:"><a href="#2-定义路由:" class="headerlink" title="2. 定义路由:"></a>2. 定义路由:</h2><ol><li><p>新建文件夹controlers,新建文件 myToDoControler</p></li><li><p>导出函数</p></li><li><p>定义路由:请求列表时需要的路由,新增项时需要的路由,删除项目时需要的路由</p></li></ol><h2 id="3-如何引用路由?"><a href="#3-如何引用路由?" class="headerlink" title="3. 如何引用路由?"></a>3. 如何引用路由?</h2><ol><li>导出路由</li><li>传入参数</li></ol><p>controller:请求相关的控制器,请求会到controller里</p><p>model:用来处理数据</p><p>view:视图相关</p><h2 id="4-使用模版引擎view-engine-ejs构建页面"><a href="#4-使用模版引擎view-engine-ejs构建页面" class="headerlink" title="4. 使用模版引擎view engine ejs构建页面"></a>4. 使用模版引擎view engine ejs构建页面</h2><ol><li>引入jQuery:在bootCDN找jquery的动态链接</li><li>渲染这个页面:在路由中render,进入路由会渲染这个ejs文件</li><li>在内存中渲染这个页面:</li></ol><p>渲染数据:</p><ol><li><p>res.render(‘myTodo’,{flags: data});</p></li><li><p>ejs中通过<% %>插入js代码,forEach 循环插入数据</p></li></ol><p>数据和服务器通信:</p><ol><li>点击按钮把数据发送给服务器</li><li>服务器得到内容进行处理,</li><li>服务器把数据给浏览器,下面的列表会多加一行</li></ol><h3 id="5-js功能实现:"><a href="#5-js功能实现:" class="headerlink" title="5. js功能实现:"></a>5. js功能实现:</h3><p>实现添加项目:</p><ol><li>把内容发给服务器</li><li>浏览器自动刷新:如何在数组中添加一个项目</li><li>res.json只是让请求不报错</li><li>如何把post数据取出来:用到一个库:body-parser</li></ol><p>实现删除项目:</p><ol><li>点击之后,得到项的内容,后端就知道删除的是哪一项,设置method为delete,</li><li>要注意:空格变成了横线,路由多了参数,路由错误会报错404,正则表达式更改路由:</li></ol><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> item = $(<span class="keyword">this</span>).text().trim().replace(<span class="regexp">/ /g</span>, <span class="string">"-"</span>);</span><br></pre></td></tr></table></figure><ol start="3"><li>filter 取出来的内容是要的,用来过滤一些想要的数据,每一项的内容和传过来的内容进行比较,返回true就是要的</li></ol><h3 id="6-mongoDB:"><a href="#6-mongoDB:" class="headerlink" title="6. mongoDB:"></a>6. mongoDB:</h3><p>存储json文件</p><p>注册Mlab<br>test test666</p><p>链接数据库:</p><ol><li>安装mongoose并导入</li><li>连接数据库</li><li>定义schema,定义字段名,值,值的类型item:String,相当于一个数据库表的模版,保证数据格式的正确类型,规定类型的属性,保证程序的健壮性 </li><li>定义model,model和数据库中的表是对应关系 ,程序对应操作model同步操作表,新增一条记录</li><li>保存数据,同时记得返回报错信息</li></ol><h3 id="7-通过数据库进行存取数据:"><a href="#7-通过数据库进行存取数据:" class="headerlink" title="7. 通过数据库进行存取数据:"></a>7. 通过数据库进行存取数据:</h3><ol><li>从mongoDB中读取数据实现渲染</li></ol><figure class="highlight javascript"><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"></span><br><span class="line">Flag.find({},<span class="function"><span class="keyword">function</span>(<span class="params">err,data</span>)</span>{</span><br><span class="line"> <span class="keyword">if</span>(err) <span class="keyword">throw</span> err;</span><br><span class="line"> res.render(<span class="string">'myTodo'</span>,{<span class="attr">flags</span>:data});</span><br><span class="line"> });</span><br></pre></td></tr></table></figure><ol start="2"><li>把项目添加到列表中</li></ol><p>(把之前写死的数据改成动态数据)</p><figure class="highlight javascript"><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"><span class="keyword">var</span> flagOne = Flag(req.body).save(<span class="function"><span class="keyword">function</span> (<span class="params">err,data</span>) </span>{</span><br><span class="line"> <span class="keyword">if</span> (err) <span class="keyword">throw</span> err;</span><br><span class="line"> res.json(data);</span><br><span class="line"> <span class="comment">// console.log('已保存: item saved');</span></span><br><span class="line"> })</span><br></pre></td></tr></table></figure><p>保存请求体</p><ol start="3"><li>删除数据</li></ol><p>找到这条记录,删除掉,用正则表达式进行转换</p><figure class="highlight javascript"><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">Flag.find({<span class="attr">item</span>: req.params.item.replace(<span class="regexp">/-/g</span>, <span class="string">" "</span>)}).remove(<span class="function"><span class="keyword">function</span>(<span class="params">err,data</span>)</span>{</span><br><span class="line"> <span class="keyword">if</span> (err) <span class="keyword">throw</span> err;</span><br><span class="line"> res.json(data);</span><br><span class="line">});</span><br></pre></td></tr></table></figure><h2 id="问题记录:"><a href="#问题记录:" class="headerlink" title="问题记录:"></a>问题记录:</h2><p>js中$ 的用法:</p><p>JQuery中一个自定义函数名,这个函数是获取指定网页元素的函数</p><figure class="highlight javascript"><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></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">$</span>(<span class="params">Nid</span>)</span>{</span><br><span class="line"> <span class="keyword">return</span> <span class="built_in">document</span>.getElementById(Nid);</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">- $()可以是$(element),即一个特定的DOM元素</span><br><span class="line"></span><br><span class="line">$(<span class="built_in">document</span>).find(<span class="string">"div>p"</span>).html());</span><br><span class="line"></span><br><span class="line">- $()可以是$(expresion)</span><br><span class="line"></span><br><span class="line">alert($(<span class="string">"div>p"</span>).html());</span><br><span class="line"></span><br><span class="line">- $()可以是$(<span class="function"><span class="keyword">function</span>),即一个函数</span></span><br><span class="line"><span class="function"></span></span><br><span class="line"><span class="function"><span class="title">$</span>(<span class="params">function(</span>)</span>{</span><br><span class="line">alert(<span class="string">"Hello world!"</span>);</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 class="built_in">document</span>).ready(<span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>{ </span><br><span class="line">alert(<span class="string">"Hello world!"</span>); </span><br><span class="line">});</span><br></pre></td></tr></table></figure><p>这是为了防止文档在完全加载(就绪)之前运行 jQuery 代码,即在 DOM 加载完成后才可以对 DOM 进行操作。<br>如果在文档没有完全加载之前就运行函数,操作可能失败。下面是两个具体的例子:</p><ul><li>试图隐藏一个不存在的元素</li><li>获得未完全加载的图像的大小</li></ul>]]></content>
<summary type="html">
<h1 id="也可以看成一个ToDoList"><a href="#也可以看成一个ToDoList" class="headerlink" title="也可以看成一个ToDoList"></a>也可以看成一个ToDoList</h1><p>a To-Do-List using jQuery, nodejs, Express, mongoDB</p>
<p>实现一个flag清单,添加或删除flag</p>
<p>前端使用模版引擎EJS,引用jQuery库,后端使用nodejs,采用express框架,数据储存在mongoDB上</p>
<p>GitHub源地址:<a href="https://github.com/0rainge/myToDoList" target="_blank" rel="noopener">https://github.com/0rainge/myToDoList</a></p>
<h2 id="界面展示:"><a href="#界面展示:" class="headerlink" title="界面展示:"></a>界面展示:</h2><p>前端:<br><img src="https://github.com/0rainge/myToDoList/blob/master/img/demo.png?raw=true" alt="image"></p>
<p>后端:<br><img src="https://github.com/0rainge/myToDoList/blob/master/img/db.png?raw=true" alt="image"><br>
</summary>
<category term="缓慢的前端学习-练手项目记录" scheme="https://0rainge.github.io/categories/%E7%BC%93%E6%85%A2%E7%9A%84%E5%89%8D%E7%AB%AF%E5%AD%A6%E4%B9%A0-%E7%BB%83%E6%89%8B%E9%A1%B9%E7%9B%AE%E8%AE%B0%E5%BD%95/"/>
<category term="JavaScript" scheme="https://0rainge.github.io/tags/JavaScript/"/>
<category term="NodeJs" scheme="https://0rainge.github.io/tags/NodeJs/"/>
<category term="jQuery" scheme="https://0rainge.github.io/tags/jQuery/"/>
<category term="express" scheme="https://0rainge.github.io/tags/express/"/>
<category term="mongoDB" scheme="https://0rainge.github.io/tags/mongoDB/"/>
</entry>
<entry>
<title>JavaScript/两只猫咪</title>
<link href="https://0rainge.github.io/2019/01/29/JavaScript-%E8%B4%AA%E5%90%83%E8%9B%87/"/>
<id>https://0rainge.github.io/2019/01/29/JavaScript-贪吃蛇/</id>
<published>2019-01-28T16:00:00.000Z</published>
<updated>2019-02-22T05:11:54.722Z</updated>
<content type="html"><![CDATA[<h1 id="灵感来源于贪吃蛇retroSnakeGame"><a href="#灵感来源于贪吃蛇retroSnakeGame" class="headerlink" title="灵感来源于贪吃蛇retroSnakeGame"></a>灵感来源于贪吃蛇retroSnakeGame</h1><p>GitHub源地址:<a href="https://github.com/0rainge/retroSnakeGame" target="_blank" rel="noopener">https://github.com/0rainge/retroSnakeGame</a></p><h2 id="0-界面展示"><a href="#0-界面展示" class="headerlink" title="0.界面展示"></a>0.界面展示</h2><ul><li><h4 id="游戏开始界面"><a href="#游戏开始界面" class="headerlink" title="游戏开始界面"></a>游戏开始界面</h4><img src="https://github.com/0rainge/retroSnakeGame/blob/master/img/docImg/demo1.jpeg?raw=true" alt="image"></li><li><h4 id="游戏界面"><a href="#游戏界面" class="headerlink" title="游戏界面"></a>游戏界面</h4><img src="https://github.com/0rainge/retroSnakeGame/blob/master/img/docImg/demo2.jpeg?raw=true" alt="image"></li><li><h4 id="游戏结束界面"><a href="#游戏结束界面" class="headerlink" title="游戏结束界面"></a>游戏结束界面</h4><img src="https://github.com/0rainge/retroSnakeGame/blob/master/img/docImg/demo3.png?raw=true" alt="image"><a id="more"></a><h2 id="1-HTML:DOM结构"><a href="#1-HTML:DOM结构" class="headerlink" title="1. HTML:DOM结构"></a>1. HTML:DOM结构</h2></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">开始页面——开始按钮</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"> ——主页面——头——分数div——“分数”</span><br><span class="line"> | | |</span><br><span class="line"> | | ———分数数字span</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><p>(写一个分析dom树的小工具)</p><h2 id="2-分析游戏思路"><a href="#2-分析游戏思路" class="headerlink" title="2. 分析游戏思路"></a>2. 分析游戏思路</h2><ul><li>点击开始按钮:startPage消失,游戏开始 </li></ul><ol><li>游戏开始:</li><li>右侧播放按钮改为暂停按钮</li><li>在main中生成大猫咪(长度和运动方向),默认长度为带两个心心,默认运动方向为右侧</li><li>main随机生成大猫咪的真爱的位置</li><li>大猫咪每过一秒钟向当前方向移动一个单位长度</li><li>接受键盘按键向上下左右方向移动</li><li>大猫咪碰到了真爱:小心心+1,随机再次生成真爱位置</li><li>大猫咪碰到了墙壁游戏结束</li><li>点击暂停按钮,蛇停止运动,播放按钮改为暂停按钮,点击播放按钮,恢复运动,改为暂停按钮</li></ol><ul><li>游戏结束:显示游戏结束页面,分数为大猫咪的心心,按钮改为播放按钮</li></ul><h2 id="3-实现问题记录"><a href="#3-实现问题记录" class="headerlink" title="3. 实现问题记录"></a>3. 实现问题记录</h2><ul><li><h4 id="游戏初始化"><a href="#游戏初始化" class="headerlink" title="游戏初始化"></a>游戏初始化</h4></li></ul><p>init() 初始化参数<br>content所有区域都用坐标属性来表示,一个单位长度是一个心心的长度,用坐标乘自身20的宽就是</p><ul><li><h4 id="如何随机生成大猫咪真爱位置:"><a href="#如何随机生成大猫咪真爱位置:" class="headerlink" title="如何随机生成大猫咪真爱位置:"></a>如何随机生成大猫咪真爱位置:</h4></li></ul><ol><li><p>找到能够容纳的最多单位数:mapW/foodW = 最大宽度</p></li><li><p>找到随机单位:通过随机数在0-最多食物数之间挑一个,即0-1之间的随机数*最大宽度 =[0,最大单位数] = 随机单位数(记得取整)</p></li><li><p>找到随机位置:随机位置 = 随机单位<em>单位长度 = 随机单位(整数)</em>20</p></li></ol><ul><li><h4 id="如何生成大猫咪:"><a href="#如何生成大猫咪:" class="headerlink" title="如何生成大猫咪:"></a>如何生成大猫咪:</h4></li></ul><ol><li>数据结构:用二维数组数组代表整个大猫咪:包括坐标和结构</li><li>设置每个小块div的大小和定位,添加类名</li></ol><ul><li><h4 id="移动大猫咪:"><a href="#移动大猫咪:" class="headerlink" title="移动大猫咪:"></a>移动大猫咪:</h4></li></ul><ol><li>直线移动:移动到上一个节点的位置</li><li>改变方向:x和y + 和 - </li><li>刷新移动:删掉旧的位置的大猫咪,渲染新的位置的大猫咪</li><li>只能左右90度转弯:判断位置能否改变:加锁,用布尔变量判断能否改变?</li><li>改变方向:监听键盘落下的事件</li><li>一直运动:添加定时器,速度</li><li>改变大猫咪的图片方向</li></ol><ul><li><h4 id="增加亲密度(分数):"><a href="#增加亲密度(分数):" class="headerlink" title="增加亲密度(分数):"></a>增加亲密度(分数):</h4></li></ul><ol><li>条件:位置一样</li><li>分数增加,改变html</li></ol><ul><li><h4 id="增加尾巴心心:"><a href="#增加尾巴心心:" class="headerlink" title="增加尾巴心心:"></a>增加尾巴心心:</h4></li></ul><ol><li>确定新增位置坐标</li><li>向其中心心队列push新的心心</li></ol><ul><li><h4 id="遇到边距-碰到自己:"><a href="#遇到边距-碰到自己:" class="headerlink" title="遇到边距/碰到自己:"></a>遇到边距/碰到自己:</h4></li></ul><ol><li>确定大猫咪的定位</li><li>分别和0,最大值,自身的位置比较:判断是否结束游戏</li></ol><ul><li><h4 id="游戏结束:"><a href="#游戏结束:" class="headerlink" title="游戏结束:"></a>游戏结束:</h4></li></ul><ol><li>数据回归原始值</li><li>显示窗口</li><li>关闭游戏结束窗口</li></ol><ul><li><h4 id="设置游戏控制逻辑:"><a href="#设置游戏控制逻辑:" class="headerlink" title="设置游戏控制逻辑:"></a>设置游戏控制逻辑:</h4></li></ul><ol><li>点击:开始按钮——开始新游戏,播放按钮——开始新游戏或继续当前游戏,暂停按钮——暂停游戏</li><li>判断游戏状态:startPaushBool——暂停/开始,startGameBool——新游戏/当前游戏</li><li>新游戏:开始游戏,改变状态startGameBool,改变状态startPaushBool,开始移动,监听键盘事件,改变图标。</li><li>继续游戏:改变状态startPaushBool,开始移动,监听键盘事件,改变图标。</li><li>暂停游戏:改变图标,停止键盘监听,停止移动,改变startPaushBool状态</li></ol>]]></content>
<summary type="html">
<h1 id="灵感来源于贪吃蛇retroSnakeGame"><a href="#灵感来源于贪吃蛇retroSnakeGame" class="headerlink" title="灵感来源于贪吃蛇retroSnakeGame"></a>灵感来源于贪吃蛇retroSnakeGame</h1><p>GitHub源地址:<a href="https://github.com/0rainge/retroSnakeGame" target="_blank" rel="noopener">https://github.com/0rainge/retroSnakeGame</a></p>
<h2 id="0-界面展示"><a href="#0-界面展示" class="headerlink" title="0.界面展示"></a>0.界面展示</h2><ul>
<li><h4 id="游戏开始界面"><a href="#游戏开始界面" class="headerlink" title="游戏开始界面"></a>游戏开始界面</h4><img src="https://github.com/0rainge/retroSnakeGame/blob/master/img/docImg/demo1.jpeg?raw=true" alt="image"></li>
<li><h4 id="游戏界面"><a href="#游戏界面" class="headerlink" title="游戏界面"></a>游戏界面</h4><img src="https://github.com/0rainge/retroSnakeGame/blob/master/img/docImg/demo2.jpeg?raw=true" alt="image"></li>
<li><h4 id="游戏结束界面"><a href="#游戏结束界面" class="headerlink" title="游戏结束界面"></a>游戏结束界面</h4><img src="https://github.com/0rainge/retroSnakeGame/blob/master/img/docImg/demo3.png?raw=true" alt="image">
</summary>
<category term="缓慢的前端学习-练手项目记录" scheme="https://0rainge.github.io/categories/%E7%BC%93%E6%85%A2%E7%9A%84%E5%89%8D%E7%AB%AF%E5%AD%A6%E4%B9%A0-%E7%BB%83%E6%89%8B%E9%A1%B9%E7%9B%AE%E8%AE%B0%E5%BD%95/"/>
<category term="JavaScript" scheme="https://0rainge.github.io/tags/JavaScript/"/>
</entry>
<entry>
<title>html/css/淘猫网</title>
<link href="https://0rainge.github.io/2019/01/24/html:css-%E6%B7%98%E7%8C%AB%E7%BD%91%E4%BB%BF%E7%AB%99/"/>
<id>https://0rainge.github.io/2019/01/24/html:css-淘猫网仿站/</id>
<published>2019-01-23T16:00:00.000Z</published>
<updated>2019-02-22T05:11:39.301Z</updated>
<content type="html"><![CDATA[<h1 id="参考淘宝首屏布局"><a href="#参考淘宝首屏布局" class="headerlink" title="参考淘宝首屏布局"></a>参考淘宝首屏布局</h1><p>做网页时的笔记整理,有些意识流。。</p><p>GitHub源地址:<a href="https://github.com/0rainge/taobaoHomePageDemo" target="_blank" rel="noopener">https://github.com/0rainge/taobaoHomePageDemo</a></p><h2 id="1-demo展示"><a href="#1-demo展示" class="headerlink" title="1. demo展示"></a>1. demo展示</h2><p><img src="https://github.com/0rainge/taobaoHomePageDemo/blob/master/doc_img/demoPage.png?raw=true" alt="image"><br><a id="more"></a></p><h2 id="2-涉及的问题"><a href="#2-涉及的问题" class="headerlink" title="2. 涉及的问题"></a>2. 涉及的问题</h2><ol><li>title目的</li><li>Css样式引入(style link 行间样式)</li><li>css选择器,权重问题</li><li>滚动条问题</li><li>快捷键</li><li>display</li><li>浮动</li><li>居中</li><li>文字竖直居中</li><li>盒模型</li><li>伪类与伪元素</li><li>背景图片background</li><li>定位:position/relative/fixed</li><li>盒模型的margin和padding</li><li>form</li><li>背景颜色的渐变 linear-gradient</li><li>圆角:border-radius</li><li>overflow</li><li>input样式处理 outline/padding/text-indent</li><li>文字环绕图片</li><li>雪碧图</li><li>盒模型的转换</li><li>背景定位 </li></ol><h2 id="3-笔记整理"><a href="#3-笔记整理" class="headerlink" title="3. 笔记整理"></a>3. 笔记整理</h2><h3 id="第0步:布局"><a href="#第0步:布局" class="headerlink" title="第0步:布局"></a>第0步:布局</h3><h4 id="0-1-布局划分"><a href="#0-1-布局划分" class="headerlink" title="0.1 布局划分"></a>0.1 布局划分</h4><p>先实现结构,后实现样式。<br>整个页面分为五部分:顶部导航栏,顶部搜索栏,中部横向导航栏,中部图片内容展示区,右侧信息服务区域,细化如下<br><img src="https://github.com/0rainge/taobaoHomePageDemo/blob/fdb31458a125b24fa7e802a0d77614e9a695e3d7/img/layout.png?raw=true" alt="image"></p><h4 id="0-2-布局过程"><a href="#0-2-布局过程" class="headerlink" title="0.2 布局过程"></a>0.2 布局过程</h4><h4 id="设置div"><a href="#设置div" class="headerlink" title="设置div"></a>设置div</h4><p>通配符选择器 初始化样式</p><figure class="highlight css"><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"> <span class="attribute">padding</span>: <span class="number">0</span>;</span><br><span class="line"> <span class="attribute">margin</span>: <span class="number">0</span>;</span><br><span class="line"> <span class="attribute">list-style</span>: none;</span><br><span class="line"> <span class="attribute">text-decoration</span>: none;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h4 id="宽度高度都占满整屏幕"><a href="#宽度高度都占满整屏幕" class="headerlink" title="宽度高度都占满整屏幕"></a>宽度高度都占满整屏幕</h4><p>宽度设置占满浏览器,设置父级document-html,body,wrapper 基于父级定位</p><figure class="highlight css"><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></pre></td><td class="code"><pre><span class="line"><span class="selector-tag">html</span>,<span class="selector-tag">body</span>{</span><br><span class="line"> <span class="attribute">width</span>: <span class="number">100%</span>;</span><br><span class="line"> <span class="attribute">height</span>: <span class="number">100%</span>;</span><br><span class="line">}</span><br><span class="line"><span class="selector-class">.wrapper</span>{</span><br><span class="line"> <span class="attribute">width</span>: <span class="number">100%</span>;</span><br><span class="line"> <span class="attribute">height</span>: <span class="number">100%</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>直接设置wrapper高度,将会被内容区撑开</p><p>做样式是从外往里面实现:根据结构的嵌套关系从外往里</p><p>架构上:加上CSS结构,条理,定位比较快,分块加注释</p><p>根据class层级选中导航条的wrap部分</p><p>子集div</p><p>最外面的区域整条100% 文字内容区域是局中的子集,有</p><figure class="highlight css"><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"><span class="selector-class">.wrapper</span> <span class="selector-class">.top-nav-wrap</span>{</span><br><span class="line"> <span class="attribute">width</span>: <span class="number">100%</span>;</span><br><span class="line"> <span class="attribute">height</span>: <span class="number">105px</span> ;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>高度包含导航条和广告的高度</p><p>当水平超过100%就会出现横向的滚动条</p><p>内容区域超出浏览器宽度就会出现横向的滚动条<br>.wrapper .top-nav-wrap{<br> width: 100%;<br> height: 105px ;<br> background-color: red;<br> border: 10px solid #000000;<br>}</p><h4 id="滚动条问题消失:"><a href="#滚动条问题消失:" class="headerlink" title="滚动条问题消失:"></a>滚动条问题消失:</h4><p>横向滚动条消失x<br>overflow-x: hidden;<br>给body加上;<br>如果没有-x 横向竖向都消失了;也不会向下滚屏</p><p>宽度100%的父集内有一个子集局中显示</p><h4 id="0-3-注意事项"><a href="#0-3-注意事项" class="headerlink" title="0.3 注意事项"></a>0.3 注意事项</h4><h5 id="问题:"><a href="#问题:" class="headerlink" title="问题:"></a>问题:</h5><p>.wrapper .top-nav-wrap(有空格)和.wrapper.top-nav-wrap(没有空格)有什么区别?</p><p>有空格:选中的是子元素,没有空格:选中的是通过两个class并列的</p><h5 id="拿到字体颜色"><a href="#拿到字体颜色" class="headerlink" title="拿到字体颜色"></a>拿到字体颜色</h5><p><img src="https://github.com/0rainge/taobaoHomePageDemo/blob/master/doc_img/get-font-color.png?raw=true" alt="image"></p><h5 id="如何看高度:"><a href="#如何看高度:" class="headerlink" title="如何看高度:"></a>如何看高度:</h5><p><img src="https://github.com/0rainge/taobaoHomePageDemo/blob/master/doc_img/getHeight.png?raw=true" alt="image"><br>97+24:height97 padding-top24</p><p>导航条部分 不占100% 屏幕大于的时候做居中处理的,大范围的展示区 ,2和3中有导航条 缩小部分没有横向滚动条 </p><h5 id="下面两栏实现左右局中:"><a href="#下面两栏实现左右局中:" class="headerlink" title="下面两栏实现左右局中:"></a>下面两栏实现左右局中:</h5><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-tag">margin</span>: 0 <span class="selector-tag">auto</span>;</span><br></pre></td></tr></table></figure><h3 id="第1步:顶部导航栏和广告栏"><a href="#第1步:顶部导航栏和广告栏" class="headerlink" title="第1步:顶部导航栏和广告栏"></a>第1步:顶部导航栏和广告栏</h3><h4 id="1-1导航条"><a href="#1-1导航条" class="headerlink" title="1.1导航条"></a>1.1导航条</h4><h4 id="1-1-1-导航条展示"><a href="#1-1-1-导航条展示" class="headerlink" title="1.1.1 导航条展示"></a>1.1.1 导航条展示</h4><p><img src="https://github.com/0rainge/taobaoHomePageDemo/blob/master/doc_img/demo01nav.png?raw=true" alt="image"></p><h4 id="1-1-2-导航条实现思路"><a href="#1-1-2-导航条实现思路" class="headerlink" title="1.1.2 导航条实现思路"></a>1.1.2 导航条实现思路</h4><h4 id="分析:"><a href="#分析:" class="headerlink" title="分析:"></a>分析:</h4><p>首先有一个父级包含广告和导航条,然后有一个导航条自己的父级和广告的父级,父级100% 图片有固定的宽度做了局中处理,广告有a标签或者div</p><p>导航条的样式如何实现:<br>上一个div没有高度和宽度</p><p>导航栏实现:左侧有一组小列表,右侧有一排小列表,并列的 span a ,左边一组 右边一组 左右 ul li 无序列表 ,左侧3个li 登录注册算一个 右侧7个li</p><h4 id="1-1-3-导航条注意事项"><a href="#1-1-3-导航条注意事项" class="headerlink" title="1.1.3 导航条注意事项"></a>1.1.3 导航条注意事项</h4><p>小三角符号用 iconfont 字体图库<br>![image]</p><h4 id="快捷键"><a href="#快捷键" class="headerlink" title="快捷键"></a>快捷键</h4><p>选中后control+D进行批量操作</p><p>control + ? 开启注释</p><p>竖着排列 ul是块级元素 ul水平并列,左侧ul在左侧 右侧ul在右侧:左侧ul在左侧浮动 右侧ul在右侧浮动,讲ul中的li标签变成水平的 行级元素/行级块元素 display 浮动 :将ul中的li浮动,包含两个ul 左右两个宽高,局中处理:宽度的临界值是1190px</p><p>浮动:脱离文档流,碰到上一个浮动元素停止</p><p>!!!坑:类名多加一个空格就会无法识别</p><p>把所有的元素水平横过来:</p><figure class="highlight html"><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">.wrapper .top-nav-wrap .top-nav ul li{</span><br><span class="line"> float: left;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>用ul的浮动跑到左侧和右侧 ,再用ul li中的浮动 让ul把竖着的块级元素变成水平的</p><p>处理文字样式,文字包含到了导航栏的a标签</p><p>文字竖直居中:文字行高=父级的高度</p><p>文字的行高 line-height</p><p>盒模型:标准盒模型和IE模式下的盒模型</p><p>细节的问题hover 伪类 鼠标覆盖 </p><p>input search区域有伪元素</p><p>因为可能的命名冲突和权重问题,最好写选择器的时候把层级关系写上</p><p>单独选中而非批量li</p><p>所有的背景图片有大小的范围</p><p>让背景图片先出现 再以背景图片不同的class类名 替换成不同的图片</p><p>背景图片有一个相同的类名,并且都是span标签<br>需要具有固定宽高,水平排列行级块元素 </p><p>选中独立的class名剔除</p><p>display inline block的对齐方式 竖直的对齐方式默认是bottom 设置居中对齐<br>vertical-align: middle;</p><h4 id="1-2广告条"><a href="#1-2广告条" class="headerlink" title="1.2广告条"></a>1.2广告条</h4><h4 id="1-2-1-广告条展示"><a href="#1-2-1-广告条展示" class="headerlink" title="1.2.1 广告条展示"></a>1.2.1 广告条展示</h4><h4 id="1-2-2-广告条实现思路"><a href="#1-2-2-广告条实现思路" class="headerlink" title="1.2.2 广告条实现思路"></a>1.2.2 广告条实现思路</h4><h4 id="广告实现:"><a href="#广告实现:" class="headerlink" title="广告实现:"></a>广告实现:</h4><figure class="highlight html"><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"><span class="tag"><<span class="name">div</span> <span class="attr">class</span>=<span class="string">"ad-wrap "</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">div</span> <span class="attr">class</span>=<span class="string">"ad"</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">img</span> <span class="attr">src</span>=<span class="string">""</span> <span class="attr">alt</span>=<span class="string">""</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">div</span>></span></span><br><span class="line"><span class="tag"></<span class="name">div</span>></span></span><br></pre></td></tr></table></figure><h4 id="1-2-3-广告条注意事项"><a href="#1-2-3-广告条注意事项" class="headerlink" title="1.2.3 广告条注意事项"></a>1.2.3 广告条注意事项</h4><p>广告条长度固定,多余部分换成相同颜色的背景</p><h3 id="第2步:搜索框部分"><a href="#第2步:搜索框部分" class="headerlink" title="第2步:搜索框部分"></a>第2步:搜索框部分</h3><h4 id="2-1-搜索框展示"><a href="#2-1-搜索框展示" class="headerlink" title="2.1 搜索框展示"></a>2.1 搜索框展示</h4><p><img src="https://github.com/0rainge/taobaoHomePageDemo/blob/master/doc_img/demo02search.png?raw=true" alt="image"></p><h4 id="2-2-搜索框实现思路"><a href="#2-2-搜索框实现思路" class="headerlink" title="2.2 搜索框实现思路"></a>2.2 搜索框实现思路</h4><p>架构:</p><figure class="highlight"><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"><div class="search-wrap "></span><br><span class="line"> <div class="search-con"></span><br><span class="line"> <div class="logo-box"></div></span><br><span class="line"> <div class="search-box"></div></span><br><span class="line"> <div class="code-box"> </div></span><br><span class="line"> </div></span><br><span class="line"></div></span><br></pre></td></tr></table></figure><p>padding把内容区域撑开</p><p>固定高度和宽度:1190</p><p>大于居中处理,小于做滚动条(over flow)超出滚动条消失</p><p>本来是3个块级元素div:竖直排列改为水平——行级块元素/浮动</p><p>基于下水平线进行对齐</p><h4 id="2-3-搜索框注意事项"><a href="#2-3-搜索框注意事项" class="headerlink" title="2.3 搜索框注意事项"></a>2.3 搜索框注意事项</h4><p>定位:<br>position: relative;<br> 相对于自身的位置向上 top -10</p><p>相对定位 绝对定位 相对浏览器 默认值</p><p>一缩小浏览器/发生改动之后有变化</p><p>为什么: 要知道是相对谁进行定位<br>relative——相对自身(默认值?)进行定位</p><p>absolute——相对最近的有定位(除了默认的都行:relative absolute fixed)的父级进行定位</p><p>一般:想要被定位的元素——父级设为relative 自身设为absolute 然后通过top值等进行控制定位</p><p>基础有应用很多</p><p>盒模型的margin和padding</p><p>margin 外边距<br>paddign 内边距</p><p>两个a标签以背景图片的方法出现</p><p>form表单</p><p>ul li 通过表格横过来</p><p>处于pannel的上面</p><p>浮动元素脱离文档流 不能主动撑开父级,可以手动增加 </p><p>利用绝对定位:基于search panel</p><p>跑到右边:</p><pre><code>position: absolute;top: 0;right: 0;</code></pre><p>查看动作的颜色,手动触发伪类</p><p>渐变色</p><p>background: linear-gradient(to right,#ff9000 0, #ff5000 100% )</p><p>CSS3的内容</p><p>input的格式 outline</p><p>i标签引入的字体</p><p>标签的背景图片 </p><p>多个选择器并列</p><figure class="highlight css"><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"><span class="selector-class">.wrapper</span> <span class="selector-class">.search-wrap</span> <span class="selector-class">.search-con</span> <span class="selector-class">.search-box</span> <span class="selector-class">.magnifier</span>,</span><br><span class="line"><span class="selector-class">.wrapper</span> <span class="selector-class">.search-wrap</span> <span class="selector-class">.search-con</span> <span class="selector-class">.search-box</span> <span class="selector-class">.camera</span>{</span><br><span class="line"> <span class="attribute">display</span>: inline-block;</span><br><span class="line"> <span class="attribute">position</span>: absolute;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h3 id="第3步:中间导航条"><a href="#第3步:中间导航条" class="headerlink" title="第3步:中间导航条"></a>第3步:中间导航条</h3><h4 id="3-1-中部导航条展示"><a href="#3-1-中部导航条展示" class="headerlink" title="3.1 中部导航条展示"></a>3.1 中部导航条展示</h4><p><img src="https://github.com/0rainge/taobaoHomePageDemo/blob/master/doc_img/demo03midNav.png?raw=true" alt="image"></p><h4 id="3-2-中间导航条注意事项"><a href="#3-2-中间导航条注意事项" class="headerlink" title="3.2 中间导航条注意事项"></a>3.2 中间导航条注意事项</h4><p>h2 后面跟了三个ul 标签</p><p>缩小到一定程度会有一栏标签消失:媒体查询——子适应</p><p>一组消失比较方便</p><p>鼠标覆盖时头上出现小动画:伪元素</p><p>.wrapper .screen-nav .screen-nav-con ul li :hover::before</p><p>伪类和伪元素</p><p>伪元素只有两个:before和after,真实的添加一个元素(可以用伪元素来清除浮动)<br>伪类有很多:hover,可以看成是触发的一个状态</p><h3 id="第4步:内容标签图片展示区域"><a href="#第4步:内容标签图片展示区域" class="headerlink" title="第4步:内容标签图片展示区域"></a>第4步:内容标签图片展示区域</h3><p>两栏 上下 三栏 轮播图+图片展示<br><img src="https://github.com/0rainge/taobaoHomePageDemo/blob/master/doc_img/demo04content2.png?raw=true" alt="image"></p><p>浮动 伪类 居中</p><p>文字属性:line-height text-aligin font-size font-wight</p><p>文字环绕图片</p><p> .wrapper .screen-box .main .main-bottom .content a img{<br> float: left;<br> }</p><p>图片浮动之后脱离了当前的文档流 但是没有脱离之前的文本流</p><h3 id="第5步:右侧信息服务区域"><a href="#第5步:右侧信息服务区域" class="headerlink" title="第5步:右侧信息服务区域"></a>第5步:右侧信息服务区域</h3><p>包括:登录,信息展示区域,论坛信息展示区域,模块信息展示区域,APP信息展示区域</p><p><img src="https://github.com/0rainge/taobaoHomePageDemo/blob/master/doc_img/demo05colRignt.png?raw=true" alt="image"></p><p>登录,信息论坛等5部分</p><ol><li>雪碧图</li><li>盒模型的转换</li><li>背景定位</li></ol><p>雪碧图:通过调整背景图片调整性能</p><p>设置了宽度之后 text-align</p><figure class="highlight css"><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"><span class="selector-class">.wrapper</span> <span class="selector-class">.screen-box</span> <span class="selector-class">.col-right</span> <span class="selector-class">.member</span> <span class="selector-class">.member-head</span> <span class="selector-tag">p</span> <span class="selector-tag">a</span> <span class="selector-tag">span</span> {</span><br><span class="line"> <span class="attribute">position</span>: absolute;</span><br><span class="line"> <span class="attribute">display</span>: inline-block;</span><br><span class="line"> <span class="attribute">width</span>: <span class="number">16px</span>;</span><br><span class="line"> <span class="attribute">height</span>: <span class="number">16px</span>;</span><br><span class="line"> <span class="attribute">top</span>: <span class="number">0px</span>;</span><br><span class="line"> <span class="attribute">left</span>: <span class="number">0px</span>;</span><br><span class="line"> <span class="comment">/* border: 1px solid #000000; */</span></span><br><span class="line"> <span class="attribute">background-image</span>: <span class="built_in">url</span>(<span class="string">'./img/pics.png'</span>);</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="selector-class">.wrapper</span> <span class="selector-class">.screen-box</span> <span class="selector-class">.col-right</span> <span class="selector-class">.member</span> <span class="selector-class">.member-head</span> <span class="selector-tag">p</span> <span class="selector-tag">a</span><span class="selector-class">.icon</span> <span class="selector-tag">span</span> {</span><br><span class="line"> <span class="attribute">background-position</span>: <span class="number">0</span> -<span class="number">572.5px</span></span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="selector-class">.wrapper</span> <span class="selector-class">.screen-box</span> <span class="selector-class">.col-right</span> <span class="selector-class">.member</span> <span class="selector-class">.member-head</span> <span class="selector-tag">p</span> <span class="selector-tag">a</span><span class="selector-class">.club</span> <span class="selector-tag">span</span> {</span><br><span class="line"> <span class="attribute">background-position</span>: <span class="number">0</span> -<span class="number">572.5px</span></span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>盒模型转换</p><p>因为左右两边设置了8px的padding值</p><pre><code>width: 100%;padding: 0 8px;</code></pre><p>把标准模式下的盒模型转换为IE模式下的盒模型</p><p>标准模式下的盒模型:width+padding<br>IE模式下的盒模型:width(里面有padding)</p><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-tag">box-sizing</span>: <span class="selector-tag">border-box</span>;</span><br></pre></td></tr></table></figure><p>选中a标签下的 .active 类<br>.wrapper .screen-box .col-right .notice .title li a.active</p><p>注意没有空格!</p><p>让文字下面的线变长:<br> padding: 0 2px;</p><figure class="highlight css"><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></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="selector-class">.wrapper</span> <span class="selector-class">.screen-box</span> <span class="selector-class">.col-right</span> <span class="selector-class">.notice</span> <span class="selector-class">.title</span> <span class="selector-tag">li</span> <span class="selector-tag">a</span>{</span><br><span class="line"> <span class="attribute">color</span>: <span class="number">#3c3c3c</span>;</span><br><span class="line"> <span class="attribute">font-size</span>: <span class="number">13px</span>;</span><br><span class="line"> <span class="attribute">line-height</span>: <span class="number">20px</span>; </span><br><span class="line"> <span class="attribute">padding</span>: <span class="number">0</span> <span class="number">2px</span>;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="selector-class">.wrapper</span> <span class="selector-class">.screen-box</span> <span class="selector-class">.col-right</span> <span class="selector-class">.notice</span> <span class="selector-class">.title</span> <span class="selector-tag">li</span> <span class="selector-tag">a</span><span class="selector-class">.active</span>{</span><br><span class="line"> <span class="attribute">font-weight</span>: <span class="number">700</span>;</span><br><span class="line"> <span class="attribute">border-bottom</span>: <span class="number">2px</span> solid <span class="number">#f40</span>;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"><span class="selector-tag">a</span>中加<span class="selector-tag">padding</span> <span class="selector-tag">width</span>是100% 会溢出</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"> <span class="selector-class">.wrapper</span> <span class="selector-class">.screen-box</span> <span class="selector-class">.col-right</span> <span class="selector-class">.module</span>{</span><br><span class="line"> <span class="attribute">width</span>: <span class="number">100%</span>;</span><br><span class="line"> <span class="attribute">height</span>: <span class="number">230px</span>;</span><br><span class="line"> <span class="attribute">border</span>: <span class="number">1px</span> solid <span class="number">#000000</span>; </span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="selector-class">.wrapper</span> <span class="selector-class">.screen-box</span> <span class="selector-class">.col-right</span> <span class="selector-class">.module</span> <span class="selector-tag">ul</span> <span class="selector-tag">li</span>{</span><br><span class="line"> <span class="attribute">float</span>: left;</span><br><span class="line"> <span class="attribute">width</span>: <span class="number">71px</span>;</span><br><span class="line"> <span class="attribute">height</span>: <span class="number">75px</span>;</span><br><span class="line"> <span class="attribute">border</span>: <span class="number">1px</span> solid <span class="number">#000000</span>; </span><br><span class="line"> <span class="comment">/* box-sizing: border-box; */</span></span><br><span class="line"> }</span><br></pre></td></tr></table></figure><p>受盒模型影响 边框+内容区域大于总区域,溢出:</p><p>把标准模式下的盒模型 content-box<br>转移成IE模型下的盒模型 border-box</p><p>inline-block 既可以设置宽高 又可以设置 text-align: center 进行居中</p><p>position 默认:距离左侧和上侧的距离</p>]]></content>
<summary type="html">
<h1 id="参考淘宝首屏布局"><a href="#参考淘宝首屏布局" class="headerlink" title="参考淘宝首屏布局"></a>参考淘宝首屏布局</h1><p>做网页时的笔记整理,有些意识流。。</p>
<p>GitHub源地址:<a href="https://github.com/0rainge/taobaoHomePageDemo" target="_blank" rel="noopener">https://github.com/0rainge/taobaoHomePageDemo</a></p>
<h2 id="1-demo展示"><a href="#1-demo展示" class="headerlink" title="1. demo展示"></a>1. demo展示</h2><p><img src="https://github.com/0rainge/taobaoHomePageDemo/blob/master/doc_img/demoPage.png?raw=true" alt="image"><br>
</summary>
<category term="缓慢的前端学习-练手项目记录" scheme="https://0rainge.github.io/categories/%E7%BC%93%E6%85%A2%E7%9A%84%E5%89%8D%E7%AB%AF%E5%AD%A6%E4%B9%A0-%E7%BB%83%E6%89%8B%E9%A1%B9%E7%9B%AE%E8%AE%B0%E5%BD%95/"/>
<category term="html" scheme="https://0rainge.github.io/tags/html/"/>
<category term="css" scheme="https://0rainge.github.io/tags/css/"/>
</entry>
<entry>
<title>fission二次测试以及组件日志分析</title>
<link href="https://0rainge.github.io/2018/06/07/fission%E4%BA%8C%E6%AC%A1%E6%B5%8B%E8%AF%95%E4%BB%A5%E5%8F%8A%E7%BB%84%E4%BB%B6%E6%97%A5%E5%BF%97%E5%88%86%E6%9E%90/"/>
<id>https://0rainge.github.io/2018/06/07/fission二次测试以及组件日志分析/</id>
<published>2018-06-06T16:00:00.000Z</published>
<updated>2018-06-07T09:30:44.000Z</updated>
<content type="html"><![CDATA[<p>对fission进行测试分析组件日志:</p><h3 id="进行测试如下:"><a href="#进行测试如下:" class="headerlink" title="进行测试如下:"></a>进行测试如下:</h3><ol><li>创建语言环境镜像、给函数创建路由route trigger、上传函数、测试函数、请求函数、查看函数日志</li><li>编译多个文件组成的源码函数:对源码进行打包上传,根据压缩包创建函数、创建路由、通过fission进行解释或编译链接、查看bulid日志</li><li>编译artifacts(已打包函数),创建函数、创建路由、测试函数、查看全部函数</li><li>创建语言环境镜像、创建builder、查看环境</li><li>自动扩容(需要未安装工具hey)</li><li>创建trigger:包括http trigger,time trigger,message queue trigger</li><li>传源码包:通过fission创建由多个文件组成的函数压缩包,创建package,查看package信息,通过package创建函数</li><li>创建部署包:通过fission创建由一个文件组成的函数压缩包,创建package,查看package信息,通过package创建函数</li><li>测试函数对k8s中secret和ConfigMaps的访问(demo中的secret路径出现问题,还没找到对的路径) </li><li>fission的workflow测试</li></ol><h3 id="组件分析如下:"><a href="#组件分析如下:" class="headerlink" title="组件分析如下:"></a>组件分析如下:</h3><h4 id="builder:"><a href="#builder:" class="headerlink" title="builder:"></a>builder:</h4><ul><li>作用:编译链接上传的源码package</li><li>日志包括:记录创建builder service、builder deployment、builder pod、build程序包(注意给build.dh加权限)、上传部署包、更新部署包、build失败报错信息</li></ul><h4 id="controller:"><a href="#controller:" class="headerlink" title="controller:"></a>controller:</h4><ul><li>作用:每次http请求函数的信息</li><li>日志包括:服务器状态,端口,返回http请求的head信息,每次向fission请求时http信息(包括请求错误url的proxy error)如<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">127.0.0.1 - - [07/Jun/2018:01:50:33 +0000] "GET /v2/packages/demo-src-pkg-zip-8lwt?namespace=default HTTP/1.1" 404 9</span><br><span class="line">以及(应该是)每次请求的函数地址和传入参数的地址如</span><br><span class="line">github.com/fission/fission/controller.(*API).respondWithError(0xc420082ae0, 0x7f5c883e4e60, 0xc4201a4960, 0x178ea60, 0xc420510b40)</span><br><span class="line">/Volumes/MacintoshHD/Dropbox/Dropbox/goWorkspace/src/github.com/fission/fission/controller/api.go:98 +0x29</span><br></pre></td></tr></table></figure></li></ul><h4 id="executor:"><a href="#executor:" class="headerlink" title="executor:"></a>executor:</h4><ul><li>作用:创建函数</li><li>日志包括:检查是缓冲中跑起来的函数,没有找到的话创建一个,为函数分配环境,设置一个数据结构记录函数信息(如函数名,GenerateName:命名空间;SelfLink,Generation;创建时间戳,删除时间戳,存活时间(DeletionGracePeriodSeconds),标签,实例化url),从pool中得到这个函数,选择pod,通过pod ip实例化pod,从pool中找到可以实例化的pod,对函数和pod进行映射,对pod加上标签,选择pod,调用fetcher 拷贝函数到指定url上,实例化pod,用环境镜像实例化pod,为pod加上ip,创建对应语言的pool,拉取fetcher镜像等。</li></ul><h4 id="kubewatcher:"><a href="#kubewatcher:" class="headerlink" title="kubewatcher:"></a>kubewatcher:</h4><p>没有查到日志</p><h4 id="router:"><a href="#router:" class="headerlink" title="router:"></a>router:</h4><ul><li>作用:对http请求进行转发</li><li>日志包括:<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">2018/06/07 05:47:12 Calling getServiceForFunction for function: hello</span><br><span class="line">2018/06/07 05:47:30 Tapped 1 services in batch</span><br><span class="line">2018/06/07 05:47:30 Tapped 1 services in batch</span><br><span class="line">2018/06/07 05:48:00 Tapped 1 services in batch</span><br><span class="line">2018/06/07 05:48:00 Tapped 1 services in batch</span><br><span class="line">2018/06/07 05:48:15 Tapped 1 services in batch</span><br><span class="line">2018/06/07 05:48:15 Tapped 1 services in batch</span><br></pre></td></tr></table></figure></li></ul><h4 id="storagesvc:"><a href="#storagesvc:" class="headerlink" title="storagesvc:"></a>storagesvc:</h4><ul><li>作用:储存服务</li><li>日志包括:<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">time="2018-06-06T07:24:53Z" level=info msg="Storage service started"</span><br><span class="line">time="2018-06-06T07:24:53Z" level=info msg="listening to archiveChannel to prune archives"</span><br><span class="line">time="2018-06-06T08:24:53Z" level=info msg="getting orphan archives"</span><br><span class="line">time="2018-06-06T09:24:53Z" level=info msg="getting orphan archives"</span><br><span class="line">time="2018-06-06T09:32:41Z" level=info msg="Handling upload for /packages/demo-src-pkg-zip-fbza-o3s5sk-icbzii.zip"</span><br><span class="line">172.16.76.86 - - [06/Jun/2018:09:32:41 +0000] "POST /v1/archive HTTP/1.1" 200 72</span><br><span class="line">172.16.76.115 - - [06/Jun/2018:09:40:01 +0000] "GET /v1/archive?id=%2Ffission%2Ffission-functions%2Fde313c06-247e-44a5-83a6-0d257d224212 HTTP/1.1" 200 103852</span><br><span class="line">time="2018-06-06T10:24:53Z" level=info msg="getting orphan archives"</span><br><span class="line">time="2018-06-07T01:50:32Z" level=info msg="Handling upload for /packages/demo-src-pkg-zip-d20x-rnhpna-i8fmoq.zip"</span><br><span class="line">172.16.76.95 - - [07/Jun/2018:01:50:32 +0000] "POST /v1/archive HTTP/1.1" 200 72</span><br><span class="line">time="2018-06-07T02:24:53Z" level=info msg="getting orphan archives"</span><br></pre></td></tr></table></figure></li></ul><h4 id="timer:"><a href="#timer:" class="headerlink" title="timer:"></a>timer:</h4><ul><li>作用:一个基于时间的triggers,定时向请求指定函数。这里是每30s请求一次。</li><li>日志包括:<br>2018/06/07 08:17:30 Making HTTP request to <a href="http://router.fission/fission-function/hello" target="_blank" rel="noopener">http://router.fission/fission-function/hello</a><br>主要是记录时间</li></ul>]]></content>
<summary type="html">
<p>对fission进行测试分析组件日志:</p>
<h3 id="进行测试如下:"><a href="#进行测试如下:" class="headerlink" title="进行测试如下:"></a>进行测试如下:</h3><ol>
<li>创建语言环境镜像、给函数创建路由r
</summary>
<category term="FaaS踩坑系列" scheme="https://0rainge.github.io/categories/FaaS%E8%B8%A9%E5%9D%91%E7%B3%BB%E5%88%97/"/>
<category term="fission" scheme="https://0rainge.github.io/tags/fission/"/>
</entry>
<entry>
<title>SqueezeNet介绍</title>
<link href="https://0rainge.github.io/2018/06/01/SqueezeNet%E4%BB%8B%E7%BB%8D/"/>
<id>https://0rainge.github.io/2018/06/01/SqueezeNet介绍/</id>
<published>2018-05-31T16:00:00.000Z</published>
<updated>2018-06-05T09:22:11.000Z</updated>
<content type="html"><![CDATA[<h3 id="定义:"><a href="#定义:" class="headerlink" title="定义:"></a>定义:</h3><p>压缩神经网络参数——轻量化网络<br>SqueezeNet是一个小型化的网络模型结构,在保证不降低检测精度的同时,用了比AlexNet少50倍的参数。</p><p>同时采用了deep compression技术,对squeezenet进行了压缩,将原始AlexNet模型压缩至原来的1/500(模型文件< 0.5MB,原始AlexNet模型约为200MB,同时增大了计算量。</p><h3 id="措施:"><a href="#措施:" class="headerlink" title="措施:"></a>措施:</h3><ol><li>将一部分3x3的filter(卷集核)替换成1x1的filter;<br>本文替换3x3的卷积kernel为1x1的卷积kernel可以让参数缩小9X。但是为了不影响识别精度,并不是全部替换,而是一部分用3x3,一部分用1x1。</li><li>减少输入的channels(3x3卷积核的input feature map数量,输入通道数);<br>如果是conv1-conv2这样的直连,那么实际上是没有办法减少conv2的input feature map数量的。因此把一层conv分解为两层,封装为一个Fire Module。使用squeeze layers来实现。</li><li>在整个网络后期才进行下采样,使得卷积层有比较大的activation maps;<br>分辨率越大的特征图(延迟降采样)可以带来更高的分类精度,因为分辨率越大的输入能够提供的信息就越多。将欠采样操作延后,可以给卷积层提供更大的激活图:更大的激活图保留了更多的信息,可以提供更高的分类准确率。</li></ol><p>其中:措施1、2可降低参数数量。措施3用来大化网络精度。</p><h3 id="fire-module:"><a href="#fire-module:" class="headerlink" title="fire module:"></a>fire module:</h3><p>一个类似inception的网络单元结构。SqueezeNet的网络结构由若干个 fire module 组成。<br>将原来一层conv层变成两层:squeeze卷集层(有1x1卷集核)+expand卷集层(1x1和3x3卷积核)。</p><ol><li>策略1:squeeze层用1x1的卷集filter。squeeze层借鉴了inception的思想,利用1x1卷积核来降低输入到expand层中3x3卷积核的输入通道数channels。</li><li>策略2: 定义squeeze层中1x1卷积核的数量是s1x1,expand层中1x1卷积核的数量是e1x1, 3x3卷积核的数量是e3x3。令s1x1 < e1x1+ e3x3从而保证输入到3x3的输入通道数减小,这样squeeze layer可以限制输入通道数量。<br>激活函数:为了保证1x1卷积核和3x3卷积核具有相同大小的输出,3x3卷积核采用1像素的zero-padding和步长 squeeze层和expand层均采用RELU作为激活函数 。</li></ol><p>Fire module输入的feature map为H<em>W</em>M的,输出的feature map为H<em>M</em>(e1+e3),可以看到feature map的分辨率是不变的,变的仅是维数,也就是通道数,这一点和VGG的思想一致。<br>首先,H<em>W</em>M的feature map经过Squeeze层,得到S1个feature map,这里的S1均是小于M的,以达到“压缩”的目的。<br>其次,H<em>W</em>S1的特征图输入到Expand层,分别经过1<em>1卷积层和3</em>3卷积层进行卷积,再将结果进行concat,得到Fire module的输出,为 H<em>M</em>(e1+e3)的feature map。<br>fire模块有三个可调参数:S1,e1,e3,分别代表卷积核的个数,同时也表示对应输出feature map的维数,在本文提出的SqueezeNet结构中,e1=e3=4s1</p><h3 id="模型:"><a href="#模型:" class="headerlink" title="模型:"></a>模型:</h3><p>SqueezeNet以卷积层(conv1)开始,接着使用8个Fire modules (fire2-9),最后以卷积层(conv10)结束。每个fire module中的filter数量逐渐增加,并且在conv1, fire4, fire8, 和 conv10这几层之后使用步长为2的max-pooling,即将池化层放在相对靠后的位置,这使用了以上的策略(3)。<br>最后是一个conv10,在fire9后采用50%的dropout 由于全连接层的参数数量巨大,因此借鉴NIN的思想,去除了全连接层FC而改用global average pooling。</p><h3 id="减少参数的优点:"><a href="#减少参数的优点:" class="headerlink" title="减少参数的优点:"></a>减少参数的优点:</h3><p>1、实现更高效的分布式训练;<br>服务器间的通信是分布式CNN训练的重要限制因素。对于分布式 数据并行 训练方式,通信需求和模型参数数量正相关。小模型对通信需求更低。<br>2、训练出轻量级的模型,减小下载模型到客户端的额外开销 ;<br>比如在自动驾驶中,经常需要更新客户端模型。更小的模型可以减少通信的额外开销,使得更新更加容易。<br>3、在FPGA和嵌入式硬件上的部署实现;</p><h3 id="GitHub项目:"><a href="#GitHub项目:" class="headerlink" title="GitHub项目:"></a>GitHub项目:</h3><p>SqueezeNet <a href="https://github.com/DeepScale/SqueezeNet" target="_blank" rel="noopener">https://github.com/DeepScale/SqueezeNet</a> 1.4k star<br>SqueezeNet-Deep-Compression: <a href="https://github.com/songhan/SqueezeNet-Deep-Compression" target="_blank" rel="noopener">https://github.com/songhan/SqueezeNet-Deep-Compression</a> 314 star <a href="https://arxiv.org/abs/1602.07360" target="_blank" rel="noopener">https://arxiv.org/abs/1602.07360</a><br>SqueezeNet-Generator: <a href="https://github.com/songhan/SqueezeNet-Generator" target="_blank" rel="noopener">https://github.com/songhan/SqueezeNet-Generator</a><br>SqueezeNet-DSD-Training: <a href="https://github.com/songhan/SqueezeNet-DSD-Training" target="_blank" rel="noopener">https://github.com/songhan/SqueezeNet-DSD-Training</a><br>SqueezeNet-Residual: <a href="https://github.com/songhan/SqueezeNet-Residual" target="_blank" rel="noopener">https://github.com/songhan/SqueezeNet-Residual</a><br><a href="https://github.com/vonclites/squeezenet" target="_blank" rel="noopener">https://github.com/vonclites/squeezenet</a> 52 star 有原论文 <a href="https://arxiv.org/abs/1602.07360" target="_blank" rel="noopener">https://arxiv.org/abs/1602.07360</a><br><a href="https://github.com/rcmalli/keras-squeezenet" target="_blank" rel="noopener">https://github.com/rcmalli/keras-squeezenet</a> 251 star Keras实现 squeezenet<br><a href="https://github.com/DT42/squeezenet_demo" target="_blank" rel="noopener">https://github.com/DT42/squeezenet_demo</a> 175 star </p><h3 id="相关论文:"><a href="#相关论文:" class="headerlink" title="相关论文:"></a>相关论文:</h3><p><a href="https://arxiv.org/pdf/1602.07360v3.pdf" target="_blank" rel="noopener">https://arxiv.org/pdf/1602.07360v3.pdf</a> squeezenet用了比AlexNet少50倍的参数,达到了AlexNet相同的精度<br><a href="https://arxiv.org/pdf/1506.02626v3.pdf" target="_blank" rel="noopener">https://arxiv.org/pdf/1506.02626v3.pdf</a> Learning both Weights and Connections for Efficient Neural Network (NIPS’15)<br><a href="https://arxiv.org/pdf/1510.00149v5.pdf" target="_blank" rel="noopener">https://arxiv.org/pdf/1510.00149v5.pdf</a> 深度压缩,用剪枝来压缩深度神经网络,训练量化和 Huffman 编码<br><a href="https://arxiv.org/pdf/1602.01528v1.pdf" target="_blank" rel="noopener">https://arxiv.org/pdf/1602.01528v1.pdf</a> 压缩神经网络的Efficient Inference Engine</p><h3 id="总结:"><a href="#总结:" class="headerlink" title="总结:"></a>总结:</h3><p>squeezenet采用“多层小卷积核”策略,通过增加计算量换来更少的参数,把参数读取的代价转移到计算量上。计算耗时还是要远远小于数据存取耗时的,是“多层小卷积核”策略成功的根源。</p><h3 id="其他:"><a href="#其他:" class="headerlink" title="其他:"></a>其他:</h3><p>mobilenet和,squeezenet都是alexnet参数量1/50,mobilenet速度比alexnet快10倍,squeezenet提升3%</p>]]></content>
<summary type="html">
<h3 id="定义:"><a href="#定义:" class="headerlink" title="定义:"></a>定义:</h3><p>压缩神经网络参数——轻量化网络<br>SqueezeNet是一个小型化的网络模型结构,在保证不降低检测精度的同时,用了比AlexNe
</summary>
<category term="SqueezeNet" scheme="https://0rainge.github.io/categories/SqueezeNet/"/>
<category term="SqueezeNet" scheme="https://0rainge.github.io/tags/SqueezeNet/"/>
<category term="神经网络" scheme="https://0rainge.github.io/tags/%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C/"/>
</entry>
<entry>
<title>SqueezeNet的ARM和树莓派案例</title>
<link href="https://0rainge.github.io/2018/06/01/SqueezeNet%E7%9A%84ARM%E5%92%8C%E6%A0%91%E8%8E%93%E6%B4%BE%E6%A1%88%E4%BE%8B/"/>
<id>https://0rainge.github.io/2018/06/01/SqueezeNet的ARM和树莓派案例/</id>
<published>2018-05-31T16:00:00.000Z</published>
<updated>2018-06-05T09:07:21.000Z</updated>
<content type="html"><![CDATA[<h2 id="ARM"><a href="#ARM" class="headerlink" title="ARM"></a>ARM</h2><ol><li>ARM Compute Library案例:</li></ol><ul><li>案例:<br>ARM 计算库(ACL)提供了CNN的基本构造块,比如激活、卷积、全连接和局部连接、规范化、池化和softmax功能. 文章通过这些组件构建SqueezeNet ,并与通过tensorflow构建的SqueezeNet进行比较,</li><li>产品化程度:<br>理论性较强,产品化程度不高。重点介绍了如何通过ACL构建SqueezeNet架构的CNN推理机 ,并与通过Zuluko上tensorflow构建的SqueezeNet进行比较。<br>-SqueezeNet 起到的作用:<br>作为用于测试ACL性能的神经网络模型。</li><li>链接:<br><a href="https://arxiv.org/pdf/1704.03751.pdf" target="_blank" rel="noopener">https://arxiv.org/pdf/1704.03751.pdf</a> 和<br><a href="https://community.arm.com/iot/embedded/b/embedded-blog/posts/perceptin-enabled-embedded-deep-learning-inference-engine-with-the-arm-compute-library" target="_blank" rel="noopener">https://community.arm.com/iot/embedded/b/embedded-blog/posts/perceptin-enabled-embedded-deep-learning-inference-engine-with-the-arm-compute-library</a></li><li>代码:<br>ACL中样例SqueezeNet的C++代码 <a href="https://github.com/ARM-software/ComputeLibrary/blob/master/examples/graph_squeezenet_v1_1.cpp" target="_blank" rel="noopener">https://github.com/ARM-software/ComputeLibrary/blob/master/examples/graph_squeezenet_v1_1.cpp</a></li></ul><h2 id="Raspberry-Pi-3"><a href="#Raspberry-Pi-3" class="headerlink" title="Raspberry Pi 3"></a>Raspberry Pi 3</h2><ol><li>用opencv在树莓派上部署SqueezeNet</li></ol><ul><li>案例:用OpenCV3.3.0在Raspberry Pi 3上部署 pre-trained SqueezeNet Neural Network</li><li>产品化程度:<br>比较高,可以输出结果。</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></pre></td><td class="code"><pre><span class="line">(1)在图像上绘出最高的预测分类标签和相应的概率</span><br><span class="line">(2)将前五个结果和概率打印到终端</span><br><span class="line">(3)将图像显示在屏幕上</span><br><span class="line"></span><br><span class="line">[INFO] loading model...</span><br><span class="line">[INFO] classification took 0.4432 seconds</span><br><span class="line">[INFO] 1. label: drake, probability: 0.25705</span><br><span class="line">[INFO] 2. label: goose, probability: 0.18581</span><br><span class="line">[INFO] 3. label: black stork, probability: 0.10414</span><br><span class="line">[INFO] 4. label: hornbill, probability: 0.074497</span><br><span class="line">[INFO] 5. label: quail, probability: 0.051127</span><br></pre></td></tr></table></figure><ul><li>SqueezeNet 起到的作用:<br>用于图像识别,在案例中起主要作用。</li><li>代码:<a href="https://github.com/appinho/Raspberry_Pi_3_Image_Classification/tree/master/SqueezeNet" target="_blank" rel="noopener">https://github.com/appinho/Raspberry_Pi_3_Image_Classification/tree/master/SqueezeNet</a></li></ul><ol start="2"><li>使用Raspberry Pi和预先训练的深度学习神经网络对输入图像进行分类</li></ol><ul><li>案例:使用Raspberry Pi 部署预先训练的深度学习网络.不通过树莓派训练模型,只做用来部署预先训练好的模型</li><li>产品化程度:<br>比较高,可以输出具体结果,SqueezeNet比GoogLeNet速度更快,但准确率没它高</li><li>SqueezeNet 起到的作用:进行图片分类</li><li>链接:<a href="https://www.pyimagesearch.com/2017/10/02/deep-learning-on-the-raspberry-pi-with-opencv/" target="_blank" rel="noopener">https://www.pyimagesearch.com/2017/10/02/deep-learning-on-the-raspberry-pi-with-opencv/</a></li><li>代码:<a href="https://www.getdrip.com/forms/353154548/submissions" target="_blank" rel="noopener">https://www.getdrip.com/forms/353154548/submissions</a></li></ul><ol start="3"><li>在Raspberry Pi 中运行Movidius Neural Compute Stick</li></ol><ul><li>案例: 通过Raspberry Pi 、Raspbian jessie(2017-07-05)、cheep USB camera和SqueezeNet实现。</li><li>产品化程度:高,已实现,有demo视频可以进行实时识别。</li><li>SqueezeNet 起到的作用:用于图像分类</li><li>链接:<a href="https://www.youtube.com/watch?v=41E5hni786Y" target="_blank" rel="noopener">https://www.youtube.com/watch?v=41E5hni786Y</a> 和 <a href="https://www.youtube.com/watch?v=f39NFuZAj6s" target="_blank" rel="noopener">https://www.youtube.com/watch?v=f39NFuZAj6s</a></li></ul><ol start="4"><li>使用Raspberry Pi 3进行目标检测</li></ol><ul><li>案例:使用树莓进行对象检测</li><li>产品化程度:不高,理论分析</li><li>SqueezeNet 起到的作用:建议使用的神经网络之一</li><li>链接:<a href="https://medium.com/dt42/run-object-detection-using-deep-learning-on-raspberry-pi-3-1-55027eac26c3" target="_blank" rel="noopener">https://medium.com/dt42/run-object-detection-using-deep-learning-on-raspberry-pi-3-1-55027eac26c3</a></li></ul><h2 id="其他"><a href="#其他" class="headerlink" title="其他"></a>其他</h2><ol><li>通过SqueezeNet进行猫狗识别</li></ol><ul><li>案例:猫狗识别</li><li>产品化程度:一般。</li><li>SqueezeNet 起到的作用:图像识别</li><li>代码:<a href="https://github.com/chasingbob/squeezenet-keras" target="_blank" rel="noopener">https://github.com/chasingbob/squeezenet-keras</a></li></ul><ol start="2"><li>MXNet在Raspberry Pi上的实时对象检测</li></ol><ul><li>案例:AWS的loT,MXNet和Raspberry Pi</li><li>产品化程度:比较高</li><li>SqueezeNet 起到的作用:主要是MXNet</li><li>链接:<br><a href="https://mxnet.incubator.apache.org/tutorials/embedded/wine_detector.html" target="_blank" rel="noopener">https://mxnet.incubator.apache.org/tutorials/embedded/wine_detector.html</a></li></ul><ol start="3"><li>手机上的Squeezing Deep Learning<br>链接:<a href="https://www.slideshare.net/anirudhkoul/squeezing-deep-learning-into-mobile-phones" target="_blank" rel="noopener">https://www.slideshare.net/anirudhkoul/squeezing-deep-learning-into-mobile-phones</a></li></ol>]]></content>
<summary type="html">
<h2 id="ARM"><a href="#ARM" class="headerlink" title="ARM"></a>ARM</h2><ol>
<li>ARM Compute Library案例:</li>
</ol>
<ul>
<li>案例:<br>ARM 计算库(AC
</summary>
<category term="SqueezeNet" scheme="https://0rainge.github.io/categories/SqueezeNet/"/>
<category term="SqueezeNet" scheme="https://0rainge.github.io/tags/SqueezeNet/"/>
<category term="ARM" scheme="https://0rainge.github.io/tags/ARM/"/>
<category term="Raspberry Pi" scheme="https://0rainge.github.io/tags/Raspberry-Pi/"/>
</entry>
<entry>
<title>交叉编译在树莓派的tensorflow lite</title>
<link href="https://0rainge.github.io/2018/05/23/%E4%BA%A4%E5%8F%89%E7%BC%96%E8%AF%91%E5%9C%A8%E6%A0%91%E8%8E%93%E6%B4%BE%E7%9A%84tensorflowLite%20/"/>
<id>https://0rainge.github.io/2018/05/23/交叉编译在树莓派的tensorflowLite /</id>
<published>2018-05-22T16:00:00.000Z</published>
<updated>2018-06-07T09:11:50.000Z</updated>
<content type="html"><![CDATA[<p>系统:ubuntu、树莓派(centos系统)、</p><ol><li><p>调整树莓派时间(默认好像是去年)<br>用ntpdate同步时间<br><a href="https://jingyan.baidu.com/article/f71d6037815a0d1ab741d167.html" target="_blank" rel="noopener">https://jingyan.baidu.com/article/f71d6037815a0d1ab741d167.html</a></p></li><li><p>失败的尝试,看了之前的博客<br><a href="https://www.wandianshenme.com/play/build-tensorflow-on-raspberry-pi-step-by-step-guide/" target="_blank" rel="noopener">https://www.wandianshenme.com/play/build-tensorflow-on-raspberry-pi-step-by-step-guide/</a><br><a href="http://www.cnblogs.com/jojodru/p/7744630.html" target="_blank" rel="noopener">http://www.cnblogs.com/jojodru/p/7744630.html</a><br>写的比较复杂,而且都没有成功,可能是现在tensorflow lite 发展的比较快,信息更新的比较快</p></li><li><p>成功的尝试,官网<br><a href="https://github.com/tensorflow/tensorflow/blob/master/tensorflow/contrib/lite/g3doc/rpi.md" target="_blank" rel="noopener">https://github.com/tensorflow/tensorflow/blob/master/tensorflow/contrib/lite/g3doc/rpi.md</a><br>很快就build好了</p></li></ol>]]></content>
<summary type="html">
<p>系统:ubuntu、树莓派(centos系统)、</p>
<ol>
<li><p>调整树莓派时间(默认好像是去年)<br>用ntpdate同步时间<br><a href="https://jingyan.baidu.com/article/f71d6037815a0d1ab
</summary>
<category term="tensorflow" scheme="https://0rainge.github.io/categories/tensorflow/"/>
<category term="Raspberry Pi" scheme="https://0rainge.github.io/tags/Raspberry-Pi/"/>
<category term="tensorflow lite" scheme="https://0rainge.github.io/tags/tensorflow-lite/"/>
</entry>
<entry>
<title>复现activitynet2016未剪辑视频分类冠军算法模型</title>
<link href="https://0rainge.github.io/2018/05/20/%E5%A4%8D%E7%8E%B0activitynet2016%E6%9C%AA%E5%89%AA%E8%BE%91%E8%A7%86%E9%A2%91%E5%88%86%E7%B1%BB%E5%86%A0%E5%86%9B%E7%AE%97%E6%B3%95%E6%A8%A1%E5%9E%8B/"/>
<id>https://0rainge.github.io/2018/05/20/复现activitynet2016未剪辑视频分类冠军算法模型/</id>
<published>2018-05-19T16:00:00.000Z</published>
<updated>2018-06-07T04:25:22.000Z</updated>
<content type="html"><![CDATA[<p>复现activitynet2016未剪辑视频分类冠军算法模型:</p><p>代码链接:<a href="https://github.com/yjxiong/anet2016-cuhk" target="_blank" rel="noopener">https://github.com/yjxiong/anet2016-cuhk</a></p><p>系统:ubuntu</p><p>装上unzip和cmake</p><p>复现activitynet2016未剪辑视频分类冠军算法模型:<a href="https://github.com/yjxiong/anet2016-cuhk" target="_blank" rel="noopener">https://github.com/yjxiong/anet2016-cuhk</a></p><p>主要通过脚本安装<a href="https://github.com/yjxiong/anet2016-cuhk/blob/master/build_all.sh" target="_blank" rel="noopener">https://github.com/yjxiong/anet2016-cuhk/blob/master/build_all.sh</a></p><p>环境准备如下:</p><ol><li>安装anaconda</li><li>安装caffe</li><li>安装tensorflow</li><li>安装opencv</li></ol><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><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></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">#!/usr/bin/env bash</span><br><span class="line"># TODO: add compilation steps</span><br><span class="line"></span><br><span class="line"># update the submodules: Caffe and Dense Flow</span><br><span class="line">git submodule update --remote</span><br><span class="line"></span><br><span class="line"># install Caffe dependencies</span><br><span class="line">sudo apt-get -qq install libprotobuf-dev libleveldb-dev libsnappy-dev libhdf5-serial-dev protobuf-compiler libatlas-base-dev</span><br><span class="line">不对!!!!!!!!!!sudo apt-get -qq install --no-install-recommends libboost1.55-all-dev</span><br><span class="line"> 改成sudo apt-get -qq install --no-install-recommends libboost-all-dev</span><br><span class="line">sudo apt-get -qq install libgflags-dev libgoogle-glog-dev liblmdb-dev</span><br><span class="line"></span><br><span class="line"># install Dense_Flow dependencies</span><br><span class="line">sudo apt-get -qq install libzip-dev</span><br><span class="line"></span><br><span class="line"># install common dependencies: OpenCV</span><br><span class="line"># adpated from OpenCV.sh</span><br><span class="line">version="2.4.13"</span><br><span class="line"></span><br><span class="line">echo "Building OpenCV" $version</span><br><span class="line">mkdir 3rd-party/</span><br><span class="line">cd 3rd-party/</span><br><span class="line"></span><br><span class="line">echo "Installing Dependenices"</span><br><span class="line">不对!!!!!!!!!sudo apt-get -qq install libopencv-dev build-essential checkinstall cmake pkg-config yasm libjpeg-dev libjasper-dev libavcodec-dev libavformat-dev libswscale-dev libdc1394-22-dev libxine-dev libgstreamer0.10-dev libgstreamer-plugins-base0.10-dev libv4l-dev python-dev python-numpy libtbb-dev libqt4-dev libgtk2.0-dev libfaac-dev libmp3lame-dev libopencore-amrnb-dev libopencore-amrwb-dev libtheora-dev libvorbis-dev libxvidcore-dev x264 v4l-utils</span><br><span class="line"></span><br><span class="line">改成sudo apt-get -qq install libopencv-dev build-essential checkinstall cmake pkg-config yasm libjpeg-dev libjasper-dev libavcodec-dev libavformat-dev libswscale-dev libdc1394-22-dev libxine2-dev libgstreamer0.10-dev libgstreamer-plugins-base0.10-dev libv4l-dev python-dev python-numpy libtbb-dev libqt4-dev libgtk2.0-dev libfaac-dev libmp3lame-dev libopencore-amrnb-dev libopencore-amrwb-dev libtheora-dev libvorbis-dev libxvidcore-dev x264 v4l-utils</span><br><span class="line"></span><br><span class="line">echo "Downloading OpenCV" $version</span><br><span class="line"></span><br><span class="line">echo "Installing OpenCV" $version</span><br><span class="line">unzip OpenCV-$version.zip</span><br><span class="line">cd opencv-$version</span><br><span class="line">mkdir build</span><br><span class="line">cd build</span><br><span class="line">cmake -D CMAKE_BUILD_TYPE=RELEASE -D WITH_TBB=ON -D WITH_V4L=ON -D WITH_QT=ON -D WITH_OPENGL=ON ..</span><br><span class="line"></span><br><span class="line">!!!!!!!!!!</span><br><span class="line">在这里Makefile.config加入:</span><br><span class="line">LINKFLAGS := -Wl,-rpath,/root/anaconda3/lib</span><br><span class="line">!!!!!!!!!!</span><br><span class="line">??????????cmake -D CMAKE_BUILD_TYPE=RELEASE -D CMAKE_INSTALL_PREFIX=/usr/local -D WITH_TBB=ON -D BUILD_NEW_PYTHON_SUPPORT=ON -D WITH_V4L=ON -D INSTALL_C_EXAMPLES=ON -D INSTALL_PYTHON_EXAMPLES=ON -D BUILD_EXAMPLES=ON -D BUILD_TIFF=ON -D WITH_OPENGL=ON..</span><br><span class="line"></span><br><span class="line">cmake -D CMAKE_BUILD_TYPE=RELEASE -D WITH_TBB=ON -D WITH_V4L=ON -D WITH_QT=ON -D WITH_OPENGL=ON -D BUILD_TIFF=ON ..</span><br><span class="line"></span><br><span class="line">cp lib/cv2.so ../../../</span><br><span class="line">echo "OpenCV" $version "built"</span><br><span class="line"></span><br><span class="line"># build dense_flow</span><br><span class="line">cd ../../../</span><br><span class="line"></span><br><span class="line">echo "Building Dense Flow"</span><br><span class="line">cd lib/dense_flow</span><br><span class="line">mkdir build</span><br><span class="line">cd build</span><br><span class="line">OpenCV_DIR=../../../3rd-party/opencv-$version/build/ cmake .. -DCUDA_USE_STATIC_CUDA_RUNTIME=OFF</span><br><span class="line">make -j</span><br><span class="line">!!!!!!!!需要下载</span><br><span class="line">echo "Dense Flow built"</span><br><span class="line"></span><br><span class="line">https://github.com/jaejunlee0538/openfabmap/issues/3</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"># build caffe</span><br><span class="line">echo "Building Caffe"</span><br><span class="line">cd ../../caffe-action</span><br><span class="line">mkdir build</span><br><span class="line">cd build</span><br><span class="line">OpenCV_DIR=../../../3rd-party/opencv-$version/build/ cmake .. -DCUDA_USE_STATIC_CUDA_RUNTIME=OFF </span><br><span class="line"></span><br><span class="line">!!!!!!!!!!!!!!!改成</span><br><span class="line">OpenCV_DIR=../../../3rd-party/opencv-$version/build/ cmake .. -DCUDA_USE_STATIC_CUDA_RUNTIME=OFF -D BUILD_TIFF=ON</span><br><span class="line">然后如果你装了anaconda包的话,删除anaconda/lib/下面的 libm https://blog.csdn.net/ccemmawatson/article/details/42004105</span><br><span class="line">sudo rm -rf libm*</span><br><span class="line"></span><br><span class="line">make -j32</span><br><span class="line">echo "Caffe Built"</span><br><span class="line">cd ../../../</span><br><span class="line"></span><br><span class="line"># install python packages</span><br><span class="line">pip install -r py_requirements.txt</span><br><span class="line"></span><br><span class="line"># setup for web demo</span><br><span class="line">mkdir tmp</span><br><span class="line"></span><br><span class="line"># copy website files to the folder</span><br><span class="line">wget -O 3rd-party/bootstrap-fileinput.zip https://github.com/kartik-v/bootstrap-fileinput/zipball/master</span><br><span class="line">cd 3rd-party</span><br><span class="line">unzip bootstrap-fileinput.zip</span><br><span class="line">mv kartik-v-bootstrap-* Bootstrap-fileinput</span><br><span class="line"></span><br><span class="line">!!!!!!!!!!!cannot move 'kartik-v-bootstrap-fileinput-61c9523' to 'Bootstrap-fileinput/kartik-v-bootstrap-fileinput-61c9523': Directory not empty</span><br><span class="line"></span><br><span class="line">cp -r Bootstrap-fileinput/js ../static/js</span><br><span class="line">cp Bootstrap-fileinput/css/* ../static/css/</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">export ANET_HOME=/root/anet2016-cuhk</span><br></pre></td></tr></table></figure>]]></content>
<summary type="html">
<p>复现activitynet2016未剪辑视频分类冠军算法模型:</p>
<p>代码链接:<a href="https://github.com/yjxiong/anet2016-cuhk" target="_blank" rel="noopener">https://git
</summary>
<category term="activitynet" scheme="https://0rainge.github.io/categories/activitynet/"/>
<category term="activitynet" scheme="https://0rainge.github.io/tags/activitynet/"/>
<category term="caffee" scheme="https://0rainge.github.io/tags/caffee/"/>
<category term="opencv" scheme="https://0rainge.github.io/tags/opencv/"/>
<category term="tensorflow" scheme="https://0rainge.github.io/tags/tensorflow/"/>
</entry>
<entry>
<title>论文阅读笔记之CNN_C3D_averagePooling_LSTM_MoE</title>
<link href="https://0rainge.github.io/2018/05/15/CNN_C3D_averagePooling_LSTM_MoE/"/>
<id>https://0rainge.github.io/2018/05/15/CNN_C3D_averagePooling_LSTM_MoE/</id>
<published>2018-05-14T16:00:00.000Z</published>
<updated>2018-06-05T09:39:24.000Z</updated>
<content type="html"><![CDATA[<h4 id="作者"><a href="#作者" class="headerlink" title="作者"></a>作者</h4><p>Feng Mao </p><h4 id="思路"><a href="#思路" class="headerlink" title="思路"></a>思路</h4><p>提取CNN和C3D特征作为帧特征,使用average pooling 和 LSTM 将帧特征聚集为视频特征,使用MoE进行分类<br>CNN_C3D_averagePooling_LSTM_MoEcd </p><h4 id="特征提取"><a href="#特征提取" class="headerlink" title="特征提取"></a>特征提取</h4><p>CNN:使用数据集ImageNet 21k 训练模型inception-v1 。在分类层POOL5/7X7YS1,选择分类层之前的那一个hidden层作为帧级特征第一部分。<br>C3D:使用PCA降维</p><h4 id="特征聚合"><a href="#特征聚合" class="headerlink" title="特征聚合"></a>特征聚合</h4><p>无监督 average pooling<br>有监督 aggregation LSTM</p><h4 id="分类"><a href="#分类" class="headerlink" title="分类"></a>分类</h4><p> MoE(Mixture of experts) ,结合不同特征和不同聚合模型:</p><ul><li>CNN + average pooling </li><li>CNN + LSTM </li><li>C3D + average pooling</li><li>C3D + LSTM </li></ul><p>需要训练的参数是CNN and C3D 的LSTM参数和 MoE parameters </p>]]></content>
<summary type="html">
<h4 id="作者"><a href="#作者" class="headerlink" title="作者"></a>作者</h4><p>Feng Mao </p>
<h4 id="思路"><a href="#思路" class="headerlink" title="思路">
</summary>
<category term="Untrimmed_Video_Classification论文阅读笔记" scheme="https://0rainge.github.io/categories/Untrimmed-Video-Classification%E8%AE%BA%E6%96%87%E9%98%85%E8%AF%BB%E7%AC%94%E8%AE%B0/"/>
<category term="ActivityNet2017论文笔记" scheme="https://0rainge.github.io/tags/ActivityNet2017%E8%AE%BA%E6%96%87%E7%AC%94%E8%AE%B0/"/>
<category term="CNN" scheme="https://0rainge.github.io/tags/CNN/"/>
<category term="C3D" scheme="https://0rainge.github.io/tags/C3D/"/>
<category term="averagePooling" scheme="https://0rainge.github.io/tags/averagePooling/"/>
</entry>
<entry>
<title>论文阅读笔记之CNN_MBH_StackedC3D_ovrSVM_Voting</title>
<link href="https://0rainge.github.io/2018/05/15/CNN_MBH_StackedC3D_ovrSVM_Voting/"/>
<id>https://0rainge.github.io/2018/05/15/CNN_MBH_StackedC3D_ovrSVM_Voting/</id>
<published>2018-05-14T16:00:00.000Z</published>
<updated>2018-06-05T09:37:40.000Z</updated>
<content type="html"><![CDATA[<h4 id="作者"><a href="#作者" class="headerlink" title="作者"></a>作者</h4><p>Jianqin Yin1, Bin Wang2, Xiaoli Liu1, Bin Fang2, Yanchun Wu1, Yanyan Bao2 </p><h4 id="思路"><a href="#思路" class="headerlink" title="思路"></a>思路</h4><p>提取CNN(主要捕获外观特征) , MBH 和 stacked C3D 特征(主要捕获动态特征) ,构造one-vs-rest 线性 SVM ,对结果进行投票</p><h4 id="特征提取"><a href="#特征提取" class="headerlink" title="特征提取"></a>特征提取</h4><ul><li>MBH:运动边界直方图,通过GMM和Fisher Vector 进行编码</li><li>Stacked C3D:提取时间和空间信息。由数据集Sport-1M 进行训练,通过PCA降维。通过把序列分为3部分mean-pool 获取时间信息。最后对特征堆叠获得stacked 3D</li><li>CNN(ImageNetShuffle) :从Google inception net提取,在每秒2帧的pool5层提取CNN特征,对帧进行mean-pool,然后使用L1-normalization.</li></ul><h4 id="分类"><a href="#分类" class="headerlink" title="分类"></a>分类</h4><p>通过one-vs-rest linear SVM分类,weight voting 和 hard voting 做决策<br>如果3个结果都不同,使用weight voting:通过one-vs-rest linear SVM 学习每个动作的权重,归一所有动作得到每个动作的置信度,最高票动作是最终结果<br>如果至少2个结果相同,使用one-vs-rest linear SVM 对每类特征学习其置信度</p><h5 id="置信度计算公式:"><a href="#置信度计算公式:" class="headerlink" title="置信度计算公式:"></a>置信度计算公式:</h5><ul><li>cof =1- (1- c1) (1- c2) </li><li>cof =1- (1- c1) (1- c2) (1- c3) </li></ul>]]></content>
<summary type="html">
<h4 id="作者"><a href="#作者" class="headerlink" title="作者"></a>作者</h4><p>Jianqin Yin1, Bin Wang2, Xiaoli Liu1, Bin Fang2, Yanchun Wu1, Yanyan B
</summary>
<category term="Untrimmed_Video_Classification论文阅读笔记" scheme="https://0rainge.github.io/categories/Untrimmed-Video-Classification%E8%AE%BA%E6%96%87%E9%98%85%E8%AF%BB%E7%AC%94%E8%AE%B0/"/>
<category term="CNN" scheme="https://0rainge.github.io/tags/CNN/"/>
<category term="MBH" scheme="https://0rainge.github.io/tags/MBH/"/>
<category term="StackedC3D" scheme="https://0rainge.github.io/tags/StackedC3D/"/>
<category term="SVM" scheme="https://0rainge.github.io/tags/SVM/"/>
</entry>
<entry>
<title>ActivityNet2017问题</title>
<link href="https://0rainge.github.io/2018/05/10/activity2017-challenge/"/>
<id>https://0rainge.github.io/2018/05/10/activity2017-challenge/</id>
<published>2018-05-09T16:00:00.000Z</published>
<updated>2018-06-05T09:08:54.000Z</updated>
<content type="html"><![CDATA[<h2 id="1-Untrimmed-Video-Classification"><a href="#1-Untrimmed-Video-Classification" class="headerlink" title="1. Untrimmed Video Classification"></a>1. Untrimmed Video Classification</h2><h3 id="描述"><a href="#描述" class="headerlink" title="描述"></a>描述</h3><p>预测未剪辑视频中的活动。未剪辑视频视频可以包含不止一个活动,并包含包含大量活动上下文信息。要求算法可以整体分析一个视频并进行分类。</p><h3 id="数据集"><a href="#数据集" class="headerlink" title="数据集"></a>数据集</h3><p>ActivityNet Version 1.3 dataset,包含超过648小时的20k视频,平均一个视频1.5个注解。包含200个不同的活动,50%为训练集,25%验证集,25%测试集</p><h3 id="评估指标"><a href="#评估指标" class="headerlink" title="评估指标"></a>评估指标</h3><p>用 top-1 error (e)评估算法好坏</p><p>m个视频,n个标签,p为预测值,g为真实值,计算公式如下:</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">e = \frac{1}{m} \sum_{i=1}^{m} f(i)</span><br><span class="line"></span><br><span class="line">f(i) = \frac{1}{n} \sum_{j=1}^{n} d(p_i, g_{ij})</span><br></pre></td></tr></table></figure><p>预测成功时fd = 1</p><p>代码在这里:<br><a href="https://github.com/activitynet/ActivityNet/blob/master/Evaluation/get_classification_performance.py" target="_blank" rel="noopener">https://github.com/activitynet/ActivityNet/blob/master/Evaluation/get_classification_performance.py</a></p><h2 id="2-Trimmed-Action-Recognition"><a href="#2-Trimmed-Action-Recognition" class="headerlink" title="2. Trimmed Action Recognition"></a>2. Trimmed Action Recognition</h2><h3 id="描述-1"><a href="#描述-1" class="headerlink" title="描述"></a>描述</h3><p>在经过裁剪的视频中进行动作识别,每个视频只有一个单度的动作,动作都持续10秒</p><h3 id="数据集-1"><a href="#数据集-1" class="headerlink" title="数据集"></a>数据集</h3><p>使用 Kinetics 数据集,包含大约300k视频剪辑,400个人类动作,每个视频只有1类,取自不同的YouTube视频,包括人与物的交互以及人与人的交互</p><h3 id="评估指标-1"><a href="#评估指标-1" class="headerlink" title="评估指标"></a>评估指标</h3><p>算法对每个视频预测k个预测标签lj,j = 1,2…k。该视频的真实标签是g,预测成功时d = 1 否则 d=0<br><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">e = \min_{j} d(l_{j}, g)</span><br></pre></td></tr></table></figure></p><p>代码在这<br><a href="https://github.com/activitynet/ActivityNet/blob/master/Evaluation/get_kinetics_performance.py" target="_blank" rel="noopener">https://github.com/activitynet/ActivityNet/blob/master/Evaluation/get_kinetics_performance.py</a></p><h2 id="3-Temporal-Action-Proposals"><a href="#3-Temporal-Action-Proposals" class="headerlink" title="3. Temporal Action Proposals"></a>3. Temporal Action Proposals</h2><h3 id="描述-2"><a href="#描述-2" class="headerlink" title="描述"></a>描述</h3><p>在未剪辑视频中定位并识别发生了人类活动的短期片段,要计算编码评分是高效的,且可以有效识别时间段。</p><p>在许多大规模视频分析场景中,人们有兴趣定位和识别长时间未修剪的视频中短时间间隔内出现的人类活动。目前的行为检测方法仍然很难处理大规模视频集合,并且有效地解决这一任务对于计算机视觉系统仍然很难。这是由于:<br>(1)当前动作识别方法的计算复杂性;<br>(2)缺少可以针对每个视频提出更少间隔的方法,使得行为处理仍然集中在大量候选时间片段中。这些候选时间片段被广泛称为行为建议(Action Proposals)。</p><p>为了在大规模和实际情况下适用,有用的Action Proposals方法由两个目标驱动:<br>(1)Proposal方法必须在计算上高效,对时间段进行表示,编码和打分。<br>(2)Proposal方法必须区分我们感兴趣的活动,以便仅检索包含指示这些活动类别的视觉信息的时间片段。</p><h3 id="数据集-2"><a href="#数据集-2" class="headerlink" title="数据集"></a>数据集</h3><p>ActivityNet Version 1.3 dataset ,该数据集包含超过648个小时的未修剪视频,共约2万个视频。它包含200种不同的日常活动,例如:’walking the dog’, ‘long jump’, and ‘vacuuming floor’等。数据量分布:train(~50%), validation(~25%), test(~25%)。<br>下载链接</p><h3 id="评估指标-2"><a href="#评估指标-2" class="headerlink" title="评估指标"></a>评估指标</h3><p>此任务使用Average Recall和Average Number of Proposals per Video(AR-AN)曲线作为评估指标。一个proposal为真的条件:该proposal的时间区间和真实值(ground-truth)的区间的tIOU(temporal intersection orver union)大于等于一个阈值(比如:tIOU>0.5<br>)。AR<br> 被定义为召回值的平均值(满足0.5<tIOU≤0.9<br>,步长为0.05<br>)。AN<br> 被定义为proposals总数除以测试子集中的视频数量。当计算 AR−AN<br> 曲线上的值时,我们考虑 AN<br> 集中在1到100(含)之间的值,步长为1。</p><p>使用此评估指标评估提交文件的具体过程:</p><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">\frac{\text{total number of proposals in the submission file}}{\text{total number of videos in the testing subset}}</span><br></pre></td></tr></table></figure><p>ANmax<br> 表示在评估方法允许每个视频平均proposals数量的最大值。这里,ANmax=100<br>。让 R=ANmaxANsubmission<br>,那么我们按照以下方式预处理提交文件:</p><p>若 R<1<br>,那么对于测试子集中的每个视频,我们会根据proposal得分对其proposal进行分类,并丢弃得分最低的 R%<br> 的proposal。<br>若 R≥1<br>,那么对于测试子集中的每个视频,我们会根据提案得分对提案进行排序,并复制每个视频中得分最低的 (R−1)%<br> 提案,并将结果数据点添加到 AR−AN<br> 曲线上。然后计算所得到的最终曲线下的面积并将其作为提交文件的度量分数。<br>过滤后的提交结果文件将有:AN=ANmax<br>。对于每一个 p<br> 值(从1到100,步长为1),仅仅使用得分前 p%<br> 的proposal计算 AR<br>,并将结果数据点添加到 AR−AN<br> 曲线上。然后计算所得到的最终曲线下的面积并将其作为提交文件的度量分数。</p><p>在验证子集上提供基线proposal方法(称为统一随机)的结果。统一随机(Uniform Random):每个proposal的中心和长度是独立地从间隔内的均匀随机分布 [0,d]<br> 中抽取的,其中 d<br> 为视频长度。这个模型的得分:44.88%<br>。<br>虚线表示在平均超过一个 tIoU<br> 阈值时的召回性能,而实线表示跨所有 tIoU<br> 阈值的平均召回率。可以看出,在 tIoU<br> 比较小时召回性能较高,但在 tIoU<br> 较大时急速下降。因此,对于在评估指标上得分较高的proposal方法,需要重点关注对低和高 tIoU<br> 阈值下都得到相对较高的召回率。</p><h2 id="4-Temporal-Action-Localization"><a href="#4-Temporal-Action-Localization" class="headerlink" title="4. Temporal Action Localization"></a>4. Temporal Action Localization</h2><h3 id="描述-3"><a href="#描述-3" class="headerlink" title="描述"></a>描述</h3><p>尽管最近在大规模视频分析方面取得了进展,但Temporal Action Localization仍然是计算机视觉中最具挑战性的未解决问题之一。这种搜索问题阻碍了从消费者视频摘要到监控,人群监控和老年护理等各种实际应用。因此,我们致力于推动开发高效,准确的自动化方法,以搜索和检索视频集合中的事件和活动。</p><p>这项任务旨在鼓励计算机视觉研究人员设计高性能的行为定位系统。</p><h3 id="数据集-3"><a href="#数据集-3" class="headerlink" title="数据集"></a>数据集</h3><p>此任务采用ActivityNet 1.3版本数据集。该数据集包含超过648个小时的未修剪视频,共约2万个视频。它包含200种不同的日常活动,例如:’walking the dog’, ‘long jump’, and ‘vacuuming floor’等。数据量分布:train(~50%), validation(~25%), test(~25%)。</p><h3 id="评估指标-3"><a href="#评估指标-3" class="headerlink" title="评估指标"></a>评估指标</h3><p>评估服务器使用的评估代码可以在这里<br><a href="https://github.com/activitynet/ActivityNet/blob/master/Evaluation/get_detection_performance.py。" target="_blank" rel="noopener">https://github.com/activitynet/ActivityNet/blob/master/Evaluation/get_detection_performance.py。</a></p><p>插值平均精度(Average Precision,AP)作为评估每个行为类别结果的指标。然后,AP<br> 对所有活动类别进行平均,得到 mAP<br>。</p><p>一个detection为真的条件:该tIOU(temporal intersection orver union)大于等于一个阈值(比如:tIOU>0.5<br>)。此任务中使用的官方指标是平均mAP,其被定义为所有mAP值的平均值,其中 tIOU<br> 阈值满足:0.5<tIOU≤0.9<br>,步长为0.05<br>。</p><h2 id="5-Dense-Captioning-Events-in-Videos"><a href="#5-Dense-Captioning-Events-in-Videos" class="headerlink" title="5. Dense-Captioning Events in Videos"></a>5. Dense-Captioning Events in Videos</h2><h3 id="描述-4"><a href="#描述-4" class="headerlink" title="描述"></a>描述</h3><p>大多数自然视频包含众多活动。例如,在“人弹钢琴”的视频中,视频可能还会包含另一个“人跳舞”或“人群鼓掌”。这项挑战研究密集字幕事件的任务,其中涉及检测和描述视频中的事件。这个挑战使用了ActivityNet Captions数据集,这是一个新的密集字幕事件的大型基准。ActivityNet Captions包含20K个视频,总计849个视频小时,总共有100K个描述,每个视频都有其独特的开始和结束时间。</p><h3 id="数据集-4"><a href="#数据集-4" class="headerlink" title="数据集"></a>数据集</h3><p>ActivityNet Captions数据集将用于此挑战。数据集对视频用一系列时间注释的句子进行描述。每个句子涵盖视频的一个唯一的片段,描述发生的多个事件。这些事件可能会在很长或很短的时间内发生。平均而言,Captivity网络中的每个视频都包含3.65个句子,总共产生了10万个句子。每个视频的句子数量遵循相对正态的分布。而且,随着视频持续时间的增加,句子的数量也增加。每个句子的平均长度为13.48个字,也是正态分布的。</p><h3 id="评估指标-4"><a href="#评估指标-4" class="headerlink" title="评估指标"></a>评估指标</h3><p>评估代码可以在这里:<a href="https://github.com/ranjaykrishna/densevid_eval" target="_blank" rel="noopener">https://github.com/ranjaykrishna/densevid_eval</a></p><p>受密集图像字幕指标的启发,使用类似的指标来衡量模型对定位和字幕事件的联合能力。在前1000个proposal时,评估指标计算 tIOU<br> 在 0.3,0.5,0.7<br> 阈值上的平均准确率(AP)。使用传统评估指标来衡量我们标题的精确度:BLEU,METEOR和CIDDEr。</p>]]></content>
<summary type="html">
<h2 id="1-Untrimmed-Video-Classification"><a href="#1-Untrimmed-Video-Classification" class="headerlink" title="1. Untrimmed Video Classific
</summary>
<category term="ActivityNet2017" scheme="https://0rainge.github.io/categories/ActivityNet2017/"/>
<category term="ActivityNet2017" scheme="https://0rainge.github.io/tags/ActivityNet2017/"/>
<category term="视频处理" scheme="https://0rainge.github.io/tags/%E8%A7%86%E9%A2%91%E5%A4%84%E7%90%86/"/>
</entry>
<entry>
<title>git学习</title>
<link href="https://0rainge.github.io/2018/05/01/git%E5%AD%A6%E4%B9%A0%E7%AF%87/"/>
<id>https://0rainge.github.io/2018/05/01/git学习篇/</id>
<published>2018-04-30T16:00:00.000Z</published>
<updated>2018-06-05T09:35:40.000Z</updated>
<content type="html"><![CDATA[<p>git(改变指针来管理版本)</p><h3 id="基本概念"><a href="#基本概念" class="headerlink" title="基本概念"></a>基本概念</h3><p>Working Tree 工作区:本地文件夹<br>Repository 版本库 :工作区中的隐藏目录.git .git中包含了暂存区(stage或index),分支(master),以及指针head<br>add 把文件添加进暂存区,commit把repo里的文件提交到当前分区</p><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></pre></td><td class="code"><pre><span class="line">git init 新建本地版本库</span><br><span class="line">git add <filename>把文件添加到repo</span><br><span class="line">git commit -m “XXXXXXX说明”</span><br><span class="line">git status 查看repo状态 (有3种状态)</span><br><span class="line">git diff 查看修改</span><br><span class="line">git diff HEAD —<filename>查看filename在工作区和repo的区别</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></pre></td><td class="code"><pre><span class="line">git checkout —<filename>丢弃工作区修改</span><br><span class="line">git reset HEAD <filename> 丢弃暂存区修改</span><br><span class="line">撤销本地提交:版本退回</span><br><span class="line"></span><br><span class="line">git log 查看历史提交版本</span><br><span class="line">git reset —hard HEAD^ 退回上个版本</span><br><span class="line">git reset —hard XXXXid 前进到新版本</span><br><span class="line">git reflog 记录命令历史</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></pre></td><td class="code"><pre><span class="line">工作区文件删除后删除版本库文件</span><br><span class="line">git rm <filename></span><br><span class="line">git commit -m “delete filename”</span><br><span class="line"></span><br><span class="line">工作区文件删除后通过版本库文件进行删除 </span><br><span class="line">git checkout — <filename></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></pre></td><td class="code"><pre><span class="line">git remote -v查看远程repo版本</span><br><span class="line">git push -u origin master 把本地仓库push到远程仓库上</span><br><span class="line">git clone git@github.com:XXXXXXX/XXXXXXXXXX.git 从远程仓库克隆项目到本地仓库</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></pre></td><td class="code"><pre><span class="line">git checkout -b dev 创建dev分支并切换过去</span><br><span class="line">git branch dev 创建dev分支 </span><br><span class="line">git checkout dev 切换dev分支</span><br><span class="line">git branch 查看当前分支</span><br><span class="line">git merge dev 合并分支</span><br><span class="line">git branch -d dev删除分支</span><br><span class="line">git log --graph 查看分支合并图</span><br></pre></td></tr></table></figure>]]></content>
<summary type="html">
<p>git(改变指针来管理版本)</p>
<h3 id="基本概念"><a href="#基本概念" class="headerlink" title="基本概念"></a>基本概念</h3><p>Working Tree 工作区:本地文件夹<br>Repository 版本库
</summary>
<category term="git" scheme="https://0rainge.github.io/categories/git/"/>
<category term="git" scheme="https://0rainge.github.io/tags/git/"/>
</entry>
<entry>
<title>FaaS踩坑之openwhisk文档阅读笔记</title>
<link href="https://0rainge.github.io/2018/04/11/FaaS%E8%B8%A9%E5%9D%91%E4%B9%8Bopenwhisk%E6%96%87%E6%A1%A3%E9%98%85%E8%AF%BB%E7%AC%94%E8%AE%B0/"/>
<id>https://0rainge.github.io/2018/04/11/FaaS踩坑之openwhisk文档阅读笔记/</id>
<published>2018-04-10T16:00:00.000Z</published>
<updated>2018-04-11T14:30:41.000Z</updated>
<content type="html"><![CDATA[<ul><li>FaaS,serverless分布式事件驱动型计算服务,也称为无服务器计算或功能即服务 Function-as-a-Service</li><li>计算单元:不是虚拟机,而是一个封装了待执行代码(事件触发)的函数</li></ul><ul><li>yaml:”Yet Another Markup Language”(仍是一种置标语言)</li></ul><ul><li><p>post与get <a href="http://www.w3school.com.cn/tags/html_ref_httpmethods.asp" target="_blank" rel="noopener">http://www.w3school.com.cn/tags/html_ref_httpmethods.asp</a></p></li><li><p>微服务:一种架构风格,一个大型复杂软件应用由一个或多个微服务组成。系统中的各个微服务可被独立部署,各个微服务之间是松耦合的。每个微服务仅关注于完成一件任务。在所有情况下,每个任务代表着一个小的业务能力。</p></li><li>反向代理,用于外部网络访问内部网络时使用,正向代理或包过滤方式用于拒绝其他外部访问方式并提供内部网络对外部网络的访问能力。因此可以结合这些方式提供最佳的安全访问方式。</li><li>nginx:web服务器</li><li><p>Spray:spray is an open-source toolkit for building REST/HTTP-based integration layers on top of Scala and Akka.</p></li><li><p>Akka:Akka是JAVA虚拟机JVM平台上构建高并发、分布式和容错应用的工具包和运行时。Akka用Scala语言写成,同时提供了Scala和JAVA的开发接口</p></li><li><p>rest api :<a href="http://blog.csdn.net/px01ih8/article/details/78674685" target="_blank" rel="noopener">http://blog.csdn.net/px01ih8/article/details/78674685</a></p></li><li><p>openwhisk:从CouchDB 中的 whisks 数据库装入操作</p></li><li><p>Scala:一门多范式的编程语言,一种类似java的编程语言,设计初衷是实现可伸缩的语言、并集成面向对象编程和函数式编程的各种特性,Scala 运行在Java虚拟机上,并兼容现有的Java程序。</p></li></ul><ul><li><p>Kafka是一种高吞吐量的分布式发布订阅消息系统,它可以处理消费者规模的网站中的所有动作流数据</p></li><li><p>ActivationId:激活利用特定的标识符来表示远程对象,对象能随着时间被激活。一个激活标识符(类 ActivationID的一个实例)包含了激活一个对象所需的几部分信息:<a href="http://www.oschina.net/uploads/doc/javase-6-doc-api-zh_CN/java/rmi/activation/ActivationID.html" target="_blank" rel="noopener">http://www.oschina.net/uploads/doc/javase-6-doc-api-zh_CN/java/rmi/activation/ActivationID.html</a></p></li></ul><ul><li><p>异步调用模型,其中一旦系统接受调用操作的 HTTP 请求后,该请求即会终止</p></li><li><p>Docker 用于以快速、隔离且受控的方式为我们调用的每个操作设置新的自封装环境(称为容器)。对于每个操作调用,都会衍生一个 Docker 容器,将操作码注入其中</p></li><li><p>Restful:网络上的所有事物都被抽象为资源,每个资源都有一个唯一的资源标识符,同一个资源具有多种表现形式(xml,json等),对资源的各种操作不会改变资源标识符,所有的操作都是无状态的</p></li><li><p>ssl终止:在处理SSL加密/解密的负载均衡器上发生的进程,以便负载均衡器和后端服务器之间的流量处于HTTP中。 后端必须通过限制对负载均衡器的IP的访问来加以保护</p></li><li><p>Ansible是一个简单的自动化运维管理工具</p></li><li><p>Cloud Functions 处理流入系统的事件。</p></li><li><p>触发器在技术上是指某类事件的名称。每个事件属于恰好一个触发器;若用类比说明,触发器类似于基于主题的发布/预订系统中的主题。规则 T -> A 表示“每当来自触发器 T 的事件到达时,通过触发器有效内容调用操作 A。”</p></li><li><p>订阅源是全部属于某个触发器 T 的事件的流。订阅源通过订阅源操作进行控制,订阅源操作用于处理组成订阅源的事件流的创建、删除、暂停和恢复。通常,订阅源操作通过使用管理通知的 REST API 来与生成事件的外部服务进行交互。</p></li></ul>]]></content>
<summary type="html">
<ul>
<li>FaaS,serverless分布式事件驱动型计算服务,也称为无服务器计算或功能即服务 Function-as-a-Service</li>
<li>计算单元:不是虚拟机,而是一个封装了待执行代码(事件触发)的函数</li>
</ul>
<ul>
<li>yam
</summary>
<category term="FaaS踩坑系列" scheme="https://0rainge.github.io/categories/FaaS%E8%B8%A9%E5%9D%91%E7%B3%BB%E5%88%97/"/>
<category term="openwhisk" scheme="https://0rainge.github.io/tags/openwhisk/"/>
<category term="微服务" scheme="https://0rainge.github.io/tags/%E5%BE%AE%E6%9C%8D%E5%8A%A1/"/>
<category term="分布式" scheme="https://0rainge.github.io/tags/%E5%88%86%E5%B8%83%E5%BC%8F/"/>
</entry>
<entry>
<title>FaaS踩坑之fission使用记录</title>
<link href="https://0rainge.github.io/2018/04/11/FaaS%E8%B8%A9%E5%9D%91%E4%B9%8Bfission%E4%BD%BF%E7%94%A8%E8%AE%B0%E5%BD%95/"/>
<id>https://0rainge.github.io/2018/04/11/FaaS踩坑之fission使用记录/</id>
<published>2018-04-10T16:00:00.000Z</published>
<updated>2018-04-11T05:32:55.000Z</updated>
<content type="html"><![CDATA[<h4 id="1-fission命令"><a href="#1-fission命令" class="headerlink" title="1. fission命令"></a>1. fission命令</h4><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">function, fn Create, update and manage functions</span><br><span class="line"></span><br><span class="line">httptrigger, ht, route Manage HTTP triggers (routes) for functions</span><br><span class="line"></span><br><span class="line">timetrigger, tt, timer Manage Time triggers (timers) for functions</span><br><span class="line"></span><br><span class="line">mqtrigger, mqt, messagequeue Manage message queue triggers for functions</span><br><span class="line"></span><br><span class="line">environment, env Manage environments</span><br><span class="line"></span><br><span class="line">watch, w Manage watches</span><br><span class="line"></span><br><span class="line">package, pkg Manage packages</span><br><span class="line"></span><br><span class="line">spec, specs Manage a declarative app specification</span><br><span class="line"></span><br><span class="line">upgrade Upgrade tool from fission v0.1</span><br><span class="line"></span><br><span class="line">tpr2crd Migrate tool for TPR to CRD</span><br><span class="line"></span><br><span class="line">help, h Shows a list of commands or help for one command</span><br></pre></td></tr></table></figure><h4 id="2-使用记录——function"><a href="#2-使用记录——function" class="headerlink" title="2. 使用记录——function"></a>2. 使用记录——function</h4><ol><li>已有函数hello.js</li></ol><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">module.exports = async function(context) {</span><br><span class="line">return {</span><br><span class="line">status: 200,</span><br><span class="line">body: "Hello, world!\n"</span><br><span class="line">};</span><br><span class="line">}</span><br></pre></td></tr></table></figure><ol start="2"><li>为函数创建route(http请求时用到):</li></ol><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">fission route create --function hello --url /hello</span><br></pre></td></tr></table></figure><ol start="3"><li>创建基于pool executor 的函数</li></ol><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">fission fn create --name hello --code hello.js --env node --executortype poolmgr</span><br></pre></td></tr></table></figure><ol start="4"><li><p>点击函数的url 获得结果</p><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">curl http://$FISSION_ROUTER/hello</span><br><span class="line">Hello, world!</span><br></pre></td></tr></table></figure></li><li><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">fission fn create --name hello --code hello.js --env node --minscale 1 --maxscale 5 --executortype newdeploy</span><br></pre></td></tr></table></figure></li><li><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">fission fn update --name hello --code ../hello.js</span><br></pre></td></tr></table></figure></li><li><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">fission fn test --name hello</span><br></pre></td></tr></table></figure></li><li><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">Error calling function hello: 500 Internal server error (fission)</span><br></pre></td></tr></table></figure></li><li><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">fission fn logs --name hello</span><br></pre></td></tr></table></figure></li><li><p>building function</p></li></ol><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">sourcepkg/</span><br><span class="line">├── __init__.py</span><br><span class="line">├── build.sh</span><br><span class="line">├── requirements.txt</span><br><span class="line">└── user.py</span><br><span class="line"></span><br><span class="line">$ cat user.py</span><br><span class="line">import sys</span><br><span class="line">import yaml</span><br><span class="line"></span><br><span class="line">document = """</span><br><span class="line">a: 1</span><br><span class="line">b:</span><br><span class="line">c: 3</span><br><span class="line">d: 4</span><br><span class="line">"""</span><br><span class="line"></span><br><span class="line">def main():</span><br><span class="line">return yaml.dump(yaml.load(document))</span><br><span class="line"></span><br><span class="line">$ cat requirements.txt</span><br><span class="line">pyyaml</span><br><span class="line"></span><br><span class="line">$ cat build.sh</span><br><span class="line">#!/bin/sh</span><br><span class="line">pip3 install -r ${SRC_PKG}/requirements.txt -t ${SRC_PKG} && cp -r ${SRC_PKG} ${DEPLOY_PKG}</span><br><span class="line">$zip -jr demo-src-pkg.zip sourcepkg/</span><br><span class="line">adding: __init__.py (stored 0%)</span><br><span class="line">adding: build.sh (deflated 24%)</span><br><span class="line">adding: requirements.txt (stored 0%)</span><br><span class="line">adding: user.py (deflated 25%)</span><br><span class="line"></span><br><span class="line">fission fn create --name hellopy --env python --src demo-src-pkg.zip --entrypoint "user.main" --buildcmd "sh build.sh"</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">$ fission route create --function hellopy --url /hellopy</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">fission fn update --name hellopy --env python --src demo-src-pkg.zip --entrypoint "user.main" --buildcmd “sh build.sh”</span><br></pre></td></tr></table></figure><p>11.compiled artifacts with Fission</p><h4 id="3-使用记录————environment"><a href="#3-使用记录————environment" class="headerlink" title="3 使用记录————environment"></a>3 使用记录————environment</h4><ol><li>准备环境<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">fission env create --name node --image fission/node-env:0.4.0 --mincpu 40 --maxcpu 80 --minmemory 64 --maxmemory 128 --poolsize 4</span><br></pre></td></tr></table></figure></li></ol><p>设置环境,语言镜像,环境中支持几个pre-warmed pod</p><ol start="2"><li><p>在启动环境的时候设置builder</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">fission env create --name python --image fission/python-env:latest --builder fission/python-builder:latest</span><br></pre></td></tr></table></figure></li><li><p>查看env信息</p><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">fission env list</span><br><span class="line">fission env get --name node</span><br></pre></td></tr></table></figure></li></ol><p>使用记录————Controlling Function Execution</p><p>安装go<br>安装 hey</p><ol><li><p>用hey</p></li><li><p>HorizontalPodAutoscaler</p></li></ol><h4 id="4-使用记录————trigger"><a href="#4-使用记录————trigger" class="headerlink" title="4.使用记录————trigger"></a>4.使用记录————trigger</h4><ol><li><p>http trigger:通过http get到一个函数</p></li><li><p>time trigger:定时执行函数</p></li><li><p>message queue trigger:基于message queue来执行函数</p></li></ol><p>(NATS and Azure Storage Queue are supported queues.)</p><h4 id="5-使用记录————打包"><a href="#5-使用记录————打包" class="headerlink" title="5.使用记录————打包"></a>5.使用记录————打包</h4><ol><li><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">fission package create --sourcearchive demo-src-pkg.zip --env pythonsrc --buildcmd "./build.sh"</span><br></pre></td></tr></table></figure></li><li><p>打包deployment</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">fission env create --name pythondeploy --image fission/python-env:latest --builder fission/python-builder:latest --mincpu 40 --maxcpu 80 --minmemory 64 --maxmemory 128 --poolsize 2</span><br></pre></td></tr></table></figure></li></ol><h4 id="6-使用问题记录:"><a href="#6-使用问题记录:" class="headerlink" title="6.使用问题记录:"></a>6.使用问题记录:</h4><ol><li><p>fission host路径问题,创建环境(go,python,js…),创建executors和函数(创建pod),创建trigger(调用函数)因为第二步和第三步存在依赖关系顺序不能反</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">fission env create --name nodejs --image fission/node-env:0.6.0</span><br><span class="line">fission route create --function hello --url /hello</span><br><span class="line">fission fn create --name hello --code hello.js --env nodejs --executortype poolmgr,</span><br></pre></td></tr></table></figure></li><li><p>fission创建package的时候有权限问题builder不起来,用sh 不用./ 或者用chmod给文件加权限777</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">chmod –R 777 *</span><br></pre></td></tr></table></figure></li><li><p>测试时 ,需要把$FISSION_ROUTER换了,用的minikube直接换成它的地址,用的k8s换成外部ip</p><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">curl http://$FISSION_ROUTER/hello 换成</span><br><span class="line">curl http://35.194.204.59/hello</span><br></pre></td></tr></table></figure></li><li><p>按照fission命令删除函数以及删除trigger后,发现相关的pod没有被删除</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">fission fn delete --name hellopy</span><br></pre></td></tr></table></figure></li><li><p>build的路径问题未解决:</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">Error starting cmd: exec: "sh build.sh": executable file not found in $PATH</span><br></pre></td></tr></table></figure></li><li><p>查看builder日志:</p><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">k -n fission-builder logs -f py3-4214348-59555d9bd8-ks7m4 builder 换成</span><br><span class="line">kubectl logs python-39799-58b5b4f844-np94r -n fission-builder --container=builder</span><br></pre></td></tr></table></figure></li><li><p>创建 fn,env,ht等时,一个属性赋值错误时:依然被创建会存在,但会使用失败</p></li><li>测试时的hey 和 k:需要安装go ,hey ,HorizontalPodAutoscaler</li><li>创建env时,在这里找镜像:<a href="https://docs.fission.io/0.6.0/concepts/environments/" target="_blank" rel="noopener">https://docs.fission.io/0.6.0/concepts/environments/</a></li><li>packge创建失败?感觉builder有问题<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">Build timeout due to environment builder not ready</span><br></pre></td></tr></table></figure></li></ol>]]></content>
<summary type="html">
<h4 id="1-fission命令"><a href="#1-fission命令" class="headerlink" title="1. fission命令"></a>1. fission命令</h4><figure class="highlight plain"><ta
</summary>
<category term="FaaS踩坑系列" scheme="https://0rainge.github.io/categories/FaaS%E8%B8%A9%E5%9D%91%E7%B3%BB%E5%88%97/"/>
<category term="fission" scheme="https://0rainge.github.io/tags/fission/"/>
<category term="微服务" scheme="https://0rainge.github.io/tags/%E5%BE%AE%E6%9C%8D%E5%8A%A1/"/>
<category term="docker" scheme="https://0rainge.github.io/tags/docker/"/>
</entry>
<entry>
<title>FaaS踩坑之openwhisk与fission对比</title>
<link href="https://0rainge.github.io/2018/04/11/FaaS%E8%B8%A9%E5%9D%91%E4%B9%8Bopenwhisk%E4%B8%8Efission%E5%AF%B9%E6%AF%94/"/>
<id>https://0rainge.github.io/2018/04/11/FaaS踩坑之openwhisk与fission对比/</id>
<published>2018-04-10T16:00:00.000Z</published>
<updated>2018-04-11T05:55:47.000Z</updated>
<content type="html"><![CDATA[<h2 id="实现层面"><a href="#实现层面" class="headerlink" title="实现层面"></a>实现层面</h2><h3 id="fission运行流程"><a href="#fission运行流程" class="headerlink" title="fission运行流程"></a>fission运行流程</h3><p><img src="https://www.kubernetes.org.cn/img/2017/08/20170811193044.jpg" alt="image"></p><ol start="0"><li>controller:对外提供api,通过fission CLI 控制内部组件</li><li>router:用户发送http请求请求服务(调用函数)。收到请求,查看缓存(fiction与podurl间的映射)。对于调用过function,router会很快的拿到返回值;没调用过,向 poolmgr 请求一个新的实例。poolmgr 有一个空闲 pods 池,它会选择一个 pod,将函数加载进去(将请求发送到 pod 的容器中),并将 pod 地址返回给 router。</li><li>创建环境:对于用户创建的environment,poolmgr中有循环的线程自动在kubernetes中根据env的镜像创建包含三副本pod的deployment,每个pod中有两个container,一个使用env的镜像创建,另一个是fission中的辅助container,镜像是fission/fetcher。两个container共享一个volume。因为env是定义基础镜像,而一个env可能会关联许多function,所以需要fetcher根据具体的function在通用的container里运行不同的code。</li><li>poolmgr还会定期清理“不活跃”的deployment,如env。还会定期删除不活跃的pod,让kubernetes自动创建新的、干净的pod供其他function使用。poolmgr提供的API只有两个,一个是根据function获取对应的service url,另一个是类似心跳API帮助维护缓存。因为router里也维护有function到service url的缓存,所以当function被调用时,router会通知poolmgr更新一下对应service对象的时间,避免被误删。</li></ol><h3 id="openwhisk运行流程"><a href="#openwhisk运行流程" class="headerlink" title="openwhisk运行流程"></a>openwhisk运行流程</h3><p><img src="http://kityminder-img.gz.bcebos.com/fddf5b1af7a3a2de4aebc65b54514d9a203e502f" alt="image"></p><ol><li>nginx:处理用户发送(如调用函数操作等)将其转发(以及ssl终止)。</li><li>contraller:是用户可执行操作( CRUD请求以及操作调用)的接口。</li><li>CouchDB:存储操作(whisk数据库),身份验证(subjects数据库)。</li><li>consul:服务发现组件,持续检查系统中可用执行者的运行状态来监视invoker,告诉contraller哪些invoker可用</li><li>kafka:contraller和invoker只通过由 Kafka 缓冲和持久存储的消息进行通信。缓冲,减轻内存负担。确保消息不会在系统崩溃时丢失。</li><li>invoker:启动Docker执行操作。对于每个操作调用,衍生一个 Docker 容器,将操作码注入。使用传递给代码的参数来执行代码,获取结果,然后销毁该容器</li><li>储存结果:存储在CouchDB终端 whisks 数据库中作为 ActivationId 下的激活</li></ol><h3 id="开发语言"><a href="#开发语言" class="headerlink" title="开发语言"></a>开发语言</h3><h5 id="fission"><a href="#fission" class="headerlink" title="fission"></a>fission</h5><ul><li>Go语言</li></ul><h5 id="openwhisk"><a href="#openwhisk" class="headerlink" title="openwhisk"></a>openwhisk</h5><ul><li>scala语言</li></ul><h3 id="组件"><a href="#组件" class="headerlink" title="组件"></a>组件</h3><h5 id="fission-1"><a href="#fission-1" class="headerlink" title="fission"></a>fission</h5><ul><li>controller</li><li>router</li><li>executor</li><li>kubeWatcher</li><li>timer</li><li>MessageQueueMgr</li><li>storageSvc</li><li>builderMgr</li></ul><h5 id="openwhisk-1"><a href="#openwhisk-1" class="headerlink" title="openwhisk"></a>openwhisk</h5><ul><li>nginx</li><li>contraller</li><li>CouchDB</li><li>consul</li><li>kafka</li><li>invoker</li></ul><h2 id="功能层面"><a href="#功能层面" class="headerlink" title="功能层面"></a>功能层面</h2><h3 id="组件-1"><a href="#组件-1" class="headerlink" title="组件"></a>组件</h3><h4 id="控制器"><a href="#控制器" class="headerlink" title="控制器"></a>控制器</h4><h5 id="fission-2"><a href="#fission-2" class="headerlink" title="fission"></a>fission</h5><ul><li>controller,是fission对外提供管理API的组件。所有其他组件通过关注 controller 来更新负责追踪函数、HTTP 路由、事件触发器和环境镜像</li></ul><h5 id="openwhisk-2"><a href="#openwhisk-2" class="headerlink" title="openwhisk"></a>openwhisk</h5><ul><li>contraller:是用户可执行操作(如CRUD请求以及操作调用)的接口。</li><li>consul:服务发现组件,持续检查系统中可用执行者的运行状态来监视invoker,告诉contraller哪些invoker可用</li><li>kafka:一种高吞吐量、分布式的发布/预订消息传递系统。contraller和invoker只通过由 Kafka 缓冲和持久存储的消息进行通信。可以减轻在内存中进行缓冲的负担并降低伴随的 OutOfMemoryException 风险,确保消息不会在系统崩溃时丢失。使用异步调用模型</li></ul><h4 id="请求响应"><a href="#请求响应" class="headerlink" title="请求响应"></a>请求响应</h4><h5 id="fission-3"><a href="#fission-3" class="headerlink" title="fission"></a>fission</h5><ul><li><p>router:收到请求,查看缓存(fiction与podurl间的映射)。对于调用过function,router会很快的拿到返回值;没调用过,向 poolmgr 请求一个新的实例。poolmgr 有一个空闲 pods 池,它会选择一个 pod,将函数加载进去(将请求发送到 pod 的容器中),并将 pod 地址返回给 router。</p><h5 id="openwhisk-3"><a href="#openwhisk-3" class="headerlink" title="openwhisk"></a>openwhisk</h5></li><li><p>API网关</p></li></ul><h4 id="服务发现组件"><a href="#服务发现组件" class="headerlink" title="服务发现组件"></a>服务发现组件</h4><h5 id="fission-4"><a href="#fission-4" class="headerlink" title="fission"></a>fission</h5><ul><li>router,与controller和poolmgr打交道,会监听 controller 中triggers的更新,动态的更新web service的route定义。</li><li>poolmgr 负责管理空闲的环境容器池、将函数加载到这些容器当中、以及杀死空闲的函数实例。</li></ul><h5 id="openwhisk-4"><a href="#openwhisk-4" class="headerlink" title="openwhisk"></a>openwhisk</h5><ul><li>consul:服务发现组件,持续检查系统中可用执行者的运行状态来监视invoker,告诉contraller哪些invoker可用</li></ul><h4 id="触发器"><a href="#触发器" class="headerlink" title="触发器"></a>触发器</h4><h5 id="fission-5"><a href="#fission-5" class="headerlink" title="fission"></a>fission</h5><ul><li>Http Trigger</li><li>Time Trigger </li><li>MQ Trigger </li></ul><h5 id="openwhisk-5"><a href="#openwhisk-5" class="headerlink" title="openwhisk"></a>openwhisk</h5><ul><li><p>invoker:启动Docker执行操作,对于每个操作调用,都会衍生一个 Docker 容器,将操作码注入。使用传递给代码的参数来执行代码,获取结果,然后销毁该容器</p></li><li><p>cloudant</p></li><li>custom trigger</li><li>github</li><li>messahub</li><li>moblie push</li><li>priodic</li></ul><h4 id="数据存储"><a href="#数据存储" class="headerlink" title="数据存储"></a>数据存储</h4><h5 id="fission-6"><a href="#fission-6" class="headerlink" title="fission"></a>fission</h5><ul><li>etcd</li></ul><h5 id="openwhisk-6"><a href="#openwhisk-6" class="headerlink" title="openwhisk"></a>openwhisk</h5><ul><li>CouchDB</li></ul><h3 id="函数"><a href="#函数" class="headerlink" title="函数"></a>函数</h3><h4 id="语言支持"><a href="#语言支持" class="headerlink" title="语言支持"></a>语言支持</h4><h5 id="fission-7"><a href="#fission-7" class="headerlink" title="fission"></a>fission</h5><ul><li>Binary </li><li>Go </li><li>.NET </li><li>.NET 2.0 </li><li>NodeJS (Alpine) </li><li>NodeJS (Debian) </li><li>Perl </li><li>PHP 7 </li><li>Python 3 </li><li>Ruby</li></ul><h5 id="openwhisk-7"><a href="#openwhisk-7" class="headerlink" title="openwhisk"></a>openwhisk</h5><ul><li>JavaScript</li><li>Python</li><li>Swift</li><li>PhP</li><li>Docker</li></ul><h4 id="函数上传支持"><a href="#函数上传支持" class="headerlink" title="函数上传支持"></a>函数上传支持</h4><h5 id="fission-8"><a href="#fission-8" class="headerlink" title="fission"></a>fission</h5><ul><li>环境支持的语言</li><li>任何兼容二进制的可执行文件和脚本</li></ul><h5 id="openwhisk-8"><a href="#openwhisk-8" class="headerlink" title="openwhisk"></a>openwhisk</h5><ul><li>环境支持的语言</li><li>Java 方法</li><li>任何兼容二进制的可执行文件,包括打包为 Docker 容器的 Go 程序和定制可执行文件</li></ul><h5 id="源码形式"><a href="#源码形式" class="headerlink" title="源码形式"></a>源码形式</h5><h6 id="云端编译环境"><a href="#云端编译环境" class="headerlink" title="云端编译环境"></a>云端编译环境</h6><p>####### 内容</p><p>####### 指令</p><h5 id="二进制形式"><a href="#二进制形式" class="headerlink" title="二进制形式"></a>二进制形式</h5><h6 id="本地编译环境要求"><a href="#本地编译环境要求" class="headerlink" title="本地编译环境要求"></a>本地编译环境要求</h6><h4 id="开发方式"><a href="#开发方式" class="headerlink" title="开发方式"></a>开发方式</h4><h5 id="fission-9"><a href="#fission-9" class="headerlink" title="fission"></a>fission</h5><ul><li>CLI</li></ul><h5 id="openwhisk-9"><a href="#openwhisk-9" class="headerlink" title="openwhisk"></a>openwhisk</h5><ul><li>浏览器开发</li><li>Cloud Functions CLI</li></ul><h4 id="启动方式"><a href="#启动方式" class="headerlink" title="启动方式"></a>启动方式</h4><h5 id="fission-10"><a href="#fission-10" class="headerlink" title="fission"></a>fission</h5><ul><li>冷启动</li></ul><h5 id="openwhisk-10"><a href="#openwhisk-10" class="headerlink" title="openwhisk"></a>openwhisk</h5><h4 id="函数操作"><a href="#函数操作" class="headerlink" title="函数操作"></a>函数操作</h4><h5 id="fission-11"><a href="#fission-11" class="headerlink" title="fission"></a>fission</h5><ul><li>通过kubectl对pod进行操作</li></ul><h5 id="openwhisk-11"><a href="#openwhisk-11" class="headerlink" title="openwhisk"></a>openwhisk</h5><ul><li>contraller:是用户可执行操作(如CRUD请求以及操作调用)的接口。</li></ul><h5 id="打包上传"><a href="#打包上传" class="headerlink" title="打包上传"></a>打包上传</h5><h5 id="调用方式"><a href="#调用方式" class="headerlink" title="调用方式"></a>调用方式</h5><h5 id="fission-12"><a href="#fission-12" class="headerlink" title="fission"></a>fission</h5><ul><li>触发器关联</li></ul><h5 id="openwhisk-12"><a href="#openwhisk-12" class="headerlink" title="openwhisk"></a>openwhisk</h5><ul><li>触发器关联</li><li>Cloud Functions API</li><li>Cloud Functions CLI</li><li>iOS移动SDK</li></ul><h5 id="执行时间上限"><a href="#执行时间上限" class="headerlink" title="执行时间上限"></a>执行时间上限</h5><h4 id="运行环境"><a href="#运行环境" class="headerlink" title="运行环境"></a>运行环境</h4><h5 id="fission-13"><a href="#fission-13" class="headerlink" title="fission"></a>fission</h5><ul><li>k8s的pod</li></ul><h5 id="openwhisk-13"><a href="#openwhisk-13" class="headerlink" title="openwhisk"></a>openwhisk</h5><ul><li>docker</li></ul><h5 id="运行环境的启动"><a href="#运行环境的启动" class="headerlink" title="运行环境的启动"></a>运行环境的启动</h5><h5 id="fission-14"><a href="#fission-14" class="headerlink" title="fission"></a>fission</h5><ul><li>Pool-based executor(poolmgr): </li><li>New-deployment executor(newdeploy):创建一个Kubernetes部署、Service和HorizontalPodAutoscaler</li></ul><h5 id="openwhisk-14"><a href="#openwhisk-14" class="headerlink" title="openwhisk"></a>openwhisk</h5><h5 id="运行环境的回收"><a href="#运行环境的回收" class="headerlink" title="运行环境的回收"></a>运行环境的回收</h5><h5 id="fission-15"><a href="#fission-15" class="headerlink" title="fission"></a>fission</h5><ul><li>poolmgr定期清理“不活跃”的deployment,定期删除不活跃的pod,让kubernetes自动创建新的、干净的pod供其他function使用。(如何定期待查)</li></ul><h5 id="openwhisk-15"><a href="#openwhisk-15" class="headerlink" title="openwhisk"></a>openwhisk</h5><h4 id="结果返回"><a href="#结果返回" class="headerlink" title="结果返回"></a>结果返回</h4><h5 id="fission-16"><a href="#fission-16" class="headerlink" title="fission"></a>fission</h5><ul><li>直接返回</li></ul><h5 id="openwhisk-16"><a href="#openwhisk-16" class="headerlink" title="openwhisk"></a>openwhisk</h5><ul><li>储存在CouchDB的输出中</li></ul><h3 id="使用"><a href="#使用" class="headerlink" title="使用"></a>使用</h3><h4 id="事件"><a href="#事件" class="headerlink" title="事件"></a>事件</h4><h5 id="fission-17"><a href="#fission-17" class="headerlink" title="fission"></a>fission</h5><h5 id="openwhisk-17"><a href="#openwhisk-17" class="headerlink" title="openwhisk"></a>openwhisk</h5><ul><li>package</li><li>包含操作和订阅源</li><li>绑定到包指定缺省参数</li></ul><h4 id="身份认证"><a href="#身份认证" class="headerlink" title="身份认证"></a>身份认证</h4><h5 id="fission-18"><a href="#fission-18" class="headerlink" title="fission"></a>fission</h5><h5 id="openwhisk-18"><a href="#openwhisk-18" class="headerlink" title="openwhisk"></a>openwhisk</h5><ul><li>CouchDB:在whisk数据库中存储操作,subjects数据库用于身份验证与授权操作并装入操作</li></ul><h4 id="订阅源支持"><a href="#订阅源支持" class="headerlink" title="订阅源支持"></a>订阅源支持</h4><p>全部属于某个触发器 T 的事件的流</p><h5 id="fission-19"><a href="#fission-19" class="headerlink" title="fission"></a>fission</h5><ul><li>workflow?</li></ul><h5 id="openwhisk-19"><a href="#openwhisk-19" class="headerlink" title="openwhisk"></a>openwhisk</h5><p>发布自己的订阅源使用,创建订阅源体系结构:</p><ul><li>Hook </li><li>轮询</li><li>连接</li></ul><h4 id="自动伸缩"><a href="#自动伸缩" class="headerlink" title="自动伸缩"></a>自动伸缩</h4><h5 id="fission-20"><a href="#fission-20" class="headerlink" title="fission"></a>fission</h5><ul><li>自动伸缩</li></ul><h5 id="openwhisk-20"><a href="#openwhisk-20" class="headerlink" title="openwhisk"></a>openwhisk</h5><h4 id="图形仪表盘"><a href="#图形仪表盘" class="headerlink" title="图形仪表盘"></a>图形仪表盘</h4><h5 id="fission-21"><a href="#fission-21" class="headerlink" title="fission"></a>fission</h5><p>不支持</p><h5 id="openwhisk-21"><a href="#openwhisk-21" class="headerlink" title="openwhisk"></a>openwhisk</h5><ul><li>存在。用于监视活动摘要,活动日志,时间线以及过滤选项</li></ul><h2 id="项目发展现况"><a href="#项目发展现况" class="headerlink" title="项目发展现况"></a>项目发展现况</h2><h3 id="社区发展"><a href="#社区发展" class="headerlink" title="社区发展"></a>社区发展</h3><h5 id="fission-22"><a href="#fission-22" class="headerlink" title="fission"></a>fission</h5><ul><li>3.2k star</li></ul><h5 id="openwhisk-22"><a href="#openwhisk-22" class="headerlink" title="openwhisk"></a>openwhisk</h5><ul><li>3k star</li></ul><h3 id="使用者"><a href="#使用者" class="headerlink" title="使用者"></a>使用者</h3><h5 id="fission-23"><a href="#fission-23" class="headerlink" title="fission"></a>fission</h5><ul><li>Autodesk</li><li>cielo24</li></ul><h5 id="openwhisk-23"><a href="#openwhisk-23" class="headerlink" title="openwhisk"></a>openwhisk</h5><ul><li><a href="https://www.ibm.com/cloud-computing/bluemix/case-studies" target="_blank" rel="noopener">https://www.ibm.com/cloud-computing/bluemix/case-studies</a></li></ul><h3 id="支持厂商"><a href="#支持厂商" class="headerlink" title="支持厂商"></a>支持厂商</h3><h5 id="fission-24"><a href="#fission-24" class="headerlink" title="fission"></a>fission</h5><ul><li>Platform9</li></ul><h5 id="openwhisk-24"><a href="#openwhisk-24" class="headerlink" title="openwhisk"></a>openwhisk</h5><ul><li>Apache/IBM</li></ul><h2 id="底层基础设施对接层面"><a href="#底层基础设施对接层面" class="headerlink" title="底层基础设施对接层面"></a>底层基础设施对接层面</h2><h3 id="组建部署方式"><a href="#组建部署方式" class="headerlink" title="组建部署方式"></a>组建部署方式</h3><h5 id="fission-25"><a href="#fission-25" class="headerlink" title="fission"></a>fission</h5><ul><li>通过helm部署在kubernetes上</li></ul><h5 id="openwhisk-25"><a href="#openwhisk-25" class="headerlink" title="openwhisk"></a>openwhisk</h5><ul><li>通过 Ansible部署在docker中</li></ul><h3 id="function部署方式"><a href="#function部署方式" class="headerlink" title="function部署方式"></a>function部署方式</h3><h5 id="fission-26"><a href="#fission-26" class="headerlink" title="fission"></a>fission</h5><ul><li>以pod形式运行在kubernetes中</li></ul><h5 id="openwhisk-26"><a href="#openwhisk-26" class="headerlink" title="openwhisk"></a>openwhisk</h5><ul><li>运行在docker中</li></ul><h4 id="参考:"><a href="#参考:" class="headerlink" title="参考:"></a>参考:</h4><ul><li><a href="https://fission.io" target="_blank" rel="noopener">https://fission.io</a></li><li><a href="https://console.bluemix.net/docs/openwhisk/index.html#cloud-functions-" target="_blank" rel="noopener">https://console.bluemix.net/docs/openwhisk/index.html#cloud-functions-</a></li><li><a href="https://www.tuicool.com/articles/6NnEb2b" target="_blank" rel="noopener">https://www.tuicool.com/articles/6NnEb2b</a></li><li><a href="https://lingxiankong.github.io/2017-03-05-faas-fission.html" target="_blank" rel="noopener">https://lingxiankong.github.io/2017-03-05-faas-fission.html</a></li><li><a href="https://www.kubernetes.org.cn/2523.html" target="_blank" rel="noopener">https://www.kubernetes.org.cn/2523.html</a></li><li><a href="https://blog.csdn.net/qq_34463875/article/details/60960244" target="_blank" rel="noopener">https://blog.csdn.net/qq_34463875/article/details/60960244</a></li><li><a href="https://www.ibm.com/developerworks/cn/opensource/os-introducing-openwhisk-microservices-made-easy/" target="_blank" rel="noopener">https://www.ibm.com/developerworks/cn/opensource/os-introducing-openwhisk-microservices-made-easy/</a></li></ul>]]></content>
<summary type="html">
<h2 id="实现层面"><a href="#实现层面" class="headerlink" title="实现层面"></a>实现层面</h2><h3 id="fission运行流程"><a href="#fission运行流程" class="headerlink" ti
</summary>
<category term="FaaS踩坑系列" scheme="https://0rainge.github.io/categories/FaaS%E8%B8%A9%E5%9D%91%E7%B3%BB%E5%88%97/"/>
<category term="FaaS" scheme="https://0rainge.github.io/tags/FaaS/"/>
<category term="fission" scheme="https://0rainge.github.io/tags/fission/"/>
<category term="openwhisk" scheme="https://0rainge.github.io/tags/openwhisk/"/>
</entry>
<entry>
<title>FaaS踩坑之fission安装</title>
<link href="https://0rainge.github.io/2018/04/10/FaaS%E8%B8%A9%E5%9D%91%E4%B9%8Bfission%E5%AE%89%E8%A3%85/"/>
<id>https://0rainge.github.io/2018/04/10/FaaS踩坑之fission安装/</id>
<published>2018-04-09T16:00:00.000Z</published>
<updated>2018-06-05T08:27:53.000Z</updated>
<content type="html"><![CDATA[<p>上个月申请了sel实验室,来到公司。和丁博士沟通了一下,确定方向是边缘计算中的faas,给我布置了下任务,用一周的时间把fission跑起来,熟悉fission的用法,并比较fission和openwhisk。</p><p>fission是跑在k8s上的服务,因此要先申请几个公司的虚拟机做集群,在虚拟机上安装k8s,再安装k8s上的包管理工具helm,最后装fission。安装k8s比较麻烦,丁博士让我不懂就问一个前辈,前辈装过minikube,所以让我从minikube开始。<br>对docker完全真空的我感觉有点懵逼,不过感觉很激动。。就开始啦。</p><p>参考 <a href="https://docs.fission.io/0.6.0/installation/installation" target="_blank" rel="noopener">fission官网安装文档</a></p><h4 id="0-科学上网"><a href="#0-科学上网" class="headerlink" title="0. 科学上网"></a>0. 科学上网</h4><p>科学上网太重要了。这14天学到各种姿势:</p><ol><li><p>本地设置http代理在浏览器翻</p></li><li><p>shadowsocks : 转化socks5协议,可以设置pac自动模式访问墙内网站不走代理。</p></li><li><p>shadowsocks + privoxy:终端翻,每次运行下面的脚本</p></li></ol><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></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">sudo /usr/local/sbin/privoxy /usr/local/etc/privoxy/config</span><br><span class="line"></span><br><span class="line">export http_proxy='http://localhost:8118'</span><br><span class="line"></span><br><span class="line">export https_proxy='http://localhost:8118'</span><br><span class="line"></span><br><span class="line">curl www.google.com</span><br></pre></td></tr></table></figure><ol start="4"><li><p>ss + privoxy + proxifier :配置所有应用的流量走ss,可以直接docker pull 墙外镜像</p></li><li><p>ssh到虚拟机(比如k8s)一直没实现有些遗憾不然又能跳过一堆坑</p></li></ol><h4 id="1-安装minikube"><a href="#1-安装minikube" class="headerlink" title="1. 安装minikube"></a>1. 安装minikube</h4><p>minikubi是只有一个节点的,可以看成是单机版的k8s,用来编排docker(类似虚拟机,感觉像是运行在镜像上的进程)的工具,可以在minikube上面运行各种跑在docker上的服务(比如fission)。</p><p>每一个服务有一个namespace用于防止服务间命名冲突,服务由各种deployment组成,deployment负责启动相关pod,pod可以看成包含很多豆子(docker/image)的豆荚,里面的豆子包括跑着服务的组件和fission里起来的函数。</p><p>通过命令行kubectl可以对相关deployment,pod,namespace进行操作如查看或删除等。之后安装fission会经常有pod没起来,用kubectl查看或删除fission重新安装。常用命令有:</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></pre></td><td class="code"><pre><span class="line">kubectl get svc --all-namespaces 查看所有服务</span><br><span class="line">kubectl get pods --all-namespaces 查看所有pod</span><br><span class="line">kubectl get ns --all-namespaces 查看所有命名空间</span><br><span class="line">kubectl get secrets --all-namespaces 查看所有secret</span><br><span class="line">kubectl get deployment --all-namespaces 查看deployment</span><br><span class="line">kubectl describe kube-dns-1326421443-19zxq 查看某一pod</span><br><span class="line">kubectl describe pod python-39799-58b5b4f844-zwlc6 -n fission-builder命名空间下查看pod</span><br><span class="line">kubectl describe pods kube-dns-1326421443-19zxq -n kube-system</span><br><span class="line">kubectl logs python-39799-58b5b4f844-zwlc6 -n fission-builder —container=builder 查看pod 的logs</span><br></pre></td></tr></table></figure><p>安装minikube,就是安装一个linux,并在上面安装minikube的相关组件,当所有pod跑起来之后就可以了。<br>参考了其他博客,感觉写的很好,按照博客安装的。<br><a href="https://blog.csdn.net/aixiaoyang168/article/details/78331847?locationNum=6&fps=1" target="_blank" rel="noopener">https://blog.csdn.net/aixiaoyang168/article/details/78331847?locationNum=6&fps=1</a></p><p>因为minikube在墙内,安装所需的gcr镜像没有拉下来,通过阿里的镜像库和公司的私有库把镜像docker pull下来传到本机,在本地虚拟机加绝对路径直接docker load进来(感觉非常神奇,不知道本机和本机虚拟机怎么交流的)</p><h4 id="或者-1-安装k8s"><a href="#或者-1-安装k8s" class="headerlink" title="或者 1. 安装k8s"></a>或者 1. 安装k8s</h4><p>申请三台虚拟机(4c8g50g)。<br>参考观云台部署文档+脚本一键部署k8s,很快就装好了。<br>然后把k8s的~/.kube/admin.conf传入本机/etc/kubernetes中,让本机连上集群。</p><p>坑如下:</p><ol><li>部署时默认部署单节点集群,还有高可用集群可选(安装时加参数HA)。单节点集群只有一个master不是只有一个节点,高可用集群有多个master。按默认即可差点装错。</li><li><p>k8s虚拟机里的DNS服务器能ping通,但是ping其他的网站ping不通。因为公司虚拟机的dns服务器是自己搭建的,什么都解析不了。所以无法用docker pull(因为docker官网都不知道是什么)需要自己添加dns服务器</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">vim /etc/resolv.conf</span><br><span class="line">nameserver 8.8.8.8</span><br><span class="line">/etc/init.d/network restart</span><br></pre></td></tr></table></figure></li><li><p>添加了dns服务器好像也不能解析个别地址,比如helm里阿里的repo,所以还要自己添加地址。</p><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">vim /etc/hosts</span><br><span class="line">116.62.99.172 https://aliacs-app-catalog.oss-cn-hangzhou.aliyuncs.com</span><br></pre></td></tr></table></figure></li></ol><h4 id="再或者-1-申请谷歌云"><a href="#再或者-1-申请谷歌云" class="headerlink" title="再或者 1. 申请谷歌云"></a>再或者 1. 申请谷歌云</h4><p>在谷歌云上建k8s集群。终端连到谷歌云的集群上。<br>完全无坑,如果只玩fission的话强烈安利,不用拉镜像换repo也没有各种诡异的问题(处理安装helm时多了一步,见安装helm)。但是自己用着玩可以,不能移植到边缘设备如网关,长远看做不成边缘计算的项目。<br><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">启动集群:gcloud container clusters create example-cluster </span><br><span class="line">关闭集群:gcloud container clusters delete example-cluster</span><br></pre></td></tr></table></figure></p><h4 id="2-安装helm"><a href="#2-安装helm" class="headerlink" title="2. 安装helm"></a>2. 安装helm</h4><p>helm是k8s上的包管理工具,可以方便的从repo源(相当于yum源)中的chart(相当于rpm包)安装在k8s。分客户端helm和服务端tiller,分别部署在本地和k8s内部上(也可以客户端也部署在k8s中),版本号要一致。客户端直接下载到本地,服务端通过helm init 自动安装到本机连接的k8s集群中。<br><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">helm init --upgrade -i registry.cn-hangzhou.aliyuncs.com/google_containers/tiller:v2.8.7 --stable-repo-url https://kubernetes.oss-cn-hangzhou.aliyuncs.com/charts</span><br></pre></td></tr></table></figure></p><p>安装参考博客:<a href="https://blog.csdn.net/weiguang1017/article/details/78045013" target="_blank" rel="noopener">https://blog.csdn.net/weiguang1017/article/details/78045013</a></p><p>需要注意的有:</p><ol><li>安装helm服务端是依然有个拉不下来的gcr镜像tiller。要么拉下来,要么在helm init时直接指定阿里的镜像进行替换。</li><li>helm是从repo上给k8s安装服务,但那个repo也被墙了,helm init时也要指定阿里的repo替换默认repo</li><li><p>通过谷歌云安装helm时要先</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">kubectl create serviceaccount --namespace kube-system tiller</span><br><span class="line">kubectl create clusterrolebinding tiller-cluster-rule --clusterrole=cluster-admin --serviceaccount=kube-system:tiller</span><br><span class="line">kubectl patch deploy --namespace kube-system tiller-deploy -p '{"spec":{"template":{"spec":{"serviceAccount":"tiller"}}}}'</span><br></pre></td></tr></table></figure></li><li><p>(隐秘的坑,如果被替换的repo地址无法被k8s的dns服务器解析,白替换了)</p></li></ol><h4 id="3-安装fission"><a href="#3-安装fission" class="headerlink" title="3. 安装fission"></a>3. 安装fission</h4><p>安装文档上的一行代码往往运行不了的,看起来就是helm从github上直接直接把fission部署在集群上,但总会出现各种诡异的错误,一开始感觉是完全凭运气安装的,后来发现报错基本可以分成4类:无法下载、什么什么已存在、超时、编译出错<br>解决是这样的</p><ol><li>把项目直接下载到本地,url变为本地绝对路径(虽然我一直感觉这个问题很奇怪,项目很小又不用翻墙为什么有时候会下不下来)</li><li><p>上次安装到一半出错了,这次安装就会报错,要把所有上次的东西删干净,再新建一个ns fission,最好写个shell,每次直接执行:</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></pre></td><td class="code"><pre><span class="line">#!/bin/bash</span><br><span class="line">kubectl delete clusterrolebindings fission-builder-crd</span><br><span class="line"></span><br><span class="line">kubectl delete clusterrolebindings fission-fetcher-crd</span><br><span class="line"></span><br><span class="line">kubectl delete clusterrolebindings fission-crd</span><br><span class="line"></span><br><span class="line">kubectl delete ns fission-function</span><br><span class="line"></span><br><span class="line">kubectl delete ns fission-builder</span><br><span class="line"></span><br><span class="line">kubectl delete ns fission</span><br><span class="line"></span><br><span class="line">kubectl delete secrets influxdb -n fission</span><br></pre></td></tr></table></figure></li><li><p>这个错误只在通过公司脚本安装的k8s上遇到了,因为部署fission需要的镜像没拉下来,应该是k8s拉镜像有问题。于是需要镜像较少的精简版fission-core。<br>先通过fission的源码查到需要镜像 fission/fission-bundle:0.6.0 和 fission/fluentd:0.6.0。拖进去发现还是不行,在谷歌云集群安装了一次fission-core发现上面还跑了一个镜像fission/alpinecurl,load进来把fission跑起来了。记得3个节点都要load,因为fission不一定在哪个节点跑着。</p></li></ol><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></pre></td><td class="code"><pre><span class="line">传镜像的代码</span><br><span class="line">docker save id(XXX) > XXXXXX.tar</span><br><span class="line">scp XXXXXX.tar root@XX.XX.XX.XX:/images</span><br><span class="line">docker load XXXXXX.tar</span><br><span class="line">docker images | grep XXX</span><br><span class="line">docker images | more</span><br><span class="line">docker tag id(XXX) 原名</span><br><span class="line">docker save id(XXX) > XXXXXX.tar</span><br></pre></td></tr></table></figure><ol start="4"><li>安装fission-core有个奇怪的错误,如下,结果是fission源码错误<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">release harping-dragonfly failed: Deployment.apps "router" is invalid: [spec.template.spec.containers[0].livenessProbe.httpGet.port: Invalid value: "8888": must contain at least one letter or number (a-z, 0-9), spec.template.spec.containers[0].readinessProbe.httpGet.port: Invalid value: "8888": must contain at least one letter or number (a-z, 0-9)]。</span><br></pre></td></tr></table></figure></li></ol><p>。。感觉还是靠运气的。</p><h4 id="4-安装fission-ctl"><a href="#4-安装fission-ctl" class="headerlink" title="4. 安装fission ctl"></a>4. 安装fission ctl</h4><p>按文档安装没错的</p><h4 id="5-fission使用"><a href="#5-fission使用" class="headerlink" title="5. fission使用"></a>5. fission使用</h4><ol><li><p>路径问题:触发函数时curl,FISSION_ROUTER 要换掉,若是minikube安装,直接换成minikube虚拟机地址;若是k8s安装,换成外部ip</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">curl http://$FISSION_ROUTER/hello 变成 curl http://35.194.204.59/hello</span><br></pre></td></tr></table></figure></li><li><p>顺序问题:下面的每一步之间有依赖关系,顺序不能颠倒:<br>创建环境(go,python,js…),创建executors和函数(创建pod),创建trigger(调用函数)</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">fission env create --name nodejs --image fission/node-env:0.6.0</span><br><span class="line">fission fn create --name hello --code hello.js --env nodejs --executortype poolmgr</span><br><span class="line">fission route create --function hello --url /hello</span><br></pre></td></tr></table></figure></li><li><p>package打包上传问题:</p></li></ol><p>报错:Build timeout due to environment builder not ready ,builder组件有问题</p><p>更多关于fission的问题在后面写</p><h4 id="参考"><a href="#参考" class="headerlink" title="参考"></a>参考</h4><p><a href="https://docs.fission.io/0.6.0/installation/installation" target="_blank" rel="noopener">https://docs.fission.io/0.6.0/installation/installation</a><br><a href="http://www.jdon.com/48109" target="_blank" rel="noopener">http://www.jdon.com/48109</a><br><a href="https://www.jianshu.com/p/51a19ef5f8cf" target="_blank" rel="noopener">https://www.jianshu.com/p/51a19ef5f8cf</a><br><a href="https://www.cnblogs.com/Leo_wl/p/6055252.html" target="_blank" rel="noopener">https://www.cnblogs.com/Leo_wl/p/6055252.html</a><br><a href="https://www.kubernetes.org.cn/3096.html" target="_blank" rel="noopener">https://www.kubernetes.org.cn/3096.html</a><br><a href="https://www.kubernetes.org.cn/3280.html" target="_blank" rel="noopener">https://www.kubernetes.org.cn/3280.html</a><br><a href="http://www.dockone.io/article/932" target="_blank" rel="noopener">http://www.dockone.io/article/932</a><br><a href="http://blog.csdn.net/moshenglv/article/details/55806421" target="_blank" rel="noopener">http://blog.csdn.net/moshenglv/article/details/55806421</a><br><a href="http://blog.csdn.net/aixiaoyang168/article/details/78331847?locationNum=6&fps=1" target="_blank" rel="noopener">http://blog.csdn.net/aixiaoyang168/article/details/78331847?locationNum=6&fps=1</a><br><a href="https://blog.csdn.net/weiguang1017/article/details/78045013" target="_blank" rel="noopener">https://blog.csdn.net/weiguang1017/article/details/78045013</a></p><p>感谢刘吉安学长虽然不在边缘计算组还每天教我填坑到晚上11点,丁博士教我k8s相关和fission源码分析,崔前辈和高前辈带我入门,没嫌弃我各种弱智的问题。</p>]]></content>
<summary type="html">
<p>上个月申请了sel实验室,来到公司。和丁博士沟通了一下,确定方向是边缘计算中的faas,给我布置了下任务,用一周的时间把fission跑起来,熟悉fission的用法,并比较fission和openwhisk。</p>
<p>fission是跑在k8s上的服务,因此要先申请
</summary>
<category term="FaaS踩坑系列" scheme="https://0rainge.github.io/categories/FaaS%E8%B8%A9%E5%9D%91%E7%B3%BB%E5%88%97/"/>
<category term="FaaS" scheme="https://0rainge.github.io/tags/FaaS/"/>
<category term="minikube" scheme="https://0rainge.github.io/tags/minikube/"/>
<category term="Kubernetes" scheme="https://0rainge.github.io/tags/Kubernetes/"/>
<category term="helm" scheme="https://0rainge.github.io/tags/helm/"/>
<category term="fission" scheme="https://0rainge.github.io/tags/fission/"/>
</entry>
</feed>