Go - Web
API
项目结构1234567891011121314151617$ tree.├── cmd│ └── bookstore│ └── main.go├── go.mod├── internal│ └── store│ └── memstore.go├── server│ ├── middleware│ │ └── middleware.go│ └── server.go└── store ├── factory │ └── factory.go └── store.go
逻辑结构
具体实现store
定义 Domain 和 Action
store/store.go12345678910111213141516package storetype Book struct { Id string `json:"id"` Name string `json:"name"` Authors []string `json:"authors& ...
Go - Main + Init
main.main
main 包中的 main 函数 - 所有可执行程序的用户层执行逻辑的入口函数
123456package main// 无参数 + 无返回值func main() { // 用户层执行逻辑}
可执行程序的 main 包必须定义 main 函数,否则会编译报错function main is undeclared in the main package
main.go1package main
123$ go build main.go# command-line-argumentsruntime.main_main·f: function main is undeclared in the main package
在启动了多个 goroutine 的 Go 应用中,main.main 将在 Go 应用的主 goroutine 中执行
main.main 函数返回意味着整个 Go 程序结束
除了 main 包外,其它包也可以拥有自己的 main 函数
但依据 Go 的可见性规则,非 main 包中的 main 函数仅限于包内使用
123456 ...
Go - Go Module
添加依赖
github.com/google/uuid
main.go1234567891011package mainimport ( "github.com/google/uuid" "github.com/sirupsen/logrus")func main() { logrus.Println("hello, gomodule mode") logrus.Println(uuid.NewString())}
go.mod 里的 require 字段中,没有任何 Module 提供了包 github.com/google/uuid
123$ go buildmain.go:4:2: no required module provides package github.com/google/uuid; to add it: go get github.com/google/uuid
手动 go get,下载依赖到本地 Module 缓存,并更 ...
Go - Build Mode
构建过程
确定包版本 + 编译包 + 链接目标文件(编译后得到的)
构建模式
Mode
Desc
GOPATH
不关注依赖版本
Vendor - 1.5
Reproducible Build
Go Module - 1.11
Dependency Management
GOPATH
Go 首次开源时,内置了 GOPATH 的构建模式
Go 编译器可以在本地 GOPATH 下搜索 Go 程序依赖的第三方包
如果存在,则使用这个本地包进行编译;如果不存在,则会报编译错误
main.go1234567package mainimport "github.com/sirupsen/logrus"func main() { logrus.Println("hello, gopath mode")}
无法找到依赖包而构建失败
1234567891011121314151617$ go versiongo version go1.10.8 linux/amd64$ echo $GOROOT/home/zhongming ...
Go - Project Layout
演进历史Go 1.3
以 all.bash 为代表的源码构建脚本放在了 src 的顶层目录下
123456789101112131415161718192021222324$ tree -LF 1 ./src./src/├── Make.dist├── all.bash*├── all.bat├── all.rc*├── clean.bash*├── clean.bat├── clean.rc*├── cmd/├── lib9/├── libbio/├── liblink/├── make.bash*├── make.bat├── make.rc*├── nacltest.bash*├── pkg/├── race.bash*├── race.bat├── run.bash*├── run.bat├── run.rc*└── sudo.bash*
./src/cmd 存放着 Go 可执行文件的相关目录,每个子目录都是一个 Go 工具链命令或子命令对应的可执行文件
12345678910111213141516171819$ tree -LF 1 ./src/cmd./src/cmd/├── 5a/ ...
Go - Code Structure
源文件
Go 源文件使用全小写字母形式的短小单词命名,并以 .go 扩展名结尾
如果使用多个单词,将多个单词直接连接起来,而不使用其它分隔符
即 helloworld.go,而非 hello_world.go
尽量不要使用两个以上单词组合作为文件名,否则很难辨认
Hello, World1234567package mainimport "fmt"func main() { fmt.Println("Hello, World!")}
12345678910111213$ tree.└── main.go$ go build main.go$ tree.├── main└── main.go$ ./mainHello, World!
程序结构1package main
package 是 Go 语言的基本组成单位,通常使用单个小写单词命名
整个 Go 程序仅允许存在一个 main 包
main.go12345import "fmt"func main() { fmt.Println(&quo ...
Kubernetes - DevOps
基本概念流程概览
实现自动化,最核心的投入为编写测试用例
分支管理
提交 PR 时会触发 CI Pipeline;生产系统版本不能直接使用 master 分支(最新代码),而是要基于 Release 分支
CICD
CI
CD
GitOps
一切皆代码,通过 Git 来触发 Ops
Jenkins
Jenkins 不是云原生
Container CI
需要保证 CI 构建环境和开发环境的统一
使用容器作为标准的构建环境,将代码库作为 Volume 挂载进容器
需要在构建容器中执行 docker build 命令,即 Docker in Docker = DIND
Kubernetes CI
Jenkins 可以被容器化(on Kubernetes),并支持 Cloud Provider,通过插件的方式支持 Kubernetes
https://github.com/jenkinsci/kubernetes-pluginJenkins plugin to run dynamic agents in a Kubernetes/Docker environment
...
Kubernetes - Production Ops
镜像仓库
镜像仓库(Registry)负责存储、管理和分发镜像
Registry 管理多个 Repository(通过命名区分)
每个 Repository 包含一个或多个镜像(通过镜像名和标签区分)
客户端拉取镜像:Registry/Repository/Image:Tag
分发规范
镜像仓库应遵循 OCI Distribution Spec
HTTP Verb
URL
Desc
GET
/v2/
检查 Registry 实现的规范和版本
GET
/v2/_catalog
获取 Repository 列表
GET
/v2//tags/list
获取某个 Repository 下所有的标签
PUT
/v2//manifests/
上传 Image 的 manifest 信息
DELETE
/v2//manifests/
删除 Image
GET
/v2//manifests ...
Kubernetes - Manage Production Clusters
操作系统
通用操作系统 - 成熟
Ubuntu
CentOS
Fedora
专为容器优化的操作系统 - 最小化主机操作系统
CoreOS
最早的容器化操作系统,已被收购
RedHat Atomic
将 RPM Repository 转换成 ostree,可以被 bootloader 直接加载
Snappy Ubuntu Core
Canonical 出品,最初为移动设备设计
RancherOS
相对较新,RancherOS 中运行的所有服务都是 Docker 容器
评估选型的标准
是否有生态系统
成熟度
内核版本
对运行时的支持
Init System
包管理和系统升级
安全
不可变基础设施
不可变的容器镜像
不可变的主机操作系统
Atomic - 打包成一个经过裁剪后的操作系统
由 Red Hat 支持的软件包安装系统
多种发行版:Fedora / CentOS / RHEL
优势
不可变操作系统,面向容器优化的基础设施
只有 /etc 和 /var 可以修改,其它目录均为只读
基于 rpm-ostree 管理系统包
IaC:输 ...
Kubernetes - Service Discovery
基本概念发展历程
数据包
负载均衡的核心原理 - 修改包头数据
通过浏览器访问某网站的过程(组包在应用层,传包在内核层)
在浏览器输入网站的网址
浏览器本质上是一个 HTTP 客户端,组装成 HTTP 包
做 DNS 解析(递归)
封装 TCP 包(源端口 + 目标端口)
封装 IP 包(源 IP + 目标 IP - 来自于 DNS)
负载均衡
面向连接的负载均衡不一定能保证平均,如 grpc 是基于 http/2,会复用 TCP 连接,L4 的负载均衡就无法实现平均
方案集中式
F5(HLB) / Nginx(SLB) - 接入集群外部流量
在服务消费者和服务提供者之间有一个独立的 LB
LB 上有所有服务的地址映射表,通常由运维配置注册
当服务消费者调用某个目标服务时,向 LB 发起请求,由 LB 以某种策略做负载均衡后将请求转发到目标服务
LB 一般具备健康检查的能力,能自动摘除不健康的服务实例
服务消费者通过 DNS 发现 LB,运维人员配置一个指向该 LB 的 DNS 域名
优缺点
优点
方案简单,在 LB 上容易实现集中式的访问控制,为业界主流
...