采用asyncore进行实时同步
最近在维护项目的时候,发现某个实时数据同步功能非常容易失败,故静下心来彻底弄清楚该设计的实现原理,以及其中用到的python异步sockethandler : asyncore。
实时数据同步功能的设计非常简单,用户在网页上触发某个记录的"Sync Up" button, 后台把该记录的id和type传入asyncore Client,asyncore Client把信息传入local的另一个asyncore server进程,asyncore server端调用相应的同步数据API,进行同步,并把同步的数据信息(包括同步过程的log和status)写入数据库;同时在click button的时候,会触发一个循环的js call,不断发出异步请求,获取存入的实时同步log信息,把log信息打印到页面上,更新progress bar。
asyncore Client:
class Client(asyncore.dispatcher_with_send):
def __init__(self, host, port, message):
asyncore.dispatcher.__init__(self)
self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
self.connect((host, port))
self.out_buffer = message
self.response = '' def handle_close(self):
self.close() def handle_read(self):
self.response = self.recv(1024)
self.close() def send(command):
c = Client('127.0.0.1', 8081, command)
asyncore.loop()
return c.response if __name__ == '__main__':
send('quit')
asyncore server
class asyncoreServer(asyncore.dispatcher): def __init__(self, address, handlerClass=ServerHandler):
print ">>> Server Socket init with address:%s:%s" % (address[0], address[1])
self.address = address
self.handlerClass = handlerClass
self.address_family = socket.AF_INET
self.socket_type = socket.SOCK_STREAM
self.request_queue_size = 5
self.allow_reuse_address = True asyncore.dispatcher.__init__(self)
self.create_socket(self.address_family,self.socket_type) if self.allow_reuse_address:
self.set_reuse_addr() self.server_bind()
self.server_activate() def server_bind(self):
self.bind(self.address)
log.debug("bind: address=%s:%s" % (self.address[0], self.address[1]))
print ">>> Begin bind server" def server_activate(self):
self.listen(self.request_queue_size)
log.debug("listen: backlog=%d" % self.request_queue_size) def fileno(self):
return self.socket.fileno() def serve_forever(self):
asyncore.loop() def handle_accept(self):
(conn_sock, client_address) = self.accept()
print "Receive Client request socket=%s, client_address=%s:%s" % (conn_sock, client_address[0], client_address[1])
if self.verify_request(conn_sock, client_address):
self.process_request(conn_sock, client_address) def verify_request(self, conn_sock, client_address):
return True def process_request(self, conn_sock, client_address):
log.info("conn_made: client_address=%s:%s" % (client_address[0],client_address[1]))
self.handlerClass(conn_sock, client_address, self) def handle_close(self):
self.close()
关于asyncore的介绍:
asyncore库是python的一个标准库,它是一个异步socket的包装。
asyncore提供一个方法和一个基类:loop()方法和dispatcher基类。
每一个继承dispatcher的类的对象,都可以看做一个需要处理的Socket,可以是TCP也可以是UDP,子类override一些dispatcher的方法,主要是重写‘handle_’打头的方法,比如:
handle_connect, handle_close, handle_read, handle_write ...
loop()方法负责检查一个dict, dict中保存dispatcher的实例,这个字典被称为channel。每次创建一个dispatcher对象,都会把自己加入到一个默认的dict里面去(当然也可以自己指定channel)。当对象被加入到channel中的时候,socket的行为都已经被定义好,程序只需要调用loop(),一切功能就实现了。
reference:
https://docs.python.org/2/library/asyncore.html
采用asyncore进行实时同步的更多相关文章
- lsyncd 实时同步
1. 几大实时同步工具比较 1.1 inotify + rsync 最近一直在寻求生产服务服务器上的同步替代方案,原先使用的是inotify + rsync,但随着文件数量的增大到100W+,目录下的 ...
- 烂泥:rsync与inotify集成实现数据实时同步更新
本文由秀依林枫提供友情赞助,首发于烂泥行天下. 上篇文章我们介绍了如何使用rsync同步文件,这篇文章我们再来介绍下,如何把rsync与inotify集成实现数据的实时同步. 要达到这个目的,我们需要 ...
- Rsync+Inotify-tools实现数据实时同步
inotify是一种强大的,细粒度的,异步文件系统时间监控机制,它可以替代crond实现与rsync的触发式文件同步,从而监控文件系统中添加,删除,修改,移动等细粒事件,从LINUX 2.6.13起, ...
- rsync+inotify实现服务器之间文件实时同步--转
之前做了“ssh信任与scp自动传输脚本”的技术文档,此方案是作为公司里备份的方法,但在实际的运行中,由于主服务器在给备份服务器传输的时候,我们的主服务器需要备份的文件是实时.不停的产生的,造成不知道 ...
- linux下两台服务器文件实时同步方案设计和实现
inux下两台服务器文件实时同步方案设计和实现 假设有如下需求: 假设两个服务器: 192.168.0.1 源服务器 有目录 /opt/test/ 192.168.0.2 目标服务器 有目录 /o ...
- hexo建立github,gitcafe博客并实时同步的要点
把hexo博客的源码和生成的页面实时同步到github和gitcafe. 用搜索引擎搜索"github 博客"等关键字会出现大量很好的文章教小白一步步搭建.我这里列出一些关键点,希 ...
- lsyncd —— 多机器实时同步文件神器
lsyncd 是一个支持实时.双向.多机器的多模式文件同步工具. 使用 Lua 语言封装了 inotify 和 rsync 工具,采用了 Linux 内核(2.6.13 及以后)里的 inotify ...
- rsync+inotify实现实时同步案例【转】
1.1 inotify介绍 inotify是一种强大的.细粒度的.异步的文件系统事件控制机制.linux内核从2.6.13起,加入了inotify支持,通过inotify可以监控文件系统中添加.删除. ...
- sersync基于rsync+inotify实现数据实时同步
一.环境描述 需求:服务器A与服务器B为主备服务模式,需要保持文件一致性,现采用sersync基于rsync+inotify实现数据实时同步 主服务器A:192.168.1.23 从服务器B:192. ...
随机推荐
- LightOJ1105 Fi Binary Number(数位DP)
题目要求第k个没有连续两个1的二进制数. 这算数位DP吧,只不过以前遇到的是统计区间的数字情况,而这题是求第几个数字,差不多是反过来的. 本来我想用状态dp[i][0/1]表示长度i末尾0或1的二进制 ...
- Partran,Nastran和ANSYS的区别
Partran .Nastran是MSC公司的产品.Patran是前处理器,用于建模.划分网格.设定载荷和边界条件等等:Nastran只是MSC公司提供的求解器之一,主要用于结构分析和热分析,应用的是 ...
- 什么是 IntentService
service 默认也运行在 UI 线程,所以里面不能直接做耗时操作,要做耗时操作还得开启子线程来做. IntentService 就是一个 Service, 只不过里面给你默认开启了一个子线程来处理 ...
- Java中的线程
http://hi.baidu.com/ochzqvztdbabcir/item/ab9758f9cfab6a5ac9f337d4 相濡以沫 Java语法总结 - 线程 一 提到线程好像是件很麻烦很复 ...
- Web 设计新趋势: 使用 SVG 代替 Web Icon Font
如果你还在使用 Icon Font 作为网页中显示图标的实现方案,那么你可能有点 Out 了. 由于使用 Icon Font 显示图标存在一些缺陷,开发者们一直在致力于探索使用 SVG 作为替代的方法 ...
- Windows环境下Redis
Redis 是一个高性能的key-value数据库, 使用内存作为主存储,数据访问速度非常快,当然它也提供了两种机制支持数据持久化存储.比较遗憾的是,Redis项目不直接支持Windows,Windo ...
- zabbix企业级监控概述和部署
官方网站:http://www.zabbix.com/ zabbix是一个基于WEB界面的提供分布式系统监视以及网络监视功能的企业级的开源解决方案 zabbix能监视各种网络参数,保证服务器系统的安全 ...
- javascript 原型及继承
一般继承方式如下 function people(n){ this.name =n; } function worker(name,num){ people.call(this, name); thi ...
- [转]Efficiently Paging Through Large Amounts of Data
本文转自:http://msdn.microsoft.com/en-us/library/bb445504.aspx Scott Mitchell April 2007 Summary: This i ...
- YII 查找View的5种方式
别名开头,路径指定view文件@app/views/site/about.php //开头,使用 app目录下面的views//site/about.php /开头,使用当前Module中的views ...