Neio Notes Share knowledge and experience with you

30Oct/095

Thrift C#for Hypertable Issue

前言

近日在为Hypertable做一层.NET(C#)的封装,遇到了一个较为严重的问题:用Thrift封装的Hypertable C#客户端在连接Hypertable ThriftBroker的时候被主动断开,造成数据无法读取的现象。

过程

1、用Wireshark检查了TCP封包,观察到在发送第一笔数据后就被Hypertable ThriftBrokeryper主动发送FIN结束了连接,于是后面发送数据就丢掉了,更不用说接收信息;

2、检查Hypertable中的日志,查看到以下信息:
TConnection : transition() Negative Frame Size -2147418111, remote side not using TFramedTransport?
注意到这里可以看出,Hypertable使用了TFramedTransport作为其传输层接口。然而,C#的Thrift中尚无此接口。

26Oct/096

Thrift简介

Thrift是一个跨语言服务部署框架,最初由Facebook于2007年开发,后于2008年进入Apache孵化器(Apache Incubator)。

类似于SOAP,COM 和CORBA,Thrift通过定义一个中间定义语言和Thrift代码生成工具,生成指定语言的代码。目前,Thrift支持C++,Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, Smalltalk和OCaml的代码生成。

简单分析其机理,Thrift就是实现C/S模式,通过代码生成工具将接口定义文件生成服务器端和客户端代码(可以为不同语言),从而实现服务端和客户端跨语言的支持。

Thrift可以分为传输层和协议层:

1、传输层定义了数据的传输方式,可以为TCP/IP传输,内存共享或者文件共享等形式;
2、协议层定义了数据的传输格式,可以为二进制流或者XML等形式。

简单例子:

中间语言定义:

struct UserProfile {
1: i32 uid,
2: string name,
3: string blurb
}
service UserStorage {
void store(1: UserProfile user),
UserProfile retrieve(1: i32 uid)
}

Python客户端代码:

# Make an object
up = UserProfile(uid=1,
                 name="Mark Slee",
                 blurb="I'll find something to put here.")

# Talk to a server via TCP sockets, using a binary protocol
transport = TSocket.TSocket("localhost", 9090)
transport.open()
protocol = TBinaryProtocol.TBinaryProtocol(transport)

# Use the service we already defined
service = UserStorage.Client(protocol)
service.store(up)

# Retrieve something as well
up2 = service.retrieve(2)

服务器端代码:

class UserStorageHandler : virtual public UserStorageIf {
 public:
  UserStorageHandler() {
    // Your initialization goes here
  }

  void store(const UserProfile& user) {
    // Your implementation goes here
    printf("store\n");
  }

  void retrieve(UserProfile& _return, const int32_t uid) {
    // Your implementation goes here
    printf("retrieve\n");
  }
};

int main(int argc, char **argv) {
  int port = 9090;
  shared_ptr<UserStorageHandler> handler(new UserStorageHandler());
  shared_ptr<TProcessor> processor(new UserStorageProcessor(handler));
  shared_ptr<TServerTransport> serverTransport(new TServerSocket(port));
  shared_ptr<TTransportFactory> transportFactory(new TBufferedTransportFactory());
  shared_ptr<TProtocolFactory> protocolFactory(new TBinaryProtocolFactory());
  TSimpleServer server(processor, serverTransport, transportFactory, protocolFactory);
  server.serve();
  return 0;
}

参考资料

1. http://incubator.apache.org/thrift

25Oct/090

First C++ Programming Experience with Hypertable(A)

前言

目前正在为Hypertable做一层封装,使之通过ZeroMQ或RabbitMQ提供一个通用数据访问接口。

说来蛮郁闷的,编译一个Hypertable的example耗费了我一天半的时间。一来,网速慢,下载boost, thrift, log4cpp等库,耗费了很多时间;二来,没有在Linux下做过项目。

下面我以example里面的freebase作为例子,说明编译环境的配。

编译Freebase例子

一、环境

Ubuntu 8.10

hypertable 0.9.2.7  (hypertable-0.9.2.7-linux-i386.deb

25Oct/090

Ubuntu源出现公钥问题的解决方式

Ubuntu等debian系统使用中,若添加第三方源,在apt-get update的时候可能会出现NO_PUBKEY的错误提示。

解决方式:

根据apt-get update出现的pubkey提示,运行以下两句可以解决问题:

$gpg --keyserver keyserver.ubuntu.com -recv-key [所提示的公钥]

$gpg --export --armor [所提示的公钥] | sudo apt-key add -

-----------------------------

added on 2009.10.27

or
sudo apt-key adv --recv-keys --keyserver keyserver.ubuntu.com [YOURKEY]

[THE END]

21Oct/090

在Linux下使用Google拼音输入法

习惯于Windows下的搜狗输入法,真觉得在Linux下的拼音输入法非常不顺手。

近日才恍然发现某位仁兄移植了Android下的谷歌输入法到Linux下(链接),于是赶紧弄下来体验了一把。总体感觉顺手很多,当然也有少许的BUG(例如有时候输入完拼音后,直接只显示了拼音原文而不是汉字)。

下面是安装步骤(需要自己编译):

A. 获取代码:

$ git clone git://github.com/tchaikov/scim-googlepinyin.git
$ cd scim-googlepinyin.git

B. 编译前提:

上面给的链接里面有介绍怎么编译的,但少提了几个必需组件,这里列一下:

* autotools-dev
* libgtk2.0-dev
* libscim-dev
* libtool
* automake1.9

用下面命令看看是不是安装了,如果没有,会自动帮你安装上:

$ aptitude install autotools-dev libgtk2.0-dev libscim-dev libtool automake1.9

C. 编译:
记住系统必须先存在SCIM(没有的话 sudo apt-get install scim 一下)

$ ./autogen.sh
$ make
$ sudo make install

大功告成,重启下SCIM然后就能体验了。

17Oct/0911

在.NET上使用ZeroMQ

前言

最近在设计一个Web系统(公司在建项目,故保密不能详述),要满足高并发,高访问量、高可靠性的需求,又会涉及到多种业务外部系统,甚至业务可能是可“热插拔”的形式,同时又要最求成本最低。

考虑到总总因素,排除了使用Oracle数据库,以及其他各种商业组件的方案;同时又由于公司项目很多,缺乏人手来自己开发一些组件,故除了业务系统是自己开发外,其他基本上采用了清一色的开源软件。 由于业务比较复杂,同时大量使用了各种开源系统,会使用到C++, Java, Erlang, C#, PHP等众多语言。故设计用系统总线(Bus)来作为消息的介质,协调整体的运行,而这条总线的性能和特性也将关系到系统的命运。

RabbitMQ or ZeroMQ?

经过比较选型,从多语言的支持的角度,最后筛选得到RabbitMQ和ZeroMQ两个选择。

RabbitMQ是采用Erlang开发的,支持完善的AMQP协议;ZeroMQ使用C语言开发,重点在于效率;两者均有多语言支持,其中ZeroMQ支持得较多。

比较看, RabbitMQ支持的AMQP协议,较为完整和复杂;而ZeroMQ的接口极为简单。速度上,还未对亲自对两者做压力测试。从网上的资料看,RabbitMQ较慢,几十个并发以内,延时为几十毫秒,但当客户端达到1000个并发的时候,速度就无法容忍了(参考);ZeroMQ上则据称可以达到13毫米延时和高达每秒4.1兆次传递(参考, 国内需要翻墙才能访问)。如果队列较多的话,RabbitMQ很容易把内存耗尽,而ZeroMQ则把队列内容保存在发送端。

故最终还是决定选择了ZeroMQ,然后在上面加一层我自己的封装,作为Web系统的消息总线。

在.NET上使用ZeroMQ

ZeroMQ的.NET封装很简单,基本上是来自C-API的,但有所简化。使用上,由于习惯了在C#里面用强类型约束,API上的int类型让我感觉封装得"非常不.NET"

首先要明确下ZeroMQ的几个概念:

12Oct/090

加法分解

今天在首尔大学读硕士的老同学问了我一个简单的算法,他的要求描述是:

多项式参数的穷举:
1*A1+2*A2+3*A3+...+n*An=n
n是固定值,要打印出所有A的排列。

太久没写算法,发现自己在一天的班上下来后,思考能力已经退化到可怕的境界了。最后花了2个多小时才完全写好,通过测试。
简要分析一下(以5为例子):

11Oct/094

Password Reader for CuteFTP Pro 8【含工具下载】

平时都直接用CuteFTP来管理各个服务器,竟然把密码都忘记掉了。痛定思痛,确定从CuteFTP中把密码挖出来。

CuteFTP Pro中,密码显示都是*号,即使用里面的站点管理器(Site Manager)导出,用的也是星号。用Spy++查看密码框,是空的,也就是说那个框只能用来输入。

那么,要找出密码,可以有三种方法:

一、抓包

用Wireshark(即Ethereal)等工具,可以简单地根据FTP协议分析出来。这个方法以前用过,但似乎对于SSL等连接,这种方法变得不切实际。

二、分析内存

用OllyDbg等工具,调试分析之,然后从内存中找出来。此方法费时费力,每次找都要花一番功夫。

三、读取CuteFTP Pro的文件

我们知道CuteFTP Pro的密码都保存在sm.dat文件中。那么只要分析出sm.dat的结构和密码存储的方法,就可以读出来了。

分析过程不多说,只说结果:

在sm.dat文件中,对于每个站点,都用相同的结构。每个站点前是 0B 00 00 00,接下去是“记录名”,然后是几条类型数据,再下去就是站点,用户名,密码等。(其他不累赘了)密码当然不是用明文,而是加密过的。加密后的密码和原文长度一致,是一一对应的。下面是我分析出其规则后写的解密算法:

uint L = code & 0xF;
L = L > 7 ? L - 8 : L + 8;
uint H = ((code & (byte)0xF0)) - 0x80;
H = H > 0x30 ? H - 0x40 : H + 0x40;
byte PCode = (byte)(L + H);

随手写了个CuteFTP Pro 的密码读取器,用MPL协议发布
CuteFTP Pro Password Reader
上面是编译后的文件下载地址。

注意:运行这个程序需要.NET Framework 2.0 或以上版本

想对其扩展的朋友,可以联系我拿源码。

9Oct/091

为Apache2添加URL重写

上一次碰Apache已经是好几年前的事情了,也很久没有弄过PHP。现在准备重开博客,在自己的Ubuntu上先安装了WordPress,照例要开启URL重写。

现在的Apache配置比过去方便多了,国内文章中关于rewrite的配置一大堆,但都显得过时,或者过于麻烦。所以我单列这篇出来,希望对初学者有所帮助。

过去,一般要打开apache2.conf或者httpd.conf,在里面使用LoadModule 来加载rewrite_module,现在可以不用这么写了。

比较简单的方法是用:

"a2enmod rewrite"

这样一条命令就可以搞定。当然,如果你当前不是Ubuntu的管理员,前面记得加上“sudo”。

然后记得重启下Apache服务器。(/etc/init.d/apache2 restart

然后在你要允许使用rewrite的站点配置中,例如安装apache的时候的默认站点:

sudo gedit /etc/apache2/site-enabled/000-default

把里面的AllowOverride None 改为 AllowOverride all

DocumentRoot /var/www/

<Directory />

Options FollowSymLinks

AllowOverride all

</Directory>

<Directory /var/www/>

Options FollowSymLinks

AllowOverride all

Order allow, deny

allow from all

</Directory>