go 中没怎么用过的 sync.Map
我们知道 golang 的 map 并发会有问题,所以 go 官方在 sync 包中加入了一个 sync.map 来作为一个官方的并发安全的 map 实现。
如果你了解过 java 中常用的一个并发安全的 map 叫做 ConcurrentHashMap 就会知道它有两个亮点设计:一是当链表长度过长的时候会转换为红黑树的实现,还有一个就是分段锁。得益于这两个设计也导致 java 中实现的代码非常复杂,偷笑。
那么 go 里面是如何设计的呢?今天我们就来看看它是怎么实现的。
PS: 本文 go 源码基于版本1.16.2,我觉得当有了泛型之后这个库十有八九是要改的….
数据结构定义123456type Map struct { mu Mutex read atomic.Value // readOnly dirty map[interface{}]*entry misses int}
123456// readOnly is an immutable struct stored atomically in the Map ...
k8s 基于角色的权限控制 RBAC
RBAC 之所以一直没有写这个,一方面是因为它确实并不复杂,二来平常确实接触不多,今天就来顺路讲讲它
定义Role-Based Access Control 我们常说的 RBAC,我们知道在一个后台管理系统里面经常会有权限管理。而最常用的一种权限设计方式就是基于角色的权限设计,A 用户是管理员拥有所有的权限,B 是普通用户角色只有部分权限等等,而 k8s 也是如此,k8s 内部也有许许多多的资源,通过 RBAC 的权限设计进行管理授权工作。
Role: 角色,定义了一组对 Kubernetes API 对象的操作权限
Subject: 用户,绑定角色的对象
RoleBinding: 用户和角色的绑定关系
其实非常好理解: 用户 -> 角色 -> 权限
Role123456789apiVersion: rbac.authorization.k8s.io/v1kind: Rolemetadata: namespace: default name: pod-readerrules:- apiGroups: [""] # "" 标 ...
k8s 部署 prometheus
看到很多部署 prometheus 到 k8s 集群的教程,发现都是非常麻烦的各种配置,懒人的我就想整个一键部署的,开箱即用的,既然有了 helm 那肯定只要一个 charts 就可以搞定了吧,想着就是这样,所以在网上找来找去,终于被我发现了。下面记录一下使用过程,方便以后进行部署。
PS: 本文适用于开发者单 k8s 集群部署 prometheus,如果是运维可建议进行独立部署,一方面不需要占用集群内部资源并保证多活,另一方面可以支持多集群扩展。
安装12345# helm 添加对应 repohelm repo add prometheus-community https://prometheus-community.github.io/helm-charts# helm 安装 可以添加参数 --set rbacEnable=true,-n 指定安装的 namespacehelm install prometheus prometheus-community/kube-prometheus-stack -n monitoror
默认用户名密码admin/prom- ...
让你最快上手 go 的 pprof 性能分析大杀器
前言,发现一直没有记录过 pprof 分析的博客,其实在实际的业务场景中已经使用它很多次了,对于性能分析来说它真的是一大杀器,基本上有了它,80% 的性能问题都能被一目了然。每次出现性能问题,总是下面几个步骤,测试环境开 pprof,启动,流量重放,火焰图生成,一看,仔细分析一下,问题就浮于水面。
今天来用最简单的一个案例,来让你快速上手 pprof,所以本博客包含以下内容
最快能让你用上 pprof
能让你最快学会认识火焰图
学会了之后其他剩下的功能你就可以慢慢自己摸索了
废话不多直接上案例
前期准备首先你肯定有 go 环境,需要看火焰图还需要安装 graphviz http://www.graphviz.org/download/
第一个坑来了,如果 mac 使用 brew install graphviz 安装容易出现失败,还有很多奇怪的依赖如 svn java 等,所以建议使用 sudo port install graphviz 安装
问题发现
使用一些监控软件发现问题,如当前我发现有一个项目在刚启动之后,其他相同类似的项目 cpu 使用都是 20 多,但是它有 ...
初识 CGO - 利用 CGO 使用 C++ STL
之前我也了解过 CGO 相关的知识,但是当时给我的印象全部都是 “CGO 性能差” “完全没有必要,实际根本用不到”,但是这次听了大佬的一些分享发现 CGO 其实就是黑科技啊,有了它你在使用 go 的时候有了更多的想象力。本文将带你初步了解和使用 CGO,本文只是抛砖头,因为有关 CGO 的文档其实蛮少的,在其中也有很多坑,所以今天来踩一次,不知道会不会留下什么坑….
有了 CGO,Go 就有机会继承 C/C++近半个世纪的遗产 by 曹大
CGO 使用案例分享 首先来看一下最近我看到使用 CGO 的两个案例
案例 1 mosn
https://github.com/mosn/mosn
其中 mosn 通过 CGO 的能力,想办法在 envoy 后面加了一层,使得其底层网络具备 C 同等的处理能力的同时,又能使上层业务可高效复用 mosn 的处理能力及 go 的高开发效率。
案例 2 主动式缓存
这个 GopherChina 上一个学而思网校的分享,主要讲的是如何设计一个主动式内存缓存,其中提到了 Go 的 GC 导致当有大量内存缓存的时候,对象数量过多,GC 扫描 ...
Golang逃逸分析
逃逸分析,看着一个非常高大上的名词,很多人第一次听到它的感觉会觉得它好厉害的样子,其实说到底它很好理解,并不复杂。之前一直没有写也是有原因的,因为其实在实际中,我真的很难用上它。这次写也是有原因的,因为有人催更了…其实拖了有一段时间了,最近终于忙完了,开始补债了。
栈和堆在说逃逸分析之前,我们需要有一些前置知识点
栈我们常说的栈是一种数据结构,当然这里说的栈特指我们在谈论内存分配的时候说的栈。它的作用是在函数调用的过程中保存函数的参数局部变量等数据。而且当函数调用完毕后,它所使用的栈空间将立即释放。所以它“便宜”。
堆堆的概念我们就应该非常熟悉了,它用来存放很多需要使用的对象,这些对象的生命,在 go 里面是交给 GC 去管理的,当我们再也不使用的时候,GC 会将它们回收。所以它“贵”,因为它需要额外的做功才能将它回收掉。
为什么?那为什么需要堆?不用堆不行吗?其实答案显然不行,因为如果所有的变量对象都在栈上,用完了就扔掉,那么其他人想要再使用的时候就无法使用了。
那全部都在堆上不行吗?答案也很显然不行,因为栈便宜,用完就扔,堆很贵,你不能将所有的东西都扔给 GC,这样它要累死。 ...
GopherChina2021 个人总结
今年本来没想着要去的,因为确实有点远,加上疫情之下不太方便,但是意料之外来了一张门票,那就必须去一下了,这次收获也不少,有了上次的经验,这次就听得很舒服,不像上次那样那么累了,这次能准确的知道什么应该仔细听,什么应该略过,所以这次的笔记就相对来说少一些,精炼一点。
这次去也面基了大佬,果然北京的都是大佬,都比我卷的厉害,以后还要多学习,哈哈哈,膜拜膜拜~
基于 Golang 构建高可扩展的云原生 PaaS 平台端点 PaaS 介绍整个历程 主要是推 Erda,主要有以下几点个人觉得可以
自定义 pipeline 开箱即用
微服务治理 兼容 java 族(spring 那一套,还有 dubbo)
可观察性数据采集
个人总结:写个这的一定是 java 过来的,autowired 很 java 味道
https://github.com/erda-project/erda
MOSN 云原生演进历程MOSN 之前就有听说的,我觉得很像给 Envoy 加个 buff
CGO 并没有想的那么性能堪忧
通过 hacker 的方式可以在调用链路中加一层 filter 实现
想办法做到 zer ...
轻量级 k8s 应用日志收集方案 loki
微服务早已是一个过时的热词,同时,容器 和 k8s 的出现让它更一步成为了一种时尚。同样会带来很多附赠的问题,日志收集就是其中一个比较重要的问题。当应用容器化之后,需要查看日志,如果还需要登录服务器,找到对应目录,然后 tail 查看,成本太高了,极大的影响效率。当前其实日志收集方案很多,在实践了多个方案之后,我终于能在今天写出我个人认为我最喜欢的一个方案了 loki
我的需求技术上没有银弹,需要根据实际需求来选择方案,那么我的需求是这样的,你可以做个比较:
当前所有的应用是部署在 k8s 中的,需要收集所有的应用的日志到一个地方做展示
部署最好要轻量,对于性能要求并不高(当前日志量并不大)
日志展示方式友好,能支持基本的时间查询,或者是定位到某个关键字
可选方案从之前的公司包括个人的一些项目上都尝试过很多不同的组合和方案,列举出三个最具有可比性的方案:(以下为个人使用案例,并不能代表所有大众观点,图片来源本地测试服,线上日志不允许公开,但同样禁止转载~)
ELK
这似乎是业界最成熟的日志收集方案之一了,因为无论你问哪个有点经验的程序员,提到日志收集,必然会给到这个,我当然不是 ...
monitoror/monitoror 最轻量的监控大屏
一提到监控大屏,那第一想法就是 grafana 对吧,各种样式图形都非常好看,而且支持各种数据源。而今天要分享的是一个更加轻量的监控大屏 monitoror/monitoror
有了它能帮你快读构建一个的对于网站或者应用的监控页面,特别是在小应用数量多的时候非常简单易用,作为一个大屏展示时它我觉得它足够简洁
demo & repohttps://demo.monitoror.com/
https://github.com/monitoror/monitoror
优点
部署轻量
配置简单
大屏简洁
部署二进制部署https://monitoror.com/documentation/get-started/
非常简单,只需要将二进制文件下载,然后按照要求配置对应的配置文件,就可以了
12chmod +x monitoror./monitoror
配置文件.env
1MO_CONFIG="./config.json"
配置文件config.json
12345678910111213141516171819202122 ...
k8s 意外集锦 - oom 的连锁反应
一开始觉得 oom 是一个常见问题,应该没有什么大问题,反正 k8s 集群会调度的,但其实它造成的连锁反应很恐怖。
问题描述具体简单描述过程:一台机器 OMM, 导致将对应的pod调度到了其他节点上,导致其他节点 OOM 然后开始疯狂输出日志信息,然后导致 master 磁盘不足开始清理并驱逐,然后导致驱逐(Evicted)的应用再次调度到其他节点,然后连锁反应,最终相关大量服务不可用….
pod 出现告警信息 The node had condition: [DiskPressure].
总的来说就是一个 应用的 oom 不停的被调度来调度去,导致日志疯狂的输出,导致磁盘不足了。
问题解决设置合适的内存请求和限制条件限制单个应用的使用内存还是非常有必要的,免得出现很多意外的情况
1234567resources: requests: cpu: 100m memory: 128Mi limits: cpu: 200m memory: 256Mi
应用 bug 修复代码 bug 肯定要修复的,这个毕竟是导致问题的主要原因
升级 ECS 的内 ...
k8s 意外集锦 - configmap 挂载 目录 只读
OCI runtime create failed:
/var/lib/docker/overlay2/6573e40fef5bc51b4e565ad9554f225806f05a9f9089cc9e210c0e35a80e6e1f/merged/etc/resolv.conf: read-only
报错信息123456789Error response from daemon: OCI runtime create failed: container_linux.go:344: starting container process caused"process_linux.go:424: container init caused \"rootfs_linux.go:58: mounting\\\"/var/lib/docker/containers/1ec387b2e168281ed480c5050b08893976ac84a2751691e1a9429ae6a66a ...
k8s 小技巧
本博客持续更新…用于记录 k8s 使用过程中的很多的小技巧,也希望你能提供更多的小技巧来~
图形化管理工具 lens图形化 k8s 管理工具: https://github.com/lensapp/lens
我觉得可以少部署一个 dashboard,并且比官方的 dashboard 好看很多
重启 deployment 命令我一开始总是 delete 一次 apply 一次,感觉很蠢,又换成调整 scle 但是还是很慢,查了之后发现原来本来就有重启的命令
1kubectl rollout restart deployment nginx-dep
查看链接配置信息1kubectl config view --minify --raw
kubectx当你需要使用 kubectl 操作多个集群的时候,可以使用 kubectx 切换 context,非常方便
多集群管理切换工具:https://github.com/ahmetb/kubectx
更新 configmap 脚本对于配置文件 configmap 的更新我真的没有找到合适的命令,直接 使用 kubectl edit 那么原来 ...
Weave Scope 监控 k8s 集群
之前一直在寻找一个 k8s 监控的工具,因为一直使用的是本地的 lens 的客户端,虽然使用上已经非常方便了,但是其实对于资源消耗的监控少了一点,有些资源消耗并不是能容易看到,并且服务间依赖是没有办法表现出来的,后来发现了 Weave Scope 满足了我的需求。
链接https://github.com/weaveworks/scope
特点
资源监控:能实时反映整个集群中的资源状况 cpu 内存 使用情况 并且支持各种角度
服务间依赖:能通过图形展现出服务之间访问的依赖关系
容器交互:实时查看日志和描述信息
支持插件:可以通过插件扩展
部署方便:一个命令即可部署完成
监控页面资源监控
可以清楚的看到每个 node 的资源使用情况
服务间依赖
因为内部服务与服务之间通过 rpc 进行交互,从这里可以很容易看出,某个服务被别的五个服务所依赖调用
容器交互
可以看到占用的 cpu 和内存的情况,然后占用的端口等,还有日志信息
部署支持直接部署在 k8s 集群中,不需要额外的任何配置
https://www.weave.works/docs/scope/latest/installi ...
GopherChina2020 个人总结
之前去过几次相关 go 的线下 meetup,这次相对来说比较大型一些,两天的听下来还是比较烧脑的,光是记录的笔记都有近千行了,整体来说收获很大。
有的人问,值票价吗?我回答:对喜欢的投资没有不值得的。对我来说值了~
有的人问,值得去吗?我回答:不一定,因为可能在很多大佬看来能听到的点不多(采访了几位现场的大厂观众,普遍表示只有其中 1 到 2 场满足他们的要求)但是如果你的小白或者一年到两年左右,还是能见识很多东西的。可能是我听多了,和之前自己学到的有点重复…
下面是个人精炼总结,全是个人总结,自己如果对这个知识或者相关点比较清晰的我就没有记录了。其中会伴随一些个人思考和疑问,可以小声 bb 。大会分 1和 2 会场,所以只能选其中一个听,我也是记录我自己听到的,另外一个会场不清楚(我交叉穿来穿去的)注意并不是有的老师讲的真的不好,而是对我个人来说意义不明显,可能由于知识点已经掌握,也可能是由于工作上确实用不到哦
最后会附上会上笔记,仅做个人使用,乱了也不管~ 最后无论如何,感谢每一位老师的付出~~~
要点总结
分布式数据库设计难题:数据分片,节点加入和减少
如果让你设计一个系统 ...
下一个 nginx?caddy 自动 https 真香
我们通常在部署 web 服务的时候往往会选择 nginx 作为最前面的一个狠角色,它的性能和能力大家也是有目共睹的,反向代理负载均衡等等。而作为后起之秀 caddy 却不被人所熟知,不过渐渐的也开始展露头角。今天我就来介绍这个 caddy ,为什么我会称它有可能成为下一个 nginx。
我先列举几个痛点你看下:
nginx 的配置文件你是否感觉有时候有点臃肿
https 需要购买或者申请证书,然后配置是否觉得麻烦?
linux 下安装 nginx 需要部分依赖
而 caddy 确实给我了一种眼前一亮的感觉。
使用官网:https://caddyserver.com/
安装https://caddyserver.com/docs/download安装很简单,直接下载对应的二进制文件即可,或者按照对应到操作系统去安装也可以。没有其他依赖。
使用https://caddyserver.com/docs/getting-started一个命令就可以启动,caddy,默认会去当前目录下寻找 Caddyfile 配置文件,也可以通过 –config 去指定文件位置
123caddy sta ...
openfaas/faas 环境搭建和开发使用
serverless 大环境下出现了 faas,即 function as a service,函数即服务;其意思也非常好理解,就是能将一个函数作为一个服务进行使用,用户只需要编写一个函数功能即可,不需要额外去关心别的东西。https://github.com/openfaas/faas 是其中的一种实现方式。
环境准备以下环境在 mac 上进行搭建:
首先需要准备 docker 和 kubernetes 的环境,先做 k8s 的环境直接能通过 docker 桌面进行配置,已经算是很方便了。
安装步骤openfaas-cli1curl -sL https://cli.openfaas.com | sh
namespace123git clone https://github.com/openfaas/faas-netescd faas-neteskubectl apply -f namespaces.yml
password12345678$ cat passwd.sh # PASSWORD=$(head -c 12 /dev/urandom | sha1sum |c ...
Golang Mutex 到底是否应该使用指针
在写 go 的时候,你使用 Mutex 的时候使用的是指针还是说没有使用指针,还是随意来?
前两天我收到了下面这样的一个 PR,我突然就想到了这个问题,于是就有了这篇博客。
我一开始的想法其实我一开始的想法很简单,因为我一直没有使用指针
在我的某些印象中我曾经记得,使用锁不申明为指针是一个代码规范类似的东西
大多数的(我看过的一些)源码中,没有见过将锁申明为指针的用法
但是当时我没有办法回答这个 PR,你总不能说我是一厢情愿吧…需要一个更加合理的解释
仔细分析上网搜索一番https://www.reddit.com/r/golang/comments/6uyf16/confusion_about_mutex_and_reference/
很多类似的问题都在问(你不用点开,只是举个例子)
问题关键sync.Mutex 这个东西不能被 copy!(这个我之前也是知道的,毕竟都分析过源码了)
刨根问底虽然这个锁不能被拷贝,那么就应该被申明为指针防止拷贝出现问题吗?
别慌,先写个例子测测看
1234567891011121314151617181920212223242526272 ...
Linux 图形化监控工具
最近在分析线上问题,需要监控 Linux 相关指标,如果只是用命令,总是只能知道当前的值,无法记录过程。而设备不是云厂商的设备,所以没有相关监控,zabbix 有,但是没有相关权限可以看到。所以找到一些好用的监控小方案。
nmon安装yum install nmon
使用
总结
安装方便,使用简单,最快速度能搞定,无需过多依赖,控制台展示
当然它还有其他内存等相关信息的展示
不是特别好看(毕竟是控制台要求也不能太高),精度相对低,只能有个大概峰值
bottom安装因为是 rust 搞的,所以可能有相关依赖,需要手动处理
12345678910111213141516wget https://github.com/ClementTsang/bottom/releases/download/0.4.5/bottom_x86_64-unknown-linux-gnu.tar.gztar xvf bottom_x86_64-unknown-linux-gnu.tar.gz./btm# 如果出现以下错误需要安装 glibc # /btm: /lib64/libc.so.6: version ...
你的网络还好吗
之前说了 CPU、内存 、IO 在排查过程中可能出现的问题以及出现问题会影响的指标,这次就来看看在 linux 中网络的问题。
在实际中我们遇到的最多的网络问题就是:不通!!!无论是 ping 不通,物理链路不通,还是 dns 解析有问题导致的不通,还是容器间网络访问网络隔离造成的不通,等等,这个问题总是由于部署上的环境导致的。还有一类比较烦的问题就是网络带宽本来就不高的情况下,大量的请求导致网络的拥塞,最明显的感受就是接口请求超时,各种超时,nginx 超时,请求本身超时等等。对于这些问题如何进行排查呢?
诊断指标sar命令sar -n DEV 1
12345678910[root@Linkin ~]# sar -n DEV 1Linux 3.10.0-1062.9.1.el7.x86_64 (Linkin) 07/04/2020 _x86_64_ (2 CPU)03:03:40 PM IFACE rxpck/s txpck/s rxkB/s txkB/s rxcmp/s txcmp/s rxmcst/s03:03:41 PM br-22 ...
你的 IO 还好吗
在 CPU 看来内存好慢啊,看我跑的多快;在内存看来磁盘你好慢啊,看我比你还快点;磁盘…
IO 问题并非特别常见,但是因为最终要落到磁盘上,当它成为瓶颈时,往往会拖慢你的脚本,今天我们来分析下在 linux 中的 IO 问题
指标看 IO 并不只是看 IO,记住这句话,因为很多时候,IO 问题总会伴随着别的问题一起出现,而会导致误判的,从而遗漏了问题的关键。
IO 问题的指标来源于两块:
文件系统
磁盘
iowait命令top
iostat
%iowait 表示在一个采样周期内有百分之几的时间属于以下情况:CPU空闲、并且有仍未完成的I/O请求。
指标iowait 升高或者居高不下,可以考虑存在 IO 瓶颈或压力
rs / ws命令iostat -x -d 1
123Device: rrqm/s wrqm/s r/s w/s rkB/s wkB/s avgrq-sz avgqu-sz await r_await w_await svctm %utilvda 0.00 ...
快速上手 dubbo-go
每次技术调研总会发现自己学不动了怎么办?用已有的知识来拓展要学习的新知识就好了~ by LinkinStar最近需要调研使用 dubbo,之前完全是 0 基础,对于 dubbo 只存在于听说,今天上手实战一把,告诉你如何快速用 go 上手 dubboPS:以下的学习方式适用于很多新技术
基本概念首先学习一个技术首先要看看它的整体架构和基本概念,每个技术都有着自己的名词解释和实现方式,如果文档齐全就简单很多。
http://dubbo.apache.org/zh-cn/docs/user/preface/background.html
大致浏览了背景、需求、架构之后基本上有一个大致概念
其实整体架构和很多微服务的架构都是类似的,就是有一个注册中心管理所有的服务列表,服务提供方先向注册中心注册,而消费方向注册中心请求服务列表,通过服务列表调用最终的服务。总的来说 dubbo 将整个过程封装在了里面,而作为使用者的我们来说更加关心业务实现,它帮我们做好了治理的工作。
然后我抓住了几个我想要知道的重点:
注册中心可替换,官方推荐的是 zk
如果有变更,注册中心将基于长连接推送变更数 ...
你的内存还好吗
内存问题往往是线上环境最容易导致的问题,因为其实对于程序来说,内存总是不够用的。而大多数我们在线上遇到的问题总是一个叫 OOM 的,导致这个问题的原因也有很多,今天我们就来看看,如何在线上定位或者排查这样的问题。
诊断指标free命令free -h
1234[root@Linkin /]# free -htotal used free shared buff/cache availableMem: 7.6G 326M 6.2G 480K 1.1G 7.0GSwap: 0B 0B 0B
指标这个命令可以看到当前设备的内存总体使用情况,以及很清楚的看到交换区的内存使用情况
total:总内存
used: 已使用内存,包含共享内存
free: 未使用内存
shared: 共享内存
buff/cache 缓存和缓冲区
available 新进程可用内存
top命令top + M
指标1 ...
Golang 监控全局变量
你是否曾经遇到过这样的情况,在开发环境排查问题,因为一些数据保存在了一些全局变量中,这些变量往往是一个 map 或者是一个数组,想看看在运行过程中,这里面究竟存放了什么数据,有时不得不在运行的时候将它输出到日志中,那么如果我想实时看到这些数据的情况又怎么办呢?
其实 golang 中已经存在这样的库,就是来做这个事情的 expvar
使用案例废话不多数,直接上案例
123456789101112131415161718192021222324252627282930313233343536373839package mainimport ( "expvar" "net/http")var ( s map[string]string user User)type User struct { Name string `json:"name"` Age int `json:"age"`}func showMap() interface{} { r ...
你的 CPU 还好吗
最近经常在线上排查一些问题,在大多数情况下,都是代码写的业务逻辑有问题;还有一些情况是内存上导致的问题,如 OOM 或者由于数据量大导致的一些问题;但是很少会关注,但常常又会瞟一眼的,这个关注点就是 CPU。
在说到 CPU 的时候往往除了 top 看一下 CPU 使用率之外,你还会关注别的什么吗?好像也不会。
但是其实当真正出现问题的时候,很多 CPU 相关的指标都会反映出一些问题,经过之前的学习今天就来总结记录一下。
诊断指标平均负载定义系统处于可运行状态和不可中断状态的平均进程数,也就是平均活跃进程数(单位时间内活跃进程数)
查看
uptime
top
指标当平均负载高于 CPU 数量的 70% 可能就有问题了(在实际中如果你看到平均负载突然升高,也就是三个值呈现递减的趋势,就需要考虑 CPU 问题了)
CPU 使用率定义除了空闲时间外的其他时间占总 CPU 时间的百分比
查看
top
ps
mpstat -P ALL 5
pidstat
指标这个其实不用说你就有感觉的,如果你看到你的程序占用了 30%CPU 使用率,而别人都没得用,那就肯定奇怪了
上下文切换定义 ...
python 基础语法笔记
记录python的一些基础语法,用于查阅
列表和元组
列表和元组都是有序的,可以存储任意数据类型的集合
列表是动态的,长度可变,存储空间和性能略逊与元组
元组是静态的,长度大小固定,不能增加修改
创建一个列表使用 empty_list = [] 相比于 list() 更好,因为 [] 底层走的c,而 list() 是函数,更加贵
1234567891011121314151617181920l = [1, 2, 3, 4]tup = (1, 2, 3, 4)list((1, 2, 3))[1, 2, 3]l.count(3)l.index(7)l.reverse()l.sort()l.append(4)# extend会将里面的元素添加进去,而append会直接将[1,2]作为一个元素加入l.extend([1,2])tuple([1, 2, 3])(1, 2, 3)tup.count(3)tup.index(7)list(reversed(tup))sorted(tup)
字典和集合本质就是hash表
删除会赋值为特殊值并在rehash调整大小的时候进行处理
会保 ...
Golang用300行代码实现内网穿透
我们经常会遇到一个问题,如何将本机的服务暴露到公网上,让别人也可以访问。我们知道,在家上网的时候我们有一个 IP 地址,但是这个 IP 地址并不是一个公网的 IP 地址,别人无法通过一个 IP 地址访问到你的服务,所以在例如:微信接口调试、三方对接的时候,你必须将你的服务部署到一个公网的系统中去,这样太累了。
这个时候,内网穿透就出现了,它的作用就是即使你在家的服务,也能被其人访问到。
今天让我们来用一个最简单的案例学习一下如何用 go 来做一个最简单的内网穿透工具。
整体结构首先我们用几张图来说明一下我们是如何实现的,说清楚之后再来用代码实现一下。
当前网络情况
我们可以看到,画实线的是我们当前可以访问的,画虚线的是我们当前无法进行直接访问的。
我们现在有的路是:
用户主动访问公网服务器是可以的
内网主动访问公网服务也是可以的
当前我们要做的是想办法能让用户访问到内网服务,所以如果能做到公网服务访问到内网服务,那么用户就能间接访问到内网服务了。
想是这么想的,但是实际怎么做呢?用户访问不到内网服务,那我公网服务器同样访问不到吧。所以我们就需要利用现有的链路来完成这件事。
基 ...
将版本信息打包到go的二进制中
很多时候对于go打包后的二进制文件,我们是无法知道这个二进制是什么当前什么版本、什么时候打包的,而很多软件的命令行都会有一个 -version 的选项来打印出当前程序的版本号,当然你可以直接在程序里面写死这个版本号,但是还有更加优雅的解决方式。
实现其实很简单,只需要在 build 的时候通过 -X 参数去指定变量值就可以了
1234567891011121314package mainimport "fmt"var ( Tag = "v0.0.0" CommitID = "" Branch = "" DATE = "")func main() { fmt.Println("tag:", Tag, "branch:", Branch, "commitID:", CommitID, "DATE:", DATE)}
123456789101112 ...
回首网络知识之 TCP 协议
之前我们说了 UDP 协议,也说到了 UDP 协议和 TCP 协议的对比,知道了 TCP 协议有那么一些复杂,所以这次就来仔细说说这个复杂的 TCP
前言提到 TCP 你第一想到的应该就是两个字 “靠谱”~ 因为它的所有设计都是围绕着这个任务展开的。
报文格式
很多人一看到这个就头疼了,因为格式好复杂啊,和 UDP 对比起来,怎么多了那么多东西呢?
别急,其实并不是很多,而且只要你想着为什么,你就知道会有什么。
首先是两个端口,这个和 UDP 一样,肯定需要端口,不然的话不知道是发给谁的
然后是序号和确认序号,序号是为了解决乱序的问题,如果没有序号,那么我是不知道那个先那个后,同时我还要告诉对方我收到了这个序号的信息,所以需要一个确认序号,确认的方式是告诉你我要的下一个序号是多少
首部长度也很好理解,告诉你首部有多长,你就知道前面有多长,你才知道数据从哪里开始
中间那几个标识位需要知道的是:
SYN:建立连接时用的,建立连接会标识为 1
ACK:回复你建立连接,建立连接之后标识为 1
RST:重新连接
FIN:结束连接
窗口大小,接收方告诉发送方别发太快了或者太慢了,用于流 ...
Golang 之 WaitGroup 源码解析
如果我们有一个大的任务要做,我们会尝试将这个任务分解,分解完成之后并发交由 goroutine 去做,并且我需要当全部的任务完成之后再进行下面的步骤,在 sync 包下,就有这样一个东西适合上述情况,WaitGroup,今天我们来看看具体它是怎么实现的。
PS:在下面我统一用 wg 来简称 WaitGroup
使用它的使用非常简单,如下:
12345678910111213func main () { wg := sync.WaitGroup {} for i := 0; i < 10; i++ { wg.Add (1) go func (job int) { defer wg.Done () //do something fmt.Printf ("job % d done\n", job) }(i) } wg.Wait () fmt.Println ...
回首网络知识之 UDP 协议
最近开始在恶补网络知识,算是一个复习,在学习了很多上层建筑之后回来看看之前的基础确实又有一个新的认识。一开始准备看完之后做一个整体的总结,但是发现知识点太多所以分了几期来写,每期都会短一点,这期我们先来简单了解一下 UDP
前言传输层中重要的两个协议 UDP 和 TCP ,在平时的时候,你虽然一直用着他们,但是往往感受不到他们的存在,他们两个往往经常会在面试的时候出现,打你一个措手不及。
在学习它之前,你首先要有一个概念,为什么我们需要 UDP 或者 TCP 这样的协议,它到底是在什么时候,什么地方,帮我们完成了什么样的事情?
在网络,我们研究的往往都是如何以一种合理的方式传递数据
而且协议则指定了这样的规定,当双方都遵守这样的规定,才能看懂互相说的话,才能达到合理传递数据的目的。
UDP 怎么样
UDP 格式简单,没有花里胡哨的东西
UDP 不会先探路,而是直接就发上了
UDP 不会管你卡不卡,发给你我就不管了
报文格式
源端口号(16 位,2 字节)
目的端口(16 位,2 字节)
UDP 长度(16 位,2 字节)
UDP 校验和(16 位,2 字节)
...
实现分布式锁,你能想到什么?
所谓分布式锁,即在多个相同服务水平扩展时,对于同一资源,能稳定保证有且只有一个服务获得该资源 — by LinkinStar
其实对于分布式锁,也是属于那种看似简单,实则有很多细节的问题。很多人在被问到这个问题的时候,一上来就会说用redis嘛,setnx嘛,我知道我知道。但仅仅是这样就能搞定了吗?那么当我们在实现一个分布式锁的时候,我们究竟需要考虑些什么呢?
必考点首先作为一个分布式锁,你一定要保证的是什么呢?
不能有两个服务同时获取到一把锁(资源)
不能出现有一个资源一直被锁住(锁一直被持有)
我认为上面两点是必须要保证的,其他的点,比如锁的获取是否高效,锁获取的非阻塞等等是评价一个锁是否好用的点(当然也不是说不重要)
下面我们一个个实现方案来说,来看看究竟有多少细节是我们需要考虑的。
redis实现先从最普遍的实现方案开始说起,redis。利用redis的特性,nx,资源不存在时才能够成功执行 set 操作,同时设置过期时间用于防止死锁
加锁SET resource_key random_value NX PX lock-time
解锁DEL resource_key
...
细说kubernetes - 初识deployment
当我们认识的k8s的时候,我们第一个认识的是pod,那么我觉得第二个认识的应该就是Deployment了。作为k8s中一个非常常见的对象,今天我们来看看它的实现原理和设计思想。
PS: 本文需要你对pod的定义和理解有一定的基础
定义在k8s中,对象常常都是以一个yaml格式的文件来定义的,deployment也不例外。如果你对k8s还不是特别了解,你大可以将一个文件看做是一个对象的所有属性,每个属性都有对应的值,其实也并不复杂。deployment的定义如下:
1234567891011121314151617181920212223242526# 定义版本apiVersion: apps/v1# 定义类型kind: Deployment# 定义名称和标签metadata: name: nginx-deployment labels: app: nginx# 定义规格spec: replicas: 2 selector: matchLabels: app: nginx # 定义模板 template: metadata: labe ...
细说kubernetes - 为什么是pod
k8s作为现在最火的容器编排调度平台,好用我也就不必多说了。当我们初识k8s的时候一个新的概念就到了我们眼前,那就是pod。我们在使用了之后也就渐渐的接受了pod这个东西,但是你有没有想过,为什么是pod?k8s为什么会有这样的设计?今天我们就来细细说说这个pod
架构图首先我们来回忆看看k8s的架构图是什么样子的这个是来源于 https://www.kubernetes.org.cn/ 中文官网的一个架构图
从架构图中我们可以看到,整个k8s的设计架构有以下几个要点:
master、node架构;master就是大脑充当着管理者的角色
master中提供了api-server、controller-manager、scheduler、etcd用于管理node并向外提供服务
node就是实际干活的,提供了kubelet、proxy用于向master汇报情况,并管理pod的网络
而pod是k8s中最小的调度单位,Pod就是最小的,管理,创建,计划的最小单元.
当然其他组件都非常重要,这个我们以后再说,我们今天就来看看主角“pod”
为什么是pod?一开始用的时候我就好奇为什么k8 ...
细说docker - 容器技术
docker对于现在的我们来说,已经是一个非常熟悉的东西了,docker无论是在部署打包,自动化,等方方面面都起着重要的作用,但是你是否有疑问,docker究竟是如何帮我们创建一个个隔离的环境的呢?今天我们就来看看,仔细说说docker
PS: 以下的讨论都限定在linux环境下,在windows和macos下容器技术实现不相同,不在讨论范围内。
大方向为什么先要提到这个词呢?因为所有在操作系统上运行的程序都叫做进程。docker也不例外,从大的方向来讲,docker就是帮你创建了一个进程而已。而不一样的是,docker通过限制了各种环境,就像给这个进程画了一个圈,所以在这个进程本身看来,它自己好像被隔离了一般。
docker容器技术的核心,就是通过约束和修改进程的动态表现,从而为其创造出一个“边界”
限制条件那么我们有了大方向,那么来细细看看,首先的第一个问题就来了,docker是通过什么方法对这个进程进行限制的呢?
Namespace命名空间,没错就是它,是它限制了docker容器的环境。其实这是linux的一个功能而已,只不过没人想到docker会那它来做这个事情。下面看 ...
再看golang垃圾回收
首先要说一些废话:之前我已经有博客写过golang的垃圾回收相关的内容,虽然很简略,但是涵盖了整体的流程,现在为啥又来写一遍呢?一方面有一些政治(你懂得)因素在里面,一方面最近又再研究。那么问题来了,那么多博客已经写过了它,我怎么把它讲出花来呢?我思前想后,于是想出了几个独特的角度来重新诠释一下golang的垃圾回收。
那首先如果再把整个gc过程简单说一遍,可能就没有人愿意听了,但是golang的gc说简单也简单说复杂其实也有很多细节,如何做到有自己的想法呢?于是我就强行举例了几个问题。
问题&角度在研究golang垃圾回收的时候,你有没有想过下面几个问题
golang如果有两个对象循环互相引用,是否会出现永远回收不了的对象?
golang的gc标记方式为什么用bfs而不是dfs?
是否有可能永远不触发gc?
为什么golang的gc不整理、不分代?
个人理解首先说明一下,这些问题都是我自己想的,也没有什么所谓的正确答案,所以下面也是我的个人理解,如果有问题可以在下方留言进行讨论。
问题1
golang如果有两个对象循环互相引用,是否会出现永远回收不了的对象?
为什么 ...
快速上手kubernetes——minikube最小实现
最近在研究k8s,就来写一个关于k8s快速上手,并记录采坑的点。需要的前置知识点:docker、k8s的一些基本概念,下面这个可能对你有帮助。https://juejin.im/post/5d1b2a656fb9a07edc0b7058
什么是k8s我们知道,我们可以将项目制作成docker镜像,然后利用docker去部署我们的项目,这样可以解决很多服务器环境所带来的问题;但是容器多了,容器与容器之间就需要访问,之间就需要网络配置等等,从而就有了docker-compose;但是当我们的服务进行升级,或者服务需要进行调度,扩容等等,这个时候就需要一个大管家来管所有的东西;这个大管家就是 - Kubernetes
初学会遇到的问题因为k8s的东西太多了,所以学习成本现在越来越高,好在k8s已经很多教程。我说一下现在学的时候肯定会遇到的大问题:
国内的问题(国内环境很多镜像拉不到)
本地搭建环境(原来搭建k8s需要一些服务器)
电脑环境的问题(windows和mac都有坑点)
最小实现现在我们就来在本机实现一个最小的k8s的实现,给出一个hello-worldk8s提供了minik ...
快速上手terraform —— 阿里云OSS和ECS的创建
最近在研究terraform,采了一圈坑,记录一下。
什么是terraform?terraform 通过代码配置实现物理机等一些资源的分配。简单说就是,写一个配置文件,启动,就能帮你购买一台云的机器,或者说申请到oss的资源,或者是别的什么。具体功能见官网。
https://www.terraform.io/docs/index.html
名词解释:provider你可以把它看做各个厂商对terraform提供的插件,terraform可以调用这些插件从而实现对资源的操作管理。terraform流程:init -> plan -> apply -> destroy对应为:初始化,计划验证,实际应用,销毁
最小demo我将用一个最小的demo来演示它怎么干活的:通过terraform来创建一个阿里云的oss(以下没有利益相关)只是因为阿里云我有账号而已,其他供应商也有。
我的本地环境:macOS
步骤1 下载相关资源下载对应的客户端:https://www.terraform.io/downloads.html下载解压后得到:terraform的客户端,将它复制到 ...
golang中神奇的sync.Pool
在 golang 中有一个池,它特别神奇,你只要和它有个约定,你要什么它就给什么,你用完了还可以还回去,但是下次拿的时候呢,确不一定是你上次存的那个,这个池就是 sync.Pool
说实话第一次看到这个东西的时候,真的想不到这个东西有啥用啊,为什么要有这个东西呢?等我看完之后,嗯,还有有点用的;等到有一次优化经历的时候,嗯,这个有点意思了。今天我们就来看看这个神奇的 sync.Pool
简单案例首先我们来看看这个 sync.Pool 是如何使用的,其实非常的简单。它一共只有三个方法我们需要知道的:New、Put、Get
1234567891011121314151617181920package mainimport ( "fmt" "sync")var strPool = sync.Pool{ New: func() interface{} { return "test str" },}func main() { ...
图解golang内存分配
我们知道所有程序运行都需要使用内存,而内存的管理和分配又是非常重要的,它决定了你的程序能不能在有限的资源内跑的更快。可以设想一下,如果你自己来设计的一个内存分配的规则,会遇到什么问题呢?如果你有了一大块内存你要怎么去合理的分配和使用呢?今天我们通过几张图来看看golang中的内存分配是怎样的。
前置知识:对golang的GPM模型有所了解,对GC有一定的了解,有助于你理解下面的内容。
想一想我们首先来想一下,如果我们自己来分配内存的时候可能会遇到什么问题。
我想要512G,你能给吗?操作系统的内存不是你想要多少就给你多少的。比如我跟操作系统说我要512G内存,你赶紧给我,不给我我就掐死你,如果你是操作系统,是不是立马就想把我给结束了?
能随便分割吗?如果我拿到一块内存,挺大的,你把它想象成一块地,我今天要用这块地的这个部分,肯定是从中间切一块出来用,然后明天要另一个部分,然后再切出来一部分。如果随便切,今天要一块三角形,明天要一块圆形,那么肯定会留有很多小块的地方,那些地方没有办法被合理的使用,就会浪费。等到想再要一块正方形的地的时候发现没地方可以切了。
不用了我需要放回去吗?如果我 ...
大话图解gin源码
最近在网上搜了一下,对于gin框架用的人还是比较多的,我自己之前也在使用,但是对于源码解析这块,我没有看到自己想看到的那种从框架入手的解析图,所以嘿嘿嘿,我的机会就来了,今天就带来最完整的gin源码图解。希望通过这篇博客你也能自己学会拆轮子。
PS:本文建立在你已经能熟练使用gin的基础之上,如果还没用过可以去官网看一下:https://gin-gonic.com/zh-cn/docs/然后gin是对golang的http包的封装,所以最好对http包也要有了解。
整体分析逻辑先来说明一下我整体拆解的逻辑,对于一个框架,我喜欢从下面几个方面去入手拆解:
启动方式
如何使用
实现与特点针对于gin,我也将从这几个方面去入手,就会得到下面几个问题,带着问题看源码是必备条件。首先启动的时候gin做了些什么?gin封装了什么然后怎么去实现的?gin整体结构是怎么样的,有哪些结构?…
然后使用一个比较小的demo,然后先从方法入手,进源码看。
12345678910111213141516func main() { router := gin.Default() ...