golang

go并发需要注意的问题

  用go写并发的确很方便,协程相比于线程轻量很多,关于协程与线程的区别,可以参考我的这篇博客:go中的协程与线程的区别。本文主要讲一下一些并发中应该注意的坑,学习go没多久,可能有认知不到位的地方,欢迎指正。 1. channel   go中通过channel进行消息通信,channel函数传参通过引用实现。go中有2种channel,分别是无缓存的channel(unbuffered channel)和有缓存的channel(buffered channel),前者cap为0,后者大于0。无缓存的channel主要用于同步:生产者写入channel然后阻塞,直到消费者读取后,生成者才从阻塞状态返回;有缓存队列适用于异步:在队列为满的情况下(len < cap),生产者将消息塞入channel就返回。   由于go存在垃圾…

Read more

go中的协程与线程的区别

  对用户来说,协程与线程几乎没什么区别,但是实际上还是有一些区别的。   说明:本文对协程和goroutine,OS线程和内核线程都是一个概念,未加区分。 1. 栈大小区别   我们知道,线程是有固定的栈的,基本都是2MB,当然,不同系统可能大小不太一样,但是的确都是固定分配的。这个栈用于保存局部变量,用于在函数切换时使用。但是对于goroutine这种轻量级的协程来说,一个大小固定的栈可能会导致资源浪费:比如一个协程里面只print了一个语句,那么栈基本没怎么用;当然,也有可能嵌套调用很深,那么可能也不够用。   所以go采用了动态扩张收缩的策略:初始化为2KB,最大可扩张到1GB。 2. goroutine没有id   每个线程都有一个id,这个在线程创建时就会返回,所以可以很方便的通…

Read more

golang net/rpc源码分析

  为什么需要rpc框架?一次rpc需要指定调用的方法,参数,接收返回值。如果没有rpc框架,裸写tcp,什么时候知道报文传递完毕的界限。最简单我们可以搞个私有协议,TLV格式指定:T(type)指定类型,L(length)指定长度,V(Value)指定值,但是这个也会带入一些问题,比如规范问题,不同服务提供不同协议,这不乱套了吗;另外还有效率问题,比如我要传递一个数组怎么传?基于以上几个问题,rpc框架出现了,rpc框架采用序列化操作将请求和返回在发送端进行序列化,然后在接收端进行解序列化达到目的,如下图所示,图片来自博客。 服务调用流程如下: client调用client stub,这是一次本地过程调用 client stub将参数打包成一个消息,然后发送这个消息。打包过程(序列化)也叫做 marshalling client所在的系统将消息发送给serve…

Read more

golang实现mapreduce单进程版本

  元旦放假的第一天,在家没事干,用golang实现了一下mapreduce的单进程版本,github地址。处理对大文件统计最高频的10个单词,因为功能比较简单,所以设计没有解耦合。   本文先对mapreduce大体概念进行介绍,然后结合代码介绍一下,如果接下来几天有空,我会实现一下分布式高可用的mapreduce版本(1月6日update:这个主要看需求,1.如果master挂了,当前执行的任务丢了就丢了,接下来下发的任务还能执行,那么这个很好实现,可以做多个Master,每次任务分发给一个master执行,北向搞一个负载均衡器就可以,或者弄一个注册中心;2.如果要高可用指的是已经执行的mapreduce任务在主master挂掉后仍然继续执行,那么多个master之间需要做数据同步,可以用Redis或者kafka做消息同步,但是有种过度设计的感觉…

Read more

go https example

  本文首先大概介绍一下https的协议原理(其实是TLS协议原理),然后给出构建https的go代码例子。 1.HTTPS协议   网上已经有很多资料介绍HTTPS协议了,我归纳一下,加深自己的记忆。   HTTPS是HTTP通过SSL/TLS加密的方式进行通讯,TLS是SSL的改进版本。TLS协议可以分为握手阶段和对话阶段,握手阶段采用非对称加密方式(密钥由第三方机构提供),对话阶段采用对称加密方式(密钥由握手阶段协商得出)。   握手阶段主要分为4个步骤(细分来说,可以有多个步骤,具体查看RFC文档): 1.1 Client Hello   客户端向服务器端发起hello请求,同时带入以下信息: 客户端支持的加密方式 客户端支持的SSL/TLS协议版本号 客户端生成的随机数1,该随机数…

Read more