erlang 热更新实现分析

原文 2015-02-10 01:08:22 发表于 CSDN,这里对以前写的文章做下收录。

Joe Armstrong 在描述 Erlang 的设计要求时,就提到了软件维护应该能在不停止系统的情况下进行。在实践中,我们也因为这种不停止服务的热更新获益良多。那么 Erlang 是如何做到热更新的呢?这就是本文要讨论的问题。

erlang VM 为每个模块最多保存 2 份代码,当前版本'current'和旧版本'old',当模块第一次被加载时,代码就是'current'版本。如果有新的代码被加载,'current'版本代码就变成了'old'版本,新的代码就成了'current'版本。erlang 用两个版本共存的方法来保证任何时候总有一个版本可用,对外服务就不会停止。

前言

为什么代码热更新时不影响进程运行?
为什么进程要使用外部调用(M:F/A)才能切换到新代码?
为什么可以同时使用2个版本的代码?
为什么只能一个模块一个模块热更?
....

我们总会有很多疑问,但一切的答案都在源码上。现在深入剖析下 erlang 热更新实现机制,相信你的疑惑可以找到答案。
继续阅读erlang 热更新实现分析

lua5.3 垃圾回收分析

前注

最近我一直在看lua gc,阶段性做一下总结。网上很多文章没讲明白,我也当弥补下这个问题。文章以我看的lua 5.3.6做分析。

lua 垃圾回收发展历程

5.0 及以前使用的是双色标记清除法,gc 过程会停止主程序执行,直到 gc 完成;
5.1 实现了增量式 gc,采用三色标记法,gc 过程分多步,与主程序交替执行;
5.2 实现了分代 gc,实际效果不理想;
5.3 移除了分代 gc;
5.4 重新实现了分代 gc

两种标记清除算法

标记清除算法,就是遍历所有对象,将还在使用的对象打上标记,遍历完成后,没有标记的对象就是垃圾对象,要清理掉。

所以,系统至少需要记录两个数据集合,一个是所有的对象集合,一个是还在使用的对象集合。在 lua 中,还在使用的对象集合包括了全局变量、 栈中对象、处于激活状态的协程等。
继续阅读lua5.3 垃圾回收分析

lua table怎么检查数据变了

为了缓解数据库压力,数据会缓存在lua table,满足频繁读写需求,再定时检查,发现数据变了则落地。

问题来了,lua table怎么检查数据变了?

table检查数据变了

答案很简单,使用 metatable,这里贴一个简单的例子。

-- db数据
db = {openid="openid_123", token="token_123"}

-- 缓存
cache = {}

setmetatable(cache, {
	__index = function(t, k)
		return db[k]
	end,
	__newindex = function(t, k, v)
		if k ~= "__dirty" then
			db.__dirty = true
		end
		db[k] = v
	end,
	__pairs = function(t, k)
		return next, db, k
	end,
})


for k, v in pairs(cache) do
	print(k, v)
end

cache.__dirty = nil
print("cache.__dirty", cache.__dirty)

cache.token = "token_456"
print("cache.__dirty", cache.__dirty)


执行结果如下:

> dofile("test.lua")
token   token_123
openid  openid_123
cache.__dirty      nil
cache.__dirty      true

问题到这里就结束了。

接下来,我们再提出一个问题,lua table如何检查子项为table的数据变了?
继续阅读lua table怎么检查数据变了

Google Protobuf协议分析

原文 2014-12-22 00:07:12 发表于 CSDN,这里对以前写的文章做下收录。

protobuf 是google开源的一个序列化框架,类似xml,json,最大的特点是基于二进制,比传统的XML表示同样一段内容要短小得多。还可以定义一些可选字段,用于服务端与客户端通信。前面几篇文章说了protobuf的用法,看到网上也没有分析protobuf协议的文章,就利用一些时间写了 protobuf 的协议分析。

protobuf协议核心思想
基于128bits的数值存储方式(Base 128 Varints)
数据表示方式:每块数据由接连的若干个字节表示(小的数据用1个字节就可以表示),每个字节最高位标识本块数据是否结束(1:未结束,0:结束),低7位表示数据内容。(可以看出数据封包后体积至少增大14.2%)

数字1的表示方法为:0000 0001,这个容易理解
数字300的表示方法为:1010 1100 0000 0010
继续阅读Google Protobuf协议分析

Erlang集群IP及端口管理

原文 2015-06-25 02:23:52 发表于 CSDN,这里对以前写的文章做下收录。

erlang集群是依靠epmd维护的,epmd是erlang集群节点间端口映射的守护进程,负责维护集群内的节点连接,提供节点名称到IP地址及端口的解析服务。

epmd 自定义端口号

epmd端口配置
默认情况下,epmd绑定在4369端口。但是,端口固定的话,容易遭受攻击,可能导致新节点的认证失败而无法启动,或无法加入集群。或者要在一台机器上部署不同的erlang集群,希望不会互相干扰。
epmd -daemon -port 5000
如果想用调试模式启动 epmd,使用 epmd -d -port 5000

另外,epmd通常伴随着erlang节点启动时自动启动,无须手动处理,所以,这里也可以通过修改erl启动参数以达到自动调整epmd端口。
erl -name hello@127.0.0.1 -epmd "epmd -port 5000 -daemon" 
继续阅读Erlang集群IP及端口管理