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中尚无此接口。
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;
}
参考资料
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)
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]
在.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的几个概念:
加法分解
今天在首尔大学读硕士的老同学问了我一个简单的算法,他的要求描述是:
多项式参数的穷举:
1*A1+2*A2+3*A3+...+n*An=n
n是固定值,要打印出所有A的排列。
太久没写算法,发现自己在一天的班上下来后,思考能力已经退化到可怕的境界了。最后花了2个多小时才完全写好,通过测试。
简要分析一下(以5为例子):
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 或以上版本
想对其扩展的朋友,可以联系我拿源码。
为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>