November 19, 2020
Golang中的并发原语 Singleflight
"在Golang中有一个并发原语是 Singleflight,好像知道的开发者并不多。其中著名的 https://github.com/golang/groupcache 就用到了这个并发原语。\nGolang版本 go1.15.5\n相关知识点 map、Mutex、channel、\n使用场景 一般用在对指定资源频繁操作的情况下,如高并发下的“缓存击穿”问题。\n缓存击穿:一个存在的key,在缓存过期的瞬间,同时有大量的请求过来,造成所有请求都去DB读取数据,这些请求都会击穿缓存到DB,造成瞬时DB请求量大、压力瞬间骤增,导致数据库负载过高,影响整个系统正常运行。(缓存击穿不同于 缓存雪崩 和 缓存穿透)\n怎么理解这个原语呢,简单的讲就是将对同一个资源的多个请求合并为一个请求。\n举例说明,假如当有10万个请求来获取同一个key的值的时候,正常情况下会执行10万次get操作。而使用singleflight并发语后,只需要首次的地个请求执行一次get操作就可以了,其它请求再过来时,只需要只需要等待即可。待执行结果返回后,再把结果分别返回给等待中的请求,每个请求再返回给客户端,由此看看,在一定的高并 …"
September 27, 2020
Protobuf协议实现原理
"protobuf是Google开源的一款支持跨平台、语言中立的结构化数据描述和高性能序列化协议,此协议完全基于二进制,所以性能要远远高于JSON/XML。由于出色的传输性能因此常见于微服务之间的通讯,其中最为著名的是Google开源的 gRPC 框架。\n那么protobuf是如何实现高性能的,又是如何实现数据的编码和解码的呢?\nprotobuf协议原理 基于128bits的数据存储方式(Base 128 Varints)\nVarint 是一种紧凑的表示数字的方法。它用一个或多个字节来表示一个数字,值越小的数字使用越少的字节数。这能减少用来表示数字的字节数。\n比如对于 int32 类型的数字,一般需要 4 个 byte 来表示。但是采用 Varint,对于很小的 int32 类型的数字,则可以用 1 个 byte 来表示。当然凡事都有好的也有不好的一面,采用 Varint 表示法,大的数字则需要 5 个 byte 来表示。从统计的角度来说,一般不会所有的消息中的数字都是大数,因此大多数情况下,采用 Varint 后,可以用更少的字节数来表示数字信息\nVarint 中的每个 byte 的最 …"
September 19, 2020
Golang开发中中使用GitHub私有仓库
"私有仓库地址为\ngithub.com/cfanbo/websocket 一、设置私有环境变量 GOPRIVATE $ go env -w GOPRIVATE=github.com/cfanbo/websocket 对于为什么需要设置 GOPRIMARY 变量,可以参考 这里\n对于GOPRIVATE值级别分为仓库级别和账号级别。\n如果只有一个仓库,直接设置为仓库地址即可。如果有多个私有仓库的话,使用”,”分开,都在这个账号下,也可以将值设置为账号级别,这样账号下的所有私有仓库都可以正常访问。如 http://github.com/cfanbo\n如果不想每次都重新设置,我们也可以利用通配符,例如:\n$ go env -w GOPRIVATE=\u0026#34;*.example.com\u0026#34; 这样子设置的话,所有模块路径为 example.com 的子域名(例如:git.example.com)都将不经过 Go module proxy 和 Go checksum database,需要注意的是不包括 example.com 本身。\n国内用户访问仓库建议设置 GORPOXY …"
July 21, 2020
MySQL DBA利器innodb_ruby
"innodb_ruby简介 innodb_ruby是一款用ruby写的用来分析 innodb 物理文件的专业DBA工具,可以通过这款工具来窥探innodb内部的一些结构。 注意不要在生产环境中使用此工具,以避对线上服务造成影响。官方网址 https://rubygems.org/gems/innodb_ruby。\n注意如果(Linux)平台安装中遇到错误一般情况是由于缺少依赖库造成的,可以先安装 sudo apt-get install libxslt1-dev libxml2-dev 相关库。\n命令语法 在执行以下命令时,建议切换到MySQL 的 datadir 目录里。\nsxf@ubuntu:~$ innodb_space --help Usage: innodb_space \u0026lt;options\u0026gt; \u0026lt;mode\u0026gt; innodb_space \u0026lt;选项\u0026gt; \u0026lt;模式\u0026gt; 命令主要分 options 和 mode 两大部分。 Invocation examples: innodb_space -s ibdata1 [-T tname [-I …"
June 6, 2020
利用jenkins+github实现应用的自动部署及回滚
"对于jenkins的介绍这里不再详细写了,此教程只是为了让大家对部署和回滚原理有所了解。\n一、创建项目 点击左侧的“New Item”,输入项目名称,如 rollback-demo。\n选中 ” 丢弃旧的构建(Discard old builds)”项,在“策略(Strategy” 选择”Log Rotation“, 并输入保留的最大构建个数。\n二、常规配置 设置参数,点击”Add Parameter“,依次选择 “Choice Parameter” 和 “String Parameter“这两,填写如下\n这里的Name 项为参数名称,用户在操作的时候,会在deploy 和 rollback 两个值中选择一项。\n三、源码管理 我们这里选择Git.并填写github.com上的项目地址,记得设置认证 Credentials。构建分支直接使用默认的 */master 即可以了。查看代码浏览器选择 githubweb,并填写项目的github地址。\n四、构建触发事件 选择 “GitHub hook trigger for GITScm polling”,表示使用github webhook来触 …"
May 27, 2020
golang中几种对goroutine的控制方法
"我们先看一段代码\nfunc listen() { ticker := time.NewTicker(time.Second) for { select { case \u0026lt;-ticker.C: fmt.Println(time.Now()) } } } func main() { go listen() time.Sleep(time.Second * 5) fmt.Println(\u0026#34;main exit\u0026#34;) } 非常简单的一个goroutine用法,想必每个gopher都看过的。\n不过在实际生产中,我们几乎看不到这种用法的的身影,原因很简单,我们无法实现对goroutine的控制,而一般业务中我们需要根据不同情况对goroutine进行各种操作。\n要实现对goroutine的控制,一般有以下两种。\n一、手动发送goroutine控制信号 这里我们发送一个退出goroutine的信号。\n// listen 利用只读chan控制goroutine的退出 func listen(ch \u0026lt;-chan bool) { ticker := …"
May 3, 2020
Golang遍历切片删除元素引起恐慌问题
"删除一个切片的部分元素, 告知切片操作:Golang遍历切片恐慌时删除元素\n问题描述 代码( 演示代码):\npackage main import ( \u0026#34;fmt\u0026#34; ) func main() { slice := []int{1, 2, 3, 4, 5, 6, 7, 8, 9} for i, value := range slice { if value%3 == 0 { // remove 3, 6, 9 slice = append(slice[:i], slice[i+1:]...) } } fmt.Printf(\u0026#34;%v\u0026#34;, slice) } 运行结果\npanic: runtime error: slice bounds out of range [8:6] goroutine 1 [running]: main.main() /tmp/sandbox2635969259/prog.go:11 +0x212 Program exited. 解决办法: 以下是网友想到的几种办法"
April 30, 2020
Golang中select用法导致CPU占用100%的问题分析
"上一节( golang中有关select的几个知识点)中介绍了一些对于select{}的一些用法,今天介绍一下有关select在 for语句 中由于使用不当引起的CPU占用100% 的案例。\n先看代码\npackage main import ( \u0026#34;fmt\u0026#34; \u0026#34;time\u0026#34; ) func main() { ch := make(chan int, 10) // 读取chan go func() { for { select { case i := \u0026lt;-ch: // 只读取15次chan fmt.Println(i) default: // 读取15次chan以后的操作一直在这个空语句无任何IO操作的default条件里死循环,无法出让P,以保证一个GPM关系。 // 而如果无default条件的话,则系统当读取完15次chan后,当前goroutine会发生 chan IO 阻塞, Go调度器根据GPM的调度关系,会将当前执行关系中的G切换出去,再从LRQ队列中取一个新的G,重新组成一个GPM继续执行,以实现合理利用计算机资源,提高GO的高并发性能 } …"
April 21, 2020
基于 GitHub Actions 实现 Golang 项目的自动构建部署
"前几天 GitHub官网宣布 GitHub 的所有核心功能对所有人都免费开放,不得不说自从微软收购了GitHub后,确实带来了一些很大的改变。\n以前有些项目考虑到协作关系的原因,虽然放在github上面,但对于一些项目的持续构建和部署一般是通过自行抢建Travis CI、jenkins等系统来实现。虽然去年推出了Actions用来代替它类三方系统,但感觉着还是不方便,必须有些核心功能无法使用,此消息的发布很有可能将这种格局打破。\n本篇教程将介绍使用github的系列产品来实现项目的发布,构建,测试和部署,当然这仅仅是一个非常小的示例,有些地方后期可能会有更好的瞿恩方案。\nGitHub Actions 是一款持续集成工具,包括clone代码,代码构建,程序测试和项目发布等一系列操作。更多内容参考:\n如果你对CI/CD不了解的话,建议先找些文档看看。\n项目源文件见\nGitHub Actions 术语 GitHub Actions 相关的术语。\n(1)workflow (工作流程):持续集成一次运行的过程,就是一个 workflow。\n(2)job (任务):一个 workflow 由一个或 …"
March 28, 2020
k8s中的Service与Ingress
"集群中的服务要想向外提供服务,就不得不提到Service和Ingress。 下面我们就介绍一下两者的区别和关系。\nService 必须了解的一点是对 Service 的访问只有在 Kubernetes 集群内有效,而在集群之外是无效的。\nService可以看作是一组提供相同服务的Pod对外的访问接口。借助Service,应用可以方便地实现服务发现和负载均衡。对于Service 的工作原理请参考\n当需要从集群外部访问k8s里的服务的时候,方式有四种:ClusterIP(默认)、NodePort、LoadBalancer、ExternalName 。\n下面我们介绍一下这几种方式的区别\n一、ClusterIP 该方式是指通过集群的内部 IP 暴露服务,但此服务只能够在集群内部可以访问,这种方式也是默认的 ServiceType。\n我们先看一下最简单的Service定义\napiVersion: v1 kind: Service metadata: name: hostnames spec: selector: app: hostnames ports: - name: default …"