Golang Mock 原理分析

在写单元测试时,通常需要对某些不容易构造或者不容易获取的对象进行 mock,那么在 Golang 中,我们可以 mock 哪些对象,又有哪些 mock 的方法呢,以及它们是如何实现的?本文将对几个 Golang 常见的开源库进行分析,了解其实现原理。

gomock 的实现

https://github.com/golang/mock 用于 interface 接口的 mock,需要先通过命令行工具 mockgen 生成 interface 的 mock 类型,通常会把命令用 //go:generate 写在代码中,比如:

package main

//go:generate mockgen -source=main.go -destination=foo_mock.go -package=main Foo

type Foo interface {
	Say(string, []string) string
}

func main() {
}

mockgen 会为 Foo 生成 MockFoo 类型的实现:

// MockFoo is a mock of Foo interface.
type MockFoo struct {
   ctrl     *gomock.Controller
   recorder *MockFooMockRecorder
}

// MockFooMockRecorder is the mock recorder for MockFoo.
type MockFooMockRecorder struct {
   mock *MockFoo
}

// NewMockFoo creates a new mock instance.
func NewMockFoo(ctrl *gomock.Controller) *MockFoo {
   mock := &MockFoo{ctrl: ctrl}
   mock.recorder = &MockFooMockRecorder{mock}
   return mock
}

Read more...

2021-06-19

MySQL DDL

MySQL 表结构信息存储

InnoDB 表和索引可以创建在系统表空间或者独立表空间(innodb_file_per_table=on)。对于 InnoDB 表,MySQL 会将表的数据字典信息存储在 .frm 文件中,同时也会存储入口信息(数据库名/表名)到系统表空间,在 INFORMATION_SCHEMA.INNODB_SYS_* 系统表中能够查询到表结构信息;如果 innodb_file_per_table=on,MySQL 会将表的数据存储在 .ibd 文件中,否则存储在系统表空间中。


Read more...

2020-12-13

Istio 学习笔记

常用的 Istio 资源类型

VirtualService

控制请求路由到网格中哪个服务。

  • hosts: 可以配置为带通配符前缀的 DNS 名称,或者 IP 地址。如果采用缩写,比如 reviews,那么在 Kubernetes 平台上就会根据 VirtualService 所在的命名空间,解释为 reviews.default.svc.cluster.local
  • gateways: 该 VirtualService 应用于哪些 Gateway 和 Sidecar。如果没有配置,那么默认值为 mesh。mesh 表示所有的 Sidecar。
  • http HTTPRoute[]: 匹配 HTTP 流量的有序路由规则列表,按顺序应用于 Kubernetes service.spec.ports.name(以 http-/http2-/grpc-* 命名)、gateway.spec.servers.port.protocol(HTTP/HTTP2/GRPC/ TLS-terminated-HTTPS)、serviceentry.spec.ports.protocol(HTTP/HTTP2/GRPC),第一条匹配路由规则将被使用。
    • name: 路由的名字,会被记录到 access log 中
    • match HTTPMatchRequest[]: 单个 HTTPMatchRequest 中的条件是 AND 语义,多个 HTTPMatchRequest 之间是 OR 语义
      • name: 与路由的名字拼接后记录到 access log 中
      • uri StringMatch: 匹配 URI,支持三种匹配规则:
        • exact: 精确匹配
        • prefix:前缀匹配
        • regex:正则匹配
      • ignoreUriCase: 不区分大小写匹配 URI
      • scheme StringMatch: 匹配 URI Scheme
      • method StringMatch: 匹配 HTTP method
      • authority StringMatch: 匹配 HTTP Authority
      • headers map<string, StringMatch>: 必须小写,并且采用连字符作为分隔符,例如 x-request-id。如果值为空,则判断请求头是否存在。注意 key 如果为 uri、scheme、method、authority 将被忽略
      • port: 端口
      • sourceLabels: 限制部分 Sidecar 应用此匹配规则,gateways 必须包含 mesh 值
      • gateways: 覆盖顶层的 gateways
      • queryParams map<string, StringMatch>: 匹配查询参数,不支持前缀匹配
      • withoutHeaders map<string, StringMatch>: 与 headers 参数相反的含义
      • sourceNamespace: 限制应用此匹配规则的命名空间,gateways 必须包含 mesh 值
    • route HTTPRouteDestination[]: 流量被转发到哪个服务上
      • destination Destination:
        • host: 必须存在于 service registry(Kubernetes services)中,或来自 ServiceEntry 中定义的 hosts
        • subset: DestinationRule 中定义的 subset 名字
        • port: 转发的端口
      • weight: 权重
      • headers Headers: 对请求头或响应头进行修改
    • redirect: 配置重定向
    • delegate: route 和 redirect 为空时才可以设置,用于指定把流量转交给其他 VirtualService 处理
    • rewrite: 转发请求之前对 uri 和 Authority/Host 请求头进行重写
    • timeout: 请求超时
    • retries: 重试策略
    • fault: 故障注入
    • mirror Destination: 流量镜像
    • mirrorPercentage: 流量镜像百分比,默认 100%
    • corsPolicy:CORS 策略
    • headers Headers:对请求头或响应头进行修改
  • tls: 匹配 HTTPS 流量的有序路由规则列表。
  • tcp: 匹配 TCP 流量的有序路由规则列表。
  • exportTo string[]: 控制 VirtualService 能否被其他命名空间的 Gateway 和 Sidecar 使用,如果不设置值,默认导出到所有命名空间
    • . 表示当前命名空间
    • * 表示所有命名空间

Read more...

2020-12-01

Kubernetes CronJob 完全指南

Linux Crontab 在过去作为执行定时任务的服务被广泛使用至今,但因其缺乏弹性,也出现了一些分布式的定时任务解决方案,比如 vipshop/Saturn、ihaolin/antares,那么在云原生时代,Kubernetes 作为最受欢迎的容器编排系统,它所提供的 CronJob 类型的工作负载,如何满足我们的需求,以及使用上会有哪些需要注意的地方,包括官方文档中没有讲述的细节,笔者将在这篇文章进行介绍。

Linux Crontab 相信很多人都熟悉,通过 crontab -u nobody -l 我们可以查看指定用户的定时任务,如果需要修改定时任务,则执行 crontab -u nobody -e,通过修改文件的方式配置定时任务,文件格式为:

# For details see man 4 crontabs

# Example of job definition:
# .---------------- minute (0 - 59)
# |  .------------- hour (0 - 23)
# |  |  .---------- day of month (1 - 31)
# |  |  |  .------- month (1 - 12) OR jan,feb,mar,apr ...
# |  |  |  |  .---- day of week (0 - 6) (Sunday=0 or 7) OR sun,mon,tue,wed,thu,fri,sat
# |  |  |  |  |
# *  *  *  *  * user-name  command to be executed

具体的调度执行是由 crond.service 负责。


Read more...

2020-09-29

MySQL 学习汇总

学习总结自《MySQL实战45讲》和 MySQL 官方文档

InnoDB 架构图


Read more...

2020-08-30

关于浮点数的运算,彻底弄懂为何 101.4 - 80.0 != 21.4

关于浮点数运算精度问题网上已有很多资料解释,但笔者还是想再造下“轮子”,加深理解。

先看一段简单的代码:

package main

func main() {
	var a float32 = 101.4
	var b float32 = 80.0
	var c float32 = 21.4
	var d float32 = 21.4
	if a-b == c {
		println("a-b = c")
	}
	if c == d {
		println("c = d")
	}
}

上述代码的运行结果为:

c = d

为何 a-b != c ? 如果我们直接在纸上用笔算,或者直接脑算都能得出 101.4 - 80.0 = 21.4。那么为何计算机算错了呢?

一句话说明原因:计算机在存储浮点数时存在精度误差。


Read more...

2020-08-18

Kubernetes 网络中数据包的流转

本文基于 kubernetes 1.17.4 + calico IPIP 模式 + kube-proxy IPtables 模式,观测 pod 间数据包的流动。

同宿主上 Pod 之间的流量

在 busybox-7d4f45df67-w2mvj 中,访问 nginx-7944498f44-7cllz。

首先查看 Pod 的路由表:

default via 169.254.1.1 dev eth0
169.254.1.1 dev eth0 scope link

busybox-7d4f45df67-w2mvj 发送给 nginx-7944498f44-7cllz 的数据包会通过 eth0 发送给网关 169.254.1.1。

但网关 169.254.1.1 并不是实际存在的,calico 通过在宿主机上的 Veth Pair 上设置 proxy_arp,代理了 169.254.1.1 的 arp 请求,这样容器发送出去的所有数据包都会送到宿主机上的 Veth Pair。

calico 对于 169.254.1.1 的相关解释:

查看 busybox-7d4f45df67-w2mvj 在宿主机上的 Veth Pair:

➜  ~ calicoctl get workloadendpoint  yangxikun-k8s-busybox--7d4f45df67--w2mvj-eth0 -o yaml
apiVersion: projectcalico.org/v3
kind: WorkloadEndpoint
metadata:
  creationTimestamp: 2020-06-21T09:05:55Z
  generateName: busybox-7d4f45df67-
  labels:
    app: busybox
    pod-template-hash: 7d4f45df67
    projectcalico.org/namespace: default
    projectcalico.org/orchestrator: k8s
    projectcalico.org/serviceaccount: default
  name: yangxikun-k8s-busybox--7d4f45df67--w2mvj-eth0
  namespace: default
  resourceVersion: "1966670"
  uid: e56e7d6f-cab2-4b2a-96a5-1c8f908e567b
spec:
  endpoint: eth0
  interfaceName: cali84b7d149337
  ipNetworks:
  - 10.200.77.220/32
  node: yangxikun
  orchestrator: k8s
  pod: busybox-7d4f45df67-w2mvj
  profiles:
  - kns.default
  - ksa.default.default

从以上信息中可以知道 busybox-7d4f45df67-w2mvj 在宿主机上的 Veth Pair 为 cali84b7d149337,查看其 proxy_arp 的设置:

➜  ~ cat /proc/sys/net/ipv4/conf/cali84b7d149337/proxy_arp
1

现在数据包出现在了宿主机上,在宿主机上观察请求数据包和响应数据包的流动。


Read more...

2020-06-21