Sunday, December 13, 2009

[宅男学厨]三明治

今年出去买了鸡蛋和煎锅:)瞅着手边的材料,除了上次还没用完的土司就还有番茄和奶酪等.那么就做个简单的三明治吧.

将土司去边,从对角线切开,奶酪也如此对切。

去鸡蛋一枚,入碗打散,加入少许盐.将之前的土司夹奶酪浸入碗中,三边开口处都要粘满蛋汁哦.

将土司丢入煎锅,先用中火炸四边,待封口后,转用小火炸两边.至两面均酥皇,将剩余的鸡蛋汁全部交上去,片刻后起锅:)




Friday, December 11, 2009

[宅男学厨]煎蛋,培根与吐司

昨天晚上和March Liu交流了下做饭的心得,得其真传.今天决定从最简单的开始,打好基本功.给自己做一顿早餐.

看看手边的材料,似乎鸡蛋为最.在我系统分析了33种鸡蛋相关做法之后,我决定做史上最有名的......煎蛋吧.岂料杯具发生了,家里的鸡蛋被我放置的太久,竟然,竟然坏掉了很多(:

好不容易找到了一个能用的,打蛋装碗.

锅里放油,开火,以油熟且尚未冒烟为宜(否则,你的油就会...)好,就是此刻,将鸡蛋丢入锅中,待蛋白部分发白略黄的时候,在其周围加水若干滴(保证下形状,嘿嘿).加盐.翻转鸡蛋,煎另一面.起锅.



怎么样,第一次煎蛋还算不错吧:)

接着,将培根丢入锅中约2min,起锅,配合我事前准备的奶酪.


战斗结束,历时6min ;)之前在网上查看食谱的时候,见到一种做法:


两片厚片土司去边 一个鸡蛋加少许盐打散 一片或两片奶酪 
平底锅里放一点黄油熔化后 将去边土司加好奶酪片 放在鸡蛋液里沾一下 
四周都要沾到 夹起来沾好蛋的土司 在锅里 用中火煎 先煎四边 
再煎两面 然后转小火 将剩下的鸡蛋均匀的倒上去 如果没剩下鸡蛋 
就免了这一步了 之后用小火慢慢煎到两面金黄松脆 里面的奶酪半融化状
的时候 就能吃了 非常好吃 蛋香奶香麦香稍微有点淡淡的咸味

 
厨艺果然是创意无限.不知为啥我想起了Bitmap来:)

使用coLinux+Debian+Putty+Emacs构建快速开发环境

本博的笔记本比较古董,跑VirtualBox之流甚是吃力,更不用说Vmware这样的超级杀器.本来一直采用的是Msys来进行*nix的模拟的,不过由于某些软件包实在不给面子,害的我每次都得连接至公司的服务集群上进行测试,如此下来,多有不便:(

于是乎,经过一番爆狗,终于找到了coLinux这样的好东西.CoLinux是在Windows上能够运行的linux. 在Windows计算机上安装Linux的时候,可以不用追加新的硬盘,也不用重新做分区等工作。 如果使用coLinux的话,不重新安装Windows,不变更硬盘分区就可以很轻松地构筑Linux环境。

如果说Cygwin是在C库程序阶段模拟UNIX(在源码级别的互换性)的话,则coLinux是在能驱动真的Linux原核程序上,与Linux和应用程序具有互换性。即:Debian和Fedora能够直接运行。换句话说,coLinux就是一个 Linux 内核,它经过修改,以与另一个操作系统协作运行。主机操作系统(Windows 或 Linux)控制操作系统的物理资源,而访客(guest)操作系统(coLinux)获得硬件的虚拟抽象。主机操作系统必须提供以特权级别(ring 0)执行驱动程序的方法,并提供分配内存的方法.

接下来的事情就很容易了,猛击此处下载当前的coLinux的二进制版本,同时本博下载了列表下方的Debian5.0的压缩包.运行coLinux的安装程序,一路Next至Over(安装目录最好不要出现中文或空格).解压前述Debian的压缩文件至coLinux的老巢.接下来,可以使用Debian提供的BAT脚本直接执行了.

不过也许各位已经发现Debian里只有2GB左右的空间,而且貌似不能上网也没有开启sshd.接下来我们一步一步解决这些问题:

首先,再次猛击一下下,我们得到一个已经做好的4GB大小的分区文件(下载文件很小,只有4xKB的样子).解压丢至coLinux的基地去.

接着,在你的Debian里配置下第二块网卡(eth1):
allow-hotplug eth1
iface eth1 inet static
address 192.168.1.6 //根据实际情况,自行改变
gateway 192.168.1.1
netmask 255.255.255.0

这里贴下我的coLinux.conf文件
# The default kernel
kernel=vmlinux

# File contains the root file system.
# Download and extract preconfigured file from SF "Images for 2.6".
cobd0="Debian-5.0r2-lenny.ext3.2gb"

# Swap device, should be an empty file with 128..512MB.
cobd1="fs_root" //扩展的4GB文件

cofs0=d:\ //与Windows交互设置,这是coLinux自己的方式

root=/dev/cobd0

initrd=initrd.gz

# Slirp for internet connection (outgoing)
# Inside running coLinux configure eth0 with this static settings:
# ipaddress 10.0.2.15   broadcast  10.0.2.255   netmask 255.255.255.0
# gateway   10.0.2.2    nameserver 10.0.2.3
eth0=slirp //dhcp
# Tuntap as private network between guest and host on second linux device
eth1=tuntap //这里就是之前在系统里设置的eth1

启动进入系统,进行挂载测试

mkdir -p /mnt/ext
mount -t ext3 /dev/cobd1 /mnt/ext

如果可以访问的话,那么写入你的/etc/fstab.系统启动时会自动挂载

/dev/cobd1 /root ext3 defaults 0 1 //这里我用来扩展了/root,你自然也可以改成/home/xxx 不过记得拷贝文件

类似的,将windows交互目录挂载进来

mkdir -p /mnt/host
mount -t cofs cofs0 /mnt/host

接下来,重启系统,通过apt-get install ssh来打开sshd,选择putty登陆上去.编译Emacs之前记得先安装ncurses (:

展示下效果


这个黑黑的CMD窗口就是coLinux启动的Debian终端,如果觉着不爽,也可以用colinux-daemon把其做成系统服务.最后赞一下,coLinux的速度真的很快

Wednesday, December 2, 2009

基于REST风格构建WEB应用的实践反思

江湖上有着这样一则传闻:
面试官:"请问REST是虾米?"
面试者:"哦,您放心,我是永远不知道休息的..."

我想面试官的这个问题,本文的读者应该大体是有一个概念的.不过为了行文的方便,这里本博还是将REST的核心原则摘录于下:.

  • 为所有“资源”定义标识(URI)
  • 将所有资源链接在一起
  • 使用标准方法
  • 资源多重表述
  • 无状态通信

由于公司战略需要一款SNS产品,本博有幸参与了整个开发活动,并主持了架构设计和实现.因此得以实战REST,并将前后遇到的一些问题和思考记录下来,遂成此文.


那么为啥会考虑采用REST作为系统架构风格呢?

首先,由于是一款自己运营SNS产品,根据产品规划部门制定的需求,在技术上要求我们实现大量的用户行为记录,同时还要为用户提供包含博客、相册、视频在内的web2.0“标准”应用以及支持第三方植入应用的OpenAPI体系.因此系统在安全性,并发性,稳定性,扩展性等方面均有较高的要求.
其次,由于项目团队的人员配备,开发模式,开发周期等因素的影响,敏捷开发也成为一个潜在的要求.
针对这些客观实际情况,本博考察了主流SNS的技术方案,结合自身特定,决定采用REST来实施构建:

  1. 资源URI可以有效描述系统涉及的角色(用户,及其产生的行为结果),无论是在用户群体还是在单一个用户对象.
  2. 系统对外以URL形式(对内则是URI)来与客户端通讯,这也是负载均衡得以实施的前提
  3. URI(Entity,QueryString,Method)封装了编程实体,后端程序可以有效建立Resource-Object映射,配合Key-Value缓存以及ORM等技术手段优化,可以满足对伸缩性的要求.
  4. REST提倡的HTTP操作方法封装了数据操作的CRUD
  5. URI之间的聚合(combination)有效建立起一组可复用的API体系.


实践中采用REST风格来构建项目,较为显著的带来了两个方面的提升:技术层次上,团队内推广和普及了敏捷开发,并在实践中性能成一套符合自身情况的开发流程;在HTTP协议,Web服务器,键值缓存,开发语言等方面开拓了技术视野并形成了相应的技术积累.管理层次上,由于构建REST应用的需要,将人员合理分配成应用开发,API开发等不同的小组,责权分明.但是很显然,这一架构的引入不可能是一帆风顺的,在实践中我们也遇到了很多问题,很多场景下我们也不得不去破坏学术定义(REST Anti-Pattern REST反模式):

  • 什么是资源?
        这样一个基础的命题上,保持怎样一个粒度,对API的构建乃至整个系统至关重要.是按照"语义"级别,将用户定义为/user/uid这样,还是针对系统级别,将数据表结构定义为资源.在这个问题上,内部产生了很多的思考和争议.虽然我们最终采用了类似前者的思路,但是这只是根据当时需求情况的取舍,这样的定义来带的后果是对"简单数据"CRUD的极大便利;资源交叉高复用,原子操作性较强.但是对集合类似资源(用户组等)至少在概念层次上是无力的,往往需要引用大量的SQL模板来进行封装使用,这也成为性能的一个隐患.而实际上后端开发人员80%的事情均用在这里(从整体最优来看,也是值得的).
        反之,如果我们将数据表,列这些定义成为资源的话,那么实际上我们将走到一条Meta-Data(元数据)编程的路子上.显然在逻辑层次上我们将不需要去考虑业务中角色以及相互关联的
问题.这种类似"虚拟机"(提供一套策略而不是机制)的架构风格应对复杂逻辑是绰绰有余的.但是在SNS这样一个毕竟存在大量单一应用以及"简单数据"访问的情况下,这样有似乎有点"过度设计".当然这只决定于需求和性能之间的平衡.

  • 对Method的使用
        几乎任何一份REST实践指南的资料中都指出过DELETE和PUT的模拟问题,使用GET/POST去实现这样一种模拟.
        完全的使用GET方式去实现,这么做的唯一好处,是开发便利:只需要将这样一条URL贴到浏览器的地址栏中,就可以完成测试.但是,这样的系统本身并没有把URI看成是"资源",而仅仅是
一种传递参数的字符串而已.同时这种链接一般不可加入书签,而且有“爬虫”造成非预期副作用的风险(假设你传递了一个?method=delete这样的参数).
        完全的使用POST方式去实现,这种做法被flicker等知名网站广泛使用,但实际上走回了SOAP的老路上.他不但完全忽视了REST的根本原则并且接下来也无法利用"缓存".我们的系统采
用这种方式的原因是设计上的"便捷"(:
  
  • NoSQL?
        SNS为NoSQL的思想贡献了相当大的关注力,这种思想意图使用key-value键值数据库来完全取代现在有的关系型数据库,通过键值缓存技术来提升性能.虽然如此,但NoSQL对系统的设计要求是相当之高,否则很容易就会发现构建出来的系统几乎不能满足良好的扩展性.

  • 工具与方法论
        开发初期,如何能使更多的开发人员理解REST思想,并应用于开发活动,我们提供了一个在线的调试器,当你输入URL的时候,可以查看返回数据以及相关信息.国内的Taobao开放平台也提供
了类似的沙盒环境(sandbox).推广一种工具往往比推广一种思想要容易的多.当我们意识到并不是所有人都需要明白什么是REST的时候,我们提供了一组language binding clinet library.


软件开发世界没有"银弹",试图用一种架构风格/模式去解决遇到的所有问题是不现实的.在实践中遇到的种种问题,探究他们的缘起以及解决之道,有利于加深对REST架构的理解和应用.那么,当我们 意识到这些问题,并尝试解决的时候,不妨跳出原有的思维局限,开拓眼界,引入更加符合实际情况的混合架构风格设计方案,这也是我们下一代技术产品的思路,并且有打算以开放源码的方式展现在 大家眼前,提供一个Resty的"砖头".