Posts
跑步两月记
扯淡篇 4月底开始恢复跑步,体检检查出轻度脂肪肝,刚步入 30 ,这个征兆不是特别好。因此,还是恢复跑步。原来在北京,是不敢跑懒得跑,雾霾太厉害,并且离奥森公园还是有点距离。到了昆山,虽然空气还是不理想,但是比北京还是好点,加上离家不远有个河边公园,人少车少,跑步的理想场所。
跑到现在,加上三周前开始去健身房锻炼,原来是不敢去健身房的,以为肌肉猛男很多,我这样的胖子估计很丢人。其实呢,健身房里猛男不少,胖子更不少,完全没人在意你。跑步的成绩从原来的 8,9 分钟每公里(跟快走差不多)的平均速度,还心率狂飙的差劲情况,进展到现在可以定速 6 分钟每公里保持个接近一个小时(也就是 10 公里在一个小时左右跑完),心率维持在150左右,自己都很得意。当然,跟跑步圣经里的老马比起来,那差距还是很大。
最近三周没去跑公路了,一方面是夏天到了,在户外心率会狂飙,有中暑晕倒的可能,另一方面是空气开始糟糕。都在健身房跑步机上跑。还有就是请了私教,尝试一个课时(12节)的训练,加强下力量,顺便减脂。总体来讲,体验不错,考虑再续一个季度。不过价格真的很贵,需要说服老婆支持。
既然决心坚持下去,也给自己定了个目标,11 月份一定要去参加杭州或者上海马拉松的半程比赛(21公里)。以我现在的耐力,完成比赛应该没有问题,成绩不在乎,重在参与嘛(弱者的自我安慰)。还没有尝试过 15 公里 和 20 公里的 LSD 训练,争取这个月内试一次。
装备篇 作为装备控,没跑多远的路,就开始在跑步圣经等论坛上看各种装备评测,最终备齐了一套,对我这样的初级跑着还是奢侈了一点。
GPS 手表:佳明 FR 620,配心率带。专业跑步手表,除了心率、距离、配速、卡路里之外,还有步频、垂直幅度、触底时间、虚拟伙伴和最大耗氧量测试等更专业的统计数据。如果准备长期跑,入这样一个跑步手表还是必须的。 佳明 FootPod 计步器,因为在跑步机上跑,虽然 FR620 的手表和心率带都内置加速器,但是距离偏差还是比较大,因此还是淘宝上入了个计步器,校准之后相对精确了一些。 跑鞋,片面强调跑鞋作用不可信,但是一双好的鞋子来保护脆弱的膝盖还是必要的,当然,强者都是赤脚跑步。在北京的时候就买了双 adidas marathon 10,这样的长跑鞋对我这样的胖子来说其实不合适。这鞋子回弹不错,相对较硬了点。去健身房之后,一口气入了两双跑鞋: Ascis nimbus 15 和 Mizuno wave legend。前者适合我这种外翻的脚型,并且是我这辈子穿过最舒服的鞋子,按照夸张点的说法是穿着它就像一路踩着“狗屎”走路。后者相对较硬,只有跑起来才能感觉到回弹十足,我穿着他跟着教练练器械。Nimbus 担心损耗很快,还是舍不得穿着健身,只用来跑步。 运动衣裤:淘宝上随便淘的耐克跑步短裤和T-shirt,这个没啥特别的,只要合身、透气,穿着舒服就好。 回忆篇 很多人说跑步是孤独者的运动。因为一个人跑,可能会比较闷。不过这个对我从来不是问题,独处是一种习惯。我在初中的时候,三年都坚持晨跑,天还没亮,就沿着乡村公路跑过坟场、山丘,跑步给我的生活带来了很多变化。工作后,在广州的时候也坚持夜跑天河公园,去了杭州才没有坚持运动,主要住的地方实在没有什么公园场地,我又不愿意在公路跑,也还不敢去健身房。在帝都更不用说了,雾霾加上工作繁忙,又没有心思锻炼,更是彻底荒废。眼看着体重直线上升。
现在恢复跑步,对我来说不是特别困难的事情,享受跑步时候的呼吸和汗水,希望能 keep running 下去。
Posts
最近做的一些 clojure 开源项目
最近总结下最近的一些开发经验,形成几个 clojure 的开源项目:
clj.qrcode:二维码生成 https://github.com/killme2008/clj.qrgen 示例: (use 'clj.qrgen) (as-file (from "hello world")) (as-bytes (from "hello world")) (from (vcard "John Doe" :email "john.doe@example.org" :address "John Doe Street 1, 5678 Doestown" :title "Mister" :company "John Doe Inc." :phonenumber "1234" :website "www.example.org")) secure-rand:安全随机数生成器 https://github.com/killme2008/secure-rand 想要安全的随机数,还是要使用 java.security.SecureRandom 类 示例: (ns test (:refer-clojure :exclude [rand rand-int rand-nth]) (:use [secure-rand.core :only [rand rand-int rand-nth]])) (rand) (rand 10) (rand-int 100) (rand-nth (range 10)) (secure-rand.core/base64 32) clj.qiniu:七牛云存储 SDK https://github.
Posts
Clojure Web 编程之安全篇
最近关注这方面稍微多了点,大概总结下。
基本原则 浏览器的安全机制:
同源策略:host、port、protocol、sub domain都能影响。 沙箱模型,比如 Chrome 的多进程模型。 恶意网址拦截,现代浏览器基本上都有提供,Google也提供了开发API查询黑名单。 Clojure的Web开发本质上是基于 Java 的 Servlet 模型,因此也同样遵循 Java 的安全编程模型。这里主要描述 Clojure 里的常见防御策略,具体的漏洞请参考《白帽子讲Web安全》等书籍。
注入 包括 SQL 注入和其他类型的注入,比如XML、JavaScript甚至HTTP头。
SQL注入 任何情况下都应该避免拼接SQL语句,而应该使用参数化的SQL语句
如果使用[clojure.java.jdbc],使用占位符?替代参数:
(require '[clojure.java.jdbc :as j]) (j/query mysql-db ["select * from fruit where appearance = ?" "rosy"] :row-fn :cost) 如果使用korma,只要避免使用exec-raw执行拼接SQL语句,默认都是参数化SQL语句:
(select users (fields :id :first (raw "users.last")) (where {:first [like "%_test5"]})) ;;Or when all else fails, you can simply use exec raw (exec-raw ["SELECT * FROM users WHERE age > ?
Posts
Swift 编程之闭包(翻译)
最近Apple新出的 Swift 语言非常火,我们公司也在陆续组织翻译《The swift programming language》 这本官方电子书,为公司博客增加一些人气。这篇博客就是我负责的其中之一的产物。在公司博客放了一份,这里也放一份。
闭包 **闭包(Closures)**是可以在你的代码里传递和使用的,自包含的功能代码块。Swift 里的闭包跟 C 和 Objective-C 里的 block 类似,也就是其他语言里的所谓的 lambda 。
闭包可以从定义的上下文(Context)里捕获和存储常量或者变量的引用。这被称为“闭合”(closing over)了这些常量和变量,这也是“闭包”名称的由来。Swift 帮你处理了所有捕获相关的内存管理。
注意
不用担心你不理解“捕获”这个概念。会在下文里详细解释。 在函数一章中介绍的全局和嵌套函数,其实是闭包的特殊形式,闭包表现为三种形式:
拥有一个函数名,并且不捕获任何值的闭包称为全局函数。 拥有一个函数名,并且从外部函数捕获值的闭包,称为嵌套函数。 使用轻量级语法编写,并且没有命名的闭包表达式,可以从周围上下文中捕获值 Swift 的闭包表达式语法拥有一个干净、清晰风格,针对大多数应用场景里做了优化,倾向于简明、整洁的语法:
根据上下文信息,为参数和返回值的自动做类型推断。 单一闭包表达式的隐式返回。 参数的速记法。 拖尾闭包(Trailing Closure)语法。 下面我们开始详细介绍。
闭包表达式 在嵌套函数一节中介绍的嵌套函数,是在一个更大的函数内部定义和命名一部分自包含的代码块的常见方式。尽管如此,编写不需要完整的声明和命名的函数构造有时候会更有用处。这在你需要将其他函数当做一个或者多个参数传递的时候会很常见。
闭包表达式 就是一种编写简短并且清晰的内联式闭包的方式。闭包表达式提供了了多种语法,优化到最简单的方式来编写闭包,而且没有失去代码的清晰和意图。下面小节中举例提到的例子,就是通过数次迭代重新定义一个排序函数来展示这些优化,每一次迭代步骤中的表达式都拥有相同的功能,但是将更加简明。
排序函数 Swift 的标准库提供了一个sort函数,可以用来排序一个已知类型的数组,在你提供的排序闭包函数的输出的基础上做到。当完成排序后,sort函数返回一个新的数组,类型和大小都跟“旧”的一样,并且里面的元素按照正确的顺序排好序。
下面的闭包表达式例子,使用sort按照字母倒序的顺序排序一个字符串数组,这是初始数组(未排序的):
let names = ["Chris", "Alex", "Ewa", "Barry", "Daniella"] sort函数接收两个参数:
一个已知类型的数组。 一个接收两个相同类型的数组元素的闭包,返回一个布尔值,表示第一个参数是在第二个参数之前还是之后。排序闭包如果返回true,表示第一个参数应该在第二个参数之前,false则相反。 这个例子排序一个字符串数组,因此排序闭包必须是一个(String, String) -> Bool签名的函数。
编写一个类型正确的普通函数就能做到,传入sort作为第二个参数:
func backwards(s1: String, s2: String) -> Bool { return s1 > s2 } var reversed = sort(names, backwards) // reversed的数组等于["Ewa", "Daniella", "Chris", "Barry", "Alex"] 如果第一个字符串(s1)比第二个字符串(s2)大,backwards函数返回true,表示最终的结果数组中s1应该在s2之前。对于字符串中的字符(character)来说,所谓“更大”的意思就是“出现在字母表的更后面”。也就是说字母 “B” 比字母 “A"更大,字符串 “Tom” 比字符串 “Tim” 更大(因为第二个位置的字母o在字母i后面——译者注)。这就实现了字母顺序的倒序排序,使得 “Barry” 放在了 “Alex” 之前等等。
Posts
Clojure里使用curator做Leader节点选举
Curator 框架刚出来的时候,我就用它帮 Storm 重构了 zookeeper 模块。使用 zookeeper,如果用 java 语言,curator 框架是最佳选择。
最近在做一个节点选举的功能,在几个节点之间选举一个 leader 来跑一个独占服务。原来的方案是直接利用 hostname 匹配,跟配置的 hostname 一致的固定某台机器来执行。Failover 靠人肉和自动化脚本。为了做让 failover 自动化,自动选举节点是更好的方案。理所当然,我尝试在 clojure 里使用 curator 框架。 curator 提供了 Leader Election功能,我要做的只是封装这个Java API,在clojure里更好地使用。
首先,肯定是继承LeaderSelectorListenerAdapter 来实现 LeaderSelectorListener ,监听本节点是否成功获取 leadership,当本节点成功被选举的时候,LeaderSelectorListener 的takeLeadership方法将调用,你应该阻塞这个方法,直到:
继承LeaderSelectorListenerAdapter我们用 proxy 函数,阻塞呢?Clojure提供了promise,当 promise 没有值的时候, deref 调用会阻塞, promise 本质上是一个CountDownLatch。我们就利用它来阻塞 takeLeadership 方法,封装下这个过程:
;;保存curator框架客户端的atom (defonce ^:private curator-framework (atom nil)) ;;保存LeaderSelector列表的atom (defonce ^:private leader-selectors (atom [])) (defn elect-leader "参与leader选举,如果被选举为leader,调用aquire函数,释放leadership的时候调用release函数。 path表示参与选举节点共同使用的zookeeper上的路径。" [path aquire release] (if (nil? @curator-framework) (throw (IllegalStateException. "Please call start at first.
Posts
拥抱 Octopress,再见 WordPress
花了点时间,从 WordPress 迁移到 Octopress,跟我们公司的官方博客刚好相反 :D 。主要是实在折腾不好WP的那一堆插件。也习惯用 mou.app 写博客了。
迁移过程中,这个工具 wordpress-to-jekyll-exporter 帮了大忙,自动从 WordPress 导出数据成 Octopress 需要的格式,相当方便。
使用了 solarized-octopress-theme 主题,再折腾下 多说 评论框,基本就完成了。
继续博客之旅。