[分布式系统学习] 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 ...
随机推荐
- geoserver 添加图层数据
1.添加shapefile文件 首先到http://www2.census.gov/geo/tiger/TIGER2011/CONCITY/上下载名称为tl_2011_47_concity的shape ...
- 解决webStorm没有cesium代码自动提示的方法
Webstorm中默认是没有cesium代码提示的,但是可以通过设置让它有智能提示 File -> Settings -> Languages&Frameworks -> J ...
- node.js模块依赖及版本号
摘要: Node.js最重要的一个文件就是package.json,其中的配置参数决定了功能.例如下面就是一个例子 { "name": "test", &quo ...
- python tornado异步性能测试
测试两个接口 # -*- coding:utf-8 -*- import time import tornado.web import tornado.gen import tornado.ioloo ...
- MTK 时区修改
1.修改packages/apps/Settings/res/xml-xx-xx/timezones.xml (xx-xx表示不同的语言和区域),添加下面的内容: <!-- timezo ...
- Git Step by Step – (6) Git远程仓库
前面文章中出现的所有Git操作都是基于本地仓库的,但是日常工作中需要多人合作,不可能一直都在自己的代码仓库工作.所以,这里我们就开始介绍Git远程仓库. 在Git系统中,用户可以通过push/pull ...
- ios开发之--UITableView中的visibleCells的用法
先上图: 具体代码如下: #import "ViewController.h" @interface ViewController ()<UITableViewDelegat ...
- JSONP 劫持漏洞实例
0x01 Jsonp简介 Jsonp(JSON with Padding) 是 json 的一种"使用模式",可以让网页从别的域名(网站)那获取资料,即跨域读取数据. 为什么我们从 ...
- RGB24转YUV420
BOOL RGB2YUV(LPBYTE RgbBuf, UINT nWidth, UINT nHeight, LPBYTE yuvBuf, unsigned long *len) { if (RgbB ...
- 把Model改成Lib
1.把库的Activity删掉 2.把库的Application节点内容删掉 3.apply plugin:' 包名.library' 4.把ApplicationId去掉, 导入即可使用