[分布式系统学习] 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 ...
随机推荐
- 【matlab】命令行窗口一直不停的输出ans=1?
ans= 1 matlab里面的ans是一个系统量,当m文件中出现非赋值性的计算时,matlab会把结果自动存入ans. 如果m文件中每一个计算都是赋值的,即所计算的结果都是保存在自己设定的变量中的, ...
- 在jsp中使用jstl,不使用JS,实现递归,生成N级菜单
参考材料: http://blog.csdn.net/kimsoft/article/details/7801564 我的实现: 1.我的recursionMenu.jsp代码如下: <%@ ...
- HTML5标签canvas制作平面图
摘要: HTML5规范已经完成了,互联网上已经有数不清的站点使用了HTML5.从现在开始研究HTML5,本文是自己在学习canvas过程中的记录,以备后需. 历史: 这个 HTML 元素是为了客户端矢 ...
- Dubbo -- 系统学习 笔记 -- 示例 -- 多协议
Dubbo -- 系统学习 笔记 -- 目录 示例 想完整的运行起来,请参见:快速启动,这里只列出各种场景的配置方式 多协议 可以自行扩展协议,参见:协议扩展 (1) 不同服务不同协议 比如:不同服务 ...
- Spring @Scheduled定时任务动态修改cron参数
在定时任务类上增加@EnableScheduling注解,并实现SchedulingConfigurer接口.(注意低版本无效) 设置一个静态变量cron,用于存放任务执行周期参数. 另辟一线程,用于 ...
- 【Cesium】坐标理解(转)
https://blog.csdn.net/qq_34149805/article/details/78393540 1. 经纬度转换为世界坐标 第一种方式:直接转换: Cesium.Cartesia ...
- Qt Creator build遇到error lnk1158 无法运行rc.exe
解决办法: 将C:\Program Files (x86)\Windows Kits\10\bin\10.0.15063.0\x64 目录下的rc.exe 和rcdll.dll 复制到 C:\Prog ...
- Linux centos 下 eclipse 打开文件时关闭
原文地址:http://processors.wiki.ti.com/index.php/Linux_Host_Support#cairo-misc.c:380:_cairo_operator_bou ...
- Linux配置示例:配置java环境变量
1.修改/etc/profile文件 如果你的计算机仅仅作为开发使用时推荐使用这种方法,因为所有用户的shell都有权使用这些环境变量,可能会给系统带来安全性问题. (1)用文本编辑器打开/etc ...
- 非IMU模式下DML语句产生的REDO日志内容格式解读
实验内容:非IMU模式下DML语句产生的REDO日志内容格式解读 最详细的解读是UPDATE的. 实验环境准备 11G中默认是开启IMU特性的,做此实验需要关闭此特性. alter system se ...