[分布式系统学习] 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 ...
随机推荐
- 代码记录——phase16,block32
HRESULT RotateZoom(PBYTE pbSrc,int iWidth,int iHeight,double dbRotate,double dbZoom,PBYTE pbTag) { / ...
- ActiveMq持久化数据
A:持久化为文件 这个你装ActiveMQ时默认就是这种,只要你设置消息为持久化就可以了.涉及到的配置和代码有 <persistenceAdapter> <kahaDB direct ...
- Docker容器的生命周期管理
https://blog.csdn.net/u010278923/article/details/78751306
- MTK 永不熄屏
步骤一: 源码/frameworks/base/packages/SettingsProvider/res/values/defaults.xml 修改<integername=</int ...
- OpenCV学习笔记:opencv_highgui模块
一,简介 本模块为跨平台的gui/IO组件,支持平台包括windows,linux,mac,IOS,android,可支持图像/视频/摄像头的读取显示以及转码. 二,分析 本模块为跨平台的gui/IO ...
- 微信公众号支付-Common
using System.Web; /// <summary> /// 公共帮助类 /// </summary> public class Common { private H ...
- iOS: 解决某些第三方库因为ARC不能使用的问题
1.在target下面的build phases下有一个compile source,下面有很多待编译文件.可以看到一个compile flag,可以针对某些文件进行arc设置.这样,某些框架不能使用 ...
- 虚拟机安装linux系统无法上网的解决方法
原文:https://www.jb51.net/article/118267.htm 周末闲来无事,用虚拟机安装了centos6.5系统,安装成功后发现不能连接网络,然后我就一脸蒙蔽了,无奈之下,只能 ...
- 创建Maven创建src/main/java提示反复
建立好一个Maven项目后.假设Java Resources资源文件下没有src/main/java目录,而且在手动创建这个文件时提示"已存在文件". 这说明,在这个项目配置中已经 ...
- iOS提交审核:您的 App 正在使用广告标识符 (IDFA)
本文转载至 https://mp.weixin.qq.com/s?__biz=MzA3NzM0NzkxMQ==&mid=401172721&idx=1&sn=a369cf1b ...