准备继续更新blog。
最近工作上一直在写业务,看些课程换换脑子。
15-440是CMU的一个分布式课程 http://www.cs.cmu.edu/~15-440/syllabus.html ,其实之前在学校的时候就上过分布式的课程,当时用的MIT 6.824的课件,可惜当时很多paper没有仔细去看,只是把作业做了下,除了lab1都没有写blog记录,导致后来有时间写blog的时候很多细节都不记得了。
这门课程的作业也是用的go语言,不过go语言在一些低版本中存在某些bug,所以如果使用 go的话尽量升级到最新
今年的P0是实现一个 kv messaging system,相对来讲是一个比较简单的系统。很久没有写过go,我也通过这个系统复习了下go语言中的一些特性,然后了解到了一些api的相关用法。
这个系统的要求是这样的:
有一个kv server, kv有两个接口, get 和put
有若干client,通过网络去调用kv server的这两个接口,去获取kv中某个key的value或者修改某个key的value。
并且server还需提供一个接口count,返回的是当前与server连接的client个数。
要求单个server支持多个client的同时访问,并且线程安全
其中还有一个特殊的要求是,client当中可能会有一些是slow reading client,它的特性就是不会立即读取来自server的消息,如果server持续的向client写数据而client一直不读的话,会导致tcp连接的output buffer爆掉。这种情况需要server对每个client开一个message queue,如果message的数量超过一定数量就自动drop掉。
实现思路如下:
首先这个系统的要求只是单机server支持多client,因此我们要考虑的东西就少了很多。
最简单的实现思路就是生产者消费者模型,client是生产者,server是消费者,而go语言中实现这个模型最简单的就是使用channel,channel本质上就是一个加锁的队列。
具体实现中
最开始开启两个线程,一个线程为工作线程,另外一个线程为accept线程,用来监听端口获取新加入的client连接。
工作线程要处理5种操作,需要使用5种channel处理
1. 新client连接的接入:新连接的检测是通过accept线程监听端口来获得,然后将连接塞进相应的channel里。 对于每个新连接进来的client,在server本地维护该client 连接的状态,并且新建两个线程,分别用来从client读取数据和向client写数据, 读线程不断的从client连接中读取数据,而写进程不断的从client对应的message queue中拉数据写给client
2. client连接的退出:对于每个要退出的client,移除在本地的维护,关闭有关线程。
3. client 发来的具体请求:get或put, get得到的消息放入对应client的message queue中,如果message queue满了就drop掉
4. client连接总数的查询: 收到该请求后,将答案放入相关channel。
5. 关闭server的请求: 将所有连接关闭,每个连接的相关线程关闭,然后退出工作线程
其中在实现中需要了解的是net包中有关tcp连接的使用方法。
server端 listener := net.Listen("tcp", ":80")即可监听80端口的连接。
然后通过conn := listener.Accept()即可在服务端获取该连接
每次读取client发来的请求:
clientReader := bufio.NewReader(conn)
message, err := clientReader.ReadBytes('\n')
即每次读消息读到换行符结束即可获取client发送来的单次请求
用go语言有时候就是对这些包不太了解所以会产生一些问题。
其他代码就先不贴了