Senlin's Blog


  • 分类

  • 归档

  • 标签

  • 关于

博客文章索引

发表于 2017-01-11   |   阅读次数

内存管理相关

  • Linux 的 OOM Killer 机制分析
  • 浅谈 Linux 的内存管理
  • Nginx 内存池源码分析
  • 谈谈 shared_ptr 的那些坑
  • 深入 C++ 的 unique_ptr
  • 使用 Valgrind 检测 C++ 内存泄漏

RPC 框架 & 网络库 & 序列化工具

  • gRPC 编程指南
  • 谈谈 gRPC 的 C++ 异步编程
  • gRPC 的 C++ 动态线程池源码分析
  • Libevent 编程指南
  • 谈谈 Libevent 的应用层 buffer
  • 浅谈 Boost.Asio 的多线程模型
  • 在 Boost.Asio 中使用协程
阅读全文 »

Linux 模拟网络丢包和延迟

发表于 2019-04-15   |   阅读次数

Linux 有个 tc 工具,即 traffic control,可以用来模拟网络丢包和延迟。在开发后台 server 时,如果我们想要知道这个 server 在特定的网络丢包情况下,是否能表现良好,就可以用 tc 来模拟丢包率。

模拟丢包

下面命令可以模拟丢包,从 eth0 网口出去的包将随机丢失 10%:

1
sudo tc qdisc add dev eth0 root netem loss 10%

模拟延迟

下面命令,从 eth0 网口出去的包将延迟 40ms:

1
sudo tc qdisc add dev eth0 root netem delay 40ms

特定场景下的丢包和延迟

注意,上面我们介绍的命令,是针对整个 eth0 网口起作用的,也就是说,只要是从 eth0 出去的所有的包,都会产生随机丢包或者延迟。但有时候,我们只想让丢包和延迟作用于某个目的地址,那要怎么做呢?

1
2
3
sudo tc qdisc add dev eth0 root handle 1: prio
sudo tc qdisc add dev eth0 parent 1:3 handle 30: netem loss 13% delay 40ms
sudo tc filter add dev eth0 protocol ip parent 1:0 u32 match ip dst 199.91.72.192 match ip dport 36000 0xffff flowid 1:3

上面的命令,我们告诉 tc,对发往 199.91.72.192:36000 的网络包产生 13% 的丢包和 40ms 的延迟,而发往其它目的地址的网络包将不受影响。

删除规则

好了,模拟完丢包和延迟之后,要记得删除掉规则:

1
sudo tc qdisc del dev eth0 root

使用 Perf 和火焰图分析 CPU 性能

发表于 2018-03-18   |   阅读次数

CPU 性能分析

  在 Linux 我们可以使用 perf 工具分析 CPU 的性能,它可以将消耗 CPU 时间比较大的用户程序调用栈打印出来,并生成火焰图。首先,在 Ubuntu 安装 perf 工具:

1
$ sudo apt-get install linux-tools-common linux-tools-generic linux-tools-`uname -r`

  使用sudo perf list命令可以看到 perf 支持的事件,事件有三种类型:Software event、Hardware event 和 Tracepoint event。使用perf stat可以对某个操作执行期间发生的事件作统计,例如我们可以对下面的命令进行统计:

1
$ dd if=/dev/zero of=/dev/null count=1000000

  我们可以统计这个命令执行期间的 CPU 使用率,上下文切换次数等信息:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
$ perf stat dd if=/dev/zero of=/dev/null count=1000000
1000000+0 records in
1000000+0 records out
512000000 bytes (512 MB) copied, 0.332629 s, 1.5 GB/s
Performance counter stats for 'dd if=/dev/zero of=/dev/null count=1000000':
331.923086 task-clock (msec) # 0.994 CPUs utilized
107 context-switches # 0.322 K/sec
0 cpu-migrations # 0.000 K/sec
226 page-faults # 0.681 K/sec
<not supported> cycles
<not supported> stalled-cycles-frontend
<not supported> stalled-cycles-backend
<not supported> instructions
<not supported> branches
<not supported> branch-misses
0.334055984 seconds time elapsed


  另一个有用的命令是perf record,它可以对事件进行采样,将采样的数据收集在一个 perf.data 的文件中,这将会带来一定的性能开销,不过这个命令很有用,可以用来找出最占 CPU 的进程。下面的命令对系统 CPU 事件做采样,采样时间为 60 秒,每秒采样 99 个事件,-g表示记录程序的调用栈。

1
$ sudo perf record -F 99 -a -g -- sleep 60

  执行这个命令将生成一个 perf.data 文件:

  • 执行sudo perf report -n可以生成报告的预览。
  • 执行sudo perf report -n --stdio可以生成一个详细的报告。
  • 执行sudo perf script可以 dump 出 perf.data 的内容。

  也可以记录某个进程的事件,例如记录进程号为 1641 的进程:

1
2
$ sudo perf record -F 99 -p 1641 -g -- sleep 60
$ sudo perf script > out.perf # 将 perf.data 的内容 dump 到 out.perf

阅读全文 »

在 AWS 使用 Kubernetes 的 Nginx Ingress

发表于 2018-02-07   |   分类于 虚拟化   |   阅读次数

安装 Nginx Ingress

  在 AWS 推荐使用 kops 安装 Kubernetes 集群,具体可以参见这篇文章。接着,在 Kubernetes 集群安装 Nginx Ingress:

1
$ kubectl create -f https://raw.githubusercontent.com/kubernetes/kops/master/addons/ingress-nginx/v1.6.0.yaml

  上面的操作会为 Nginx Ingress 创建一个 ELB,这个 ELB 工作在 4 层,即监听 TCP 的 80 和 443 端口:

1
2
3
$ kubectl get services ingress-nginx -n kube-ingress
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
ingress-nginx LoadBalancer 100.64.216.197 a81aaecb30bea... 80:32128/TCP,443:31454/TCP 1m

前端代理

  Nginx Ingress 主要用来充当前端代理,它可以根据域名以及 URL 路径,将集群外部的流量路由到集群内部的 Service。下面部署一个简单的 Service:

1
$ kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/images/echoheaders/echo-app.yaml

  接着,为这个 Service 创建一个 Ingress 配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
$ cat echoheaders-ingress.yaml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: echoheaders
annotations:
kubernetes.io/ingress.class: "nginx"
spec:
rules:
- host: echoheaders.umlife.net
http:
paths:
- path: /
backend:
serviceName: echoheaders
servicePort: 80
$ kubectl apply -f echoheaders-ingress.yaml

  可以查看这个 Ingress 对应的 ELB 地址:

1
2
3
$ kubectl get ing -o wide
NAME HOSTS ADDRESS PORTS AGE
echoheaders echoheaders.umlife.net a81aaecb30bea11e8a3ea0295ea9b1d4-315454571.cn-north-1.elb.amazonaws.com.cn 80 6m

  可以使用下面的命令检验 Ingress 是否正常工作:

1
$ curl -H "Host: echoheaders.umlife.net" http://a81aaecb30bea11e8a3ea0295ea9b1d4-315454571.cn-north-1.elb.amazonaws.com.cn

使用 Let’s Encrypt 和 kube-lego 配置 HTTPS 证书

  可以使用 kube-lego 自动创建和更新 Let’s Encrypt 的证书,下面是 kube-lego 的安装步骤:

1
2
3
4
5
6
$ kubectl apply -f https://raw.githubusercontent.com/jetstack/kube-lego/master/examples/nginx/lego/00-namespace.yaml
$ kubectl apply -f https://raw.githubusercontent.com/jetstack/kube-lego/master/examples/nginx/lego/configmap.yaml
$ kubectl apply -f https://raw.githubusercontent.com/jetstack/kube-lego/master/examples/nginx/lego/service-account.yaml
$ kubectl apply -f https://raw.githubusercontent.com/jetstack/kube-lego/master/examples/nginx/lego/cluster-role.yaml
$ kubectl apply -f https://raw.githubusercontent.com/jetstack/kube-lego/master/examples/nginx/lego/cluster-role-binding.yaml
$ kubectl apply -f https://raw.githubusercontent.com/jetstack/kube-lego/master/examples/nginx/lego/deployment.yaml

  在 DNS 服务器增加一条 CNAME 记录,将echoheaders.umlife.net解析到 ELB 的地址。接着,修改 Ingress 的配置,让 kube-lego 自动生成证书,并且在证书过期时,能够自动更新证书:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
$ cat echoheaders-ingress.yaml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: echoheaders
annotations:
kubernetes.io/tls-acme: "true"
kubernetes.io/ingress.class: "nginx"
ingress.kubernetes.io/ssl-redirect: "true"
spec:
tls:
- hosts:
- echoheaders.umlife.net
secretName: echoheaders-tls
rules:
- host: echoheaders.umlife.net
http:
paths:
- path: /
backend:
serviceName: echoheaders
servicePort: 80
$ kubectl apply -f echoheaders-ingress.yaml

  在浏览器访问echoheaders.umlife.net,就可以看到已经配置好 HTTPS 证书了。

阅读全文 »

在 AWS 使用 Kubernetes 的持久化存储

发表于 2018-01-12   |   分类于 虚拟化   |   阅读次数

挂载 EBS 磁盘

  在 AWS 中,我们可以将 EBS 磁盘挂载到 Kubernetes 的 Pod 中。由于 EBS 是云磁盘,所以就算 Pod 被调度到其它宿主机,也仍然可以访问 EBS 中的数据。
  在挂载磁盘之前,需要先创建 EBS 磁盘:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
$ aws ec2 create-volume \
--size 20 \
--region ap-northeast-1 \
--availability-zone ap-northeast-1b \
--volume-type gp2
{
"AvailabilityZone": "ap-northeast-1b",
"Encrypted": false,
"VolumeType": "gp2",
"VolumeId": "vol-0988ae4c8ead9dece",
"State": "creating",
"Iops": 100,
"SnapshotId": "",
"CreateTime": "2018-01-12T07:16:01.002Z",
"Size": 20
}

  注意,如果 Kubernetes 集群是通过 kops 1.8.0 版本安装的,那么在挂载之前,需要先为磁盘打上标签,否则会挂载失败:

1
2
3
4
5
$ export NAME=cluster.k8s.local # 集群的名称
$ VOLUME_ID = vol-0988ae4c8ead9dece
$ aws ec2 create-tags \
--resources ${VOLUME_ID} \
--tags Key=KubernetesCluster,Value=${NAME}

  挂载磁盘很简单,例如,我们可以将磁盘挂载到 Nginx Pod 的/data目录下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
$ cat nginx-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
containers:
- name: nginx
image: nginx:1.7.9
ports:
- containerPort: 80
volumeMounts:
- name: aws-ebs-volumes
mountPath: /data
volumes:
- name: aws-ebs-volumes
awsElasticBlockStore:
volumeID: vol-0988ae4c8ead9dece
$ kubectl apply -f nginx-pod.yaml

  通过这种方式挂载磁盘,有几个问题需要注意,首先,要保证 EBS 磁盘和 EC2 实例在同一个 AZ 里面,其次,EBS 磁盘只能挂载到一个 EC2 实例上。

阅读全文 »
12…13

高性能

61 日志
13 分类
14 标签
GitHub 知乎
© 2015 - 2022
由 Hexo 强力驱动
主题 - NexT.Mist
  |   总访问量: