思考并回答以下问题:
02丨环境准备:如何安装和配置一个基本的Go开发环境?
Linux服务器配置
建议使用CentOS 8.2,查看CentOS版本:1
2$ cat /etc/redhat-release
CentOS Linux release 8.4.2105
第一步,用Root用户登录Linux系统,并创建普通用户。
1 | # useradd going # 创建 going 用户,通过 going 用户登录开发机进行开发 |
第二步,添加sudoers。
将普通用户加入到sudoers中,这样普通用户就可以通过sudo命令来暂时获取Root的权限。1
$ sed -i '/^root.*ALL=(ALL).*ALL/a\going\tALL=(ALL) \tALL' /etc/sudoers
1 | $ cat /etc/sudoers |
第三步,替换CentOS系统中自带的Yum源。
CentOS 8将停止维护,官方的Yum源已不可使用,所以需要切换官方的Yum源,这里选择阿里提供的Yum源。切换命令如下:1
2
3
4$ mv /etc/yum.repos.d /etc/yum.repos.d.bak # 先备份原有的 Yum 源
$ mkdir /etc/yum.repos.d
$ wget -O /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-vault-8.5.2111.repo
$ yum clean all && yum makecache
第四步,用新的用户名(going)和密码登录Linux服务器。这一步也可以验证普通用户是否创建成功。
第五步,配置$HOME/.bashrc
文件。
我们登录新服务器后的第一步就是配置$HOME/.bashrc
文件,以使Linux登录shell更加易用,例如配置LANG解决中文乱码,配置PS1可以避免整行都是文件路径,并将$HOME/bin
加入到PATH路径中。配置后的内容如下:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22# .bashrc
# User specific aliases and functions
alias rm='rm -i'
alias cp='cp -i'
alias mv='mv -i'
# Source global definitions
if [ -f /etc/bashrc ]; then
. /etc/bashrc
fi
# User specific environment
# Basic envs
export LANG="en_US.UTF-8" # 设置系统语言为 en_US.UTF-8,避免终端出现中文乱码
export PS1='[\u@dev \W]\$ ' # 默认的 PS1 设置会展示全部的路径,为了防止过长,这里只展示:"用户名@dev 最后的目录名"
export WORKSPACE="$HOME/workspace" # 设置工作目录
export PATH=$HOME/bin:$PATH # 将 $HOME/bin 目录加入到 PATH 变量中
# Default entry folder
cd $WORKSPACE # 登录系统,默认进入 workspace 目录
有一点需要我们注意,在export PATH
时,最好把$PATH
放到最后,因为我们添加到目录中的命令是期望被优先搜索并使用的。配置完$HOME/.bashrc
后,我们还需要创建工作目录workspace。将工作文件统一放在$HOME/workspace
目录中,有几点好处。
- 可以使我们的
$HOME
目录保持整洁,便于以后的文件查找和分类。 - 如果哪一天
/
分区空间不足,可以将整个workspace目录mv
到另一个分区中,并在/
分区中保留软连接,例如:/home/going/workspace -> /data/workspace/
。 - 如果哪天想备份所有的工作文件,可以直接备份workspace。
具体的操作指令是$ mkdir -p $HOME/workspace
。配置好$HOME/.bashrc
文件后,我们就可以执行bash
命令将配置加载到当前shell中了。
依赖安装和配置
第一步,安装依赖。
首先,我们在CentOS系统上通过yum命令来安装所需工具的依赖,安装命令如下:1
$ sudo yum -y install make autoconf automake cmake perl-CPAN libcurl-devel libtool gcc gcc-c++ glibc-headers zlib-devel git-lfs telnet lrzsz jq expat-devel openssl-devel
虽然有些CentOS 8.2系统已经默认安装这些依赖了,但是为了确保它们都能被安装,我仍然会尝试安装一遍。如果系统提示Package xxx is already installed.
,说明已经安装好了,你直接忽略即可。
第二步,安装Git。
因为安装IAM系统、执行go get
命令、安装protobuf工具等都是通过Git来操作的,所以接下来我们还需要安装Git。由于低版本的Git不支持--unshallow
参数,而go get
在安装Go包时会用到git fetch --unshallow
命令,因此我们要确保安装一个高版本的Git,具体的安装方法如下:1
2
3
4
5
6
7
8
9$ cd /tmp
$ wget --no-check-certificate https://mirrors.edge.kernel.org/pub/software/scm/git/git-2.36.1.tar.gz
$ tar -xvzf git-2.36.1.tar.gz
$ cd git-2.36.1/
$ ./configure
$ make
$ sudo make install
$ git --version # 输出 git 版本号,说明安装成功
git version 2.36.1
注意啦,按照上面的步骤安装好之后,我们要把Git的二进制目录添加到PATH路径中,不然Git可能会因为找不到一些命令而报错。你可以通过执行以下命令添加目录:1
2
3
4$ tee -a $HOME/.bashrc <<'EOF'
# Configure for git
export PATH=/usr/local/libexec/git-core:$PATH
EOF
第三步,配置Git。我们直接执行如下命令配置Git:1
2
3
4$ git config --global user.name "Lingfei Kong" # 用户名改成自己的
$ git config --global user.email "colin404@foxmail.com" # 邮箱改成自己的
$ git config --global credential.helper store # 设置 Git,保存用户名和密码
$ git config --global core.longpaths true # 解决 Git 中 'Filename too long' 的错误
除了按照上述步骤配置Git之外,我们还有几点需要注意。
首先,在Git中,我们会把非ASCII字符叫做Unusual字符。这类字符在Git输出到终端的时候默认是用8进制转义字符输出的(以防乱码),但现在的终端多数都支持直接显示非ASCII字符,所以我们可以关闭掉这个特性,具体的命令如下:1
$ git config --global core.quotepath off
其次,GitHub限制最大只能克隆100M的单个文件,为了能够克隆大于100M的文件,我们还需要安装Git Large File Storage,安装方式如下:1
$ git lfs install --skip-repo
Go编译环境安装和配置
首先,我们从Go语言官方网站下载对应的Go安装包以及源码包,这里我下载的是go 1.18.3版本:1
$ wget -P /tmp/ https://golang.google.cn/dl/go1.18.3.linux-amd64.tar.gz
接着,我们完成解压和安装,命令如下:1
2
3$ mkdir -p $HOME/go
$ tar -xvzf /tmp/go1.18.3.linux-amd64.tar.gz -C $HOME/go
$ mv $HOME/go/go $HOME/go/go1.18.3
接着,我们执行以下命令,将下列环境变量追加到$HOME/.bashrc
文件中。1
2
3
4
5
6
7
8
9
10
11
12$ tee -a $HOME/.bashrc <<'EOF'
# Go envs
export GOVERSION=go1.18.3 # Go 版本设置
export GO_INSTALL_DIR=$HOME/go # Go 安装目录
export GOROOT=$GO_INSTALL_DIR/$GOVERSION # GOROOT 设置
export GOPATH=$WORKSPACE/golang # GOPATH 设置
export PATH=$GOROOT/bin:$GOPATH/bin:$PATH # 将 Go 语言自带的和通过 go install 安装的二进制文件加入到 PATH 路径中
export GO111MODULE="on" # 开启 Go moudles 特性
export GOPROXY=https://goproxy.cn,direct # 安装 Go 模块时,代理服务器设置
export GOPRIVATE=
export GOSUMDB=off # 关闭校验 Go 依赖包的哈希值
EOF
为什么要增加这么多环境变量呢?这是因为,Go语言是通过一系列的环境变量来控制Go编译器行为的。因此,我们一定要理解每一个环境变量的含义。
因为Go以后会用Go modules来管理依赖,所以我建议你将GO111MODULE设置为on。
在使用模块的时候,$GOPATH是无意义的,不过它还是会把下载的依赖储存在$GOPATH/pkg/mod
目录中,也会把go install
的二进制文件存放在$GOPATH/bin
目录中。
另外,我们还要将$GOPATH/bin
、$GOROOT/bin
加入到Linux可执行文件搜索路径中。这样一来,我们就可以直接在bash shell中执行go自带的命令,以及通过go install
安装的命令。
然后就是进行测试了,如果我们执行go version
命令可以成功输出Go的版本,就说明Go编译环境安装成功。具体的命令如下:1
2
3$ bash
$ go version
go version go1.18.3 linux/amd64
最后,初始化工作区。
本专栏使用的Go版本为go 1.18.3,go 1.18.3支持多模块工作区,所以这里也需要初始化工作区。初始化命令如下:1
2
3
4$ mkdir -p $GOPATH && cd $GOPATH
$ go work init
$ go env GOWORK # 执行此命令,查看 go.work 工作区文件路径
/home/going/workspace/golang/go.work
ProtoBuf编译环境安装
接着,我们再来安装protobuf的编译器protoc。protoc需要protoc-gen-go来完成Go语言的代码转换,因此我们需要安装protoc和protoc-gen-go这2个工具。它们的安装方法比较简单,你直接看我下面给出的代码和操作注释就可以了。1
2
3
4
5
6
7
8
9
10
11
12
13# 第一步:安装 protobuf
$ cd /tmp/
$ git clone -b v3.21.1 --depth=1 https://github.com/protocolbuffers/protobuf
$ cd protobuf
$ ./autogen.sh
$ ./configure
$ make
$ sudo make install
$ protoc --version # 查看 protoc 版本,成功输出版本号,说明安装成功
libprotoc 3.21.1
# 第二步:安装 protoc-gen-go
$ go install github.com/golang/protobuf/protoc-gen-go@v1.5.2
当你第一次执行go install
命令的时候,因为本地无缓存,所以需要下载所有的依赖模块。因此安装速度会比较慢,请你耐心等待。
Go开发IDE安装和配置
第一步,安装vim-go。
安装命令如下:1
2$ rm -f $HOME/.vim; mkdir -p ~/.vim/pack/plugins/start/
$ git clone --depth=1 https://github.com/fatih/vim-go.git ~/.vim/pack/plugins/start/vim-go
第二步,Go工具安装。
vim-go会用到一些Go工具,比如在函数跳转时会用到guru、godef工具,在格式化时会用到goimports,所以你也需要安装这些工具。安装方式如下:执行vi /tmp/test.go
,然后输入:GoInstallBinaries
安装vim-go需要的工具。
安装后的Go IDE常用操作的按键映射如下表所示:
课后练习
试着编写一个main.go,代码如下:
1 | package main |
将鼠标放在Println上,键入Enter键跳转到函数定义处,键入Ctrl+I返回到跳转点。
01丨IAM系统概述:我们要实现什么样的Go项目?
IAM系统是什么?
1,用户需要提供昵称、密码、邮箱、电话等信息注册并登录到IAM系统,这里是以用户名和密码作为唯一的身份标识来访问IAM系统,并且完成认证。
2,因为访问IAM的资源授权接口是通过密钥(secretID/secretKey)的方式进行认证的,所以用户需要在IAM中创建属于自己的密钥资源。
3,因为IAM通过授权策略完成授权,所以用户需要在IAM中创建授权策略。
4,请求IAM提供的授权接口,IAM会根据用户的请求内容和授权策略来决定一个授权请求是否被允许。
我们可以看到,在上面的流程中,IAM使用到了3种系统资源:用户(User)、密钥(Secret)和策略(Policy),它们映射到程序设计中就是3种RESTful资源:
- 用户(User):实现对用户的增、删、改、查、修改密码、批量修改等操作。
- 密钥(Secret):实现对密钥的增、删、改、查操作。
- 策略(Policy):实现对策略的增、删、改、查、批量删除操作。
IAM系统的架构长啥样?
IAM系统的完整架构
总的来说,IAM架构中包括9大组件和3大数据库。
前5个组件是我们需要实现的核心组件。后4个组件是一些旁路组件,不影响项目的使用。
通过使用流程理解架构
第1步,创建平台资源。
用户通过iam-webconsole(RESTful API)或iamctl(sdk marmotedu-sdk-go)客户端请求iam-apiserver提供的RESTful API接口完成用户、密钥、授权策略的增删改查,iam-apiserver会将这些资源数据持久化存储在MySQL数据库中。而且,为了确保通信安全,客户端访问服务端都是通过HTTPS协议来访问的。
第2步,请求API完成资源授权。
用户可以通过请求iam-authz-server提供的/v1/authz接口进行资源授权,请求/v1/authz接口需要通过密钥认证,认证通过后/v1/authz接口会查询授权策略,从而决定资源请求是否被允许。
为了提高/v1/authz接口的性能,iam-authz-server将密钥和策略信息缓存在内存中,以便实现快速查询。那密钥和策略信息是如何实现缓存的呢?
首先,iam-authz-server通过调用iam-apiserver提供的gRPC接口,将密钥和授权策略信息缓存到内存中。同时,为了使内存中的缓存信息和iam-apiserver中的信息保持一致,当iam-apiserver中有密钥或策略被更新时,iam-apiserver会往特定的Redis Channel(iam-authz-server也会订阅该Channel)中发送PolicyChanged和SecretChanged消息。这样一来,当iam-authz-server监听到有新消息时就会获取并解析消息,根据消息内容判断是否需要重新调用gRPC接来获取密钥和授权策略信息,再更新到内存中。
第3步,授权日志数据分析。
iam-authz-server会将授权日志上报到Redis高速缓存中,然后iam-pump组件会异步消费这些授权日志,再把清理后的数据保存在MongoDB中,供运营系统iam-operating-system查询。
这里还有一点你要注意:iam-authz-server将授权日志保存在Redis高性能key-value数据库中,可以最大化减少写入延时。不保存在内存中是因为授权日志量我们没法预测,当授权日志量很大时,很可能会将内存耗尽,造成服务中断。
第4步,运营平台授权数据展示。
iam-operating-system是IAM的运营系统,它可以通过查询MongoDB获取并展示运营数据,比如某个用户的授权/失败次数、授权失败时的授权信息等。此外,我们也可以通过iam-operating-system调用iam-apiserver服务来做些运营管理工作。比如,以上帝视角查看某个用户的授权策略供排障使用,或者调整用户可创建密钥的最大个数,再或者通过白名单的方式,让某个用户不受密钥个数限制的影响等等。
总结
首先,用户通过调用iam-apiserver提供的RESTful API接口完成注册和登录系统,再调用接口创建密钥和授权策略。
创建完密钥对和授权策略之后,IAM可以通过调用iam-authz-server的授权接口完成资源的授权。具体来说,iam-authz-server通过gRPC接口获取iam-apiserver中存储的密钥和授权策略信息,通过JWT完成认证之后,再通过ory/ladon包完成资源的授权。
接着,iam-pump组件异步消费Redis中的数据,并持久化存储在MongoDB中,供iam-operating-system运营平台展示。
最后,IAM相关的产品、研发人员可以通过IAM的运营系统iam-operating-system来查看IAM系统的使用情况,进行运营分析。例如某个用户的授权/失败次数、授权失败时的授权信息等。
另外,为了提高开发和访问效率,IAM分别提供了marmotedu-sdk-go SDK和iamctl命令行工具,二者通过HTTPS协议访问IAM提供的RESTful接口。