Coder Social home page Coder Social logo

Comments (5)

chaozh avatar chaozh commented on July 17, 2024

线程是操作系统级别的并发机制,可以充分利用CPU的多个运算核心,在分布式系统中IO并发都会涉及多线程操作,比如启动一个线程等待其他Server返回IO信息时主线程可以继续处理下一个请求。多线程间可以共享数据信息,但是每个线程都会有自己的程序计数器(PC)、寄存器、栈等,线程是操作系统调度的最小资源单位。

Go语言支持程序多创建线程(在Go语言中表现为协程,即用户态线程,比操作系统级别的线程机制占用资源更少),通常线程数量比物理核数多,Go运行环境会调度这些线程在多核上运行,要注意线程也并非免费的,创建线程要比一个函数方法调用还是费资源。

使用线程时的挑战:

  • 共享数据:处理临界资源(比如使用锁解决)
  • 线程协调:等待资源容易导致死锁(使用Go语言的channel机制或WaitGroup解决)
  • 并发粒度:并发度越大,越容易出现竞争和死锁

本期问题:请完成Crawler并发练习

需要解决两个挑战:

  1. 安排IO并发:获取一个URL内容的同时处理另一个URL
  2. 每个URL保证仅处理一次:避免浪费带宽,需要机制记录URL的访问历史

from mit-6.824.

chaozh avatar chaozh commented on July 17, 2024

解决方案思考: 查看Crawler示例,Go语言中的并发练习

  • 方案,使用go协程和共享map结构:为每个url创建线程,需要使用lock和waitGroup保证顺序,同时保证map的存取操作原子性
  • 方案,使用channels:go内部实现使用锁保证,会自动阻塞等待资源

最佳解决方案:
尽量使用channel取代共享变量(shared memory),与子线程同步使用channels
可以使用Go语言的并发检查机制
比如go test -race mypkg

from mit-6.824.

chaozh avatar chaozh commented on July 17, 2024

Remote Procedure Call (RPC)

分布式系统的关键部分(后面的实验都会涉及使用RPC),RPC理想上想把网络通信实现同本地函数调用一样,RPC的目的:

  • 更容易编写网络通信程序
  • 隐藏客户端服务器通信的细节
  • 客户端调用更加像本地的过程调用
  • 服务端处理更加像本地的过程调用

Go语言有比较好的实现机制

一些实现需要考虑的细节:

  • 应该调用哪个服务器函数(handler)?
  • 序列化:需要格式化数据到网络包中,可能需要处理棘手的数组,指针,对象等。还有些东西你不能传递,比如channels和function等。
  • 绑定:客户端怎么知道应该跟谁通信?也许客户端使用服务器的hostname。也许使用命名服务,将服务名字映射到最好的服务器。
  • 线程:客户端可能使用多线程,多于一个调用没有被处理,对应的处理器可能会缓慢;服务器经常将每个请求放置在独立的线程中处理。

特别是需要考虑怎么处理失败?比如:网络丢包,网络断线,服务器运行缓慢,服务器崩溃等问题。
客户端如何对待RPC请求失败?

  • 客户端没有获取到服务器的回复。
  • 客户端不知道服务器是否接收到请求!也许服务器的网络在发生请求前就失败了。

简单方案是实现“至少一次”机制:RPC库等待回复一段时间,如果还是没有回复到达,重新发生请求。重复多次,如果还是没有回复,那么返回错误给应用程序。但是需要应用处理可能出现的多个写副本(因为多次请求导致)

更好的方案是实现“至多一次”机制:服务器的RPC代码发现重复的请求,返回之前的回复,而不是重写运行。客户端让每一个请求带有唯一标示码XID(unique ID),相同请求使用相同的XID重新发送。

实现“至多一次”机制的困难之处:

  • 怎么确认xid是唯一的?使用很大的随机数或是将唯一的客户端ID(比如ip地址)和序列号组合起来
  • 老的RPC信息什么时候丢弃是安全的?使用唯一的客户端id、上一个rpc请求的序列号、客户端的每一个RPC请求包含"seen all replies <=X"、类似tcp中的seq和ack。保证每次只允许一个RPC调用,到达的是seq+1,那么忽略其他小于seq。客户端最多可以尝试5次,服务器会忽略大于5次的请求。
  • 当原来的请求还在执行,怎么样处理相同seq的请求?服务器不想运行两次,也不想回复。需要给每个执行的RPC标识pending;等待或者忽略。

Go RPC实现的”最多一次“?

  • 打开TCP连接
  • 向TCP连接写入请求
  • TCP也许会重传,但是服务器的TCP协议栈会过滤重复的信息
  • 在Go代码里面不会有重试(即:不会创建第二个TCP连接)
  • Go RPC代码当没有获取到回复之后将返回错误
    -- 也许是TCP连接的超时
    -- 也许是服务器没有看到请求
    -- 也许服务器处理了请求,但是在返回回复之前服务器的网络故障

参考讲义翻译

from mit-6.824.

lwhile avatar lwhile commented on July 17, 2024

@chaozh 讲义翻译404了

from mit-6.824.

chaozh avatar chaozh commented on July 17, 2024

先看看Lab2实验代码labrpc.go中的实现,它很像Go的RPC包,但是带有模拟网络

  • 这个模拟的网络会延迟请求和回复
  • 这个模拟的网络会丢失请求和回复
  • 这个模拟的网络会重新排序请求和回复
  • 对之后的实验二(Raft实现)测试非常有用

注意:实验一 MapReduce实现使用的是Go的RPC包

程序结构描述

  • 服务器(Server), 支持含有多个服务srv := MakeServer() srv.AddService(svc)
  • 客户端(ClientEnd),调用Call()函数,发生一个RPC请求并等待结果 reply := end.Call("Raft.AppendEntries", args, &reply)
  • 通信(Network),每个结构都持有一个sync.Mutex

关键方法

  • Server.AddService,可能在多个goroutine中调用,deter的作用是在函数退出前,调用之后的代码,就是添加完新服务后,做解锁操作。
  • Server.dispatch,分发请求,为什么持有锁?跟AddService并发访问可能冲突。
  • ClientEnd.Call,使用反射查找参数类型,使用“gob”序列化参数(Go的自带编解码包gob.NewEncoder),ClientEnd.ch(chan reqMsg)是用于发送请求的通道e.ch <- req,需要一个通道从接收回复(<- req.replyCh)
  • Network.MakeEnd,创建客户端,使用一个线程或者goroutine模拟网络,每个请求分别在不同的goroutine处理。一个端点是否可以拥有多个未处理的请求???。为什么使用rn.mu.Lock()?锁保护了什么?保护Network中的活跃数组信息
  • Network.ProcessReq,如果网络不可靠,可能会延迟或者丢失请求,在一个新的线程中分发请求。通过读取e.ch等待回复直到时间过去100毫秒。100毫秒只是来看看服务器是否崩溃。最后返回回复(req.replyCh <- reply),ProcessReq没有持有rn锁,是否安全?
  • Service.dispatch,为请求找到合适的处理方法

from mit-6.824.

Related Issues (11)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.