- 1、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。。
- 2、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载。
- 3、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
- 4、该文档为VIP文档,如果想要下载,成为VIP会员后,下载免费。
- 5、成为VIP后,下载本文档将扣除1次下载权益。下载后,不支持退款、换文档。如有疑问请联系我们。
- 6、成为VIP后,您将拥有八大权益,权益包括:VIP文档下载权益、阅读免打扰、文档格式转换、高级专利检索、专属身份标志、高级客服、多端互通、版权登记。
- 7、VIP文档为合作方或网友上传,每下载1次, 网站将根据用户上传文档的质量评分、类型等,对文档贡献者给予高额补贴、流量扶持。如果你也想贡献VIP文档。上传文档
查看更多
C语言分布式系统中的进程标识
C语言分布式系统中的进程标识
本文假定一台机器 (host) 只有一个 IP,不考虑 multihome 的情况。同时假定分布式系统中的每一台机器都正确运行了 NTP,各台机器的时间大体同步。
“进程 process”是操作系统的两大基本概念之一,指的是在内存中运行的程序。在日常交流中,“进程”这个词通常不止这一个意思。有时候我们会说 “httpd 进程”或者“mysqld 进程”,指的其实是 program,而不一定是特指某一个“进程”——某一次 fork() 系统调用的产物。一个“httpd 进程”重启了,它还是“一个 httpd 进程”。本文讨论的是,如何为一个程序每次运行 的进程取一个唯一标识符。也就是说,httpd 程序第一次运行,进程是 httpd_1,它原地重启了,进程是 httpd_2。
本文所指的“进程标识符”是用来唯一标识一个程序的“一次运行”的。每次启动一个进程,这个进程应该被赋予一个唯一的标识符,与当前正在运行的所有进程都不同;不仅如此,它应该与历史上曾经运行过,目前已消亡的进程也都不同(这两条的直接推论是,与将来可能运行的进程也都不同)。“为每个进程命名”在分布式系统中有相当大的实际意义,特别是在考虑 failover 的时候。因为一个程序重启之后的新进程和它的“前世进程”的状态通常不一样,凡是与它打交道的其他进程(s)最好能通过它的进程标识符变更来很容易地判断该程序已经重启,而采取必要的救灾措施,防止搭错话。
本文先假定每个服务端程序的端口是静态分配的,在公司内部有一个公用 wiki 来记录端口和程序的对应关系(然后通过 NIS 或 DNS 发布)。比如端口 11211 始终对应 memcached,其他程序不会使用 11211 端口;3306 始终留给 mysqld;3690 始终留给 svnserve。在分布式系统的初级阶段,这是通常的做法;到了高级阶段,多半会用动态分配端口号,因为端口号只有 6 万多个,是稀缺资源,在公司内部也有分配完的一天。本文只考虑 TCP 协议,不考虑 UDP 协议,“端口”都指的是 TCP 端口。
另外,我们假定在一台机器上,一个 listening port 同时只能由一个进程使用,不考虑古老的 listen() + fork() 模型(多个进程可以 accept 同一个端口上进来的连接),关于这点陈硕已经写的很多,见《Linux 新增系统调用的启示 》《多线程服务器的适用场合 》。
错误做法
在分布式系统中,如何指涉(refer to)某一个进程呢,或者说一个进程如何取得自己的全局标识符 (以下简称 gpid)?容易想到的有两种做法:
*ip:port (port 是这个进程对外提供网络服务的端口号,一般就是它的 tcp listening port)
*host:pid
而这两种做法都有问题。为什么?
如果进程本身是无状态的,或者重启了也没有关系,那么用 ip:port 来标识一个“服务”是没问题的,比如常见的 httpd 和 memcached 都可以用它们的惯用 port (80 和 11211)来标识。我们可以在其他程序里安全地引用(refer to)“运行在 :80 的那个 http 服务器”,或者“:11211 的 memcached”,就算这两个 service 重启了,也不会有太恶劣的后果,大不了客户端重试一下,或者自动切换到备用地址。
如果服务是有状态的,那么 ip:port 这种标识方法就有大问题,因为客户端无法区分从头到尾和自己打交道的是一个进程还是先后多个进程。在开发服务端程序的时候,为了能快速重启,我们一般都会设置 SO_REUSEADDR,这样的结果是前一秒钟站在 :8888 后面的进程和后一秒钟占据 :8888 的进程可能不相同——服务端程序快速重启了。
比方说,考虑一个类似 GFS 的分布式文件系统的 master,如果它仅以 ip:port 来标识自己,然后它向 shadows (不是 chunk server)下达同步指令,那么 shadows 如何得知 master 是不是已经重启呢?发指令的是 master 的“前世”还是“今生”?是不是应该拒绝“前世”的遗命?
如果考虑改成 host:pid 这种标识方式会不会好一点?我认为换汤不换药,因为 pid 的状态空间很小,重复的概率比较大。比如 Linux 的 pid 的最大值是 32768 (/proc/sys/kernel/pid_max),一个程序重启之后,获得与“前世”相同 pid 的概率是 1/32768。或许有读者不相信重启之后 pid 会重复,因为 pid 是递增的,遇到上限再回到目前空闲的最小 pid。考虑一个
文档评论(0)