作者归档:hongjiang

lantern的bug导致safari/mail无法访问网络

lantern似乎一直存在bug,有时将其退出后会导致mac上某些自带的应用(比如safari和mail)无法正常访问网络,而chrome等非mac自带的工具却正常。在我的机器上这种情况经常发生,影响了mail应用不及时收取邮件,不得不通过kill networkd重启网络来解决,谁要是知道更好的方式请告知我。

➜  cat ~/bin/restart-network
#!/bin/bash

pid=$( ps -ef | grep "/usr/libexec/networkd$" | awk '{print $2}' )
sudo kill -9 $pid

scala里模拟javascript/python里的生成器的效果

上一篇关于yield的字面含义,基本有答案了。对于python和javascript不太熟悉,这两个语言里yield都是配合生成器而使用的。比如下面这段 javascript 的例子从mozilla的网站上看到的,稍加改造:

➜  cat test.js

function* foo() {
  var index = 0;

  while (index <= 2 ) {
    console.log("here" + index);
    yield index++;
  }
}

var it = foo();

console.log("generator ready");

console.log(it.next());
console.log(it.next());
console.log(it.next());

它的输出结果是

➜  node test.js
generator ready
here0
{ value: 0, done: false }
here1
{ value: 1, done: false }
here2
{ value: 2, done: false }

在Scala里yield并不等效于javascript/python里的效果,要等效的话,必须通过lazy, Stream等延迟计算特性来实现:

➜  cat Test.scala
object Test {
  def main(args: Array[String]) {

    lazy val c = for( i <- (0 to 2).toStream ) yield {
      println("here" + i);
      i+1
    }

    println("ready")

    for( n <- c) {
      println(n)
    }
  }
}   

运行结果:

➜  scala Test.scala
ready
here0
1
here1
2
here2
3       

yield的字面意思

Geek Talk里的一段对话,关于yield这个单词是否在所有编程语言里都是相同的含义。出于隐私,隐去了讨论者名字。不对讨论内容的正确性负责。

W:各位,我请教一个英语问题,yield 这个词语有几个意思?我最早是在Java里,Thread 有个 yield 方法表示 当前线程让出cpu,让其他线程先执行。yield 在这里的意思是“屈服, 放弃,让出”。后来在 C# 里,迭代器的实现可以用 yield return ,我当时就对 C# 里的 yield 和 Java 里的 yield 在意思上有没有相同的根源产生过怀疑,但没深究,就把它当作“产生,生成” 的意思来理解的,(我不确定我当时的理解对不对),后来在 Scala里 for推导里也有 yield 关键字,我也同样当作“产生,生成”的意思来理解。最近看到lua 的 coroutine里也有 yield ,我觉得可能它们是有相同或相似的根源的,只是我没有get到,这几种语言里 yield 所表达的,跟操作系统的线程原语 yield 是不是都是一个意思呢?

Y:是同源。因为Java刚出来时,Linux还没有线程那时候Unix有make_context,相当于非抢占的协程,所以Java的yield是为了给这些操作系统用的,但实际上到头来并没用上。

R:我一直认为c#里yield是生产、生成的意思,因为它只能用于实现IEnumerableyield后面必须跟return<element>,或者break,代表生产终止

W:我的英文不太好,所以我在猜测,到底这个词本身就确实有很多意思(就像中文里的“打”这个字不同上下文不同的意思),在这几种语言里 yield 也是不同的意思呢,还是 我们误解 C# 和 Scala 里的 yield 其实也是 “屈服、让出” 的意思(背后其实是流控上的含义?)

W:协程本质上是一种流控,我这么说有没有问题?还是说流控是协程实现手段之一更合理

Y:yield这里是专有名词,意思就是让出的意思,不过词源我不清楚。

W:从我了解到的 yield 这个关键字在多数语言里(C#, Scala, Python)里应该都是“生产、生成”的意思,而跟 java 里表示线程的 “让出”,完全不搭边。但在lua的coroutine 里 yield 又跟 Java线程的 “让出” 意思一致

M:感觉是动作的对象不一样而已吧

W:scala / python 里的 for comprehension 里的 yield 如果也是“让出”的意思而非“生产”的意思,还是有违背直觉的,尽管从 Control flow 上能解释的通

W:一切用到 yield关键字 的编程语言,含义都可以归纳为“交出控制权”?

S:伙计,我说一下现实生活中yield的例子,可能对你有帮助。在美国的公路上碰到yield的路标都表示在前方汇合点你要让行,如果没有车你可以并线。

W:这个例子解释线程的yield原语没有问题,但对 for-comprehension 或迭代器里的yield又怎解释呢?

W:补充给python程序员,Scala 里的for-comprehension跟 Python 里的list-comprehension是一回事,只不过更泛化。

G:to yield is to give up (something you own) on demand / claim. 我觉得如果从这个含义出发去解读,不论是线程(竞争中的个体)“让出”控制权(放弃抵抗或者内心执念),还是迭代器(农作物)“产出”值(粮食)都 make sense。 #my2c

W:这正是我觉得有所不对劲儿的地方,因为编程世界里通常是不太会出现 具有多重意思(含混)的 英文单词的。所以有可能是我们误解了 yield ,没有真正理解清楚。我现在偏向于,它在所有上下文里都是统一的含义:保存当前上下文(比如栈),让出执行权。

L:我觉得你的理解没错呀,yield更像是个受控的goto

G:我觉得yield这个词虽然有多种具体的释义,我直观感觉其内涵是一致的,只不过确实抽象了些,这让我想起英语和汉语的某些根本性的差别(抽象 vs具象,不定性vs定性)。可能有人会觉得我接下来的解释太过牵强,不过anyway我还是说了:这种抽象就像monad,它抽象了一种行为特征,同时任何一种具象的实现都不能完全表达出这种抽象,但每个具象的实现都能让我们更容易理解它(或者说让它更贴近我们实际遇到的事物),因此尽管释义多种多样,干的部分是相同的。也许扯远了,我并不确定Java线程的设计者和python的迭代器的设计者在当初选择yield这个词的时候是不是背后有相同的/相通的(其含义机械且确定,没有二义性的)计算机概念,我更倾向于相信是因为英语中这个动词准确的把表达出了线程和迭代器各自上下文里的各自的、具象的含义。即:从英语来说这两种释义它们是同源的,从计算机具体的、特定的概念来说,它们未必是。

J:第一次看到这个词是在Python,我觉得它的意思是喊一声。生产完对象喊一声,不用CPU了喊一声

W:也可能是我想多了,或许这两个语境意思并不统一,这也是我们母语非英语的程序员的一大问题,在捕获信息时需要付出更多的代价才能确定其准确性。

L:ruby里面有两个地方有yield,一个是method去call传入的block,一个是fiber出让调度,本质上都是切上下文,所以我觉得你没想多

Z:这个…你想多了吧,yield 在现代英语里本来就有这两意思。我还去查了 etymology dictionary. ld English gield “payment, sum of money; service, offering, worship;” from the source of yield (v.). Extended sense of “production” (as of crops) is first attested mid-15c. Earliest English sense survives in financial “yield from investments.”

西撒克逊古英语的gieldan和盎格鲁语geldan 都来自古日耳曼语的geldan, 有pay, to repay, return的意识。到14世纪早期,在投资中得道回报,也有survives in financial的意思,发展成了survives, give oneself up, surrender 的意思。 15世纪中叶gieldan另一分支,耕作谷物得道回报,发展成了production的意思。

Q:在国外开车除了停车线stop有时会遇到让车线yield。就是如果有直行车辆正在通过,停在那里等,否则进入车道。我想在for comprehension 里应该是差不多的意思,执行for里面的sequential functions,当所有functions 都被执行,弹出结果。

G:这是个好问题,专门去复习了一下python的generator语法:yield本质上就是“让出”但不“退出”,由于整个计算还没有结束(就好比generator说:我还不能死,还得保留当前状态),故不能return。

W:javascript 里 yield 明确的含义就是“让出”,python 也是。所以 c#/ scala 这种后出的语言,基本都是“拿来主义”,尽管未必是那个含义,也是把其他语言里已经被大众所熟知的语法直接拿来。

W:scala 里的 for-yield 是个语法糖,跟 js/python 里的generator 完全无关,要实现类似generator效果需要用 lazy/Stream 等惰性计算的特性。

W:我认为 C# 里的 yield 也是 “让出” 的意思,你可以跟 C# 开发者确认一下。

W:我知道这个词有多个意思,只是在程序语言里,是不是都代表一个意思,还是代表的是不同的意思,这才是我疑惑的。

R:C#里也是延迟执行的,迭代到了才执行生成对应的item的代码。这也是让我觉得像produce的原因

Scala函数式编程中文版已上架

《Scala函数式编程》一书中文版已经可以在京东亚马逊上购买。因为相对小众领域,推荐对Scala或函数式感兴趣的人,尽快收一本,免的以后买不到,就像以前冰河翻译的那本《Practical Common Lisp》早已无法通过正常渠道购买。当然翻译的内容也难免会有问题,看到错别字或不顺畅的语句,或有些术语有更好的叫法的肯请指出来。

这里也把杨博和连城的推荐序转发一下,感谢他们为中文版写的推荐。

推荐序1

我可能是全中国程序员圈子里最不适合给《Scala函数式编程》写序的人。三年前我写过《Scala七大死穴》,算是把Scala批判了一番。前几天我则在准备 ThoughtWorks 咨询师大会上的讨论话题《没有函数的函数式编程》,又要杯葛函数式编程的样子。看起来,我无论对Scala还是对函数式编程,都没什么好评嘛。宏江莫不是疯了,居然要我来写序?

等等,事情似乎不是这样。最近几年, ThoughtWorks 的客户在越来越多的项目中采用了 Scala 技术栈,ThoughtWorks 也孵化出了若干基于 Scalaz 的开源项目。 我本人也在这些项目中起到了一些作用。为什么我会做这些“口嫌体正直”的事呢?这得从十年前说起。

我最早是在C++中开始接触到函数式编程的概念。C++ 和 Scala 一样,也是一门多范式语言。 C++ 的标准库 和 Boost 都提供了许多函数式编程的设施。但是,在我职业生涯初期,给我留下深刻印象的函数式编程库要数 Boost.Egg 。利用 Boost.Egg ,你可以写出 my_list|filtered(&is_not_X)|filtered(&is_not_Y) 这样的代码。你会注意到这种用法和 Scala 标准库非常相像,它大致相当于 Scala 的 myList.filter(isNotX _).filter(isNotY _), 这种 filter 的用法,本书第 5 章“严格求值和惰性求值”中也有讲解。

Boost.Egg 的另一个特点是“非侵入”,比如上例的 filtered 函数,本身并不是 my_list的成员。相反,我们通过重载 | 运算符给原有的类型添加新功能。这种做法在 Scala 里面相当于隐式转换,本书 第9章“语法分析器组合子”中提供的例子正是利用隐式转换,给字符串添加了中缀操作符。虽然 Boost.Egg 没能流行起来,但对我个人而言很重要,因为它很大程度塑造了我对代码的品位。有趣的是,Boost.Egg 的作者 Shunsuke Sogame 近年来的开源项目,都是些 Scala 项目,可能这也是因为 C++ 和 Scala 非常相似的缘故吧。

另一个对我代码品位影响很大的技术是 Lua 中的协程 (coroutine)。 Lua的作者 Roberto Ierusalimschy 把协程称为“单趟延续执行流”(One-shot continuation)。有了协程或者延续执行流,程序员可以手动切换执行流,不再需要编写事件回调函数,而可以编写直接命令式风格代码但不阻塞真正的线程。我的前东家网易在开发游戏时,会大量使用协程来处理业务逻辑,一个游戏程序内同一时刻会运行成千上万个协程。

而在其他不支持协程或者延续执行流的语言中,程序员需要非阻塞或异步编程时,就必须采用层层嵌套回调函数的CPS(Continuation-Passing Style)风格。 这种风格在逻辑复杂时,会陷入“回调地狱”(Callback Hell)的陷阱,使得代码很难读懂,维护起来很困难。

Scala语言本身并不支持协程或者延续执行流。因此,一般来说,程序员需要非阻塞或异步编程时,就必须使用类似本书第13章“外部作用和 I/O”中介绍的技术,注册回调函数或者用 for/yield 语句来执行异步操作。如果流程很复杂的话,即使是 for/yield 语法仍然会陷入回调地狱。

我对 Scala 开源社区的贡献之一是 stateless-future。这个库提供了一些宏,实现了延续执行流,可以把命令式风格的代码转换成 CPS 风格。 通过这种做法,程序员不再需要手写本书13.2节那样的代码了,编写的代码风格更像普通的 Java 或者 PHP 风格,直接像流水账一样描述顺序流程。后来,我把这种避免回调函数的思路,推广到了其他用途上。比如,我开发了基于 Scala.js 的前端框架 Binding.scala。使用 Binding.scala 的用户,编写普通的 HTML 模板,描述视图中的变量绑定关系,而不需要编写高阶函数就能做出交互复杂的网页。

而我的另一个开源库Each,则更进一步,支持一切 monad 。大多数情况下,使用了 Each 就不需要编写任何高阶函数,我称之为“没有函数的函数式编程”。 这意味,本书11章到15章的全部内容,你都可以直接编写类似 Java 的命令式语法,而 Each 则自动帮你生成使用 monad 的代码。

总之,我是 Scala 函数式编程的死对头,我写的 Scala 库,恰恰是为了避免使用本书中谆谆教导的各种高阶函数。如果你是个 Java 程序员,想在最短的时间内用 Scala 开始“搬砖”,那么,从实用角度出发,我建议你合上本书,直接用 Each 即可。因为,虽然 Each 最终会生成 Monad 风格代码,但是,本书中涉及的使用高阶函数的细节,就像汇编语言一样,就算你不知道也照样可以干活。

不过,如果你是个求道者,追求编程艺术的真理,希望刨根到底,理解函数式编程的内在理论和实现机制,那么本书很适合你。这本书绝不轻易放过每个知识点,全书包含有大量习题,要求你自己实现 Scala 标准库或者 Scalaz 中的既有功能。所以,当你读完本书,做完习题后,虽然你的应用开发能力并不会直接提升,但你会体会到构建函数式语言和框架时的难点和取舍,从而增进你的框架开发和语言设计的能力。

参考

Boost.Egg

关于 Lua 中的协程,参见A. L. de Moura, N. Rodriguez, and R. Ierusalimschy. Coroutines in Lua. Journal of Universal Computer Science, 10(7):910–925, 2004.

关于延续执行体的历史,参见Reynolds, John C. (1993). “The discoveries of continuations” (PDF). Lisp and Symbolic Computation 6 (3/4): 233–248.

关于 Scala 异步编程的“回调地狱”问题,参见Business-Friendly Functional Programming – Part 1: Asynchronous Operations

——ThoughtWorks Lead Consultant 杨博

推荐序2

函数式编程与命令式编程同样渊远流长,然而在计算机应用的历史进程中,二者的地位却颇不对等。命令式编程几乎自始至终都是大众的宠儿,函数式编程却长期局限于象牙塔和少数应用领域之内。尽管如此,函数式编程的重要性却从未被忽视,几十年来生机勃勃地发展,静静地等待着逆袭的时刻。事实上,即便是浸淫于命令式编程多年的工程师,也常常会与函数式编程亲密接触而不自知:例如 SQL、C++ 模板元编程,还有 C++ 标准库中的 STL 等,多少都带有一些函数式的色彩。早年,受软硬件水平的限制,函数式语言缺乏高效的编译器和运行时支持,这可能是函数式语言错失流行机会的一大原因。近年来,一方面程序语言理论和实现技术突飞猛进,函数式语言在性能上的劣势越来越不明显;另一方面,随着多核、高并发、分布式场景激增,大众也逐渐开始认识到函数式编程在这些领域得天独厚的优势。然而,流连于主流命令式语言多年积攒下的库、框架、社区等丰富资产,再加上长期的教育惯性与思维惯性,使得人们仍然难以在生产上完全转向函数式语言。

一个新的契机,来自于大数据。社交网络、个人移动设备、物联网等新技术的兴起,使得海量数据处理开始成为家常便饭。人们突然发现,自己在命令式世界的武器库中,竟找不出称手的兵器来攻打大数据这座堡垒。2008 年,Google 发表了跨时代的 MapReduce 论文。尽管学界对 MapReduce 颇有[非议][1],MapReduce 的核心思想仍然旋风般席卷了整个工业界,为大数据技术的发展带来了及时而深远的影响。有趣的是,MapReduce 的核心思想,正是来自于天生擅长高并发和分布式场景的函数式编程。自此以后,各色大数据处理系统层出不穷,而其中的函数式成分也愈加浓重:在用户接口层面,这些系统往往以 DSL 的形式提供一套类 SQL 语义、具函数式特征的申明式查询接口;在实现层面,则仰仗不变性等约束来简化并发和容错。然而,出于种种原因,大部分系统的实现语言仍然以 C++、Java、C# 这些命令式语言为主。可谓操命令式之形而施函数式之实。

自 2009 年起,我先后接触了 Erlang、Scheme、ML 等函数式语言。但出于显而易见的原因,未能有机会将之用于工程实战。2013 年春节前后,我参加了由 Scala 之父 Martin Odersky 在 Coursera 上开设的 Functional Programming Principles in Scala 课程。凑巧的是,就在课程结束后不久,我便得到一个机会加入 Intel 参与有关大数据和 Apache Spark 的工作。函数式语言和分布式系统一直是我的两大兴趣点,由 Scala 开发的 Spark 恰恰是二者的一个完美融合。于是,Scala 便成了我的第一门实战函数式语言。近年来 Spark 的火爆,更是对 Scala 和函数式编程的推广起到了推波助澜的作用。

与我所熟悉的其他函数式语言相比,我想 Scala 最大的优点之一就是过渡平滑。立足于 JVM 并将函数式融入如日中天的面向对象,这样的设计带来了两大明显的好处。第一,顺畅地集成了 Java 社区多年积累的财富。第二,Scala 和 C++ 类似,也是一门“广谱”多范式语言;不熟悉函数式编程的 Scala 初学者,随时可以安全地回退,转用熟悉的命令式面向对象范式编程,从而保证交付速度。这个设计的背后,应该与 Martin Odersky “学术工业两手抓、两手都很硬”的风格不无关系。论学术,他师承 Pascal 之父 Niklaus Wirth,在代码分析和程序语言设计方面建树颇丰;论工业应用,他一手打造了 Generic Java 和新一代的 javac 编译器。可以说 Martin 既具备了用以高瞻远瞩的理论基础,又十分了解普罗大众的痛点。两相结合,这才造就了 Scala 这样一个平衡于阳春白雪和下里巴人之间的作品。

其实函数式编程本身并没有多难。对于接受过若干年数学训练,却没有任何编程经验的人来说,相较于命令式编程中的破坏性赋值,函数式编程中的不变性、递归等概念反而应该更加亲切。譬如中学做证明题时,我们从不会先令 a = x,隔上几行再令 a = a + 1。真正的困难在于,函数式编程中的一些概念和手法——如用尾递归代替循环——与命令式编程的直觉相冲突。对于那些有着多年命令式语言编程经验,把 Java 用得比母语还溜的工程师们而言,一边要学习新的知识,一边还要克服多年编程训练所造成的思维定势,无异于逆水行舟。而在 Scala 中,你永远有机会在实战中回退至自己的舒适区。实际上,我们完全可以无视 Scala 的函数式特性,仅仅将 Scala 当作语法更加洗练的 Java。因此,对于那些操持主流命令式面向对象语言多年的工程师们而言,Scala 特别适合用作涉猎函数式编程的起步语言。

这本书所讲授的,正是基于 Scala 的函数式编程基础。基于 Scheme、Haskell 等老牌函数式语言的传统教材的问题在于,相关语言的语法和思维方式与读者现有的知识体系迥异,容易造成较为陡峭的入门门槛。此外,由于这些语言本身的实际应用机会不多,初学者也难以在实战中获得宝贵的直觉和经验。而在 Scala 的帮助下,这本书并不要求你抛开现有的思维方式另起炉灶,它所做的更像是为你现有的思维方式添砖加瓦,从而令你如虎添翼。

最后,作为曾经的译者,我深知在国内当前的大环境下技术翻译之不易。每一本优秀技术书籍的中译本背后都是译者数月乃至十数月的艰苦付出。感谢诸位译者为我们带来又一本好书!

——连城
2016.03.20

引用1: David J. DeWitt and Michael Stonebraker, MapReduce: A major step backwards, https://homes.cs.washington.edu/~billhowe/mapreduce_a_major_step_backwards.html

mysql的两个问题

最近遇到两个mysql的问题,记录一下。第一个是在微博上看到Erlang发的一个看似是mysql的bug的查询。测试了一下,确实存在问题:

mysql> desc test2;
+-------+-------------+------+-----+---------+-------+
| Field | Type        | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id    | int(11)     | YES  |     | NULL    |       |
| name  | varchar(16) | YES  |     | NULL    |       |
+-------+-------------+------+-----+---------+-------+

mysql> select * from test2 where name=0;
+------+------+
| id   | name |
+------+------+
|    1 | wang |
+------+------+

原因是mysql的类型转换的问题,对非int类型列的数据在跟int类型比较时会将其造型为int类型,结果cast成了默认值0,所以条件满足了。当然稍微严谨一点的sql不会这么写,应该对字符串类型加上引号的。

第二个问题是Cobar遇到的问题。最近一个业务需要某个时间字段为毫秒级的精度,结果直连数据库时(mysql 5.6.24)没有问题,而连到cobar上则时间的精度只能到秒,后边的小数部分被忽略掉了。DBA和我一起排查了一下,用mysql客户端直接连到cobar上insert这条语句是没有问题的,也就是说是应用层传给cobar时出的问题。通过tcpdump验证了一下,发现确实应用发送过来的sql语句里的时间列数据只精确到秒,而直连mysql是到毫秒的。

有了这个证据后,猜测是mysql驱动层面的问题,可能是cobar冒充的mysql版本太低导致mysql driver在行为上有所不同,毕竟毫秒时间精度是在5.6之后才支持的。跟cobar的开发者电话联系了一下,说了一下我们的猜测,他说有这个可能。后来我们修改了cobar server端代码里定义的版本号,把版本号改为跟后端mysql一致,结果ok了。

回头看了一下mysql driver的代码,确实在com.mysql.jdbc.PreparedStatement里有个属性是serverSupportsFracSecs,而这个属性是根据数据库的版本来判断的:

protected void detectFractionalSecondsSupport() throws SQLException {
    this.serverSupportsFracSecs = this.connection != null && 
            this.connection.versionMeetsMinimum(5, 6, 4);
}

所以修改的方式要么让cobar反回大于5.6.4版本的值,要么hack一下mysql driver让这块儿对cobar返回true。

一只坐在树杈上思考存在的鸽子

《A Pigeon Sat on a Branch Reflecting on Existence》这片子的名字很有趣味,我正是被这个名字吸引住的。但实在太面向小众人群了,对其中的大部分故事片段都因为缺乏相关的历史信息和文化背景而不能理解。这也是一部典型的慢节奏影片,观看的时候,我是用两倍的速率播放的。

最近看过的电影(14)

《Stranger than Fiction》 这部电影的港版中文名或许更合适“离奇过小说”,如果你不对作家是如何创造的有好奇心的话,这部电影就不必看了,因为拍的过于卖弄写作者的意识和技巧,并不符合大众口味。我是因为这个导演曾经导过《生死停留》才看这部电影的,看完觉得并不好看。作家的创造是很痛苦的一个过程,要体验笔下人物的真实感受就要尽量的去贴近他们的生活,要保持的对细节的精准描述,也要追求一种新的创作风格、跳出现有的流派和框架,哪有捷径,都是要把自己逼到精神分裂。

《白鲸》(Moby Dick) 这部经典著作一直没有一部好的影视作品,我看的这部是德国拍的,分上下两集。饰演starbuck的是伊桑·霍克。多年前伊桑在《死亡诗社》里饰演过一个学生,他们站在桌子上读着叶芝的诗“Oh Captain! My Captain!”以抗议学校换掉他们的文学老师。在这部电影里,伊桑饰演的年过不惑的沉稳而内敛的“星巴克”,面对这个一意孤行的亚哈船长再次叫道“My Captain”,立刻感受到那曾经羞涩胆小的小男孩已饱经风霜。

《攀登梅鲁峰》(Meru) 这部纪录片实在是太棒了,是这几年少见的五星之作。

阿里云推荐码: qbhgd8

我的阿里云推荐码: qbhgd8,使用该推荐码在购买阿里云产品时有一定优惠,对我这边也会有一定的返利。我的blog就是用阿里云的ECS,自己装了个wordpress搭建的,已经3年了系统很稳定。

继续写点什么

最近这段时间没有更新blog,主要是想说话的欲望不强烈了。不过一旦写东西的频率降了下来,就会惯性的更不想写。为了避免这种状况,强制在月底要求自己写点什么,哪怕只用十分钟,哪怕写的内容毫无价值,聊胜于无。

要说起来可写的东西还是有的,去年年底做活动的时候还是发现了不少问题的,在对问题的定位上,写了一些脚本,大概总共1000行左右的一些shell函数,对于诊断一般性的问题基本够用了,有需要的话,我可以把这些脚本开源出来。

在对这些问题的诊断脚本化的过程中,把strace仔细研究了一下,有很多问题都可以通过strace来诊断,比如说要诊断http请求header里的信息,用tcpdump你没有root权限没法玩,strace这个时候就灵光了。再比如说查看你的java进程是不是在频繁的创建socket连接(短链接),调用了哪些远程dubbo接口或远程http接口,执行了哪些sql或redis命令,读取了哪些资源文件等等。