不能解决小额支付,闪电网络还能活多久?

闪电网络自推出以来饱受质疑。为了解决比特币小额支付的问题,闪电网络引入了链下交易,并且协议运行得十分完美。截至今天,比特币全网已经拥有了7408个闪电网络节点,4万多个channel,闪电网络总容量也达到了1000BTC,折合4百万美元,并且这些数字还在保持高速增长。看起来闪电网络回击了外界的质疑,一切都运行得十分良好。

但是事实真是这样的吗?我们要从闪电网络的原理说起。

闪电网络的原理

闪电网络通道是什么,两个节点之间如何转账

闪电网络通过一个预设的智能合约来处理交易,通过智能合约,闪电网络将大量的交易转移到链下进行,从而规避了高昂的比特币手续费。这里面有一个概念是通道(Channel),闪电网络要求发生转账的双方事先开启一个通道,存入一定数量的比特币,之后发生的转账都从通道里面扣除相应数量的比特币。直到这个通道被关闭,才会产生一次宣告,将最后结算出来的余额广播到链上。

闪电网络建立通道之后可以互相转账

通过事先交押金,建立通道,可以实现两个节点之间的互相转账。

闪电网络所有节点组成了一张网

实现了两个节点之间的通道和转账,闪电网络进一步将全网的通道连接起来,形成了一张网。

闪电网络的网状交易网络

如果A要向D发起一次1BTC的转账,A和D之间没有直接的通道,只能通过A-C-D或者A-E-D两条路径来完成转账。闪电网络会自动选择一个手续费较低的通道来完成交易,我们假设这里选择了A-C-D。A->D的1BTC转账,会被拆分成A->C的1BTC转账,和C->D的1BTC转账,这样就化简为了上面说的两点之间互相转账的场景。转账结束之后,A-C通道的余额会从10-0变成9-1,C-D通道的余额会从5-2变成4-3。

通过这种路由的方式,闪电网络将各个节点连成了一张网。如果A->D转账1BTC,D->A再转账1BTC,实际上A-C-D的通道余额又变了回去,就像什么都没有发生。 而如果使用传统的BTC转账,则会发生两次手续费。闪电网络的优势得以体现。

真实世界里的闪电网络表现糟糕

很多看起来完美的设计在真实世界经常面临失败,比如著名的Plan 9

目前看来,闪电网络在所有节点都是对等的情况下完成得相当好,既加速了转账又减少了手续费。但是如果真实世界里的节点不都是对等的呢?

上面的理论分析并没有考虑各个节点在真实世界所处的角色,那现在我们假设A是一个消费者普通用户,D是一个杂货店。A在真实世界里面几乎只会发生消费,而不会发生收款,D则相反。

A为了使用闪电网络,必须至少建立一个通道,往里面存入相应的BTC,而这部分钱就被锁死在了通道里面,A每次消费就从通道里面扣除相应的BTC。由于A只会付钱不会收钱,所以通道的余额总是减少的,当用完这部分余额A只能再建立一个通道继续重复下去。想象一下,你每个月总消费是五千块,如果你不想每个月都去开通道的话,你需要一次性存入五千块以上锁死在通道里面。这真的很蠢。

而作为D则更尴尬了。D想收钱,D和C开通一个通道,D存入了10BTC的余额,那么C-D通道的余额是多少呢?是0-10。也就是说,C如果没有主动去存入通道余额,C是没法向D转账的,换个角度看就是D永远也没办法收款!如果你是D这个杂货店老板,你想接入闪电网络,你甚至需要去求别的节点往你的通道里面存点钱!简直智障。

闪电网络在理论上所有节点都是对等的情况下表现优异,但是真实世界是有的节点只会付钱,有的节点又只会收钱,闪电网络不能满足这部分节点的需求。对于消费者,或者对于杂货店老板,闪电网络基本处于不可用的状态。那么到底还有谁能用呢?

或许机构间结算才是闪电网络的出路

比特币世界里有不少的机构,甚至说大部分BTC都掌握在机构的手里。交易所、矿池、在线钱包等占据了绝大部分的比特币。这些机构每时每刻都在产生转账。

用户经常从交易所里面提取比特币到在线钱包,也经常从在线钱包转账到交易所。用户会用在线钱包支付BTC给商家,商家也会将BTC转账到交易所换成法币。这些机构之间的转账才是比特币世界里暗潮汹涌的大部分。

链上交易成本太高,机构之间不可能每次转账都去做一次链上交易,机构间可能会签署某些协议,通过双方的约定来实现链下交易,每天或者每个月再做一次链上结算。

而这个约定,正好可以用闪电网络。闪电网络提供了一个安全可靠的智能合约,比起纸面协议,闪电网络拥有物理上的强制约束力,更加可靠和高效。

闪电网络如果被认为足够的健壮,或许机构会采用闪电网络来做结算,或许这才是闪电网络最终的归宿。

闪电网络简明教程

垃圾佬进阶之路,五千块准4k最强电脑配置

断断续续花了两年时间研究电脑配置(捡垃圾),中间换了三个平台,换了三张显卡,目前为止总算是找到一套满意的配置,算是完全体了。

算了一下总共花费的成本大概五千块钱(不含显示器,不含外设),这个价位很适合进阶玩家的装机需求。横向对比了一下,这个配置应该是五千块钱区间内适用性最广、性能最好的二手配置。

当然这里不是要追求极端性能,也不是要追求极端的低价,而是用同等的价格配置主一台各项均衡没有短板,适用性广,性能相对强劲的配置。

这篇文章里会顺便提到一些两年来总结的经验和教训,就算不参考这里的配置,也可以少走很多弯路。

五千元配置,鲁大师处理器10w分显卡29w分

项目型号价格备注
CPUE5-2689480E5服务器CPU
主板华南金牌X79538官方淘宝有质保
内存DDR3 ECC 8G*457032G内存
硬盘TEAM SSD 240G240SSD随便买
硬盘希捷 4T*2800RAID0
显卡铭瑄 Vega642200垃圾矿卡
电源长城巨龙1250W150矿机电源
以上总计4978不含显示器
显示器HKC C340带鱼屏3440*1440@100Hz2000准4k@100Hz
总计6978含显示器

上面的价格全部都是你在任何时间点,不用叠加任何优惠券,能真正买到的价格。别说什么双11我花了xxx买到了2070比你这好多了,没有意义的。

吊打显卡吧推荐配置


上图是显卡吧7千元推荐配置其一,这个配置里面i5-8400比E5-2689略弱,RTX2070比Vega64略强,总体来说性能差不多。我们的配置里去掉4T*2硬盘,去掉16G内存,就和这个图的配置性能差不多了,去掉之后价格在4000元,同等配置下比这个显卡吧推荐配置还低了3000块

拿二手矿卡和全新的比?

电脑里面有些配件二手和全新相差很小,比如CPU、内存、散热、SSD、机箱、电源,这部分配件全新和二手没有太大区别,如果二手时间很短在一年以内的话,基本可以认为没有区别。我不信你日常使用还能把CPU给用坏。

二手容易出问题的其实只有三个地方:主板、显卡、HDD

HDD这里不涉及就不说了。主板我们用的华南金牌,这是一家杂牌厂商但是提供三年质保,售后靠谱能换能修。那就只剩显卡。

是的,二手矿卡质量确实不好,你脸非常黑,没用多久显卡坏了,你重新买了一张显卡,又花了2200元,你发现就算买两张显卡价格依然小于全新的这套卡吧配置,坏之前你甚至还能交火用(我们的电源功率1250W)。两张矿卡寿命加起来总能干得过全新了,况且如果没坏你就白赚3000元,是不是很刺激。

综上所述结论就是,就算二手质量差,我坏掉的配件重新换一份,价格也和全新差不多,如果没坏,那你就赚了。

矿卡质量没这么差,这两年我一直在用矿卡,没有任何问题,至少出问题前早都性能跟不上卖掉了。

为什么要这样配

这里的原则基本就是实用至上,不会考虑花里胡哨的功能,花钱在真正有用的地方,人类通过肉眼能感受到的地方。

为什么要用服务器平台

E5系列CPU性价比高,动不动就是8核16线程,并且服务器平台可以使用ECC内存,单根8G平均在100多元非常便宜,可以轻松插满四根32G。

CPU

CPU行业近几年基本没有太大发展,或者说CPU的需求近几年没有什么增长。14年Q2发布的i7-4790k,当时2500元左右的价格,属于家用中高端产品,到现在已经五年了,毫不客气的说依然满足目前市面上的所有家用需求。买了这款CPU五年之内不用升级,甚至再过四五年都还能用。

这两年英特尔为了卖CPU开始吹核显吹功耗吹DDR4内存,实际上除了办公用户用不到核显,50w功耗125w功耗也就是五十块钱风扇的事,多用的电量等于多开一个灯,DDR4内存你也感觉不到区别。别被忽悠进去了。

这里用的CPU是E5-2689,其实还有很多选择,从一百块的E5-2620到600块的E5-2680都可以用,E5-2689可以turbo到3.6GHz,单核主频相对高一点,游戏表现会好些。

E5-2689在天梯图上分数是 13747。而比较常见的R7-1700是13752,i5-8400是
11785,这两个价格至少一千块,E5便宜了不少。

当然上面说的是多线程跑分,但就我用的实际情况来看,E5-2689并没有因为单核性能差影响游戏体验,没有哪个游戏瓶颈在这个CPU上。就连吃鸡这种垃圾优化也没看到单核瓶颈出现。都2019年了,单核性能影响游戏这个话题也该过去了

主板

主板使用的是华南金牌X79大板,华南金牌的板型没有单独命名,所以也说不清楚之前买的啥。总之500多块钱能买到SATA3、USB3.0、4内存插槽的ATX大板,满足日常使用。

主板是PC配件里面最容易坏的部分,但是官方淘宝店承诺15天退换,3年售后,不管质量怎么样至少用三年了。我这里也用了两年也没啥问题。还是之前那句话,你用坏了买一个新的,依然便宜。

内存

这里使用的 三星8G ECC REG DDR3 1333 PC3-10600R,四根8G插满,满满的32G内存。

为什么要用这么大内存?

后台进程加上几个Chrome浏览器标签页用掉了8G内存

Win10系统下,一堆后台进程,加上Chrome开了十来个标签页,就用掉了8G内存,这才基本处于待机状态,还什么都没干

如果再开一个大型游戏,会再用掉4-8G内存,如果同时在用BT下载东西,多开几个软件,很有可能会突破16G,这个时候16G内存就完全不够了。

我8G内存也用得好好的,后台进程自己多关闭就好了呀,为什么非得搞这么大?

电脑是给人用的,不是用来供着的,用个电脑还要自己去清理后台任务,加速小火箭在那点点点,电脑一卡到处去关这个关那个,玩个游戏之前连浏览器都要关了,累不累啊?

另外一方面,现代软件会尽量用掉更多内存来加速软件的运行,比如Chrome,比如Java。你给的内存越多,软件会越少去使用磁盘IO,读磁盘是很慢的,会影响使用体验。还有如果你经常使用BT或者PT下载大文件,内存可以用来做磁盘缓存,甚至可以调大到2G、4G,极大避免磁盘受损,要知道HDD的写入寿命可不长,长时间挂BT非常影响寿命。

现代操作系统,比如Windows 10,已经会使用内存来做磁盘IO的缓存,大内存会提升IO性能。所以也推荐使用Windows 10,内存加速磁盘IO效果很明显。

另外你之所以觉得8G够用,是因为系统本身有内存压缩技术,有内存交换区技术,在你内存不够用的时候用各种方法给你强行怼起来了。但这样是有代价的,比如内存压缩技术会让你长时间不用的进程突然打开会卡顿,交换区技术用磁盘来做内存有多慢更是可想而知。

现在手机都配8G甚至11G内存了,内存只会越来越用得多,32G并不大。

还在用DDR3?

其一,新的 DDR3 内存价格比 DDR4 便宜不了多少,因此想装全新机请买 DDR4。以威刚旗舰店的万紫千红为例,DDR3 1600 4G 单条售价 169,8G 是 359;DDR4 2400 4G 单条售价 209,DDR4 2666 8G 单条售价 379。
其二,二手 DDR3 内存价格十分便宜,适合垃圾佬,不过建议选择金士顿威刚等大品牌。仍以威刚万紫千红为例,二手的 DDR3 1600 4G 单条售价 100,8G 是 203。装机四大件里,内存使用寿命是仅次 CPU 排第二的,在能保证兼容点亮的前提下,买二手内存是一个不错的选择。
其三,DDR3 和 DDR4 常态下对游戏玩家影响不大。主流游戏里个人测试出最明显的也就是吃鸡了,同样 i5 8400 搭配 GTX 1060 5G 的组合,两个 8G DDR4 2666 的平均帧数,能比两个 8G DDR3 1600 高不到 10;最低帧数的区别 则只有 2,可以无视。如果处理器和显卡都没到位,这个差距估计还会更小,吃鸡这游戏是显卡 > 内存容量 > 处理器 > 内存频率的。
其四,如果是做专业办公,DDR4 的优势我猜测会比较大。我并没有做过很多专业办公,只会写写前端代码,但我的 15 款 MBP(DDR3 1866)跑 WebStorm 的速度总要慢我同事的小米 Pro(DDR4 2400)不少,何况 Mac 系统还有着传说中的神优化。当然也有可能是我的 u 太慢了,不敢打包票,如果有误请指出。

转载自知乎 https://www.zhihu.com/question/57270200/answer/568847010

上面这段是知乎的高票回答,大概意思就是DDR3和高频DDR4区别,在吃鸡上就是2帧(看最低帧数,平均帧数没有意义)。而我们这里用的内存一根100块,DDR4-2400 300块起步,四根就差了一千块,一千块用来升级显卡提升可不止2帧。

使用高频双通道DDR4内存,核显性能会有很大提升,除此之外没有看到任何优势。大概可以说DDR4基本没有卵用

显卡

N卡功耗低、稳定、价格贵。A卡功耗高、品控差、价格便宜,这是普遍规律。

N卡最近也喜欢玩点花的,RTX系列最近搞出来光追、 DLSS这种听起来很棒的技术,实际上你并用不到。

光追就是让目前有限的几款游戏场景光照效果更酷一点,并且老游戏永远也不可能支持。DLSS就是把分辨率调小再通过深度学习来放大,看评测糊成屎并且只支持4k,也基本处于不可用的状态。这和英特尔卖核显的道理一样,都是没什么卵用的东西,只有帧数才最影响体验,提升帧数才是硬道理

我这里是从闲鱼买的18年初生产的AMD Vega64矿卡,没错这是一张电老虎,功耗高达300w,性能和1080ti、2070差不多,但是价格便宜很多。

另外AMD的HBM2对高分辨率有不小的提升,要按2k、4k分辨率来思考问题,都2019年了,别用1080p了。

矿卡不会质量很差?

上面也解释了,如果你担心质量,省下来的钱可以再买一张。如果没有BOOM,那恭喜你赚了一张显卡钱。

矿卡没有这么妖,其实就是满负载运行了一段时间而已,所以这个时间就很重要了。Vega64可以通过SN号来判断生产时间,我这张卡是18年2月生产,也就是说生产出来才一年,挖矿时间只能少于一年。一年以内的矿卡问题不大。

币价崩成这样,很多矿老板自己也急于出手回血,矿老板也是人也要生活的嘛,一听矿卡就妖魔的要摆正心态。

在闲鱼交易的话,尽量挑一下卖家的芝麻分,贵重物品比如显卡尽量买700分以上的,会少很多麻烦。

买回来之后记得跑一下各种压力测试,能烤个半小时都没问题基本也就没问题了。

AMD独特的黑科技

平常看NVIDIA吹逼比较多,其实AMD也有不少科技,举两个例子:

Freesync(需要显示器支持)

Freesync开启前和开启后

开启Freesync之后可以有效平滑帧数,减少画面撕裂,对FPS玩家影响很大。 NVIDIA也有类似技术叫做Gsync效果差不多,同样也需要显示器支持。不过NVIDIA对显示器厂商会收取授权费,所以市面上Gsync显示器比较少而且贵,AMD的Freesync就是很好的平价之选了。

https://zhuanlan.zhihu.com/p/37891421?utm_source=qq&utm_medium=social&utm_oi=30179707584512

视频插帧

插帧技术可以强行把24帧的视频补到60帧,在类似于在移动的汽车内看窗外的场景中会感受到非常大的区别,不会再像幻灯片一样卡顿。对于动漫画面更是效果极好,用了就回不去。

https://www.bilibili.com/read/cv318180/

A卡电费够我买张新卡了?

显卡功耗实际上要分两种,一个是待机功耗,一个是满载功耗。

一般来说不玩游戏基本上显卡风扇都不会转,处于频率极低的待机状态。Vega64的待机功耗是20w,RTX2070是15w,也就是说你刷网页的时候用Vega64还是用RTX2070其实区别不大,也就5w的差别,还不够充个手机电。

Vega64满载功耗大概是300w,2070大概是220w,差80w。按每天满载游戏4小时算,一年能用365*4*80/1000=116.8kwh,也就是116度电,按电价五毛算,恭喜你用RTX2070一年节省了50多块钱。

电源

转化率是什么东西?转化率就是输入500w电输出400w电算作80%转化率。可以看到转化率越高浪费的电越少。

80Plus把转化率分为了从铜牌银牌金牌到白金牌钛金牌几个档次,最低的铜牌转化率是85%,最高的钛金牌是96%(这里都指的是50%典型负载下)。如果你从铜牌升级到钛金牌,恭喜你节省了11%的电,按整机400w功耗算节省了40w,一年少花25块钱。但是从钛金牌电源比铜牌电源贵了好几倍,得不偿失。

我负责任的说吹嘘高转化率的80Plus认证对消费者来说卵用没有,基本可以忽略

矿老板都信任的电源你不信任?

这里我用了二手长城巨龙1250W电源,也是闲鱼收的。道理很简单,矿老板全都在用这个电源,矿老板几万块钱的显卡在上面挂着,电源好不好矿老板自己心里清楚,这比什么评测都靠谱。

另一方面不要老是听说电源炸了整机都没了这种话,大多数情况下电源炸了也是自己电容爆了,影响机器还是少。

1250w电源够大,甚至还能双路Vega64交火,一步到位。

硬盘

SSD

杂牌SSD随便挑评价好的买就好了,不必要上很好的牌子。SSD比HDD寿命长很多,可以不用太在意寿命这回事。

从30M写入速度的HDD提升到150M的杂牌SSD区别非常大,但是从150M的杂牌SSD提升到300M的高端SSD其实并不明显,至少除了跑分你都感觉不到,多花点钱在刀刃上。

同理M.2也是,不追求体积没有必要买。

HDD

这里专门把4T*2的HDD放在配置清单里了,其实不用这么大磁盘就能少800块钱。

现在一个游戏动辄就是上百G,一部蓝光电影就是50G,8T硬盘真的不算什么。Windows 10自带了软RAID,一次性买两块4T盘组RAID0,一步到位。

为什么要买4T盘呢,因为目前4T是HDD所有容量里面性价比最高的,2T和8T都不如4T。

RAID0挂一块盘就全挂,风险更大,但是其实还好,HDD用三四年还是能用的。重要数据放云盘,别放本地。我们内存很大,你可以多开好几个云盘。

显示器

显示器放在最后,因为这里说的五千块没有包含这个显示器,只是做一个参考。

我这里用了HKC C340,一个3440*1440@100Hz的垃圾带鱼屏,支持Freesync,只用2000块钱。

纸面参数很美好但是问题很多,颜色不对、品控差、嘎吱作响、有坏点、板载固件有问题,需要在京东来回换货多折腾几次才能换到各方面正常的。有时间可以多折腾几次,毕竟还是便宜了好多。

WP-AutoPost破解版支持百度翻译

WP-AutoPost是什么

WP-AutoPost是一个著名的WordPress插件,简单的说他是一个爬虫程序,你可以通过WP-AutoPost自动采集网站,自动翻译,自动发布文章。WP-AutoPost实现了零代码编写,完全通过界面来配置采集规则 ,实测下来效率很高也很准确,实用性很强。

WP-AutoPost最新破解版

目前WP-AutoPost比较新的版本是3.7.7,测试支持目前最新的WordPress 4.9.8。

下载地址:http://down-www.7down.net/pcdown/soft/xiazai/wp-autopost.rar

该版本已经破解,解压后把里面的wp-autopost-pro文件夹拷贝到WordPress插件目录下即可。

修复百度翻译功能

遗憾的是,这个版本WP-AutoPost集成的百度翻译接口已经很老了,百度官方已经停止支持,只能通过修改代码来实现百度翻译功能。

注册百度翻译API

老的翻译API已经停止服务下线了,我们需要迁移到新的翻译API。

新的百度翻译API官方介绍:http://api.fanyi.baidu.com/api/trans/product/prodinfo

注册之后开通通用翻译API,在开发者页面你会得到一个appid和key(密钥),记下这两个值后面会用到。

修改代码实现翻译

有三个地方需要修改,一个是百度翻译类,一个是百度翻译表单,一个是核心function。

修改百度翻译类

文件名:wp-autopost-utility-class.php

主要修改了调用的API地址,和参数结构。以前是传api_key,现在要传appid和key,并且要加盐之后计算md5。

找到autopostBaiduTranslator类,这个类有个translate方法,修改后的translate方法:

    public static function translate($src_text, $fromLanguage, $toLanguage, $appid, $key, $GET = false)
    {
            try
            {
                    $translateUrl = "http://api.fanyi.baidu.com/api/trans/vip/translate";
                    $postData = array();
                    $postData['q'] = $src_text;
                    $postData['from'] = $fromLanguage;
                    $postData['to'] = $toLanguage;
                    $postData['appid'] = $appid;
                    $postData['salt'] = rand(1111,9999);
                    $postData['sign'] = md5($appid . $src_text . $postData['salt'] . $key);
                    $curlResponse = self::curlRequest($translateUrl, $postData);
                    $re = json_decode($curlResponse);
                    $translated = array();
                    if (isset($re->error_code))
                    {
                            $translated['err'] = $re->error_msg . '(' . $re->error_code . ')';
                            switch ($re->error_code)
                            {
                                    case '52001': $translated['err'] .= '[Time Out]';
                                            break;
                                    case '52002': $translated['err'] .= '[The translator system error, try later]';
                                            break;
                                    case '52003': $translated['err'] .= '[Unauthorized, please check your API Key]';
                                            break;
                            }
                    }
                    else
                    {
                            $translated['trans_result'] = array();
                            foreach($re->trans_result as $trans_result)
                            {
                                    $translated['trans_result'][] = $trans_result->dst;
                            }
                    }
                    unset($curlResponse);
                    return $translated;
            }
            catch (Exception $e)
            {
                    $translated['err'] = "Exception: " . $e->getMessage();
                    return $translated;
            }
    }

可以看到这里修改了参数,从api_key改到了appid和key,后面要用到

修改表单代码

文件名:wp-autopost-translator-baidu.php

这个文件主要是百度翻译设置项的表单等,看到有api_key的地方,都改到appid和key就好,例如以前是:

if(isset($_POST['save_setting'])&&$_POST['save_setting']!=''){
$BaiduTransOptions['api_key'] = trim($_POST['api_key']);
update_option( 'wp-autopost-baidu-trans-options', $BaiduTransOptions);
$BaiduTransOptions = get_option('wp-autopost-baidu-trans-options');
}

修改到:

if(isset($_POST['save_setting'])&&$_POST['save_setting']!=''){
$BaiduTransOptions['appid'] = trim($_POST['appid']);
$BaiduTransOptions['key'] = trim($_POST['key']);
update_option( 'wp-autopost-baidu-trans-options', $BaiduTransOptions);
$BaiduTransOptions = get_option('wp-autopost-baidu-trans-options');
}

后面还有几个地方要改,以此类推,请自行修改

核心wp-autopost-function.php修改

最后是WP-AutoPost插件的核心文件wp-autopost-function.php,这个文件加密过,修改起来比较难受。

要改这个文件是因为这里调用到了autopostBaiduTranslator::translate(),这个方法已经被我们修改过,改变了传参,所以这里也要跟着修改。

全文搜索autopostBaiduTranslator::translate,一共有三处地方需要修改,每个地方加密后的字符串不大一样,需要挨个处理。

\x61\x70\x70\x69\x64是appid这5个字母的hex编码,\x6b\x65\x79是key这3个字母的hex编码。

把传参从translate(…, api_key)改到translate(…, appid, key)就好,比如最后一处translate修改之后如下:

autopostBaiduTranslator::translate(${${"G\x4cO\x42\x41\x4cS"}["\x7a\x65\x6bs\x70\x6f\x7a\x6a"]},${${"\x47\x4c\x4f\x42\x41LS"}["j\x66\x76\x6bcbv\x76\x79\x76\x78"]}[1],${${"GL\x4f\x42\x41L\x53"}["\x6a\x71n\x72\x73p\x63\x6f\x79\x6e"]}[2],${${"G\x4c\x4f\x42A\x4c\x53"}["l\x72\x75\x68\x67\x63"]}["\x61\x70\x70\x69\x64"],${${"G\x4c\x4f\x42A\x4c\x53"}["l\x72\x75\x68\x67\x63"]}["\x6b\x65\x79"]);

上面都修改完之后,填入相应的APPID和Key,百度翻译就可以正常使用了。文章自动抓取自动翻译也能正常工作。

深圳电信开启IPv6支持

为什么要开启IPv6

开启IPv6其实并没有什么卵用,大部分情况下根本用不上IPv6。不过还是有几个场景能用上:

  1. 家用摄像头、远程下载控制等。给每个内网设备分配一个IPv6地址,可以供公网访问。
  2. 访问IPv6 only的网站,比如北邮pt站等。
  3. 用IPv6联机。双方都有IPv6,且游戏支持IPv6的情况下,可以直接填IPv6地址来联机,不用再打通网络。
  4. 有了IPv6显得自己很时尚

如何开启IPv6

工信部强推下,2018年国内三大运营商大部分已经支持IPv6。但是光猫上一般不会默认开启IPv6,需要进行一些设置。

深圳电信开通IPv6已经非常容易,只需要打开光猫改几个配置就好。别的地区,移动联通等运营商基本同理,也可以参考。

开启IPv6需要的条件

  1. 光猫支持,取决于运营商
  2. 该地区已有IPv6资源,取决于运营商
  3. 路由器具备IPv6功能,华硕梅林等常见固件的较新版本都支持
  4. 上网设备具备IPv6功能,Android、iOS、Linux、Windows近几年的版本都支持

修改光猫配置,支持IPv6并开启桥接

光猫背面会有写管理地址,一般是192.168.1.1之类的,打开管理页面。

通过超级账号登录,一般来讲账号是admin,密码nE7jA%5m。注意光猫背面写着的账号密码并不是超级账号,只是普通账号,权限不够,这里我们要用的是超级账号。

如果登录不上,常见的超级账号还有:telecomadmin 、 useradmin 、 admin,常见密码:nE7jA%5m 、 admin,都可以试一下,实在不行在网上搜一下你所在地区的超级账号密码是多少。

如果上面的方法都登录不上,可以参考:

用电信天翼网关背后的useradmin 帐号和密码登录 http://192.168.1.1
下载http://192.168.1.1/backupsettings.conf
用记事本打开,找到telecomadmin+8位数,这个就是你电信天翼网关超级用户的密码
注:有些机型的超级账户是 useradmin

引用自http://bbs.mo2g.com/thread-675-1-1.html

通过超级账号登录上之后,会来到这样的古朴的界面:

具有最高权限的电信光猫管理界面

但是如果你进去之后是下面这种酷炫的界面,说明是普通账号,权限不够:

天翼网关普通用户界面

通过超级账号登录之后,打开网络-宽带设置,记住你的Internet项的VID,我这里是41。

把之前的INTERNET删掉,再新建一个INTERNET,按下图配置,记得填上自己的VID。

IP模式是IPv4&IPv6,连接模式是桥接。这样就达到了目的。

电信光猫IPv6和桥接的配置

配置路由器,获取IPv6地址

光猫改到桥接模式之后,需要用路由器来拨号,将你的路由器配置为PPPoE模式,填上ADSL账号,确保能够正常上网。

以Merlin固件为例,打开IPv6,按如下配置就能获取到IPv6地址:

路由器IPv6配置

系统记录-IPv6 里面能看到IPv6地址的分配情况,可以看到IPv6运行在DHCP-PD模式,路由器已经拿到了IPv6地址,局域网设备也都分配到了一个IPv6地址。

DHCP-PD是比较常见的模式,目前看到的运营商都是采用这个模式,可能也会有不同。多折腾一下就好。

路由器获取IPv6地址成功

检查设备IPv6地址,测试连接状况

以Mac为例,网络-TCP/IP 里面能看到IPv6地址,代表获取成功。

有时候可能会看到fe80开头的地址,这种是内网地址,并不是获取到了公网IPv6地址,不能以此作为判断依据。

Mac网络配置里看到已经获取到IPv6地址

http://ipv6-test.com测试到IPv6已经正常连通:

IPv6测试已经连通

IPv6的注意事项

目前三大运营商固网对IPv6依然还在测试状态,并没有正式启用,按这个教程不一定能配通,可能会遇到各种各样的问题。比如获取不到IPv6地址,获取到地址之后不能上网等。

IPv6的国内路由还很糟糕,例如北京教育网IPv6到全国大部分地区都会绕美国HE,延迟在200ms以上,不建议使用。

IPv6海外出口带宽很糟糕,不建议用来访问海外网站。

在同时有IPv4和IPv6地址的情况下,主流浏览器并不会选择IPv6地址,可以放心。

⚡️闪电网络简明教程

闪电网络是什么

闪电网络是目前比特币的一个发展趋势,它解决了比特币的小额高频转账的问题。

比特币实现了区块链账本,通过算力竞争的方式实现账本的一致性,这种方式注定了账本的使用成本高、速度慢、容量小。目前比特币主网的处理速度上限大概是7TPS,也就是一秒钟只能处理7次转账。比特币的出块速度是每10分钟出一次块,为了保证安全一般把转账确认设置为6个区块,也就是说一次转账至少需要60分钟才能被彻底确认。比特币作为区块链账本毫无问题,但是要用作小额高频支付工具力不从心。

为了解决这些问题,产生了许多技术方向,例如ETH目前要上线的PoS、EOS独创的DPoS、IOTA的tangle等,另外就是今天要说的闪电网络Lightning Network。(说句题外话,扩容区块只是一个临时缓解的办法,并没有解决根本问题。就算区块大小扩容十倍,7TPS也顶多到70TPS而已,依然非常低)

闪电网络依赖隔离见证(SegWit),隔离见证在2017年8月被主网确认正式生效。隔离见证有两个用处,一是变相扩容了区块(几乎等效于区块大小从1M扩容到2M)、二是为闪电网络提供底层支持。有了隔离见证,闪电网络就具备可行性了。

2017年12月6日,闪电网络协议规范RC1版本发布,同时ACINQ,、Lightning Labs、Blockstream三个团队正在着手进行软件开发。

截止到2018年7月,这三个团队都分别发布了闪电网络节点软件,还上线了第一款钱包eclair发布在Google Play。

目前闪电网络主网上运行的节点数量有2837个,处于Active状态的Channel有10042个,闪电网络总共托管了94.40BTC。这个数字每天都在增长,你可以在1ML看到具体数字。

知名网站CoinGate已经支持闪电网络支付,另外还有几家网站(Bitrefill、Blockstream、HodlMonkey、TorGuard)也支持了闪电网络。闪电网络目前的状态是几乎已经正式上线,虽然开发者警告不要放太多钱进去以防丢失。我们可以认为闪电网络已经不会再有大改动。

闪电网络的原理

闪电网络通过引入智能合约的思想来完成交易。通过事先约定的智能合约,将大量的交易放在链下进行,不受区块链速度的限制,只将最终的确认环节放在链上。这样大大提升了交易速度。

闪电网络的基础是隔离见证(SegWit),隔离见证在2017年8月被主网确认正式生效。隔离见证有两个用处,一是变相扩容了区块(几乎等效于区块大小从1M扩容到2M)、二是为闪电网络提供底层支持。有了隔离见证,闪电网络就具备可行性了。

闪电网络通过的核心概念可以分为两大块,其一是RSMC(Recoverable Sequence Maturity Contract),用来完成两个节点之间的交易确认,其二是HTLC(Hashed Timelock Contract),用来将多个节点连接成一个网络,实现跨节点支付。

RSMC:实现两个节点之间的交易确认

首先假定交易双方之间存在一个“微支付通道”(资金池)。交易双方先预存一部分资金到“微支付通道”里,初始情况下双方的分配方案等于预存的金额。每次发生交易,需要对交易后产生资金分配结果共同进行确认,同时签字把旧版本的分配方案作废掉。任何一方需要提现时,可以将他手里双方签署过的交易结果写到区块链网络中,从而被确认。从这个过程中可以可以看到,只有在提现时候才需要通过区块链。

任何一个版本的方案都需要经过双方的签名认证才合法。任何一方在任何时候都可以提出提现,提现时需要提供一个双方都签名过的资金分配方案(意味着肯定是某次交易后的结果,被双方确认过,但未必是最新的结果)。在一定时间内,如果另外一方拿出证明表明这个方案其实之前被作废了(非最新的交易结果),则资金罚没给质疑方;否则按照提出方的结果进行分配。罚没机制可以确保了没人会故意拿一个旧的交易结果来提现。

引用自:https://yeasy.gitbooks.io/blockchain_guide/content/bitcoin/lightning_network.html

简单来说,通过RSMC实现了两个节点之间的交易确认:

  1. A创建和B的支付通道Channel
  2. A投入准备金100元
  3. A给B转账实际上是在扣除准备金,A可以多次给B转账(发生在链下,不用区块确认)
  4. A或者B关闭闪电网络通道,进行提现,闪电网络将A、B的最终余额写入链上

可以看到转账都发生在链下,只有关闭通道才会产生一次链上交易

HTLC:将多个节点连接成一个网络,实现跨节点支付

可以看到,RSMC实现了两个节点之间的交易,但在现实场景中这显然不够。举个例子:

消费者A要在B、C、D网站上买东西,A要分别开通到B、C、D的交易通道,每个通道都要存入一定的准备金。如果A只和B交易一次就关闭通道,那实际上闪电网络并没有降低交易成本。

这个时候HTLC就应运而生了,HTLC实现了将闪电网络上的节点连接成一个网络,一笔交易可以路由经多个节点最终到达目的。

微支付通道是通过 Hashed Timelock Contract 来实现的,中文意思是“哈希的带时钟的合约”。这个其实就是限时转账。理解起来也很简单,通过智能合约,双方约定转账方先冻结一笔钱,并提供一个哈希值,如果在一定时间内有人能提出一个字符串,使得它哈希后的值跟已知值匹配(实际上意味着转账方授权了接收方来提现),则这笔钱转给接收方。

不太恰当的例子,约定一定时间内,有人知道了某个暗语(可以生成匹配的哈希值),就可以拿到这个指定的资金。

推广一步,甲想转账给丙,丙先发给甲一个哈希值。甲可以先跟乙签订一个合同,如果你在一定时间内能告诉我一个暗语,我就给你多少钱。乙于是跑去跟丙签订一个合同,如果你告诉我那个暗语,我就给你多少钱。丙于是告诉乙暗语,拿到乙的钱,乙又从甲拿到钱。最终达到结果是甲转账给丙。这样甲和丙之间似乎构成了一条完整的虚拟的“支付通道”。

引用自:https://yeasy.gitbooks.io/blockchain_guide/content/bitcoin/lightning_network.html

简单来说:

  1. A需要转账50给C
  2. A和B有交易通道(余额大于50),B和C有交易通道(余额大于50)
  3. A -> B -> C,交易完成

换成刚才那个例子:

消费者A要在B、C、D网站上买东西。消费者A和一个比较大的节点Z开通通道,网站B、C、D也和这个大节点Z开通通道。交易得以完成。消费者A只需要和Z打通,不需要关心网站BCD,网站BCD也只需要和Z打通不需要关心消费者A。

HTLC机制可以扩展到许多节点的场景,这里的节点Z并不一定就是同一个节点,只要闪电网络最终能找到一条可用的通道就能完成支付。可以是A->Z1->Z2->Zn….->B。

你可以在这里看到目前闪电网络的节点连接情况:https://lnmainnet.gaben.win/

HTLC的路由和手续费机制

开通通道需要存入准备金,一个足够大的节点需要大量的准备金来维持交易。目前最大的节点LN.SHITCOIN.COM已经存入了43.79478257BTC,大概是30万美元。节点不可能无偿提供服务,闪电网络设计了一套手续费体系来维持闪电网络的运行。

闪电网络上的每一个节点,都可以设置自己的手续费(fee)大小。

如果节点Z1设置了手续费1元,Z2设置了手续费2元,A->Z1->Z2->B这条支付路径里,A就需要额外付给Z1 1元,Z2 2元。

闪电网络的交易通常不只有一条通路,可能有很多条。客户端在发起支付之前可以通过getroute方法来确定每条通路的手续费情况,可以选择一条最便宜的通路来完成交易。

闪电网络的节点充满竞争,手续费太高可能造成你的节点无人使用,闪电网络节点理论上都会维持在一个相对低廉的手续费水平。

笔者通过闪电网络支付了一个在线轮盘赌网站,共花费手续费0.0000000204BTC,大概等于0.001元人民币。挑选一个手续费低的节点还能做到更低。就目前来看闪电网络的转账手续费几乎可以忽略不计。

体验闪电网络:eclair

闪电网络拥有一套完整的协议规范,在2017年12月发布了RC1版本。现在常见的闪电网络节点软件都是按照协议规范书写的,运行在同一个闪电网络上,可以互相兼容。

eclair是ACINQ团队创造的闪电网络程序,涵盖了Windows、Linux、macOS、Android平台。

桌面平台:https://github.com/ACINQ/eclair

安卓平台:https://github.com/ACINQ/eclair-wallet

以安卓为例,下载安卓钱包客户端:https://github.com/ACINQ/eclair-wallet/releases

朝eclair钱包充值一定数量的BTC(不要充值太多)

创建一个通道,这里可以选择ACINQ团队的官方通道,存入一定数量的BTC(不用担心,这里输入的金额只是通道保证金,随时可以取回)

选择一个收款方测试支付是否成功(因为手续费极低,可以测试转账一毛两毛的)

可以在这个网站搏一搏运气,最低支付一元钱:https://www.lightningspin.com/

以上是闪电网络钱包的使用方法,非常简单方便。

搭建一个自己的闪电网络节点

如果你不满足只是使用闪电网络,你还可以自己搭建一个闪电网络节点,参与到闪电网络中来,并且收取转账手续费。

一、购买云主机并安装Docker

除了临时测试外,不推荐使用自己的PC来搭建节点,一是因为国内网络环境恶劣造成很大麻烦,二是因为闪电网络的机制要求节点随时在线,长时间不在线容易被攻击。

运行比特币全节点需要磁盘空间在200G以上,并且这个大小还在持续增长。

以Vultr为例,购买NJ节点5$方案+20$的200G磁盘,月付25$。Vultr常年有新用户注册优惠活动,通过邀请链接注册送20$,足够跑一个月:https://www.vultr.com/?ref=6897056 (注意需要双币信用卡)

在Vultr购买主机可以选择预装Docker。需要自己安装Docker可以相应教程。

二、运行比特币全节点

clone项目到本地,编译bitcoind docker镜像

git clone https://github.com/dougvk/lightning-node.git
cd lightning-node
docker build . -t dougvk/bitcoind

运行bitcoind

mkdir -p /scratch/bitcoin/mainnet/bitcoind
docker run --name bitcoind_mainnet -d -v /scratch/bitcoin/mainnet/bitcoind:/data -p 8333:8333 -p 9735:9735 dougvk/bitcoind:latest

这样就启动了比特币全节点。比特币的数据文件存在了/scratch目录下。这个命令暴露了两个必要的对外端口8333和9735,不用担心,RPC端口并没有被暴露。

节点启动之后就开始了同步过程,需要同步180G左右的数据,大约需要12h。

通过这个命令可以查看同步进度:

docker run --rm --network container:bitcoind_mainnet -v /scratch/bitcoin/mainnet/bitcoind:/data dougvk/bitcoind:latest bitcoin-cli getblockchaininfo
{
  "chain": "main",
  "blocks": 532914,
  "headers": 532914,
  "bestblockhash": "0000000000000000001f2deba673d0bb65ac20a3690240324b0bb6bfe9286e23",
  "difficulty": 5178671069072.251,
  "mediantime": 1532152533,
  "verificationprogress": 0.9999936154754053,
  "initialblockdownload": false,
  "chainwork": "0000000000000000000000000000000000000000026ea366193d216bb3d37ef4",
  "size_on_disk": 200991969130,
  "pruned": false,
  "softforks": [
    {
      "id": "bip34",
      "version": 2,
      "reject": {
        "status": true
      }
    },
    {
      "id": "bip66",
      "version": 3,
      "reject": {
        "status": true
      }
    },
    {
      "id": "bip65",
      "version": 4,
      "reject": {
        "status": true
      }
    }
  ],
  "bip9_softforks": {
    "csv": {
      "status": "active",
      "startTime": 1462060800,
      "timeout": 1493596800,
      "since": 419328
    },
    "segwit": {
      "status": "active",
      "startTime": 1479168000,
      "timeout": 1510704000,
      "since": 481824
    }
  },
  "warnings": ""
}

blocksheaders数量一致代表同步完成

三、运行闪电网络节点

这里选择了clightning这个节点程序,运行节点(命令里可以设置节点名和颜色):

mkdir -p /scratch/bitcoin/mainnet/clightning
docker run --rm --name lightning --network container:bitcoind_mainnet -p9735:9735 -v /scratch/bitcoin/mainnet/bitcoind:/root/.bitcoin -v /scratch/bitcoin/mainnet/clightning:/root/.lightning --entrypoint /usr/bin/lightningd cdecker/lightningd:master --network=bitcoin --alias yournodename --rgb aa381e --announce-addr 本机ip --bind-addr 0.0.0.0 --log-level=debug

创建一个lightning-cli的命令,写入文件/usr/local/bin/lightning-cli

#!/usr/bin/env bash
docker run --rm -v /scratch/bitcoin/mainnet/clightning:/root/.lightning --entrypoint /usr/bin/lightning-cli cdecker/lightningd:master "$@"

添加执行权限

chmod +x /usr/local/bin/lightning-cli

通过getinfo可以看到闪电网络节点的运行状况

lightning-cli getinfo

到这里闪电网络节点已经启动成功

四、给闪电网络钱包充值

执行命令lightning-cli newaddr生成一个充值地址

{ "address" : "1Cd6C8i6sc1ZReskWWGHJRXvSnvM3277qz" }

朝这个地址转账适量的BTC,等待比特币网络的6次确认,设置适当的手续费一般在60分钟左右。等充值被确认了以后就可以开始创建通道了。

五、创建闪电网络通道

你可以通过这个网站来找到你想连接的节点:https://1ml.com/

或者你也可以连接我创建的节点,执行命令进行连接:

lightning-cli connect 02ed9102fe81a117b19f0c1fe0586536a04c962838677dcdb762aeb9804d9f33c7@5.135.180.50:9735

查看你连接过的节点状态:

lightning-cli getpeers

设置一个合理的手续费(这个手续费用作闪电网络合约的创建):

bitcoin-cli settxfee 0.00005

你可以查看当前的手续费水平,选择一个合适的值。如果是5sat/B,这里应该设置为0.00005。

手续费参考:https://p2sh.info/dashboard/db/fee-estimation

设置完后续费之后就可以开启通道了,开启通道需要设置准备金的数量:

lightning-cli fundchannel 02ed9102fe81a117b19f0c1fe0586536a04c962838677dcdb762aeb9804d9f33c7 20000

会返回一个txid,通过txid可以查看通道开通的进度,经过6次确认之后通道就正式开通了。

六、测试支付

同样,你也可以找个网站支付几毛钱测试一下能否成功

lightning-cli pay xxxxxxxx

通过lightning-cli getpeers命令可以查看当前通道的情况和剩余的BTC

七、查看并分享你的节点

顺利的话你的闪电网络节点已经创建成功了。

如果你和闪电网络任意一个节点创建过通道,你应该能在1ml.com上搜索到你的节点信息(可能需要过几个小时的同步时间)

https://1ml.com/node/02ed9102fe81a117b19f0c1fe0586536a04c962838677dcdb762aeb9804d9f33c7

通过lightning-cli getinfo 能查看本机节点信息,拼成id@ip:port的形式分享给别人,别人就能通过connect命令连上你的节点,比如我的节点:

02ed9102fe81a117b19f0c1fe0586536a04c962838677dcdb762aeb9804d9f33c7@5.135.180.50:9735

别人的转账路由经过了你的节点,就会向你支付一定的手续费。当然你也可以随时调整这个手续费。

0. 概览和基础原理 – 应用层通信原理与排错指南

微服务(Microservices)的兴起导致了系统的拆解、分离,以往的单个大型系统被拆分成多个单一职责的小型功能模块,模块拥有自己独立的进程和数据库,每个模块都是一个完整的小服务。

模块和模块之间需要相互通信,成熟的系统架构中应用层间通信至少涉及到三大块:服务发现、具体通信协议、负载均衡(容灾)。不仅在复杂的系统中,在你执行一次curl命令的时候你也能感受到他们的存在,通常一次curl请求至少包含了:DNS请求、HTTP协议、Nginx转发。

本文不准备学究式的去讨论技术实现,而是希望从实践的角度去讲解常见的应用层通信方式的原理和排错方法。

适宜读者:

  1. 平常只管开发的程序员
  2. 想要搞清大概原理的产品经理
  3. 还没入门的运维

 

一、互联网通信的基石:TCP/IP模型

四层简化协议的封装顺序

TCP/IP网络模型是一个金字塔结构,层层封装,越往上越应用,越往下越底层。

我们可以将这个模型简化一下,将网络连接层和传输层合起来看,四层模型中你只需要关注这两个:网络连接层+传输层(TCP/UDP + IP)、应用层(HTTP、DNS)。

应用层在传输层之上,应用层负责传输业务数据,传输层负责转发数据包。

(因为几乎不会将TCP/IP分开使用,本文统一将网络连接层和传输层合并成为传输层或者四层

二、传输层 TCP/UDP

当一条数据需要发送出去,数据包一层一层打包封装,封装到传输层的时候,数据包里都有什么信息呢?

以UDP为例,UDP/IP的报文逻辑上可以总结为这样:

UDP/IP报文简化逻辑图

可以看到,传输层UDP/IP只关心来源目的的地址和端口,只负责将数据从来源发送到目的,不会有任何别的逻辑。

另外,比起UDP,TCP保证了数据顺序的一致和报文传输的可靠,简单的说就是UDP只管将报文发出去,而TCP会保证发送的报文的先后顺序、保证每个报文都发送到位,除此之外TCP和UDP没有本质区别。

总的来看,TCP和UDP都是实现了以来源地址、来源端口、目的地址、目的端口构成四元组,将报文从来源发送到目的。

三、应用层 (以HTTP为例)

HTTP和TCP/IP的关系

HTTP协议和TCP/IP协议关系如图,TCP包的内容包着整个HTTP协议包,这里我们先不考虑分段传输等。接下来几篇文章中将着重介绍HTTP协议。

HTTP 协议中自定义返回码描述字段

HTTP 协议中每一个 Response 都有一个 Status Code,协议中预定义了若干状态码例如:

200 OK

301 Moved Permanently

404 Not Found

返回码由服务器控制,有些特殊场景下服务器会定义一些特殊返回码来表示返回状态。例如CDN服务商可能会返回自定义的5xx状态码作为回源失败的错误码。

除了状态码,状态码后面的描述其实也是包含在了 HTTP 协议里面,能够自定义返回,例如这是一个腾讯云的彩蛋页面:

HTTP 返回419状态码

HTTP 返回419状态码

http://cloud.tencent.com/419

 

HTTP 返回419状态码

HTTP 返回419状态码

抓包可以看到服务器返回了

HTTP/1.1 419 For One Night

这个419 For One Night当然是这帮工程师想出来的无聊的彩蛋页面的状态码了。

那么如何实现返回自定义状态码描述呢,在PHP里面可以通过header函数实现:

header(‘HTTP/1.1 419 For One Night’);

当然也不是服务端返回什么客户端就用什么,大部分客户端会优先使用预定义描述,也就是在HTTP标准里定义过的状态码描述客户端都会直接用,服务端返回一个非法描述客户端是不会认可的。

那么自定义状态码描述又有什么用呢,当然并没有什么卵用。

Flask路由使用装饰器的问题

需要实现验证用户登录的功能,考虑用装饰器实现:

def check_permission(func):
    def _check_permission(**args):
        #do check...
        return func(**args)
    return _check_permission

@app.route('/routea')
@check_permission
def a():
    pass

@app.route('/routeb')
@check_permission
def b():
    pass

当@check_permission只有一个时可以正常使用,但是超过一个就会报错:

AssertionError: View function mapping is overwriting an existing endpoint function: _check_permission

这样的错误是因为Flask在注册路由的时候使用了函数的名字,这个例子中是a和b,使用装饰器后a、b两个函数的名字都变成了_check_permission,造成冲突,提示overwriting。解决方法是加上@wraps():

from functools import wraps
def check_permission(func):
    @wraps(func)
    def _check_permission(**args):
        #do check...
        return func(**args)
    return _check_permission

@app.route('/routea')
@check_permission
def a():
    pass

@app.route('/routeb')
@check_permission
def b():
    pass

Python自带辅助库functools中的@wraps装饰器能够改变函数的__name__等,解决问题。具体原理参考下面:

http://coolshell.cn/articles/11265.html
http://stackoverflow.com/questions/19261833/what-is-an-endpoint-in-flask

补充:
完事之后才发现官方文档已经介绍过这个方法了,事实证明我是对的……

http://docs.jinkan.org/docs/flask/patterns/viewdecorators.html

没钱就用Arch!

在办公室找到一个2007年的完好的古董PC,然后就生命在于折腾啦。

系统安装

机器只有一个CD光驱,DVD碟读不出来,改用U盘但是引导不进去。拔掉硬盘线通过SATA to USB转接器接在笔记本电脑上,打开主机供电,成功读出硬盘。笔记本插上安装碟进了ArchLinux,/dev下果然有两个硬盘sda、sdb,转接器支持得还不错。格式化之后分好区,跟着ArchWiki走顺利装好系统。不料重启之后进了Grub,手动引导成功进入系统,Grub就懒得修复了反正又不重启。

Awesome

为了分屏+纯键盘操作+低性能支持用了Awesome,原来在笔记本上没能体会到它的优点,现在装在低性能无鼠标的环境上十分带感。作死忘加交换区,装了FireFox打开就死机,添加4G交换区之后吃上100MB的还能正常运行,趁热把密钥生成好导入到Github上。
Awesome的rc.lua配置很强大,简单配置一下就能发挥大作用。为了完全的自定义用lua脚本来做配置文件也是醉了。
装Awesome花了大量时间,主要是忘了装X嗯,下次记住了,xorg-apps也要装上。

终端

试过好多终端软件,回头发现Awesome的自带终端完全不需要换,改改颜色改改字体还能再战。
不仅主机是老古董,显示器也是旧的,KTC 7009S,1280×1024,作死的5:4。分辨率太低没办法,把终端字号改成8px,勉勉强强Vim可以开三个竖排。
中文支持很麻烦,改了LANG装了WenQuanYi,少数情况下依然有方块。

Vim

刚说了显示器很烂,Vim下的配色试了许多,花花绿绿的很刺眼。最后选了molokai,普通语句和字符串都是不刺眼的颜色,Python下def、class、return、if这些出现频率不高的关键字是红色和黄色。
考虑过用Vim来分屏还是Awesome。Vim开:vs分屏之后,中间的分界线是很粗的一条白色线条,在整个暗色的编辑环境里十分碍眼。Awesome本身对分屏支持也更好,怒选Awesome。不知道白条可不可以自定义。

目前的环境

左边是刚装好的Arch,右边是笔记本Windows。Arch写代码Win搜资料,大家都是程序员为什么要相互伤害,Linux和Win不是配合得好好的吗233333
不管怎么说环境都是自己营造的啦,虽然再恶劣也能靠自己的一点一滴来改变。没钱就用Arch!

Node_redis对数组支持的BUG

做微信公众平台的时候发现Node_redis(https://github.com/mranney/node_redis)一个严重BUG
执行redis.lpush(‘mylist’,[‘a’,’b’,’c’],callback)的时候,预计返回

mylist
a
b
c

实际返回

mylist
a,b,c

Github已经有人提出过这个问题

https://github.com/mranney/node_redis/issues/369#issuecomment-13050944

产生原因

所有的client.COMMAND会调用client.send_command()

RedisClient.prototype[command] = function (args, callback) {
    if (Array.isArray(args) && typeof callback === "function") {
        return this.send_command(command, args, callback);
    } else {
        return this.send_command(command, to_array(arguments));
    }
};

调用client.COMMAND的时候

client.COMMAND(key, ["arg1", "arg2", "arg3"], callback);

会被解析成

client.send_command(COMMAND, [key, ["arg1", "arg2", "arg3"]], callback);

send_command()有如下段落

    for (i = 0, il = args.length, arg; i < il; i += 1) {
        arg = args[i];
        if (typeof arg !== "string") {
            arg = String(arg);
        }
        command_str += "$" + Buffer.byteLength(arg) + "\r\n" + arg + "\r\n";
    }

示例中循环到第二次 arg = ["arg1", "arg2", "arg3"] ,会被String()强制转换为"arg, arg2, arg3",产生BUG。

解决方法

直接调用

client.send_command(COMMAND, [key, "arg1", "arg2", "arg3"], callback);

或者将key包含到数组里面

client.COMMAND([key, "arg1", "arg2", "arg3"], callback);

吐个槽

既然都知道原因了,2013年2月的issue为什么到现在都还没解决!!