续集:加强服务器安全性保护WordPress

自上次写过WordPress被黑之后,虽然安装了Wordfence,但发现依然不够,Wordfence能反复扫描出各种被黑的PHP木马。

没想到WordPress的安全性如此成问题,看来安全性还是必须从系统入手,不能光依赖WordPress本身。

一、禁用PHP的系统相关函数

首先经过检查,发现虽然篡改了PHP文件,甚至在tmp下面跑了一个进程,但似乎并没有渗透到系统级别,没有获得root权限,所以我立即在php.ini里面禁用了一些系统相关的函数,以防止被获得系统的权限


disable_functions = pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexi
ted,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wexitstatus,pcntl_wtermsig,pcntl_ws
topsig,pcntl_signal,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pc
ntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriorit
y,pcntl_setpriority,exec,passthru,shell_exec,system,proc_open,popen,curl_exec,cu
rl_multi_exec,parse_ini_file,show_source

二、将WordPress目录下的文件权限改为root

为了防止PHP文件被插入恶意脚本,我将PHP文件都设置为只读,虽然这样会导致WordPress无法自动更新或者是自动安装插件,但要好过被篡改。然而uploads目录是必须要可以写入的,没有这个功能无法上传图片。


# chown -R root .
# chown -R www-data wp-content/uploads

三、禁止 uploads 目录中执行任何 PHP 脚本

在做了前两步之后,我发现依然有黑客可以上传脚本到 uploads 目录下,并通过远程请求调用执行,所以必须要禁止这个目录下的PHP脚本的运行。我在nginx中增加了一下配置


server {
listen 80;
server_name shiningray.cn *.shiningray.cn ;
root /var/www/shiningray;
index index.html index.htm index.php;
include /etc/nginx/php_params;
location ~* /(?:uploads|files)/.*.php$ {
deny all;
}

}

四、配置防火墙

当我还没配置第三步的时候,我通过 netstat 和 lsof 等指令调试系统的时候,发现PHP进程会连接到很多邮件服务器的25(smtp)端口,我想起来之前Linode客服所说的经常能发现我的服务器在投递垃圾邮件,原来是拿我当肉鸡发垃圾邮件。所以我觉得直接堵死smtp端口的连接,就可以断了他们的念想。

我使用Ubuntu的ufw来配置了端口的访问:

表示拒绝任何从本地发起到外部25端口的连接,使用 deny 替换掉 reject 也可以,但是 deny 是丢弃掉链接上发出去的包,而 reject 是直接断开链接。由于木马往往会反复不停的尝试,如果只是deny的话,可能会导致进程被堵死,所以最后选择了 reject

至此之后,再也没有感染过PHP的恶意脚本了。

Ruby/Rails为什么不如以前热门了?

最近在知乎上看到了一个问题,问“Ruby和Ruby on Rails在2017年还有前途吗?”我觉得这个问题很有意思,因为其实Ruby圈子里不少很资深的朋友,都转行去做别的了,有做前端的,有做Go,还有像我开始做Nodejs了。给人的感觉就是Ruby不行了,圈子也不够活跃了,
下面我来分析一下Ruby/Rails为什么最近声音小了。首先看大公司为什么很少用rails,据我所知有
1. rails的性能和内存占用不理想,规模效益不高
2. ruby作为动态语言在大团队开发上存在劣势,不能像java有接口和静态类型检查,能够帮助大团队在开发期减少Bug。
3. 小众语言,招人(相对)困难
4. rails本身是单块设计,而且很多地方并不OO,不适合大公司拆分、细化、优化的诉求

而rails更多是创业小公司在用,我的经验包括:
1. 全栈框架,有自己的前端逻辑
2. 完善的生态
3. 开发速度快,对人员数量要求少
4. 学习曲线很线性,容易培养(全栈的)开发人员

对于小公司来说,本身资金有限,人力成本又占主要部分,产品不确定性大,所以选择走小团队,快速开发的模式是很自然的事情。而大公司,往往有完善的体制——招聘、培训、管理,等等——支持,所以往往是希望能通过增加人手来扩大生产规模以及完成更多的产出,这就要求开发工具有足够的“工程性”。这跟Rails的理念就是相违背的,而Ruby的工程性也不如Java之类的好。

大家再回想一下这几年中国经济形势如何?实体凋敝,房价暴涨,很多人都觉得创业还不如买几套房子。这样创业公司少了,用Ruby/Rails的自然也少了。

再看这几年的技术发展趋势,一个是经过多年的发展,当初Ruby/Rails的很多先进思想也都被其他语言和工具吸收了,开发效率上的领先已经达不到最早那种数量级的差异。
同时很多开发者已经熟悉了自己的一套框架和工具链,如果实现相同功能,没有十足的必要学习另外一种新的技术。

而只有前端不一样,浏览器只支持JavaScript,整个前端的生态又顺理成章建立在了nodejs之上。加上手机客户端又适逢新兴的移动互联网浪潮,需求量突飞猛进。前端、客户端之前的积累也比较少,加上需求的推动,有很大的空间来造轮子。

所以Ruby/Rails近几年声音变小也是正常现象,即使我认为目前在开发体验上还没有能超过Rails的全栈框架。

从产品角度来看,早年开发产品拼技术,主要看你东西能不能做出来。后来开始拼产品设计,又讲究快速开发和快速试错。以前在Web时代,Rails在这些方面都有优势。而到了移动时代,产品设计和快速迭代的主要部分从后端移到前端,让后端开发变成了一个配角,尤其是后端开发在早期阶段的重要程度也降低了。

然而事到如今,各端入口都被占据,流量、用户基本被巨头们瓜分干净,各种现成的平台服务也层出不穷,又进一步让技术的重要程度又降低了。想想做一个公众号,用现成的平台,经营好粉丝就能拉投资捞钱;或者在现有平台上开个微店来做生意。现在很多创业门槛完全不在技术方面,技术的重要程度被大大降低。

而往后看,VR、人工智能、大数据、IOT等等也都不是Ruby所擅长的领域。

种种加起来,可以看到Ruby/Rails几乎不可能再掀起新的浪潮。总结了这么多,就是,Rails本身所擅长的领域在现在已经变得很狭窄也不那么重要了,所以才声音小了。任何技术也都有他的生命周期,Ruby/Rails是非常优秀的技术和工具,如果你要做的事情符合他的目标,那它依然是一个很棒的选择。

链接:https://zhuanlan.zhihu.com/p/25007358

博客被黑了

之前在参加公司封闭培训特别忙,​好一阵子没看过自己的博客,突然收到 Linode 的邮件说我的服务器在发送垃圾邮件,然后问我的服务器是不是被黑了,而且一连发现好几封。前阵子一直忙着上公司的培训课还有搬家,就忘了看邮箱。现在发现居然被黑了,不知道是 WordPress 还是插件的问题,文件夹下面多了很多奇怪的文件,而且好像被混淆了。还在/tmp 目录下有几个奇怪的文件,长期运行占用了100% CPU。清理过机器之后,我想登陆 Linode 去回复一下客服提的 Ticket,结果发现换了手机之后,原来 2步验证的没改,原来的手机又坏了不能看到验证码,很郁闷又邮箱联系客服,结果用注册邮箱发邮件给客户之间被回复该邮箱已经禁用,不知道是不是因为我的账号异常。然后换了个邮箱再联系,客服让我发送身份证照片和信用卡照片,然后才帮我禁用2步验证,然后进去回复了客服的 Ticket,客服建议我给 WordPress 装个 WordFence。

安装了 WordFence 之后扫描了 WordPress 的文件,发现大量php文件都被感染了莫名的代码片段,于是让 WordFence 进行恢复和清理,终于算是告一段落了。

而我印象深刻的是 WordFence 这个插件有一个收费的 Pro 版本,提供更强大的防护能力。让我回想起来以前看到的一篇访谈,讲的是 Ruby on Rails 的插件 Sidekiq 的作者 Mike Perham 如何一个人通过维护自己的产品 Sidekiq,最终获得了百万美元的收入。当时我十分震惊,因为之前我认为一个程序员想通过纯技术做自由职业实现财务自由,是不可能的事情。我认为程序员想实现财务自由,只能通过进入一个组织内,通过组织来实现,比如加入创业公司。然而这个风险也是非常大的,因为在组织面前,个人是很难抗衡的,公司做大了,可以把程序员、甚至把合伙人换掉。而自己创业,往往很快自己就无法继续做技术了。

Sidekiq,WordFence,和 Indie Hacker 上的很多案例给了我启示,我能不能发现一些细分领域里面小而美的产品,只要一个人,或者能用两三个人的小团队,就能充分发挥个人能力,实现我的人生目的。

希望将来也有机会能做出一些这样的产品。不过,我觉得最大的天敌也许就是自己的胆怯和惰性。

互联网的未来属于实时交互

作为一个写代码的,我做互联网产品也有十个年头了,从来没有想过要在设计上指点江山,只是谈谈自己的一些感触。

我所谓的实时交互,指的是服务器端的状态会实时同步到本地并展示。比如即时通讯软件,你可以直接看到其他用户发来的消息,甚至能看到对方正在输入。比如 MMORPG 多人在线游戏中,在本地就能进入游戏世界并看到一切更新。而很多软件中使用『推送』、『通知』,还算不上实时交互。那种需要刷新页面的,就更不实时了。

我认为未来的产品的形态,交互模式会朝着这个方向去发展,过去的客户端发起请求,服务器产生响应的模式会被革新掉。以往的互联网是内容为准,以后的互联网便是以交互为主。为何呢?看我分析理由。

一、人喜欢更快的响应速度

我06年毕业,毕业论文就写的是关于 AJAX 方面的东西。从那时候开始,我就发现互联网应用是追求越来越快的响应速度的。当时Amazon有个说法是页面的请求每增加多少毫秒,销售额就会减少多少。可见响应速度是一个非常重要的『用户体验』。

从那时候开始,各种技术、组件、框架、语言,都在尽可能的提高应用的流畅度和响应速度。巨头们发明各种新的浏览器,以及 JavaScript 引擎,展开了速度上的竞赛。

用户界面也从服务器端搬到了客户端,原生 app 的兴起,为了尽可能提供能酷炫和流畅的界面。

这些都是在提高响应速度。然而,在过去的『请求-响应』的模式下,再快也是在我请求之后的,只有服务器端能直接把状态推送下来,才是真正最快的响应

二、人喜欢和活的人交互

即时通讯软件可以说是经久不衰的产品类型之一了,而且现在也是占据人类使用手机主要时间的 App。为何会这样?因为人的本质就是喜欢跟人交互的。

所以后来出现了一些特殊的产品形态,目的是为了『模拟』这种好像有活人在跟你交互的感觉。『弹幕』就是其中之一,大家知道其实弹幕最早是出现在点播的视频上的。但我们在使用的过程中,主要的体验就是好像这个时候也有其他人在吐槽视频。

twitter、微博则定时提醒用户有多少信息更新,告诉用户,我们有新鲜的信息,你赶紧来交互吧。

直播也是非常重要的产品形式,而直播上面的弹幕,毫无疑问就是最新的用户的交互了。

三、人喜欢更多的信息细节

前面说到即时通讯软件一直很火,但是我们也发现伴随即时通讯的,往往有语音对话、视频对话。当然,这些功能都是在技术的发展后,门槛越来越低。

图片、语音所包含的信息比普通的文字多,视频就更多了,所以所需要的计算时间和带宽也更多。但是也挡不住大家更喜欢用语音通讯和视频直播。

我认为,人到底都是感情动物,而感情是非常细腻的,比如人可以从细微的表情变化,语气语调中,看出很多东西,也更容易建立情感联系。这也是为何在现在的聊天当中,表情包占据了越来越多的份额。

我相信,从维持感情的角度来看,视频通话>语音通话>文本对话。而直接的对话交互又好于发一份异步的邮件。

实时交互能带来更多的信息细节,能让用户感受到真的是活生生的人,这就是大家对此爱不释手的原因。

四、现在是承上启下的时代

实时交互的技术基础基本上都已经完善了,像服务器端推送,高并发等等基础问题其实已经不是问题。在 Web 上,Socket.io,Primus 等基础通信框架帮助大家解决了实时通信的问题,而一些框架像 Sails.js,Feather.js 也号称是实时框架。最近兴起的『响应式编程』Reactive Programming 也为这种实时的响应和交互提供了支持,出现了相应的框架如 Rx 系列。

同时虚拟现实(VR)已经进入了人们的视野,难道人们会希望在一个只有自己一个人的虚拟世界里面玩吗?显然,我们需要的是一个互联的虚拟世界,在这样的世界里,不可能存在像过去那样的『请求-响应』的操作模式,一切信息都肯定是实时呈现到本地的。

这就要求我们能够打破传统的思维,能颠覆现有的交互方式,把实时交互考虑进来,去创新出一些新的产品形态。

本人也正在研究实时交互方向的产品,并希望提出一套实时交互的应用框架,最近正在写 Coronajs,有感兴趣的朋友可以一起交流。

Node.js 应该拥抱 Actor 模型

Node.js 是近年来服务器端开发工具中可以说最为成功的一个工具了,不仅仅利用 JavaScript 和 Reactor 模型来达到快速开发高并发应用的目的,也顺利入侵前端生态圈,前端开发各种必备的工具链基本都使用 Nodejs 开发。我也用 Nodejs 做过一些针对并发的项目如聊天室等等,但是始终觉得 Nodejs 的基础理念和各种框架还不足够抽象,以帮助我快速对此类项目进行清晰有条理的建模。当项目尺度越来越大之后, 为了达到更好的 Scalability 和高可用性,容错性,因此我越来越希望 Nodejs 能有类似于 Erlang 中的 Actor 模型的框架来实现这些目标。

以往解决并发,往往是一个进程服务一个链接,但是进程占用资源过多,无法很好的伸展。后来变成了一个线程服务一个链接,虽然可以开很多线程,但是频繁的上下文切换消耗过多的 CPU 时间,线程之间的状态共享又容易出问题,所以也无法很好扩展。

Reactor 模型利用事件机制,在 IO 密集的场景中,解决了两者的问题。由于 IO 密集的场景下,大部分链接都是在等待传输等,只有少数链接处于活跃状态,所以可以通过事件的方式,仅仅处理需要处理的那部分,来减少资源的开销。

但是Reactor 模型也不是没有缺点,在 Nodejs 中:

  1. 单线程,难以利用多核优势,一旦阻塞了事件循环,会导致所有任务都会延迟。
  2. 过多的回调导致难以组织代码
  3. 回调函数打乱了控制流程,让处理异常变得麻烦

Actor 模型的基本概念

同样是由于线程和进程模型的一些缺陷,Erlang 之父Joe Armstrong在解决电信交换机上的高并发问题的时候,提出了 Actor 模型。简单的说,每个 Actor 封装了自己的逻辑和状态,互相之间不共享任何状态,只能通过消息(Message)来互相通信。每个 Actor 有一个自己的邮箱(Mailbox),是一个存放消息的队列,Actor 会一个一个处理每一个消息。

_JC@ABJ3(7{)]Y1VF@3PH58

Actor 之间不共享状态,就减少了很多多线程中的锁的问题。顺序处理消息,也保证了 Actor 内部不容易出现竞争条件(Race condition)。

当然,Reactor 模型和 Actor 模型并不完全排斥,Actor 模型底层也是可以使用 Reactor 的。

Actor 具有天生的分布式特性,我整理了一张表:

Actor Process Machine Service
标识 唯一 ID 进程 ID,端口 IP 地址,Mac 地址 IP,域名,服务发现
状态 不共享 通常不共享 不共享 不共享
交互 消息 信号,管道,网络 网络 网络
容错 Supervisor 机制 supervisord, monit,等 heartbeatkeepalived Cluster 内建,DNS,服务发现

其实 Actor, Process,Machine,Service,在很多方面都是一脉相承,正因如此,内置了 Actor 模型的 Erlang 才在云时代大放光彩。

虽然 Nodejs 号称是云时代的编程工具,但实际上在这方面做得并不特别好。

那为何 Nodejs 应该加入对 Actor 的支持?

清晰的单元

首先,Actor 本身只是将一个逻辑处理单元给具体出来,即便我们的 Nodejs 程序没有使用 Actor 模型,实际上在处理并发的时候,依然会隐含着这种逻辑处理单元。Nodejs 中是通过闭包来隔离内部状态,通过事件/回调函数来处理消息。随着代码量的增加,为了让代码更加结构化清晰化,我们通常依然会封装出一些自己的接近 Actor 模型的对象。虽然我们现在有 Promise,未来有 async/await,但是这主要是封装一次『任务』,而非整个逻辑。

Actor模型理念跟面向对象一致

Actor 模型其实本质上也是符合面向对象编程的理念的,面向对象编程中

  1. 对象也是同时封装了状态和行为的单元。
  2. 对象和对象之间通过『消息』进行互相操作

其实在面向对象语言的鼻祖 Smalltalk 中,方法并不叫方法,而是叫『消息选择器』(Message Selector),故名思议就跟函数式语言中,对消息结构进行模式匹配一样。

JavaScript 同样是一门面向对象的语言,是完全可以和 Actor 模型结合起来的。

把前两点结合起来举例,在 Nodejs 中,一个 HTTP 请求往往会对应到自己的一个上下文 context,里面包含了请求request和相应response的对象。这种封装的计算单元就有了 Actor 模型的一些基本理念,像 Koa 中更是使用了 generator/yield(将来可能是 async/await)来简化控制流。

我们可以得到一个理想的单进程内的 Actor 模型

KQRGE}1IRHRI9_M8P{V}W9C

其实上图用一般的面向对象和类来理解也是非常简单的,对吧?

可以优化错误处理以及容错性

在 Node 中,由于控制流的混乱,很难确定出错的位置,有时候出错也会导致整个进程的 crash。而有了 Actor 之后,错误的范围就可以聚焦到 Actor 上,而不会像原来那样找不到出错的位置。同时,也可以引入类似于 Erlang OTP 的 Supervisor 机制。Erlang 的理念是 Failfast,但是Erlang 中的代码出错之后,会有监控者进行善后。

分布式

Actor 模型的理念具有天然的分布式潜力。如果在 Nodejs 中能有良好框架的支持,让跨进程的消息传递变得透明的话,那么在各种应用上的 Scalability 都会有极大的提升。一般 Web 服务的 nodejs 层那样是无状态的,横向扩展比较容易,加服务器就够了,而写长连接的 nodejs 应用比如聊天室的时候,为了实现 nodejs 层的横向扩展,不得不通过更后端的诸如 redis 来实现跨进程通信,更后端的压力更大,也由于中转导致延迟更大。甚至在某种程度上,我们可以实现在不同服务器之间的动态调度。

有了透明的分布特性之后,同时高可用性也更容易达成,我们可以将 Actor 的状态,跨进程/机器去进行 Replication,当某个节点 crash 之后,可以在 replication 的节点上重启相应的 Actor。

L$7%A7B]C8VKFN2BRJP8STJ

(图片来自网络)

解决方案

在众多 Actor 模型的解决方案中,使用 Fiber 是跟 Reactor 最为自然的搭配,因为 Fiber 就是封装了一个计算过程,并且可以根据情况将 Fiber 暂停和恢复,这就可以通过 Reactor 中的非阻塞的特性,利用事件机制将活跃的 Fiber 唤醒,将需要等待的 Fiber 暂停。我们可以很容易的通过对 Fiber 进行封装,在 Nodejs 中实现 Actor 模型。像 fibjs 就能很好的完成这一任务。

但我认为 Actor 模型并不一定非等需要使用 Fiber,只要内心包含相应的理念,即使只使用 Promise,async/await,也是完全没有问题的。

Virtual Actor

微软提出了一套新的理念称之为 Virtual Actor,非常接近于我所追求的框架和平台。

Virtual Actor在基础的 Actor 模型上增加了几点:

  1. 实例化后始终存在,自动 replicate 到其他节点。
  2. 不活跃的 Actor 可以进行垃圾回收或者被持久化。
  3. Actor 位置透明,任何节点之间都可以互相访问
  4. 自动 Scale Out

RMV7Y~QEWMZ_[}K93``VQ(Q

目前实现了 Virtual Actor 的框架有,微软.net 平台的 Orleans, Java 上也有开源的 Orbit。并且 Orleans 的平台在微软内部有很多的实际应用,包括 Halo 的服务器也应用了,并能达到上百万的在线。

相对于 Erlang,Akka 之类的基础 Actor 平台,Virtual Actor 更为简单易用,而 Erlang 由于更加底层,能够对自己的应用进行更好的调整。

如果 Nodejs 也能出一套类似于 Orleans 的框架,我觉得对于 Nodejs 实现更大系统有极大的帮助。

如何在 Windows 下配置 Ruby 开发环境

一般开发 Ruby/Rails 应用我们都会推荐使用 Linux、MacOS X。因为 Ruby 相关的很多工具链在这两个系统上都有成熟的生态。然而 Windows 毕竟是最普及的操作系统,所以我觉得有必要跟大家介绍一下如何在 Windows 下搭建Ruby/Rails 的开发环境。

大家可以考虑安装 RailsInstaller,或者 Bitnami RubyStack,这两个安装包集成了大部分常用的相关组件,有点类似于 PHP 生态中的 XAMPP 这样的软件。

RailsInstaller 包含以下内容:

Git 是用于管理源代码的工具,由于现在很多组件的安装可以直接用 Git 进行操作,所以一般需要安装。DevKit 其实是一个 MinGW 的环境,他是在 Windows 环境上用了一些相关的库来兼容一些*nix 的源代码,可以编译一些 *nix 下开发的源代码,Ruby 就是利用了 MinGW 编译出了 Windows 版本。在 Windows 系统上安装一些 Ruby 的 Gem 需要 DevKit 才能编译再安装。

而 Bitnami RubyStack 则包含更多的工具,如: ImageMagick(图像处理工具),MySQL 数据库,Apache,Nginx 等等。

当然,RailsInstaller 和 Bitnami RubyStack 都比较庞大,如果仅仅只是学习 Ruby,也可以只安装 Ruby 解释器。RubyInstaller 是专门为 Windows 编译的 Ruby 分发包——在 Ruby 官网上是没有直接的 windows 安装包下载的。

推荐安装 Ruby 2.2或者2.1版本的,本人比较偏好32位版(非64位,出于某些兼容性考虑)。

安装一个编辑器也是必须的,现在比较推荐使用 Atom

接下来很多操作需要在『控制台』中完成,在 Windows 的开始菜单选择『运行』,输入『cmd』回车,就可以启动一个控制台。

如果在控制台中输入『ruby -v』,回车后能看到诸如以下内容的文本,就表示 Ruby 已经安装成功了:

$ ruby -v
ruby 2.1.5p273 (2014-11-13 revision 48405) [x86_64-darwin13.0]

由于国内的一些特殊的网络状况,在安装 Ruby gems 的时候经常会无法下载,这时候我们需要利用国内淘宝的 Ruby gems 镜像来替代官方镜像,安装它的网站上指南进行替换:

这样就能基本保证以后 Gems 的安装不会因为网络问题而失败。

最后,还需要再安装 Node.js,由于 Rails 自带了对 CoffeeScript 的支持,而 CoffeeScript 的官方编译器是由 JavaScript 写成的,所以在 Rails 把 CoffeeScript 编译成 JavaScript 的过程中,需要调用某个 Javascript 引擎。在这里我们选择使用 node.js,效率较高。

欢迎观看我的直播 http://www.douyutv.com/413281

教孩子们什么编程语言好?

如今计算机已经非常普及了,智能手机也基本上人手一部了。美国总统也在吹嘘人人都要会编程。我有两个小孩,作为一个码农,总得把这门手艺传递下去。那么我就寻思究竟教他们什么好呢?

回想我个人的编程经历,最早是初中开始接触编程的。因为参加信息学奥赛,第一门学习的语言是 Pascal,然后又自学了诸如 Basic,C,Logo 等等。

我的印象中,我最喜欢的便是 Basic,原因就是他简单。Logo 也很好玩,但是功能过于简单,没法实现复杂的功能。Pascal 则过于严格。C 最让人难以入门的便是指针,而且非常容易出错。了解指针往往还需要有一些操作系统常识,否则也不能理解其中的原理。

中学时代之后还学习了 C++和 Java,但实际上都没有掌握其精髓,以当时的心智还不能理解面向对象,对于 C++的模板也是不能理解具体开发中如何使用。

其实对于一个初学者来说,最重要的是引导他建立编程的基本概念,培养他的兴趣。这个过程中应该尽量减少他们的心智负担,像什么 C 的指针,Java 中面向对象的什么 abstract,interface, C++中的 virtual、引用等等,这些深奥的概念,对初学者并不友好,如果没有实际工作经验,会让人深陷不自信的状态,无法自拔,最后往往放弃。在这方面,我觉得脚本语言在这方面则比较有优势,既没有特别严格的格式,有些也不需要强调类型系统,把关注点集中在编码本身。

另一个很重要的就是可视化,或者说所见即所得。对于孩子们来说,他们的抽象思维还不足以达到成人这样,可以直接对着一些抽象的数据进行开发。对于他们来说,像真实世界一样的东西是最好理解的,因为人的心智就是从这样的世界中进化出来的。

同时如果能立刻得到反馈,则非常有助于孩子们在编程中的探索,像一些 reactive programming 的环境,就非常好,Logo 就是这样的。

基于以上的经验,我把孩子的编程学习分成两个阶段。

第一阶段是启蒙阶段,大约就是小学阶段。根据我前面所说的三点,1. 减轻心智负担,集中于编程本身 2. 可视化  3. 实时反馈。目前首选的是 Scratch 语言。

Scratch 由 MIT 发明,就像搭积木一样,他把各种要素以积木的方式呈现给学习者,通过积木的组合来形成指令,不得不说是一种创新。然而这种概念在某些程度上是继承了 Squeak Smalltalk 的 Etoy,但是依托于互联网时代,得到了发扬光大。

第二阶段是转型阶段,有两种选择:

A 方案,让孩子们在这个阶段跟上逐渐接受工程化的开发思想。尝试教授诸如 Ruby,Python,JavaScript 这类脚本语言。逐渐引导让他发现现实生活中的需求,让他能把需求转化成设计和代码,并通过测试再去修改调试代码。通过迭代的方式不断完善代码。期间会让他熟悉敏捷开发的方式,了解单元测试,GIT 等等。

采用这个方案的孩子,在高中就基本上可以拥有非常强的实际开发能力,能独立完成小的产品。即便不上大学,也完全可以胜任一般的工作。

B 方案,让孩子们钻研算法,参加信息学竞赛。这样的好处是如果能得奖,保送进大学也是非常不错的方案,在大学里继续深造,最后进入大公司做专精的方向也是非常好的。但是毕竟竞赛是残酷的,能得奖的也就那么几个人。

以上毕竟只是设想,同时除了编程之外,还有很多精彩的东西。

重启博聆网

在本人加入暴走漫画之后,原来的创业项目博聆网就被搁置了。去年底因为文化部查处黑暗童话类信息导致博聆网被关停。到今年6月份,网站服务器到期,续费也是一笔不小的开支。但毕竟作为我曾经自己的项目,总有割舍不掉的感情。

不管怎样,失败的项目还是要总结一下的。

博聆网最初的定位是想做一个兴趣社区的平台,里面每个小组围绕一个兴趣点,网友在其中进行互动。做这个平台的本质是让用户能看到优质的内容,有足够的用户在这里可以进行社交。而初期来说没有足够的内容,也没有足够的用户,以我个人和两个同伴又不能原创,即便种子用户也没有能找到一个专精的突破口,却创建了过多的小组分散了内容和用户。随后,我给小组的帖子加入了过多的功能,希望帖子能设置为图片、视频、外部网页,投票,flash等等,却没有直接使用富文本排版,这种做法类似于做一个复杂的对象数据库,因为不同的格式会有不同的字段,这令技术实现难度变得很大,然后缺忽视了不同类型的帖子之间在用户体验上的差别,用户又因为提交内容要选择不同的格式,并没有提升用户的效率和体验。最后,在移动互联网刚开始的时候,因为自己对移动应用开发的不熟悉,没有迅速切入,痛失良机。

当然,目前我的状况也不可能对博聆网做什么大的功能升级。只是为了几个骨灰级网站用户继续维护这个网站。所以我对博聆网做了大量的功能清理,比如去除了过去的个人 timeline,完全转型成一个论坛的形式,不同的帖子格式也都统一起来,成为最简单的文本帖子。而小组的数量也会被清理,先从最基本的灌水小组开始,如果人多了,再增加不同的版块。同时,尽量优化用户体验,如果有可能,则做一个手机 app。

 

RabbitMQ简介

RabbitMQ是一个很受欢迎的消息中间件,通过它可以很方便地实现异构子系统之间的通讯,还可以将不同子系统之间进行解耦。它用erlang开发,基本上是实现了AMQP 1.0标准的消息协议。

了解RabbitMQ首先要了解以下一些概念:Message,Producer、Exchange、Queue、Consumer

Message是一些简单的字符串, Producer(Publisher)是实际发布消息的角色

Queue,是实际存放消息的地方。顾名思义,消息从Queue一端放入,另一段由Consumer(Subscriber)取出,如果有多Consumer,每个consumer各自取出不同的消息进行处理。

当Producer发布消息的时候,首先是发布到Exchange,然后RabbitMQ根据Exchange的类型和逻辑来判断应该发送到哪个Queue中。所以Queue必须bind到特定的Exchange上才能获取到消息,绑定的时候可以提供一个routing_key来判断选择什么消息,Publisher在发出信息的时候就可以指定不同的routing_key来选择如何分发消息。

当使用最基本的队列模式的时候,可以不指定exchange,这时候会使用默认exchange来进行消息的发送。

Exchange和Queue都有自己的名字,多个Publisher可以发布到同一个Exchange,多个Consumer也可以订阅到同一个Queue。

RabbitMQ支持的Exchange方式有:

  • direct 直接投递
  • fanout 广播投递
  • topic 可以按照一个topic名字的模式进行匹配routing_key,例如topic.*可以匹配topic.paragraph和topic.paragraph.word,而topic.#
  • rpc Producer可以等待Consumer处理消息结束并把结果返回给Producer

Ruby下可以使用基于EventMachine的异步客户端amqp,或者是同步模式的bunny和carrot。

用bunny,以topic订阅为例:

publisher部分:

consumer部分

RabbitMQ集群和High Scalability

由于RabbitMQ实现的是AMQP,它非常强调一致性,而AMQP本身就是一种适用于金融行业的消息协议。根据CAP原理,一致性、高可用性和分区容忍性只能选两项,RabbitMQ提供了三种配置选项:

  • ignore:默认配置,发生网络分区时不作处理,当认为网络是可靠时选用该配置
  • autoheal:各分区协商后重启客户端连接最少的分区节点,恢复集群(CAP 中保证 AP,有状态丢失)
  • pause_minority:分区发生后判断自己所在分区内节点是否超过集群总节点数一半,如果没有超过则暂停这些节点(保证 CP,总节点数为奇数个)

由于使用Erlang开发,RabbitMQ可以非常方便的搭建集群,可以随时加入节点,这些节点之间是互相等同的,可以在客户端随机选择节点,或者使用诸如haproxy等进行负载均衡反向代理,以达到水平扩展的目的。