[分布式系统学习] 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 ...
随机推荐
- linux下使用yum安装 mencached
1. 安装 yum -y install memcached 2. 启动memcached ./usr/bin/memcached -d -m 256 -u root -p 11211 -c 1024 ...
- linux 按照端口一句命令杀死进程,按照进程名称一句命令杀死进程
例如杀死nginx 按照程序名称杀死进程 例如杀死nginx的进程 ps -aux|grep nginx|grep -v grep|cut -c 9-15|xargs kill -9 或者 ps -a ...
- Python对象(上)
Python是一门面向对象的语言,在Python中一切都是对象,函数是对象,类型也是对象. 下面就看看Python中对象相关的内容. Python对象基本概念 Python对象有三个基本的要素: 身份 ...
- 开发还是应该使用linux
这几天在Windows系统下,安装了几个IDE,体量大,4.5个G,启动速度慢,占用系统资源多,并且最难受的是,这些IDE的限制性太强,只能按照UI给定的规则来操作,例如现在手中有一个已完成的项目,用 ...
- window.open被拦截
1)直接调用window.open 或 点击的时候直接调用 window.open 是不会被拦截的 // 不会被拦截$('.btn-open').click(function(){ window.op ...
- Hbase 管理页面
进入Hbase首页可以查看各种信息: http://192.168.23.128:16010/master-status
- 【DVWA】Web漏洞实战之File Upload
File Upload File Upload,即文件上传漏洞,一般的上传漏洞可能是未验证上传后缀 或者是验证上传后缀被bypass 或者是上传的文件验证了上传后缀但是文件名不重命名. LOW 直接上 ...
- 利用DB实现简单去重处理
业务需要针对某文件进行判重操作,用Perl实现如下 #!/usr/bin/perl my %h; s/\s+$// and $h{$_}++ while <>; print "$ ...
- 第四篇:MapReduce计算模型
前言 本文讲解Hadoop中的编程及计算模型MapReduce,并将给出在MapReduce模型下编程的基本套路. 模型架构 在Hadoop中,用于执行计算任务(MapReduce任务)的机器有两个角 ...
- 解决react-router 的activeClassName 首页重复匹配问题
首先先看一下我的inedx.js入口文件: 这是未点击的时候index默认的是选中状态, 这是我点击其他的路由之后:,明显index路由重复了,仔细看了官方文档之后,发现其实Navlink也应该使用e ...