[分布式系统学习] 6.824 LEC2 RPC和线程 笔记
6.824的课程通常是在课前让你做一些准备。一般来说是先读一篇论文,然后请你提一个问题,再请你回答一个问题。然后上课,然后布置Lab。
第二课的准备-Crawler
第二课的准备不是论文,是让你实现Go Tour里面的crawler。Go Tour里面原有的实现是串行的,并且可能爬到相同的url。要求让你并行并去重。
简单想法就是,为了实现并行,爬每个url都是用goroutine;为了实现去重,每次开爬就把url放到map中。
不过这里有个知识点,Crawler函数最后返回成功,所有url都要爬完,所以需要一个机制去等待所有goroutine完成。查了一下可以用sync.WaitGroup。那一个直观的实现:
// Crawl uses fetcher to recursively crawl
// pages starting with url, to a maximum of depth.
func Crawl(url string, depth int, fetcher Fetcher) {
var collector Collector;
collector.fetchedUrl = make(map[string]bool)
CrawlInt(url, depth, fetcher, &collector)
collector.Wait()
} type Collector struct {
sync.Mutex
sync.WaitGroup
fetchedUrl map[string]bool
} func CrawlInt(url string, depth int, fetcher Fetcher, collector *Collector) {
if depth <= 0 {
return
}
collector.Lock()
if _, ok := collector.fetchedUrl[url]; ok {
//visited,
collector.Unlock()
return
}
collector.fetchedUrl[url] = true
collector.Unlock()
body, urls, err := fetcher.Fetch(url)
if err != nil {
fmt.Println(err)
return
}
collector.Add(len(urls))
fmt.Printf("found: %s %q\n", url, body)
for _, u := range urls {
go func (u string) {
CrawlInt(u, depth-1, fetcher, collector)
collector.Done()
}(u)
}
return
}
不过看到了答案,觉得答案很简洁,不仅没有用到WaitGroup,甚至连一个Lock都没有使用。
//
// Concurrent crawler with channels
// func dofetch(url1 string, ch chan []string, fetcher Fetcher) {
body, urls, err := fetcher.Fetch(url1)
if err != nil {
fmt.Println(err)
ch <- []string{}
} else {
fmt.Printf("found: %s %q\n", url1, body)
ch <- urls
}
} func master(ch chan []string, fetcher Fetcher) {
n := 1
fetched := make(map[string]bool)
for urls := range ch {
for _, u := range urls {
if _, ok := fetched[u]; ok == false {
fetched[u] = true
n += 1
go dofetch(u, ch, fetcher)
}
}
n -= 1
if n == 0 {
break
}
}
} func CrawlConcurrentChannel(url string, fetcher Fetcher) {
ch := make(chan []string)
go func() {
ch <- []string{url}
}()
master(ch, fetcher)
}
Crawler函数是那个CrawlConcurrentChannel。ch里面放的是每次fetch返回的页面数组。为什么不用到Lock呢?因为fetched map的判断和加入都在主线程中。
ch里面的urls当然可能重复,但是在主线程中已经判断过了不会重复fetch。
而通过n来判断是否所有页面都被爬取了。所以有n==sizeof (ch) == sizeof (fetched)。这里的sizeof指的是所有放入的,不是某一时刻的。
Go 的RPC
我们在前面一个Lab里面已经遇到过了。觉得有点像Soap的方式,不过完全没有Soap那么复杂,需要定义wsdl。
至少发送一次 vs 至多发送一次
至少发送一次:RPC lib 等待返回,如果超时,再发。这样多尝试几次,始终没有返回,就报错。
这样能解决问题么?如果是发送的克扣余额会出现什么问题?
所以“至少发送一次”对于只读操作,和可重入操作是有效的。比如我们上一个Lab中的Map和Reduce,都是可重入的。
至多发送一次:问题在于如何检测重复请求。
client可以发送一个唯一的ID(XID)用于验证重复。服务器做如下处理。
server:
if seen[xid]:
r = old[xid]
else
r = handler()
old[xid] = r
seen[xid] = true
这里要处理的问题是:
1. client怎么保证XID唯一?现在UUID可以做到,另外也可以通过ip地址加上序列号来做hash值。
2. 服务器要在某时刻清理调之前的请求,否则每个请求都放到seen map里面,那要爆掉了。client可以在每条RPC中都包含一个”已经收到#<X的回复“的信息,这样,服务器就可以抛弃它们。
3. 服务器正在处理某个request,但是新的request已经进来了,服务器不想做第二次,那么他可以设置一个”pending“flag,让新的request等待或者忽略。
Go语言的RPC策略是”至多发送一次“。
[分布式系统学习] 6.824 LEC2 RPC和线程 笔记的更多相关文章
- [分布式系统学习] 6.824 LEC1 MapReduce 笔记
什么是Map-Reduce呢? Map指的是一个形如下面定义的函数. def Map(k, v): //return [(k1, v1), (k2, v2), (k3, v3), ...] pass ...
- [分布式系统学习] 6.824 LEC3 GFS 笔记
Google File System 第三课的准备是阅读论文GFS.该论文是分布式系统中经典论文之一. 读完做一点小总结. GFS的feature 1. 非POXIS接口API,支持对文件和文件夹的创 ...
- Netty学习摘记 —— 再谈EventLoop 和线程模型
本文参考 本篇文章是对<Netty In Action>一书第七章"EventLoop和线程模型"的学习摘记,主要内容为线程模型的概述.事件循环的概念和实现.任务调度和 ...
- 分布式系统中的必备良药 —— RPC
阅读目录 前言 成熟的解决方案 剖析 性能测试 结语 一.前言 在上一篇分布式系统系列中<分布式系统中的必备良药 —— 服务治理>中阐述了服务治理的一些概念,那么与服务治理配套的必然会涉及 ...
- Java并发学习之二——获取和设置线程信息
本文是学习网络上的文章时的总结,感谢大家无私的分享. Thread类的对象中保存了一些属性信息可以帮助我们辨别每个线程.知道它的一些信息 ID:每一个线程的独特标示: Name:线程的名称: Prio ...
- [分布式系统学习]阅读笔记 Distributed systems for fun and profit 之一 基本概念
因为工作的原因,最近打算看一些分布式学习的资料.其中这个http://book.mixu.net/distsys/就是一篇非常适合分布式入门的介绍. 这个短小的材料有下面5个小的章节,图文并茂,也没有 ...
- spring学习 8-面试(事务,解决线程安全)
1.介绍一下Spring的事物管理 参考:Spring 学习7 -事务 2.Spring如何处理线程并发问题 Spring使用ThreadLocal解决线程安全问题 参考:Spring学习11- ...
- 【Hadoop】Hadoop RPC框架线程模型
1.线程模型 2.参考资料: 源码级强力分析hadoop的RPC机制:http://weixiaolu.iteye.com/blog/1504898Hadoop RPC框架:http://blog.c ...
- 分布式系统的发展演变以及RPC简介
场景 什么是分布式系统 分布式系统是若干独立计算机的集合,这些计算机对于用户来说就像单个相关系统. 分布式系统是建立在网络之上的软件系统. 注: 博客: https://blog.csdn.net/b ...
随机推荐
- QT运行出错:QObject::connect: Parentheses expected以及QObject::connect: No such slot ***
我在QGraphicsScene子类中添加了item的弹出菜单,并连接Action到槽函数,结果槽函数不起作用,输出:QObject::connect: No such slot *** C++ C ...
- 错误 Unable to find vcvarsall.bat 的终极无敌最完美的解决办法
Windows 上通过 pip 安装 python 包,经常会出现这种错误. 如:pip install pyodbc. 这种错误的简单明了解释就是:python 编译器找不到计算机上面的 VC 编译 ...
- cordova开发ios炸鸡
cordova/lib/copy-www-build-step.sh: Permission denied 解决办法: cd platforms/ios/cordova/lib sudo chmod ...
- 恶劣条件下的apache配置(Linux)
(本文出自yangjj ^_^) 前提:1.没联网,yum挂.2.至少要有GCC,要不玩个屁. 3.你有充足的咖啡并且有几个小时时间不想打dota. 4.你要做集群. 以上条件不满足其一,看到这里 ...
- Cookie 和 Session机制具体解释
原文地址:http://blog.csdn.net/fangaoxin/article/details/6952954 会话(Session)跟踪是Web程序中经常使用的技术,用来跟踪用户的整 ...
- 5 -- Hibernate的基本用法 --1 1 对象/关系数据库映射(ORM)
ORM的全称是Object/Relation Mapping ,即对象/关系数据库映射.ORM可理解成一种规范,它概述了这类框架的基本特征:完成面向对象的编程语言到关系数据库的映射.当ORM框架完成映 ...
- [转]Struts2多个文件上传
转载至:http://blog.csdn.net/hanxiaoshuang123/article/details/7342091 Struts2多个文件上传多个文件上传分为List集合和数组,下面我 ...
- RF使用ie浏览器访问页面,浏览器启动只显示This is the initial start page for the WebDriver server,页面访问失败
问题描述:启动ie浏览器后,页面显示如下: 问题定位: 1.IE页面缩放没有设置成100% 2.ie浏览器的安全模式设置是否都将“启动保护模式”勾选上 3.iedriver驱动版本号是否和seleni ...
- Ansible 如何查看模块文档
[root@localhost ~]$ ansible-doc -l # 列出所有模块 [root@localhost ~]$ ansible-doc cron # 查看指定模块的文档
- 由于更换硬盘没有删除系统自启动读取挂载硬盘导致系统报错:fsck.ext4 unable to resolve 'UUID=a4a7a0f7-b54f-4774-9fb1'
由于更换硬盘没有删除系统自启动读取挂载硬盘导致系统报错:fsck.ext4 unable to resolve 'UUID=a4a7a0f7-b54f-4774-9fb1' 此时进入系统已root模式 ...