Archive for April, 2014

作者:AngryFox 分类: Uncategorized April 22nd, 2014 暂无评论

RabbitMQ支持全方位的互联网轻量级的消息传递协议,包括HTTP,HTTPS,STOMP,XMPP,SMTP以及广泛的消息通讯模式 ,包括点对点(RPC的风格),点和射,发布-订阅,多播,主题,路由,RPC等
1.rabbitmq DB会存储关于user,virtual host,持久化消息等信息
此目录下有两个文件夹:db,log
并会使用到这些资源:
virtual host:/
user:guest/guest [实际使用的账号]
guest会分配所有的权限到virtual host / 上

一、在php.ini里面设置 max_execution_time = 1800;
二、通过PHP的ini_set 函数设置 ini_set(“max_execution_time”, “1800″);
三、通过set_time_limit 函数设置 set_time_limit(1800) ;

Twitter的finagle,淘宝的dubbo
client 发起调用,框架拦截调用信息,序列化,传输,server端收到调用信息,反序列化,根据调用信息发起实际调用获取结果,再原路返回。

http://nacl.cace-project.eu/ 加密库

tar -C /usr/local -xzf **.tar.gz
查看linux机器是32位还是64位的方法: file /sbin/init 或者 file /bin/ls /sbin/init

https://www.npmjs.org/

Listen、Accept、Read、Write四个函数的底层实现关系

添加fd到epoll、从epoll删除fd等),只有4个函数,分别是runtime·netpollinit、runtime·netpollopen、runtime·netpollclose和runtime·netpoll。init函数就是创建epoll对象,open函数就是添加一个fd到epoll中,close函数就是从epoll删除一个fd,netpoll函数就是从epoll wait得到所有发生事件的fd,并将每个fd对应的goroutine(用户态线程)通过链表返回。

void
runtime·netpollinit(void)
{
	epfd = runtime·epollcreate1(EPOLL_CLOEXEC);
	if(epfd >= 0)
		return;
	epfd = runtime·epollcreate(1024);
	if(epfd >= 0) {
		runtime·closeonexec(epfd);
		return;
	}
	runtime·printf("netpollinit: failed to create descriptor (%d)\n", -epfd);
	runtime·throw("netpollinit: failed to create descriptor");
}
这两个create函数分别等价于glibc的epoll_create1和epoll_create函数
事件驱动的抽象层来为网络库提供一致的接口,从而屏蔽事件驱动的具体平台依赖实现。
runtime/netpoll.goc源文件就是整个事件驱动抽象层的实现,抽象层的核心数据结构是:
struct PollDesc
{
	PollDesc* link;	// in pollcache, protected by pollcache.Lock
	Lock;		// protectes the following fields
	uintptr	fd;
	bool	closing;
	uintptr	seq;	// protects from stale timers and ready notifications
	G*	rg;	// G waiting for read or READY (binary semaphore)
	Timer	rt;	// read deadline timer (set if rt.fv != nil)
	int64	rd;	// read deadline
	G*	wg;	// the same for writes
	Timer	wt;
	int64	wd;
};

net库中的这次封装实现在net/fd_poll_runtime.go文件中,主要是通过pollDesc对象来实现的:

type pollDesc struct {
runtimeCtx uintptr
}
pollDesc对象的runtimeCtx成员才是指向的runtime的PollDesc实例

消费者:接收消息
逻辑:创建连接–>创建channel–>创建交换机–>创建队列–>绑定交换机/队列/路由键–>接收消息

生产者:发送消息
逻辑:创建连接–>创建channel–>创建交换机对象–>发送消息

作者:AngryFox 分类: Uncategorized April 12th, 2014 暂无评论
-module(area_server_final).
-export([start/0, area/2]).

start() -> spawn(fun loop/0).

area(Pid, What) ->
        rpc(Pid, What).

rpc(Pid, Request) ->
        Pid ! {self(), Request},
        receive
                {Pid, Response} ->
                        Response
        end.

loop() ->
        receive
                {From, {rectangle,Width, Ht}} ->
                        From ! {self(), Width * Ht},
                        io:format("Area of rec is ~p~n", [Width * Ht]),
                        loop();
                {From, {circle, R}} ->
                        From ! {self(), 3.14159 * R * R},
                        io:format("Area of c is ~p~n", [3.14159 *R *R]),
                        loop();
                {From, Other} ->
                        From ! {self(), {error, Other}},
                        io:format("I that area ~p is ~n", [Other]),
                        loop()
        end.

在erlang shell中运行

Eshell V5.9  (abort with ^G)
1> Pid = area_server_final:start().
<0.33.0>
2> area_server_final:area(Pid, {rectangle,10,8}).
Area of rec is 80
80
3> area_server_final:area(Pid, {circle,4}).
Area of c is 50.26544
50.26544

for(Max, Max, F) -> [F(Max)]
for(I, Max,F) -> [F[I]|for(I+1,Max, F)]

在erlshell中启动 webtool:start().
然后在浏览器中分析错误

Pid = spawn(Fun)
Pid ! Message !为发送操作符
Pid1!Pid2!….!M将消息M发送到Pid1、Pid2等所有进程中
receive … end 接受一个发给当前进程的消息

作者:AngryFox 分类: Uncategorized April 10th, 2014 暂无评论

AMQP(高级消息队列协议 Advanced Message Queue Protocol)

AMQP当中有四个概念非常重要: 虚拟主机(virtual host),交换机(exchange),队列(queue)和绑定(binding)。一个虚拟主机持有一组交换机、队列和绑定。为什么需要多个虚拟主机呢?很简单,RabbitMQ当中,用户只能在虚拟主机的粒度进行权限控制。因此,如果需要禁止A组访问B组的交换机/队列/绑定,必须为A和B分别创 建一个虚拟主机。每一个RabbitMQ服务器都有一个默认的虚拟主机“/”。

Producer 要产生消息必须要创建一个 Exchange ,Exchange 用于转发消息,但是它不会做存储,如果没有 Queue bind 到 Exchange 的话,它会直接丢弃掉 Producer 发送过来的消息,当然如果消息总是发送过去就被直接丢弃那就没有什么意思了,一个 Consumer 想要接受消息的话,就要创建一个 Queue ,并把这个 Queue bind 到指定的 Exchange 上,然后 Exchange 会把消息转发到 Queue 那里,Queue 会负责存储消息,Consumer 可以通过主动 Pop 或者是 Subscribe 之后被动回调的方式来从 Queue 中取得消息。
蓝色– Client(相对于Rabbitmq Server来说)

绿色–Exchange
红色—Queue

– 交换器(Exchange),它是发送消息的实体。
– 队列(Queue),这是接收消息的实体。
– 绑定器(Bind),将交换器和队列连接起来,并且封装消息的路由信息。

左边的Client向右边的Client发送消息,流程:

1, 获取Conection
2, 获取Channel
3, 定义Exchange,Queue
4, 使用一个RoutingKey将Queue Binding到一个Exchange上
5, 通过指定一个Exchange和一个RoutingKey来将消息发送到对应的Queue上,
6, 接收方在接收时也是获取connection,接着获取channel,然后指定一个Queue直接到它关心的Queue上取消息,它对Exchange,RoutingKey及如何binding都不关心,到对应的Queue上去取消息就OK了

一个Client发送消息,哪些Client可以收到消息,其核心就在于Exchange,RoutingKey,Queue的关系上

RoutingKey就像是个中间表,将两个表的数据进行多对多关联,只不过对于相同的Exchange和Queue,可以使用不同的RoutingKey重复关联多次。

Exchange在定义的时候是有类型的,以决定到底是哪些Queue符合条件,可以接收消息
fanout
所有bind到此exchange的queue都可以接收消息
direct
通过routingKey和exchange决定的那个唯一的queue可以接收消息
topic
所有符合routingKey(此时可以是一个表达式)的routingKey所bind的queue可以接收消息
表达式符号说明:#代表一个或多个字符,*代表任何字符
例:#.a会匹配a.a,aa.a,aaa.a等

*.a会匹配a.a,b.a,c.a等
注:使用RoutingKey为#,Exchange Type为topic的时候相当于使用fanout

rabbitmq流控机制原理—实质上就是通过监控没各进程的mailbox,当某个进程负载过高来不及接收消息时,这个进程的mailbox就会开始堆积消息,当堆积到一定量时,就会阻塞住上游进程让其不得接收新消息,从而慢慢上游进程的mailbox也会开始积压消息,到了一定的量也会阻塞上游的上游的进程接收消息,最后就会使得负责网络数据包接收的进程阻塞掉,暂停接收数据。

对于交换机,有两个重要的概念:

A,类型。有三种类型: Fanout类型最简单,这种模型忽略routingkey;Direct类型是使用最多的,使用确定的routingkey。这种模型下,接收消息时绑定’key_1′则只接收key_1的消息;最后一种是Topic,这种模式与Direct类似,但是支持通配符进行匹配,比如: ‘key_*’,就会接受key_1和key_2。Topic貌似美好,但是有可能导致不严谨,所以还是推荐使用Direct。

B,持久化。指定了持久化的交换机,在重新启动时才能重建,否则需要客户端重新声明生成才行。

需要特别明确的概念:交换机的持久化,并不等于消息的持久化。只有在持久化队列中的消息,才能持久化;如果没有队列,消息是没有地方存储的;消息本身在投递时也有一个持久化标志的,PHP中默认投递到持久化交换机就是持久的消息,不用特别指定。

thrift通过IDL生成Client和Processor,然后调用 protocol 和 transport

Thrift有多种可选的 protocol ,transport和server
支持的protocol
TBinaryProtocol 直接的二进制格式
TCompactProtocol 高效和压缩的二进制格式
TDenseProtocoal 与TCompactProtocol相比,meta信息略有不同
TJSONProtocoal JSON
TDebugProtocoal text 格式 方便调试

支持的 transport
TSocket 阻塞的io
TFramedTransport 非阻塞io
TFileTransport 可以将一组thrift请求写到文件中
TMemoryTransport 使用内存 I/O
TZlibTransport 使用zlib压缩

支持的server
TSimpleServer 单线程 阻塞
TThreadPoolServer 多线程 阻塞
TNonblockingServer 多线程 非阻塞
THsHaServer api说是TNonblockingServer的扩展,半同步半异步,我也看晕了,望指点。。

可定义的数据类型:
基本类型:
bool:布尔值,true 或 false,对应 Java 的 boolean
byte:8 位有符号整数,对应 Java 的 byte
i16:16 位有符号整数,对应 Java 的 short
i32:32 位有符号整数,对应 Java 的 int
i64:64 位有符号整数,对应 Java 的 long
double:64 位浮点数,对应 Java 的 double
string:未知编码文本或二进制字符串,对应 Java 的 String
结构体类型:
struct:定义公共的对象,类似于 C 语言中的结构体定义,在 Java 中是一个 JavaBean
容器类型:
list:对应 Java 的 ArrayList
set:对应 Java 的 HashSet
map:对应 Java 的 HashMap
异常类型:
exception:对应 Java 的 Exception
服务类型:
service:对应服务的类

作者:AngryFox 分类: Uncategorized April 5th, 2014 暂无评论

作为一个RPC框架,其性能方面主要是比拼序列化和反序列化两个方面。thrift要比protobuf 快近1倍。
thrift 提供多语言的支持,RPC,序列化等功能。
protobuf 提供了序列化功能。
avro 和thrift类似,但多了动态动态类型。
压缩率的话,protobuf要好一点
Baidu使用的ICE基于C++,开源

thrift允许你定义一个简单的定义文件中的数据类型和服务接口。以作为输入文件,编译器生成代码用来方便地生成RPC客户端和服务器通信的无缝跨编程语言。

g++ lex yacc boost libevent autoconf automake libtool pkg-config
./configure –prefix=安装目录【一般不指定安装目录即可】
make
make install

boost安装有点区别:
1>./bootstrap.sh –prefix=安装目录
2>./b2
3>./b2 install

2.安装thrift:(根据情况选择配置选项)
1>./configure –with-boost=boost安装目录 –prefix=安装目录
(可能遇到configure文件没权限,自己修改该文件的权限)
2>sudo make
3>sudo make install

第一步:编写相应的*.thrift 文件
第二步:thrift –gen erl *.thrift,将生成的gen-erl复制到src中
第三步:按照例子代码写一个模块,将*.thrift中的函数全都实现了,并在里面指定服务的端口号和启动thrift的框架
第四步:将上一步写的模块添加到整个程序启动过程的最末处,启动thrift开始对外提供服务。

有时候也会遇到问题:Makefile失败、环境变量错误或者搜索路径不对。我们在遇到这些问题时也会帮你处理这些问题(issue)。

1 启动和停止Erlang shell
在Unix系统(包括Mac OS X),可以从命令行启动Erlang shell:
erlang:halt() 是一个BIF,可以立即停止系统。不过这种方法也有个问题。如果正在运行一个大型数据库应用,那么系统在下次启动时就会进入错误回复过程,所以你应该以可控的方式关闭系统。

可控的关闭系统就是如果shell可用时就输入如下:

1> q().
ok
$这会将所有打开的文件写入磁盘,停止数据库(如果在运行),并且按照顺序关闭所有OTP应用。 q() 其实只是shell上 init:stop() 的别名。
2 修改开发环境
当你启动程序时,一般都是把所有模块和文件都放在同一个目录当中,并且在这个目录启动Erlang。如果这样做当然没问题。不过如果你的应用变得更加复杂时,你可能需要把它们分成便于管理的块,把代码放入不同的目录。而且你从其他项目导入代码时,扩展代码也有其自己的目录结构。

查看linux系统的几种方法:
uname -a
cat /proc/version
cat /etc/issue
lsb_release -a

erlang默认运行时是带有终端的,在开发过程中可以很方便的检查程序的bug,但在开发完成后,应该以后台的方式运行服务。
-noshell (该参数关闭终端,但依然不会后台运行,有输出时会直接打印到当前屏幕
-noinput 禁止终端下的输入
-hidden 隐藏运行
-detached 后台方式运行
其实最好用的就是-detached,如果将此参数加入启动脚本,程序会立即进入后台运行,你可以通过进程号将其调入到前台,在加入此参数运行服务器后,查看当前正在运行的程序,你会发现这个参数自动被分解成了 -noshell 和 -noinput, 所以,在加入-detached后,就不需要再加这两个参数了。