├── .gitignore ├── Docker ├── Docker for Mac.md └── 小女孩也能看懂的插画版 Kubernetes 指南.md ├── ELK ├── ".kibana" 文件说明.md ├── Beats 安装_mac.md ├── ELK 学习笔记.md ├── Elastic Stack 安装.md ├── Elastic 之 Grok.md ├── Elastic 之 Packetbeat 概述.md ├── ElasticSearch cURL API.md ├── Elasticsearch + packetbeat 完整测试记录.md ├── Elasticsearch 中的 Index Pattern 和 Index Template.md ├── packetbeat 之 responsetime 计算问题.md ├── packetbeat 之“协议数据包分析每次输出结果均不同”问题.md ├── packetbeat 线上运行测试汇总-2.md ├── packetbeat 线上运行测试汇总-3.md ├── packetbeat 线上运行测试汇总.md ├── packetbeat 调试问题汇总.md ├── 使用 Elastic Stack 来监控和调优 Golang 应用程序.md ├── 开发者手册 - 为 Beat 新建 Kibana Dashboards.md └── 用 Elastic Stack 来看看祖国的蓝天之数据导入篇.md ├── Erlang ├── 10 Essential Erlang Tools for Erlang Developers.md ├── About Erlang:OTP and Multi-core performance in particular.pdf ├── Characterizing the Scalability of Erlang VM on Many-core Processors.pdf ├── Erlang 之 HiPE.md ├── Erlang 之 run queue 资料整理.md ├── Erlang 调试之 crashdump.md ├── How Erlang does scheduling.md ├── Inside the Erlang VM.md ├── Inside the Erlang VM.pdf └── Learn You Some Erlang for Great Good!.pdf ├── InfluxDB ├── etcd 中定义的 raft 结构说明.md ├── influxdb 开发相关.md ├── influxdb_v0.11.0_conf.md ├── influxdb_v0.11_cluster_node_configuration.md ├── influxdb_v0.11_cluster_setup.md └── influxdb_v0.11_术语大全.md ├── LICENSE ├── Linux ├── ARP 地址解析过程.md ├── BDP.md ├── CPU Utilization 和 CPU Load.md ├── CPU 隔离之 isolcpus.md ├── CPU 隔离之 numactl.md ├── CPU 隔离之任务分析.md ├── CPU 隔离问题.md ├── Cache.md ├── Context Switch.md ├── FAQ about the NUMA architecture.md ├── How to achieve 100w Concurrent TCP connections.md ├── HugePage.md ├── Kernel Networking 之 netem.md ├── Kernel 问题汇总.md ├── Linux CPU 占用率原理与精确度分析.pdf ├── Linux Cached Memory.md ├── Linux System and Performance Monitoring.pdf ├── Linux TCP 队列相关参数的总结.md ├── Linux proc-pid-xxx introduction.md ├── Linux 中的 bond 模式.md ├── Local.and.Remote.Memory.Memory.in.a.Linux.NUMA.System.pdf ├── MTR.md ├── Memory.md ├── NUMA 之 System Descriptions.md ├── Netflix 和 chaos monkey.md ├── Netlink Protocol Library Suite(libnl).md ├── PF_RING │ ├── Active vs Passive Polling in Packet Processing (PF_RING).md │ ├── Building dkms packages (PF_RING kernel module).md │ ├── IRQ Balancing.md │ ├── Introducing PF_RING DNA.md │ ├── Introducing PF_RING ZC.md │ ├── PF_RING Installation.md │ ├── PF_RING User's Guide.md │ ├── PF_RING ZC.md │ ├── PF_RING and Transparent Mode.md │ ├── PF_RING first README.md │ ├── PF_RING 家族史.md │ ├── PF_RING 杂七杂八.md │ ├── PF_RING.svg │ ├── PF_RING.xmind │ ├── PF_RING_homepage.md │ ├── Quick Start Guide (PF_RING).md │ ├── Receive Side Scaling (PF_RING).md │ ├── Vanilla PF_RING.md │ ├── 折腾 PF_RING 安装.md │ └── 折腾 PF_RING 测试.md ├── PacketCapture │ ├── Comparing and Improving Current Packet Capturing Solutions based on Commodity Hardware.pdf │ ├── Modern Packet Capture and Analysis_Multi-Core, Multi-Gigabit, and Beyond.pdf │ ├── NAPI 信息梳理.md │ ├── NAPI 模式-中断和轮询的折中以及一个负载均衡的问题.md │ ├── Packetbeat 配置之 Traffic 捕获选项.md │ ├── Programming with libpcap - Sniffing the Network From Our Own Application.pdf │ ├── Programming with pcap.md │ ├── libpcap_An Architecture and Optimization Methodology for Packet Capture.pdf │ ├── 丢包问题研究.md │ ├── 图解抓包.md │ ├── 如何选择“定时抓包”方案.md │ └── 抓包分析之 “TCP Previous segment not captured”.md ├── Performance │ ├── Broken Linux Performance Tools (NETFLIX 2016).pdf │ ├── High Performance Browser Networking - Velocity.pdf │ ├── High Performance Browser Networking - Velocity.pptx │ ├── Linux Performance Tools.pdf │ ├── Linux Performance and Tuning Guidelines.pdf │ ├── Tuning TCP and Nginx on ec2.pdf │ └── 协议栈优化总结.md ├── Process State.md ├── Ring Buffer.md ├── Socket Buffer 相关.md ├── TCP 之 TSO GSO LSO.md ├── TCP 相关统计信息详解.md ├── The Page Cache.pdf ├── UNIX Domain Socket 梳理.md ├── WAL 原理与实践.md ├── Wire Speed.md ├── esm 系统监控说明.md ├── ethtool 工具使用.md ├── flume 本地接收 UDP 日志丢失问题.md ├── insmod 和 modprobe.md ├── linux 系统调优之 drop_caches.md ├── nf_conntrack 超限问题.md ├── run queue.md ├── sar.md ├── swappiness.md ├── 关于 Recv-Q 和 Send-Q 的说明.md ├── 关于 TCP 协议中的 timestamp 问题.md ├── 吞吐量 Throughput.md ├── 基于 vmstat 进行系统分析.md ├── 多队列网卡简介.md └── 如何实现内核旁路.md ├── README.md ├── RabbitMQ ├── 2016-07-20 线上 RabbitMQ 问题排查.md ├── 2016-08-17 腾讯云网路故障+RabbitMQ 节点异常.md ├── 2016-09-03 双节点 RabbitMQ 集群故障.md ├── 2016-12-13 RabbitMQ 基于脚本导配置后发生错误.md ├── 2017-03-02 线上 RabbitMQ 异常日志分析.md ├── 2017-03-02 线上 RabbitMQ 问题排查.md ├── AMQP & RabbitMQ.pdf ├── Dissecting the Rabbitd: RabbitMQ Internal Architecture.pdf ├── HAProxy 使用姿势.md ├── README.md ├── RabbitMQ Operations.pdf ├── RabbitMQ in Action(v2.7.0).pdf ├── RabbitMQ management 插件数据库重置代价问题.md ├── RabbitMQ management 插件相关配置解析.md ├── RabbitMQ management 插件过载问题.md ├── RabbitMQ management 插件过载问题(高级篇).md ├── RabbitMQ 中发生内存和磁盘告警时的行为.md ├── RabbitMQ 中批量删除 queue 的方法.md ├── RabbitMQ 中的 consumer utilisation.md ├── RabbitMQ 中的内存使用说明.md ├── RabbitMQ 中的内存告警问题.md ├── RabbitMQ 中的磁盘告警问题.md ├── RabbitMQ 之 Delayed messages.md ├── RabbitMQ 之 Persistence 配置.md ├── RabbitMQ 之 Scaling 问题.md ├── RabbitMQ 之 Sharding 插件.md ├── RabbitMQ 之 queue 长度限制.md ├── RabbitMQ 之 rabbitmqctl status 输出分析.md ├── RabbitMQ 之吞吐量最大化.md ├── RabbitMQ 之延迟队列.md ├── RabbitMQ 之批处理问题说明.md ├── RabbitMQ 之消息堆积问题分析.md ├── RabbitMQ 之生产环境配置检查表.md ├── RabbitMQ 之确认机制.md ├── RabbitMQ 之连接阻塞通知功能.md ├── RabbitMQ 使用姿势简介.md ├── RabbitMQ 使用问题记录.md ├── RabbitMQ 错误行为模拟测试.md ├── RabbitMQ 集群启动相关问题.md └── Troubleshooting RabbitMQ and services that use it.pdf ├── Redis ├── Redis Cluster(Redis 3.X)设计要点.md ├── Redis 使用问题汇总(网文).md ├── Redis 杂七杂八.md ├── Redis 经验整理.md ├── Redis 访问延迟问题分析.md └── Redis 配置说明.md └── nonsense ├── 2016年12月02日 线上 zookeeper 异常情况问题纪要.md ├── Continuous Integration - 持续集成.md ├── GitHub Access Token.md ├── HTTP 之 GET 在 body 中携带参数问题.md ├── Homebrew 相关.md ├── Jupyter.md ├── Linux Man Pages in Dash.md ├── Mac 使用问题拾遗.md ├── Mac 和 VirtualBox 之间的文件共享.md ├── Mac 挂在 NTFS 移动硬盘 ReadOnly 问题解决.md ├── Mac 新装.md ├── Python 使用小结.md ├── Tmux 快捷键.md ├── Ubuntu 15.04 上源码安装 mysql-5.7.16.md ├── git 使用姿势.md ├── gossip 协议.md ├── iTerm2 下使用 rz sz 命令.md ├── root 权限之 su 与 sudo.md ├── shell 使用常见问题.md ├── thoughtbot 的 Git 使用规范.md ├── vim 使用_1_无插件.md ├── zsh 使用.md ├── 吹牛逼术语指南.md ├── 基于 vagrant + virtualBox + ubuntu 搭建开发环境.md ├── 大二层网络.md ├── 如何向开源社区提问题.md ├── 如何在 ubuntu 上进行系统时间调整.md ├── 如何有效地报告 Bug.md └── 编程语言进化史.pdf /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | -------------------------------------------------------------------------------- /ELK/".kibana" 文件说明.md: -------------------------------------------------------------------------------- 1 | # .kibana 文件说明 2 | 3 | 对于 kibana 4 或 5 来说,在 `kibana.yml` 中设置的默认 index 值为 ".kibana" ; 4 | 5 | kibana 配置文件中的内容如下所示: 6 | 7 | ``` 8 | # Kibana uses an index in Elasticsearch to store saved searches, visualizations and 9 | # dashboards. Kibana creates a new index if the index doesn’t already exist. 10 | #kibana.index: ".kibana" 11 | ``` 12 | 13 | 可以通过 REST API 接口获取和 `.kibana` 相关的内容; 14 | 15 | ## 获取 `.kibana` 本身的内容 16 | 17 | ``` 18 | curl -u elastic:changeme -XGET http://localhost:9200/.kibana?pretty 19 | ``` 20 | 21 | 返回值如下 22 | 23 | ``` 24 | { 25 | ".kibana" : { 26 | "aliases" : { }, 27 | "mappings" : { 28 | "dashboard" : { 29 | ... 30 | }, 31 | "server" : { 32 | ... 33 | }, 34 | "timelion-sheet" : { 35 | ... 36 | }, 37 | "visualization" : { 38 | ... 39 | }, 40 | "search" : { 41 | ... 42 | }, 43 | "graph-workspace" : { 44 | ... 45 | }, 46 | "config" : { 47 | ... 48 | }, 49 | "index-pattern" : { 50 | ... 51 | } 52 | }, 53 | "settings" : { 54 | ... 55 | } 56 | } 57 | } 58 | ``` 59 | 60 | 可以看到 61 | 62 | - 索引 `.kibana` 的内容主要由 "mappings" 和 "settings" 构成(**index template** 正是由这两部分构成的); 63 | - "mappings" 的内容由 `dashboard`/`server`/`timelion-sheet`/`visualization`/`search`/`graph-workspace`/`config`/`index-pattern` 等**映射类型(mapping type)**构成; 64 | - 针对每一种映射类型,通过 properties 定义针对每一个 field 的**映射选项**(类型/索引方式/多重索引等); 65 | 66 | 67 | > 关于 mapping 的补充说明: 68 | > 69 | > - mapping 用于定义 documents 以及其包含的 fields 是如何被**存储**和**索引**的; 70 | > 71 | > ------ 72 | > 关于 **mapping type** 的补充说明: 73 | > 74 | > - 分为 meta-fields (\_index/\_type/\_id/\_source) 和 fields/properties 两部分; 75 | > - 每种 index 均具有一种或多种映射类型,用于将 index 中的所有 documents 分为不同的逻辑分组; 76 | 77 | 78 | ## 获取 `.kibana` 索引下所有 _type 信息 79 | 80 | ``` 81 | curl -u elastic:changeme -XGET http://localhost:9200/.kibana/_search?pretty 82 | ``` 83 | 84 | 返回值如下 85 | 86 | ``` 87 | { 88 | "took" : 1, 89 | "timed_out" : false, 90 | "_shards" : { 91 | "total" : 1, 92 | "successful" : 1, 93 | "failed" : 0 94 | }, 95 | "hits" : { 96 | "total" : 268, 97 | "max_score" : 1.0, 98 | "hits" : [ 99 | { 100 | "_index" : ".kibana", 101 | "_type" : "index-pattern", 102 | "_id" : "filebeat-*", 103 | "_score" : 1.0, 104 | "_source" : { 105 | ... 106 | } 107 | }, 108 | { 109 | "_index" : ".kibana", 110 | "_type" : "dashboard", 111 | "_id" : "Filebeat-Apache2-Dashboard", 112 | "_score" : 1.0, 113 | "_source" : { 114 | ... 115 | } 116 | }, 117 | { 118 | "_index" : ".kibana", 119 | "_type" : "visualization", 120 | "_id" : "Apache2-response-codes-of-top-URLs", 121 | "_score" : 1.0, 122 | "_source" : { 123 | ... 124 | } 125 | }, 126 | { 127 | "_index" : ".kibana", 128 | "_type" : "search", 129 | "_id" : "Apache2-access-logs", 130 | "_score" : 1.0, 131 | "_source" : { 132 | ... 133 | } 134 | }, 135 | ... 136 | ``` 137 | 138 | 可以看到 139 | 140 | - 能够获取到 `.kibana` 下包含的 `index-pattern`/`dashboard`/`visualization`/`search` 相关信息; 141 | 142 | 143 | ---------- 144 | 145 | 146 | 另外,可以通过如下 API 获取指定 _index 下指定 _type 的信息 147 | 148 | ``` 149 | GET /.kibana/_search?type=dashboard&pretty=1 150 | 151 | GET /.kibana/dashboard/_search?pretty=1 152 | ``` 153 | 154 | 155 | 156 | 157 | 158 | -------------------------------------------------------------------------------- /ELK/Elastic 之 Packetbeat 概述.md: -------------------------------------------------------------------------------- 1 | # elastic 之 Packetbeat 概述 2 | 3 | ## [elastic/beats](https://github.com/elastic/beats) 4 | 5 | 特点: 6 | 7 | - 轻量(轻微安装痕迹,占用少量系统资源,无运行时依赖); 8 | - 基于 Go 语言; 9 | - 捕获全类型的操作数据(operational data),比如 logs , metrics ,或网络抓包数据; 10 | - 数据发往 Elasticsearch ,或者直接交互,或者通过 Logstash ;数据可视化基于 Kibana ; 11 | 12 | ## [libbeat](https://github.com/elastic/beats/tree/master/libbeat) 13 | 14 | libbeat 为用于创建各种 beats 的 Go 框架; 15 | 16 | 基于该框架,目前官方支持的 Beats 如下: 17 | 18 | Beat | Description 19 | --- | --- 20 | [Filebeat](https://github.com/elastic/beats/tree/master/filebeat) | Tails and ships log files 21 | [Metricbeat](https://github.com/elastic/beats/tree/master/metricbeat) | Fetches sets of metrics from the operating system and services 22 | [Packetbeat](https://github.com/elastic/beats/tree/master/packetbeat) | Monitors the network and applications by sniffing packets 23 | [Winlogbeat](https://github.com/elastic/beats/tree/master/winlogbeat) | Fetches and ships Windows Event logs 24 | 25 | 26 | ---------- 27 | 28 | 29 | ## [Packetbeat 参考手册](https://www.elastic.co/guide/en/beats/packetbeat/current/index.html) 30 | 31 | ### 概览 32 | 33 | 实时网络包分析 + 基于 Elasticsearch 实现 APM ; 34 | 35 | > Packetbeat is a real-time network packet analyzer that you can use with Elasticsearch to provide an application monitoring and performance analytics system. 36 | 37 | 为 Beats 平台提供了针对服务器间通信的“视野”; 38 | 39 | > Packetbeat completes the Beats platform by providing visibility between the servers of your network. 40 | 41 | 针对应用层协议进行解析,关联请求和应答,针对每个 transaction 记录关心的 field ; 42 | 43 | > Packetbeat works by capturing the network traffic between your application servers, decoding the application layer protocols (HTTP, MySQL, Redis, and so on), correlating the requests with the responses, and recording the interesting fields for each transaction. 44 | 45 | 帮助发现和排查后端服务器的 bug 和性能问题; 46 | 47 | > Packetbeat can help you easily notice issues with your back-end application, such as bugs or performance problems, and it makes troubleshooting them - and therefore fixing them - much faster. 48 | 49 | 即时解析应用层协议,以 transaction 为单位关联相应的消息; 50 | 51 | > Packetbeat sniffs the traffic between your servers, parses the application-level protocols on the fly, and correlates the messages into transactions. Currently, Packetbeat supports the following protocols: 52 | 53 | - ICMP (v4 and v6) 54 | - DNS 55 | - HTTP 56 | - **AMQP 0.9.1** 57 | - Cassandra 58 | - **Mysql** 59 | - PostgreSQL 60 | - **Redis** 61 | - Thrift-RPC 62 | - **MongoDB** 63 | - Memcache 64 | 65 | 可以基于 Elasticsearch 或 Redis 或 Logstash 进行存储和分析; 66 | 67 | > Packetbeat can insert the correlated transactions directly into Elasticsearch or into a central queue created with Redis and Logstash. 68 | 69 | 部署和使用方案(合并 or 单独); 70 | 71 | > Packetbeat can run on the same servers as your application processes or on its own servers. When running on dedicated servers, Packetbeat can get the traffic from the **switch’s mirror ports** or from **tapping devices**. In such a deployment, there is zero overhead on the monitored application. See [Setting Traffic Capturing Options](https://www.elastic.co/guide/en/beats/packetbeat/current/capturing-options.html) for details. 72 | 73 | 使用 JSON 文档进行保存; 74 | 75 | > After decoding the Layer 7 messages, Packetbeat correlates the requests with the responses in what we call transactions. For each transaction, Packetbeat inserts a **JSON** document into Elasticsearch. See the [Exported Fields](https://www.elastic.co/guide/en/beats/packetbeat/current/exported-fields.html) section for details about which fields are indexed. 76 | 77 | Packetbeat 和 Logstash 可以使用相同的 Elasticsearch 和 Kibana 实例; 78 | 79 | > The same Elasticsearch and Kibana instances that are used for analysing the network traffic gathered by Packetbeat can be used for analysing the log files gathered by Logstash. This way, you can have network traffic and log analysis in the same system. 80 | 81 | 82 | 这里需要知道的是:使用 Packetbeat 前,需要先搞定 **Elastic Stack** 的安装,即 83 | 84 | - **Elasticsearch** 进行数据的存储和索引查询; 85 | - **Kibana** 提供 UI 供查询和展示; 86 | - **Logstash** 用于插入数据到 Elasticsearch 中(可选); 87 | 88 | > **Elastic Stack** 的安装详见 [Getting Started with Beats and the Elastic Stack](https://github.com/moooofly/MarkSomethingDown/blob/master/Golang/Elastic%20Stack%20%E5%AE%89%E8%A3%85.md) ; 89 | 90 | 在完成 **Elastic Stack** 安装后,则可进行 Packetbeat 的安装、配置和运行,详见 [Getting Started With Packetbeat](https://www.elastic.co/guide/en/beats/packetbeat/5.0/packetbeat-getting-started.html) ; 91 | -------------------------------------------------------------------------------- /ELK/ElasticSearch cURL API.md: -------------------------------------------------------------------------------- 1 | # ElasticSearch cURL API 2 | 3 | ## 针对数据操作 4 | 5 | ### 增 6 | 7 | ```shell 8 | POST /<_index>/<_type> 9 | {} 10 | ``` 11 | 12 | ### 删 13 | 14 | ```shell 15 | # 删除整个 _index (删指定库) 16 | DELETE /<_index> 17 | 18 | # 基于通配方式删除所有匹配的 _index (删所有匹配库) 19 | DELETE /<_index_regex> 20 | 21 | # 删除指定 _index 下的指定 _type (删指定表) 22 | # FIXME: 失败 23 | DELETE /<_index>/<_type> 24 | 25 | # 基于通配方式删除指定 _index 下所有匹配 _type (删所有匹配表) 26 | # FIXME: 失败 27 | DELETE /<_index>/<_type_regex> 28 | ``` 29 | 30 | > 注意:上述四种删除,会导致相应 mapping 同时被删除; 31 | 32 | ``` 33 | # 删除单条数据 (删行) 34 | DELETE /<_index>/<_type>/<_id> 35 | 36 | ## 在不删除 index 和 type 的前提下,清除其中的所有数据 37 | ## FIXME: 失败 38 | DELETE /<_index>/<_type>/_query 39 | { 40 |   "query" : { 41 |    "match_all" : {} 42 |   } 43 | } 44 | ``` 45 | 46 | 47 | ### 查 48 | 49 | ```shell 50 | # 获取指定 _index 内容(内容像 index template 但不是) 51 | GET /<_index> 52 | 53 | # 基于通配方式获取 _index 内容 54 | GET /<_index_regex> 55 | 56 | # 获取指定 _index 下 _type 中 _id 对应内容 (获取行数据) 57 | GET /<_index>/<_type>/<_id> 58 | 59 | # 只获取 JSON 源数据部分(存入什么得到什么) 60 | GET /<_index>/<_type>/<_id>/_source 61 | 62 | # 只获取源数据中的特定字段 (获取指定行下指定的列) 63 | GET /<_index>/<_type>/<_id>?fields=,..., 64 | ``` 65 | 66 | ### 改 67 | 68 | ```shell 69 | # 全量提交 70 | POST /<_index>/<_type>/<_id> 71 | {} 72 | 73 | # 局部更新 (更新列) 74 | POST /<_index>/<_type>/<_id>/_update 75 | { 76 | "doc": { 77 | "fieldN":"yyy" 78 | } 79 | } 80 | ``` 81 | 82 | ### _search 搜索 83 | 84 | - 空搜索(在所有 _index 的所有 _type 中搜索) 85 | 86 | ```shell 87 | # 简化形式 88 | GET /_search 89 | 90 | # 完整形式 91 | GET /_all/_search 92 | ``` 93 | 94 | - 其他搜索 95 | 96 | ```shell 97 | # 全文搜索(针对 _source 中包含的全部 fields) 98 | GET /<_index>/<_type>/_search?q= 99 | 100 | # 针对单个字段(field)上的全文搜索 101 | GET /<_index>/<_type>/_search?q=: 102 | 103 | # 针对单个字段(field)上的全文精确搜索 104 | GET /<_index>/<_type>/_search?q=:"" 105 | 106 | # 在索引 _index 的所有 _type 中搜索 107 | GET /<_index>/_search 108 | 109 | # 在索引 _indexM 和 _indexN 的所有 _type 中搜索 110 | GET /<_indexM>,<_indexN>/_search 111 | 112 | # 在以 g 或 u 开头索引的所有 _type 中搜索 113 | GET /g*,u*/_search 114 | 115 | # 在索引 _indexM 的 user 类型中搜索 116 | GET /<_indexM>/user/_search 117 | 118 | # 在 _indexM 和 _indexN 索引的 user 和 tweet 类型中搜索 119 | GET /<_indexM>,<_indexN>/user,tweet/_search 120 | 121 | # 在所有索引的 user 和 tweet 类型中搜索 122 | GET /_all/user,tweet/_search 123 | ``` 124 | 125 | 另外,如下两种形式相互等价 126 | 127 | ``` 128 | GET /<_index>/<_type>/_search 129 | ``` 130 | 131 | 等价于 132 | 133 | ``` 134 | GET /<_index>/_search?type=<_type> 135 | ``` 136 | 137 | 138 | > 当搜索仅包含单一 _index 时,Elasticsearch 会转发搜索请求到该 _index 的主分片或每个分片的复制分片上,然后再聚合每个分片的结果。当搜索包含多个 _index 时,也是同样的方式,只不过会有更多的分片被关联。 139 | 140 | ### 聚合 141 | 142 | 略 143 | 144 | 145 | ### 分页 146 | 147 | ``` 148 | # 每页只显示 5 条结果 149 | GET /_search?size=5 150 | 151 | # 每页只显示 5 条结果,从第 6 条开始显示 152 | GET /_search?size=5&from=5 153 | ``` 154 | 155 | > 分页时应该避免分页太深(即 from 值过大)或者一次请求太多的结果(即 size 值过大);原因在于:结果在返回前会被排序,而一个搜索请求常常涉及多个分片,每个分片会生成自己排好序的结果,之后需要集中起来进行排序,以确保提供整体排序正确的结果。因此,若请求 `GET /_search?size=10&from=1000` 涉及 5 个分片,则每个分片都必须产生排序后的 10010 个结果,然后聚合操作还要排序这 50050 个结果,并最终丢弃 50040 个! 156 | 157 | 158 | ## 针对映射(mapping)操作 159 | 160 | ### 增 161 | 162 | ```shell 163 | PUT /<_index>/_mapping 164 | {} 165 | ``` 166 | 167 | ### 删 168 | 169 | ```shell 170 | DELETE /<_index>/_mapping/<_type> 171 | ``` 172 | 173 | > 注意:**写入数据会自动添加映射,但删除数据不会删除数据的映射**;存在一种特例:若删除整个索引 <_index> ,则映射将同时被删除; 174 | 175 | ### 查 176 | 177 | ```shell 178 | # 查询出的内容带有 "_default_" 部分,以及全部 <_type> 对应的部分 179 | GET /<_index>/_mapping 180 | 181 | # 查询出的内容没有 "_default_" 部分,只有 <_type> 对应的部分 182 | GET /<_index>/_mapping/<_type> 183 | ``` 184 | 185 | ### 改 186 | 187 | ```shell 188 | PUT /<_index>/_mapping/<_type> 189 | {} 190 | ``` 191 | 192 | > 注意:更新只对新字段有效,已经生成的字段映射是不可变更的;如果需要变更,则需要使用 `reindex` 方法解决; 193 | 194 | 195 | ## 针对模版(template)操作 196 | 197 | 198 | ### 增 199 | 200 | ``` 201 | PUT /_template/ 202 | { 203 | "template": "te*", 204 | "settings": { 205 | "number_of_shards": 1 206 | }, 207 | "mappings": { 208 | "type1": { 209 | "_source": { 210 | "enabled": false 211 | }, 212 | "properties": { 213 | "host_name": { 214 | "type": "keyword" 215 | }, 216 | "created_at": { 217 | "type": "date", 218 | "format": "EEE MMM dd HH:mm:ss Z YYYY" 219 | } 220 | } 221 | } 222 | } 223 | } 224 | ``` 225 | 226 | ### 删 227 | 228 | ``` 229 | DELETE /_template/ 230 | ``` 231 | 232 | ### 查 233 | 234 | ``` 235 | # 获取全部 index template 236 | GET /_template 237 | 238 | # 获取指定 index template 239 | GET /_template/ 240 | 241 | # 基于通配符获取多个 index template 242 | GET /_template/ 243 | 244 | # 直接指定多个 index template 名进行查询 245 | GET /_template/, 246 | 247 | # 仅确定目标 index template 是否存在 248 | HEAD /_template/ 249 | ``` 250 | 251 | ### 获取指定字段 252 | 253 | ``` 254 | GET /_template/?filter_path=*.version 255 | ``` 256 | 257 | 258 | ## ingest node pipeline 259 | 260 | ``` 261 | # 创建 ingest node pipeline 262 | PUT /_ingest/pipeline/ 263 | {} 264 | ``` 265 | 266 | 267 | ## 获取 elasticsearch 元信息 268 | 269 | ``` 270 | GET / 271 | ``` 272 | 273 | 274 | 275 | -------------------------------------------------------------------------------- /ELK/Elasticsearch 中的 Index Pattern 和 Index Template.md: -------------------------------------------------------------------------------- 1 | # Index Pattern V.S. Index Template 2 | 3 | ## Index Pattern 4 | 5 | ![Kibana 未导入 Index Pattern 前](https://raw.githubusercontent.com/moooofly/ImageCache/master/Pictures/Kibana%20%E6%9C%AA%E5%AF%BC%E5%85%A5%20Index%20Pattern%20%E5%89%8D.png "Kibana 未导入 Index Pattern 前") 6 | 7 | - 每一种加载到 Elasticsearch 的数据集都具有(符合)一种 index pattern ; 8 | - **index pattern** 就是能够匹配多种 index 的、带有可选通配符(wildcards)的字符串; 9 | 10 | 举例:针对常规的日志处理场景,一种比较典型的 index 名字将具有 `YYYY.MM.DD` 格式的日期,相应的,针对 5 月的 index pattern 看起来类似 `logstash-2015.05*` ; 11 | 12 | - 如果数据源提供的数据内容确定包含 time-series 数据(例如将 Logstash 作为数据源时),则在点击 **Add New** 定义 index 时,请务必勾选上 `Index contains time-based events` 复选框,并从 `Time-field name` 下拉列表中选择 `@timestamp` 字段(field); 13 | 14 | > **注意**:当你定义一个 index pattern 时,匹配该 pattern 的 indices **必须**事先已经存在于 Elasticsearch 之中;并且这些 indices **必须**包含了数据内容; 15 | 16 | ![Configure an Index Pattern](https://raw.githubusercontent.com/moooofly/ImageCache/master/Pictures/Configure%20an%20Index%20Pattern.jpeg "Configure an Index Pattern") 17 | 18 | 19 | - 成功使用 Kibana 的前提是你必须配置一个或多个 index pattern ;index pattern 用于确定将要针对哪些 Elasticsearch indices 运行查询和分析; 20 | - Kibana 会查找匹配指定 pattern 的 index 名字;pattern 中出现的星号 (*) 用于匹配零个或多个字符; 21 | - index pattern 也可以简单的设置为单独一个 index 的名字; 22 | - 若想在 index 名字中使用 event time ,可以在 pattern 中使用 [] 将静态文本括起来,之后再指定日期格式;例如 `[logstash-]YYYY.MM.DD` 能够匹配 `logstash-2015.01.31` 和 `logstash-2015-02-01` ; 23 | - 在你浏览 Discover 页面时,设置成默认的 index pattern 将会被自动加载;Kibana 会在默认 pattern 左侧显示一个星星;你所创建的首个 pattern 自动被指定为默认 pattern ; 24 | - 当你添加了一个 index mapping 后,Kibana 会自动扫描(scans)匹配 pattern 的 indices 以便显示(新的)index fields 列表;你也可以重新加载 index fields 列表以便获取任意新加的 fields ; 25 | 26 | 27 | 参考: 28 | 29 | - [Defining Your Index Patterns](https://www.elastic.co/guide/en/kibana/current/tutorial-define-index.html) 30 | - [Index Patterns](https://www.elastic.co/guide/en/kibana/current/index-patterns.html) 31 | 32 | 33 | ## Index Template 34 | 35 | - Index templates 允许你定义 templates ,以便在新 indices 被创建时自动被应用; 36 | - templates 内容由 settings 和 mappings 构成,以及一个简单的 **pattern template** 用于控制当前 template 是否被应用到新 index 上; 37 | > pattern template 其实就是创建模版时在 JSON 内容中设置的 `"template": ""` ; 38 | - Templates 仅在 index 创建时被应用;变更一个 template 不会对已经存在 indices 造成影响; 39 | - Index templates 提供了 C 风格的 `/* */` 块注释;注释内容允许出现在 JSON 文档的任何位置,除了 JSON 的初始 '{' 之上; 40 | - 多个 index templates 可能同时匹配到同一个 index 上,在这种情况下,settings 和 mappings 内容会**合并**为目标 index 的最终配置;而合并的顺序可以基于 `order` 参数进行控制,order 值越小越优先被应用,而值越大越后被应用(实现**覆盖**效果); 41 | - Templates 可以选择性添加一个 `version` 字段指定版本号信息(其值为任意整数),以便简化外部系统对 template 进行管理;若要重置一个版本号,只需简单的使用未指定版本号的 template 进行替换; 42 | 43 | 44 | 参考: 45 | 46 | - [Index Templates](https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-templates.html) 47 | 48 | -------------------------------------------------------------------------------- /Erlang/About Erlang:OTP and Multi-core performance in particular.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moooofly/MarkSomethingDown/3ed8d77b34dfb893b865932086065265876e3bc6/Erlang/About Erlang:OTP and Multi-core performance in particular.pdf -------------------------------------------------------------------------------- /Erlang/Characterizing the Scalability of Erlang VM on Many-core Processors.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moooofly/MarkSomethingDown/3ed8d77b34dfb893b865932086065265876e3bc6/Erlang/Characterizing the Scalability of Erlang VM on Many-core Processors.pdf -------------------------------------------------------------------------------- /Erlang/Erlang 之 HiPE.md: -------------------------------------------------------------------------------- 1 | # Erlang 之 HiPE 2 | 3 | 标签(空格分隔): erlang 4 | 5 | --- 6 | 7 | ## [[Erlang 0078] Erlang HiPE 二三事](http://www.cnblogs.com/me-sa/archive/2012/10/09/erlang_hipe.html) 8 | 9 | ## [基于LLVM的高性能Erlang(Hipe)尝鲜](http://blog.yufeng.info/archives/3104?nsukey=Q7nDoqYVW8H8Q5ouu0zE7f%2FkgmRlLIXk0G4x%2FP0USUOIt6hpgs%2BXjKlQMJEMc87dSwSFn238sp7MmlxwL4SZ14jUdZubW0YtmamcaBmAIb%2BCXvFOTlaqENQ0mcGoGC%2F9t4fSN%2Fx98UAW6gnude5Mu8okaY%2FlcjeTOuKIHgN%2BASThI93WCW5BpMylqV82vFKv) 10 | 11 | ## [Erlang之hipe](http://www.badnotes.com/2013/11/12/erlang-hipe) 12 | 13 | ## [Erlang HiPE选项](http://developerworks.github.io/2015/01/05/erlang-hipe-help-options/) 14 | 15 | ## [HiPE](http://erlang.org/doc/man/HiPE_app.html) 16 | 17 | ## [The High-Performance Erlang Project](http://www.it.uu.se/research/group/hipe/) 18 | 19 | ## [ErLLVM](http://erllvm.softlab.ntua.gr/) 20 | 21 | ---------- 22 | 23 | 24 | ## [The LLVM Compiler Infrastructure](http://llvm.org/) 25 | 26 | ## [LLVM](http://aosabook.org/en/llvm.html) 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /Erlang/Inside the Erlang VM.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moooofly/MarkSomethingDown/3ed8d77b34dfb893b865932086065265876e3bc6/Erlang/Inside the Erlang VM.pdf -------------------------------------------------------------------------------- /Erlang/Learn You Some Erlang for Great Good!.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moooofly/MarkSomethingDown/3ed8d77b34dfb893b865932086065265876e3bc6/Erlang/Learn You Some Erlang for Great Good!.pdf -------------------------------------------------------------------------------- /InfluxDB/influxdb_v0.11_cluster_node_configuration.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | > Warning! This page documents an old version of InfluxDB, which is no longer actively developed. 5 | > [InfluxDB v0.13]() is the most recent stable version of InfluxDB. 6 | 7 | 8 | ---------- 9 | 10 | 11 | 下面的内容描述了 InfluxDB cluster 中 不同类型的 node ,以及如何对其进行配置; 12 | 13 | # General node configuration 14 | 15 | 每一个 node 的 [配置文件]() 都必须制定下面各项: 16 | 17 | `[meta]` 段中的 `bind-address`;该配置为 cluster 通信使用的地址; 18 | `[meta]` 段中的 `http-bind-address`;该配置为 consensus service 通信使用的地址; 19 | `[http]` 段中的 `bind-address`; 该配置为 HTTP API 访问使用的地址; 20 | 21 | 每一条配置选项都应该指明 node 的 IP 地址或主机名,和 port 信息(详见下文示例); 22 | 23 | > NOTE: The hostnames for each machine must be resolvable by all members of the cluster. 24 | 25 | # Consensus node 26 | 27 | Consensus nodes 仅用于运行 consensus service ;consensus service 用于确保 cluster 中以下内容的一致性:node membership, [databases](), [retention policies](), [users](), [continuous queries](), shard metadata, 和 [subscriptions]() ; 28 | 29 | 30 | 配置如下: 31 | 32 | ```shell 33 | [meta] 34 | enabled = true #✨ 35 | ... 36 | bind-address = ":8088" 37 | http-bind-address = ":8091" 38 | 39 | ... 40 | 41 | [data] 42 | enabled = false #✨ 43 | 44 | [http] 45 | ... 46 | bind-address = ":8086" 47 | ``` 48 | 49 | # Data node 50 | 51 | Data nodes 仅用于运行 data service ;data service 保存了实际的时间序列数据,并相应针对那些数据的查询请求; 52 | 53 | 配置如下: 54 | 55 | ```shell 56 | [meta] 57 | enabled = false #✨ 58 | ... 59 | bind-address = ":8088" 60 | http-bind-address = ":8091" 61 | 62 | ... 63 | 64 | [data] 65 | enabled = true #✨ 66 | 67 | [http] 68 | ... 69 | bind-address = ":8086" 70 | ``` 71 | 72 | # Hybrid node 73 | 74 | Hybrid nodes 同时运行了 consensus 和 data services ; 75 | 76 | 配置如下: 77 | 78 | ```shell 79 | [meta] 80 | enabled = true #✨ 81 | ... 82 | bind-address = ":8088" 83 | http-bind-address = ":8091" 84 | 85 | ... 86 | 87 | [data] 88 | enabled = true #✨ 89 | 90 | [http] 91 | ... 92 | bind-address = ":8086" 93 | ``` -------------------------------------------------------------------------------- /InfluxDB/influxdb_v0.11_cluster_setup.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | > Warning! This page documents an old version of InfluxDB, which is no longer actively developed. 4 | > [InfluxDB v0.13]() is the most recent stable version of InfluxDB. 5 | 6 | 7 | ---------- 8 | 9 | 10 | > 注意: InfluxDB 0.11 是包含 cluster 功能的最后一个开源版本(此处的 cluster 是指 raft);更多关于此问题的信息请阅读 Paul Dix 的博客文章[InfluxDB Clustering, High-Availability, and Monetization](). 请注意,0.11 版本的 cluster 仍被认为是实验性的,仍存在很多犄角旮旯的地方需要处理。 11 | 12 | 本文简要介绍了 InfluxDB 的 cluster 模型,并提供了逐步建立 cluster 的步骤。 13 | 14 | # InfluxDB cluster model 15 | 16 | InfluxDB 支持创建任意(节点)数量的 cluster ,并且允许 [replication factor]() 的值被设置为 1 至 cluster 中的 node 数目; 17 | 18 | 在 InfluxDB cluster 中存在 3 种类型的 node :[consensus nodes](), [data nodes]() 和 [hybrid nodes]() 。一个 cluster 中要求必须存在奇数个 node 运行 [consensus service]() 以便构成 Raft consensus group ,且保持在一个健康的状态中。 19 | 20 | Hardware requirements vary for the different node types. See Hardware Sizing for cluster [hardware requirements](). 21 | 22 | # Cluster setup 23 | 24 | The following steps configure and start up an InfluxDB cluster with three [hybrid nodes](). If you’re interested in having any of the different node types, see [Cluster Node Configuration]() for their configuration details. Note that your first three nodes must be either hybrid nodes or consensus nodes. 25 | 26 | We assume that you are running some version of Linux, and, while it is possible to build a cluster on a single server, it is not recommended. 27 | 28 | 1 在 3 台机器上[安装]() InfluxDB ;但暂时不要在任何一台机器上启动 daemon 程序 29 | 30 | 2 配置 3 个 node 31 | 32 | 其中 `IP` 对应的是 node 的 IP 地址或主机名,每一个 node 均需要一个 `/etc/influxdb/influxdb.conf` 文件,其中包含如下设置信息: 33 | 34 | ```shell 35 | [meta] 36 | enabled = true 37 | ... 38 | bind-address = ":8088" 39 | ... 40 | http-bind-address = ":8091" 41 | 42 | ... 43 | 44 | [data] 45 | enabled = true 46 | 47 | ... 48 | 49 | [http] 50 | ... 51 | bind-address = ":8086" 52 | ``` 53 | 54 | 同时设置 `[meta] enabled = true` 和 `[data] enabled = true` 将使得当前 node 成为一个 hybrid node ; 55 | `[meta] bind-address` 用作当前 node 在 cluster 中的通信地址; 56 | `[meta] http-bind-address` 用作 meta node 通信地址; 57 | `[http] bind-address` 用作 HTTP API 通信地址; 58 | 59 | > 注意:针对每台机器配置的主机名必须能够被 cluster 中的所有 node 所解析; 60 | 61 | 3 将所有 node 都配置成可以与其它 node 进行通信; 62 | 63 | 针对上述 3 个 node ,在 `/etc/default/influxdb` 中设置 `INFLUXD_OPTS` 的值如下: 64 | 65 | ```shell 66 | INFLUXD_OPTS="-join :8091,:8091,:8091" 67 | ``` 68 | 69 | 其中 `IP1` 为第一个 node 的 IP 地址或主机名,`IP2` 为第二个 node 的 IP 地址或主机名,`IP3` 为第二个 node 的 IP 地址或主机名; 70 | 71 | 如果文件 `/etc/default/influxdb` 不存在,则需手动创建; 72 | 73 | 4 在每一个 node 上都启动 InfluxDB : 74 | 75 | ```shell 76 | sudo service influxdb start 77 | ``` 78 | 79 | 5 校验 cluster 的健康性 80 | 81 | 可以使用 `influx` [CLI]() 工具向 cluster 中的每一个 node 发送 `SHOW SERVERS` 查询指令;对应的输出信息显示出你的 cluster 由 3 个 hybrid node 构成(hybrid node 在 `SHOW SERVERS` 的查询结果中既作为 `data_nodes` 又作为 `meta_nodes` 显示): 82 | 83 | ```shell 84 | > SHOW SERVERS 85 | name: data_nodes 86 | ---------------- 87 | id http_addr tcp_addr 88 | 1 :8086 :8088 89 | 2 :8086 :8088 90 | 3 :8086 :8088 91 | 92 | 93 | name: meta_nodes 94 | ---------------- 95 | id http_addr tcp_addr 96 | 1 :8091 :8088 97 | 2 :8091 :8088 98 | 3 :8091 :8088 99 | ``` 100 | 101 | > Note: The `SHOW SERVERS` query groups results into `data_nodes` and `meta_nodes`. The term `meta_nodes` is outdated and refers to a node that runs the consensus service. 102 | 103 | 至此,你已经成功创建了 3 node cluster ! 104 | 105 | If you believe that you did the above steps correctly, but are still experiencing problems, try restarting each node in your cluster. 106 | 107 | ## Adding nodes to your cluster 108 | 109 | Once your initial cluster is healthy and running appropriately, you can start adding nodes to the cluster. Additional nodes can be consensus nodes, data nodes, or hybrid nodes. See [Cluster Node Configuration]() for how to configure the different node types. 110 | 111 | Adding a node to your cluster follows the same procedure that we outlined above. Note that in step 4, when you point your new node to the cluster, you must set `INFLUXD_OPTS` to every node in the cluster, including itself. 112 | 113 | ## Removing nodes from your cluster 114 | 115 | Please see the [reference documentation]() on `DROP SERVER.` 116 | 117 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 moooofly 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Linux/ARP 地址解析过程.md: -------------------------------------------------------------------------------- 1 | # ARP 地址解析过程 2 | 3 | 原文地址:[这里](http://www.bkjia.com/wlxy/495051.html) 4 | 5 | ---------- 6 | 7 | 8 | 人们最熟悉的网络可以说是以太网,而且人们都知道,每块网卡都有一个编号,也就是网卡地址(称为MAC地址),代表计算机的物理地址。另外,网络中的每一台计算机都分配了一个IP地址,这样,每台计算机上都有两个地址,IP地址和MAC地址。 9 | 10 | IP地址并不能代替MAC地址,前者是在大网中为了方便定位主机所采用的方式,如果网络规模不大,完全可以不使用IP地址。但是,无论什么网络环境物理地址都是要使用的。因为物理地址对应于网卡的接口,只有找到它才算真正到达了目的地。而IP地址是为了方便寻址人为划分的地址格式,因此**IP地址**也被称为**逻辑地址**,又因为这种结构化地址是在OSI的第3层定义的,也被称为**3层地址**。相应地,**物理地址**是在第2层定义的,被称为**2层地址**。IP地址是一种通用格式,无论其下一层的物理地址是什么类型,都可以被统一到一致的IP地址形式上,因此IP地址屏蔽了下层物理地址的差异。 11 | 12 | 既然IP地址并不能代替物理地址,它只是在逻辑上表示一台主机,物理地址才对应于网卡的接口,只有找到它才能将数据送达到目的地。那么如何把二者对应起来就是要解决的首要问题,因为二者代表的是同一台机器。为此人们开发了**地址解析协议**(Address Revolution Protocol,**ARP**),地址解析协议负责把IP地址映射到物理地址。 13 | 14 | 下面分两种情况解释ARP的工作过程:**同一子网内的arp**和**不同子网间的arp**。 15 | 16 | # 同一子网内的ARP 17 | 18 | 主机A (172.16.20.20/24)与主机B通信。假设在A上Ping主机B的IP地址172.16.20.5/24。 19 | 20 | 为了把测试信息发送到主机B和A,将构造关于Ping的IP数据包。可以确定,这个包头中的源IP地址是172.16.20.20,目的地址172.16.20.5。IP数据包构造完成以后,需要将它从网卡发送出去,在这之前必须要封装2层的帧头,本例中2层是以太网环境,因此需要构建以太网帧头。分析帧头中的MAC地址情况,它的源地址应该是00-0C-04-18-19-aa,这个地址很容易获得,主机A直接从自己的网卡中获取即可,帧头中的目的MAC地址应该是00-0C-04-38-39-bb,它对应于主机B的MAC地址。主机A如何得知主机B的MAC地址呢?这是主机A在封装2层帧头时必须解决的问题,否则无法发送这个帧出去。主机A唯一的办法是向主机B发出询问,请主机B回答它自己的MAC地址是什么。ARP协议正是负责完成这一工作的,即已知目的节点的IP地址来获取它相应的物理地址。 21 | 22 | ARP的操作过程如下: 23 | - 主机A发出ARP请求,请求帧中的**数据部分**包括发送者MAC地址00-0C-04-18-19-aa、发送者IP地址172.16.20.20和目标MAC地址,这里全部填充0,因为它未知(这正是ARP要询问的),目标IP地址是172.16.20.5。 24 | - 在请求帧的**帧头部分**,目的MAC地址是**广播地址**,因此所有收到的站点(其中就包括主机B)都打开这个帧查看其数据部分的内容。 25 | - 只有符合目标IP地址172.16.20.5的主机(主机B)回答这个ARP请求,其他站点则忽略这个请求。 26 | - 主机B把自己的MAC地址写入“目标地址”字段中,送给主机A。 27 | - 主机A通过ARP的操作得到了主机B的MAC地址,可以继续完成它的封装过程,从而最终执行了Ping的操作。 28 | 29 | ARP请求者收到应答后,会在自己的缓存中构建一个**ARP表**,将得到的地址信息缓存起来,以备将来和同一目的节点通信时直接在ARP表中查找,避免了多次的广播请求。 30 | 31 | 实际上,**完整的操作过程**是:主机A在准备构造2层帧头时,首先根据目的IP去查找ARP表,如果找到对应项,则直接得到目的MAC地址,如果没有查到才执行上面所说的ARP广播请求。这样做是为了最大限度地减少广播。 32 | 33 | # 不同子网间ARP 34 | 35 | 假设在主机A(172.16.10.10/24)上Ping主机B的IP地址172.16.20.5/24,随后主机A将构造关于Ping的IP数据包,这一过程与前面相同,只是目的地址在另外一个子网中。主机A仍然面临如何确定2层帧头中的目的MAC地址的问题。 36 | 37 | 如果仍然依照目的节点和源节点位于同一子网中的思路,这个目的MAC应该是主机B网卡的MAC地址。顺着这个思路走下去,看看会发生什么情况。 38 | 39 | 由于主机B位于路由器的另外一侧,因此主机B要想收到主机A发出的以太网帧必须通过路由器转发,那么路由器是否会转发呢?答案是否定的。路由器在收到某个以太网帧后首先检查其目的MAC,而这里假设A发出的帧中的目的MAC是B的网卡地址,路由器从Ethernet 0接口收到该帧后,查看目的MAC地址,发现它不是自己的MAC地址,从而将其丢弃掉。由此看来,位于不同子网的主机之间在通信时,目的MAC地址不能是目标主机的物理地址。 40 | 41 | 实际上,不同子网之间的主机通信要经过路由过程,这里就是需要路由器A进行转发。因此,主机A发现目标主机与自己不在同一个子网中时就要借助于路由器。它需要把数据帧送到路由器上,然后路由器会继续转发至目标节点。在该例中,主机A发现主机B位于不同子网时,它必须将数据帧送到路由器上,这就需要在帧头的“目的地址”字段上写入路由器接口Ethernet 0的MAC地址。因此,主机A需要通过ARP询问路由器Ethernet 0接口的MAC地址。 42 | 43 | 这里仍然是两个操作过程,一个是ARP请求;另一个是ARP应答。不过在ARP的请求帧中,目标IP地址将是路由器Ethernet 0接口的IP地址,这个地址实际上就是子网172.16.10.0/24中主机的默认网关。路由器收到ARP请求后回答自己Ethernet 0接口的MAC地址,这样主机A就获得了其默认网关的MAC地址。主机A构建完整的数据帧并将其发送给到路由器。路由器收到主机A的数据后,根据路由表的指示将从另一接口Ethernet 1把数据发送给主机B。同样,在发送前路由器也要封装2层帧头,也需要知道主机B的MAC地址,路由器也是通过ARP协议来获得B的MAC地址的。 44 | 45 | 综合以上两种情况,主机A的完整操作过程如下: 46 | 主机A首先比较目的IP地址与自己的IP地址是否在同一子网中,如果在同一子网,则向本网发送ARP广播,获得目标IP所对应的MAC地址;如果不在同一子网,就通过ARP询问默认网关对应的MAC地址。 47 | -------------------------------------------------------------------------------- /Linux/BDP.md: -------------------------------------------------------------------------------- 1 | # BDP 2 | 3 | ## [Bandwidth-delay product](https://en.wikipedia.org/wiki/Bandwidth-delay_product) 4 | 5 | ## [What is the Bandwidth * Delay Product ?](https://www.speedguide.net/faq/what-is-the-bandwidth-delay-product-185) 6 | 7 | ## [Tuning TCP for High Bandwidth-Delay Networks](http://www.kehlet.cx/articles/99.html) -------------------------------------------------------------------------------- /Linux/CPU 隔离之任务分析.md: -------------------------------------------------------------------------------- 1 | # CPU 隔离之任务分析 2 | 3 | 标签(空格分隔): packetbeat 4 | 5 | --- 6 | 7 | 最近被分配了一个任务,任务描述很简单,就一句话:**如何基于 `packetbeat` 分析 redis 的网路通信情况,而不对 redis 本身(CPU/Memory/Network)产生影响;** 8 | 9 | 首先,需要回答一个问题:**会产生什么影响?** 10 | 11 | 通常来讲,运行抓包系统会占用 CPU 和 Memory 等资源,而 redis 本身对 CPU 和 Memory 使用也有较高要求,即希望资源都是自己的才好; 12 | 13 | 那也问题就变成了:**redis 是怎么部署在服务器上运行的?对于 24 核或 32 核服务器,redis 是怎么使用的?** 14 | 15 | 经过确认,我们会在一台 24 核的物理机上跑 8~10 个 redis 实例(分属不同 cluster),但没有对 cpu 和内存使用进行任何限制;换句话说,24 个 CPU 核心和 Memory 都处于“任君多采撷”状态; 16 | 17 | > 由于 packetbeat 的内存占用相对 redis 来说基本可以忽略,因为后文只讨论 CPU ; 18 | 19 | 因此,我们可以得到的结论是:无论将 `packetbeat` 跑在哪个核心上,都会“占用一定的 redis 的资源”; 20 | 21 | 那么问题就变成了:**允许百分之多少的 CPU 被 packetbeat 占用?** 22 | 23 | 粗略估算结果如下: 24 | 25 | - 24 核心 CPU ,单核跑满相当于占用了 4.17% 的 CPU 资源;若占用两个 CPU 核心,则对应 8.34% ; 26 | - 我们的报警系统对 redis 的 CPU 报警设置为:单核占用达到 90% ,总体占用达到 40% ; 27 | - 对于业务比较繁忙的 redis 来说,CPU 占用能够达到整体 30% 左右; 28 | - 由此看来,即使跑满 2 个 CPU 核心也没什么大问题; 29 | 30 | 另外还有一个疑问:**从 redis 的视角来看 24 个核心真的是完全等同的么?是否存在某种优先选择策略?** 31 | 32 | 似乎这个问题又和 CPU 的硬件架构扯上了关系,即 `SMP` 和 `NUMA` 都是怎么玩的; 33 | 34 | 经确认:我们线上机器的 CPU 架构都是 NUMA(由两个 node 构成),并且 redis 会倾向于使用 NUMA node1 中的 cpusets ,那么将 `packetbeat` 绑定到 NUMA node2 上运行应该是相对更合理的方式; 35 | 36 | 谈及绑定问题,原则上讲会涉及 **CPU 绑定**,**Memroy 绑定**,**IRQ 绑定**等等;因此,它们之前的关系及影响,以及部署考量都需要研究确认; 37 | 38 | 针对 CPU 绑定,即 CPU 亲缘性问题,存在多种处理方式: 39 | 40 | - taskset 41 | - numactl 42 | - isolcpus 43 | - cgroups 44 | 45 | **需要确认这些方式有何不同,应该使用哪种,为什么?** 46 | 47 | **选定 CPU 绑定方式后,Memory 和 IRQ 绑定如何处理?IRQ 处理是否应该绑定到 CPU 亲缘性选择的相同 CPU 上么?** 48 | 49 | 上述情况还只是一般性的讨论,对于基于 go 语言实现的 `packetbeat` 来说,由于 OS thread 的创建数量是由 runtime 自行决定的,而 goroutine 跑在哪个 OS thread 上则是由 go 运行时调度器决定的;`packetbeat` 的功能至少可以拆分为**网络抓包功能**和**抓包分析功能**,而这两者基于多少 goroutine 实现,以及两者之间的相互影响(例如 CPU 跑高导致抓包时的丢包行为)都是应该考虑考虑的;总之,一般情况下,我们认为将 `packetbeat` 绑定到一组 cpu 上运行似乎是更好的选择; 50 | 51 | 52 | 现状如下: 53 | 54 | - redis 实例的运行尚未考虑 CPU 亲缘性问题; 55 | - 基于 `taskset` 控制 `packetbeat` 的 CPU 绑定,但理论上讲,无论如何绑定,总归会对 redis 产生一定影响; 56 | - 由于 redis 的网络流量非常大,万兆网卡跑满状态下,每秒大概要保存 1.2GB 数据,通常我们会抓取 10s 数据包,因为 12GB 的数据对于硬盘和带宽的影响都需要考虑; 57 | 58 | 59 | -------------------------------------------------------------------------------- /Linux/CPU 隔离问题.md: -------------------------------------------------------------------------------- 1 | # CPU 隔离问题 2 | 3 | 标签(空格分隔): linux 4 | 5 | --- 6 | 7 | ## numactl 8 | 9 | 详见《[CPU 隔离之 numactl](CPU%20隔离之%20numactl.md)》; 10 | 11 | ## taskset 12 | 13 | 详见《[CPU 隔离之 taskset](CPU%20隔离之%20taskset.md)》; 14 | 15 | ## isolcpus 16 | 17 | 详见《[CPU 隔离之 isolcpus](CPU%20隔离之%20isolcpus.md)》; 18 | 19 | ## cgroups 20 | 21 | 详见《[CPU 隔离之 cgroups](CPU%20隔离之%20cgroups.md)》; -------------------------------------------------------------------------------- /Linux/Cache.md: -------------------------------------------------------------------------------- 1 | # Cache 2 | 3 | 4 | ---------- 5 | 6 | 7 | - [linux I/O优化 磁盘读写参数设置](http://wlservers.blog.163.com/blog/static/120622304201241715945256/) 8 | - [Linux Page Cache Basics](https://www.thomas-krenn.com/en/wiki/Linux_Page_Cache_Basics) 9 | - [The Linux Page Cache and pdflush](http://www.westnet.com/~gsmith/content/linux-pdflush.htm) 10 | - [linux IO行为:page cache and pdflush](http://blog.csdn.net/chenxinl/article/details/6673708) 11 | - [The Page Cache and Page Writeback](http://sylab-srv.cs.fiu.edu/lib/exe/fetch.php?media=paperclub:lkd3ch16.pdf) 12 | - [Page Frame Reclamation](https://www.kernel.org/doc/gorman/html/understand/understand013.html) 13 | - [Page cache](https://en.wikipedia.org/wiki/Page_cache) 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /Linux/FAQ about the NUMA architecture.md: -------------------------------------------------------------------------------- 1 | # [FAQ about the NUMA architecture](http://lse.sourceforge.net/numa/faq/) 2 | 3 | > 本文解答了一些 NUMA 架构的 FAQ ; 4 | 5 | ## What does NUMA stand for? 6 | 7 | NUMA 即 Non-Uniform Memory Access. 8 | 9 | ## OK, So what does Non-Uniform Memory Access really mean to me? 10 | 11 | Non-Uniform Memory Access 表示在访问某些内存区域时会比访问另外一些区域耗时更长;这是因为不同内存区域位于物理上的不同总线上;要想获得更佳具象的描述,请参考下面关于 NUMA 架构实现的描述;另外,还可以参照针对 NUMA 架构的现实世界类比;对于不感知 NUMA 的程序来说,可能会造成运行效果变差;NUMA 还引入了 local 和 remote 内存概念; 12 | 13 | ## What is the difference between NUMA and SMP? 14 | 15 | NUMA 架构被设计出来用于解决 SMP 架构扩展性受限问题;对于 SMP 来说,即 Symmetric Multi-Processing,所有的内存访问请求都被发送给相同的共享内存总线上;这种方式对于相对少量的 CPUs 来说没有什么问题,但是当你使用数十,甚至上百 CPUs 时,共享总线的问题就出现了,因为所有 CPUs 都会竞争共享内存总线的访问权;NUMA 通过限制可以出现在任何内存总线上的 CPUs 数量,以及通过高速互联(路径)互通的方式缓解了这个瓶颈问题; 16 | 17 | ## What is the difference between NUMA and ccNUMA? 18 | 19 | 在当前这个时间点上两者几乎没有什么差别;ccNUMA 表示 Cache-Coherent NUMA,但是 NUMA 和 ccNUMA 几乎可以当作是同义的,因为基于 non-cache coherent NUMA 机器的应用几乎不存在;因此,除非特别说明,我们在说 NUMA 的时候实际上就是指 ccNUMA ; 20 | 21 | ## What is a node? 22 | 23 | 描述 NUMA 时常常遇到的问题之一就是实现该技术的方式存在许多种;这就导致了针对什么是 node 存在大量的“定义”方式;一种从技术角度来说非常正确,但同时非常丑陋的定义方式为:**a region of memory in which every byte has the same distance from each CPU** ;而更通俗的定义为:**a block of memory and the CPUs, I/O, etc. physically on the same bus as the memory** ;在某些架构中,确实存在 memory, CPUs 和 I/O 并非全部位于相同物理总线上的情况,因此,第二种定义并不总是正确的;在许多情况下,越少的技术定义可能越显得充分,但越多的技术定义会显得越准确; 24 | 25 | ## What is meant by local and remote memory? 26 | 27 | 术语 local memory 和 remote memory 通常情况下是针对当前运行进程来说的;也就是说,local memory 通常被定义为:与当前运行进程的 CPU 同属一个 node 的 memory ;而不输于该 node 的 memory 则被定义为 remote ; 28 | 29 | Local 和 remote memory 的定义也可用于针对其他东东,而非当前的运行进程;当谈及中断上下文时,技术上讲不存在当前执行进程的概念,但我们仍将处理该中断的 CPU 所属 node 上的 memory 称作 local memory ;同样的,你还可以从 disk 的角度使用 local 和 remote memory 的概念;例如,如果存在一个 disk 附属于(attatched to) node 1 ,正在执行 DMA 操作,那么其正在读取或写入的 memory 将被称作 remote ,如果该 memory 位于另外一个 node 上(即 node 0 上); 30 | 31 | ## What do you mean by distance? 32 | 33 | 基于 NUMA 的架构中非常有必要引入一个系统组件(即 CPUs, memory, I/O 总线等)之间的 distance 概念;用于衡量 distance 的 metric 经常有所不同,但是 hops 是比较受欢迎的一种 metric ,另外还有 latency 和 bandwidth ;这些术语的含义和其出现在网络上下文中时是一样的(几乎可以认为 NUMA 机器与紧耦合集群没有什么太大差别);因此,当用于描述 node 时,我们可能会将特定范围内的 memory 描述成距离 CPUs 0..3 和 SCSI Controller 0 的 distance 为 2 hops (busses);换句话说,CPUs 0..3 和 SCSI Controller 均为相同 node 的一部分; 34 | 35 | ## Could you give a real-world analogy of the NUMA architecture to help understand all these terms? 36 | 37 | 想象一下你正在烘焙蛋糕:你手头有一组配料(=**memory pages**)用于满足配方要求(=**process**);其中一些配料你可能已经保存在了小柜子中(=**local memory**),而另外一些配料你可能根本就没有,因此你不得不向邻居索取(=**remote memory**);一般性想法就是保证尽可能多的配料保存在你自己的小柜子中,因为这样才能缩短你做蛋糕的耗时和劳动量; 38 | 39 | 还需要谨记:你的小柜子只能保存一定数量的配料(=**physical nodal memory**);如果你尝试购买更多的东西,但却没有空间来保存,你将不得不拜托邻居帮你保存配料在其小柜子中,直到你需要时获取(=**local memory full, so allocate pages remotely**); 40 | 41 | A bit of a strange example, I'll admit, but I think it works. If you have a better analogy, I'm all ears! ;) 42 | 43 | ## Why should I use NUMA? What are the benefits of NUMA? 44 | 45 | NUMA 带来的最大收益,正如上面所说,是可扩展性;将 SMP 扩展至可支持 8-12 CPUs 是极其困难的;在这个 CPU 数目下,memory 总线将面临严重的竞争问题;而 NUMA 正是用于减少竞争访问共享 memory 总线的 CPUs 数量的一种方式;具体的解决办法为:提供多条 memory 总线,然后搭配相对少量的 CPUs 到每一条总线上;事实上,存在很多其他方式可以构建大规模多处理器机器,但此处为 NUMA FAQ ,因此还是将其他方法如何实现的讨论留到其他 FAQs 上吧; 46 | 47 | ## What are the peculiarities of NUMA? 48 | 49 | CPU 和/或 node caches 会导致 NUMA effects 问题;例如,位于特定 node 上的 CPUs 在访问同一 node 上的 memory 和 CPUs 时,将得到更高的带宽和/或更低的延迟;由于这个原因,您可能会在高竞争压力下看到诸如 **lock starvation** 现象;这是因为如果目标 node 上的 CPU x 请求了已被同一 node 上 CPU y 获取的 lock 时,该请求将会(倾向于)“击退”来自 remote CPU z 的请求; 50 | 51 | ## What are some alternatives to NUMA? 52 | 53 | 将 memory 进行拆分后(尽可能任意)分配给一组 CPUs 能够获得一些和真正 NUMA 类似的性能收益;类似这种构建方式已经很像常规的 NUMA 机器了,其中 local 和 remote memory 之间的界限是模糊的;因为全部 memory 实际上仍位于相同的总线之上;PowerPC 的 Regatta 系统就是这种实现的例子; 54 | 55 | 你也可以基于 clusters 达到一定程度类似 NUMA 的性能;一个 cluster 非常相似于一个 NUMA 机器,其中位于 cluster 中的每一台机器将成为我们虚拟 NUMA 机器中的 node ;唯一的真正差别在于节点间延迟;在集群环境中,节点相互之间的 latency 和 bandwidth 很可能更加糟糕; 56 | 57 | ## Could you give a brief description of the main NUMA architecture implementations? 58 | 59 | 当然!主要类型为 IBM NUMA-Q, Compaq Wildfire, 以及 SGI MIPS64 ;你可以点击[这里](NUMA%20之%20System%20Descriptions.md)查阅关于上述系统类型的详细描述和图标,以及用作比较目的的标准 SMP 系统模型; 60 | -------------------------------------------------------------------------------- /Linux/Linux CPU 占用率原理与精确度分析.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moooofly/MarkSomethingDown/3ed8d77b34dfb893b865932086065265876e3bc6/Linux/Linux CPU 占用率原理与精确度分析.pdf -------------------------------------------------------------------------------- /Linux/Linux System and Performance Monitoring.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moooofly/MarkSomethingDown/3ed8d77b34dfb893b865932086065265876e3bc6/Linux/Linux System and Performance Monitoring.pdf -------------------------------------------------------------------------------- /Linux/Local.and.Remote.Memory.Memory.in.a.Linux.NUMA.System.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moooofly/MarkSomethingDown/3ed8d77b34dfb893b865932086065265876e3bc6/Linux/Local.and.Remote.Memory.Memory.in.a.Linux.NUMA.System.pdf -------------------------------------------------------------------------------- /Linux/NUMA 之 System Descriptions.md: -------------------------------------------------------------------------------- 1 | # NUMA 之 System Descriptions 2 | 3 | 标签(空格分隔): linux 4 | 5 | --- 6 | 7 | ## [System Descriptions](http://lse.sourceforge.net/numa/faq/system_descriptions.html) 8 | 9 | 本节内容将描述各种平台相关信息;其中一些平台当前可能是存在的,而另外一些可能是虚构的,或者说将来可能会被制造出来;本文的**目的**就是为了展示**系统拓扑的潜在的多样性**;本文中描述的系统包括: 10 | 11 | - 典型的 `SMP` 系统 12 | - Alpha Wildfire 系统 13 | - IBM Numa-Q 系统 14 | - SGI Mips64 系统 15 | - 能够在单块芯片上使用多 CPU 技术的系统 16 | - 将 CPUs 和 Memory 环状连接在一起的系统 17 | 18 | 19 | ### A typical SMP system 20 | 21 | 下图展示了一个典型的 SMP 系统设计,其使用了 Intel x86 处理器: 22 | 23 | ![sys_smp](https://raw.githubusercontent.com/moooofly/ImageCache/master/Pictures/sys_smp.gif "sys_smp") 24 | 25 | 典型的 SMP 系统包括多个 CPUs ;典型 CPU 会包含一个 L1 cache ;L2 cache 在典型情况下由 CPU 所管理,但 L2 cache 的内存对于 CPU 来说是外部的;该系统可能还具有 L3 cache ,针对它的管理对于 CPU 来说是外部的;L3 cache 可能会被多个 CPUs 所共享;系统中还会包含主存(main memory),并且主存中的内容可能出现在任一个 caches 中;针对主存和各级 caches 的一致性维护需要由硬件来保证;典型的 memory latencies 为: 26 | 27 | - L1 cache hit: 28 | - L2 cache hit: 29 | - L3 cache hit: 30 | - memory access: 31 | 32 | 系统中还会包含一条或多条 IO 总线,IO 控制器会关联到这些 IO 总线上,所有设备会关联到这些 IO 控制器上; 33 | 34 | ### Compaq / Alpha Wildfire 35 | 36 | Currently searching for more information. Any help identifying this information or a volumteer to write this section would be greatly appreciated. Please send any information to Paul Dorwin (pdorwin@us.ibm.com) 37 | 38 | ### The IBM Numa-Q system 39 | 40 | IBM Numa-Q 的系统设计如下图所描述: 41 | 42 | ![sys_numaq](https://raw.githubusercontent.com/moooofly/ImageCache/master/Pictures/sys_numaq.gif "sys_numaq") 43 | 44 | 系统中的每一个 node 都由一个简单的 4 处理器 SMP 系统构成;Numa-Q 使用的 Intel X86 CPU ;该 node 上的每一个 CPU 都包含 L1 和 L2 cache ;该 node 中还回包含一个 L3 cache 用于其上所有处理器共享;单个 node 上的本地内存最多支持 2 Gb ;该 node 同样包含一个(不知道多少大小的)远端 cache ,用于缓存来自远端 nodes 的数据;Numa-Q 系统中的 nodes 是通过 Lynxer 进行互联的,其中包含了 SCI (Scalable Coherent Interface) 接口;memory latencies 如下: 45 | 46 | - L1 cache hit: 47 | - L2 cache hit: 48 | - L3 cache hit: 49 | - local memory hit: 50 | - remote cache hit: 51 | - remote memory hit: 52 | 53 | Linux 系统针对 Numa-Q 的移植(The Linux port to Numa-Q)要求修改基于 APIC 访问 CPUs 的方式;默认情况下,CPU 上的 APIC 地址是平坦的(flat), 允许最多 8 个处理器同时使用系统总线;Numa-Q 使用 `luster` 模式,其中 8 比特可以进一步拆分;4 比特用来确认(区分)最多 16 个 nodes ,而另外 4 比特用于确认(区分)每个 node 上的 4 个 cpus ;而 Lynxer card 负责确认和路由跨 node 的访问;每一个 node 同样包含 2 个 PCI 总线;(在撰写此文时)第一个 PCI 总线包含 3 个 slots 而第二个包含 4 slots (VERIFY THIS) ;Linux was verified to boot consistently on 4 nodes containing a total of 16 processors. The Numa-Q work is hidden behind CONFIG_MULTIQUAD, and the patches are being tested. Work is underway to update the kernel to allow IO boards in all nodes. Work is also underway to port discontiguous memory to the Numa-Q platform. 54 | 55 | ### Slicon Graphics Mips64 56 | 57 | Currently searching for more information. Any help identifying this information or a volumteer to write this section would be greatly appreciated. Please send any information to Paul Dorwin (pdorwin@us.ibm.com) 58 | 59 | 60 | ### CPU/Memory ring system 61 | 62 | 下图展示了一个理论上的系统:一个 CPU 连接到两个独立的 memory 节点上,并且每一个 memory 节点也会连接到两个 CPUs 上: 63 | 64 | ![sys_ring](https://raw.githubusercontent.com/moooofly/ImageCache/master/Pictures/sys_ring.gif "sys_ring") 65 | 66 | 正如你所看到的,这样就会产生一个 ring 配置的系统; 67 | 68 | ### Multiple CPU on a single chip 69 | 70 | 下图展示了理论上单块芯片包含多个 CPU 的情况: 71 | 72 | ![sys_mpct](https://raw.githubusercontent.com/moooofly/ImageCache/master/Pictures/sys_mpct.gif "sys_mpct") 73 | 74 | ### Conclusions 75 | 76 | 在这里所描述的所有系统均展示了相似的特点:均含有多个处理器和一些配套的 cache ;也都包含一些形式的 memory 和 IO ;处理器之间彼此被分开一段距离;然而针对他们的连接方式存在比较大的差别;为了重申这一点,它们均具有独一无二的拓扑结构;Therefore, it is important to present an in-kernel infrastructure which easily allows the architecture dependant code to create an in-kernel description of the system's topology. The section describing the in-kernel infrastructure will provide the details of the proposed solution. 下面是一组特性列表,可用于从系统拓扑中得到确认: 77 | 78 | - How many **processors** are in the system. 79 | - How many **memories** are in the system. 80 | - How many **nodes** are in the system 81 | - What is **encapsulated** in any given node. 82 | - For any given processor: 83 | - What is the **distance to any other processor** in the system. 84 | - What is the **distance to any memory** in the system. 85 | - How many **cache levels** exist and how large is each cache. 86 | - For any given memory: 87 | - What is the **start pfn** of the memory 88 | - What is the **size** of the memory 89 | - What **processors are directly connected** to the memory. -------------------------------------------------------------------------------- /Linux/Netlink Protocol Library Suite(libnl).md: -------------------------------------------------------------------------------- 1 | 2 | # Netlink Protocol Library Suite (libnl) 3 | 4 | ## Summary 5 | 6 | > The libnl suite is a collection of libraries providing APIs to netlink protocol based Linux kernel interfaces. 7 | 8 | **libnl 套装**由一组库的集合构成,其基于 Linux 内核接口提供了访问 `netlink` 协议的 API ; 9 | 10 | > Netlink is a IPC mechanism primarly between the kernel and user space processes. It was designed to be a more flexible successor to ioctl to provide mainly networking related kernel configuration and monitoring interfaces. 11 | 12 | `netlink` 是一种 IPC 机制,主要用于**内核空间进程与用户空间进程的交互**; 13 | `netlink` 是作为更为灵活的、`ioctl` 的**后继者**被设计出来的,主要用于**提供与网络相关的内核配置能力和监控接口**; 14 | 15 | 16 | ## Libraries 17 | 18 | > The interfaces are split into several small libraries to not force applications to link against a single, bloated library. 19 | 20 | 接口按照功能被拆分成许多个短小精悍的库,以便应用程序可以按需链接; 21 | 22 | ### libnl 23 | 24 | > Core library implementing the fundamentals required to use the netlink protocol such as socket handling, message construction and parsing, and sending and receiving of data. This library is kept small and minimalistic. Other libraries of the suite depend on this library. 25 | 26 | `libnl` 作为核心库实现了 `netlink` 协议使用所需的基础功能,例如 socket 处理,消息构建和解析,数据发送和接收;该库的设计目标就是保持短小精悍和足够抽象;**libnl 套装**中的其它库都依赖此库; 27 | 28 | ### libnl-route 29 | 30 | > API to the configuration interfaces of the NETLINK_ROUTE family including network interfaces, routes, addresses, neighbours, and traffic control. 31 | 32 | 提供可以访问 `NETLINK_ROUTE` 族配置接口的 API ,包括 network interfaces, routes, addresses, neighbours 和 traffic control 几个部分; 33 | 34 | ### libnl-genl 35 | 36 | > API to the generic netlink protocol, an extended version of the netlink protocol. 37 | 38 | 提供了针对 generic netlink 协议的 API ; 39 | 40 | ### libnl-nf 41 | 42 | > API to netlink based netfilter configuration and monitoring interfaces (conntrack, log, queue) 43 | 44 | 提供针对 netfilter 配置的 API(基于 `netlink`),以及针对 conntrack, log, queue 的监控接口; 45 | 46 | ## Installation 47 | 48 | > The easiest method of installing the libnl library suite is to use the existing packages of your linux distribution. 49 | 50 | ## Release 51 | The latest stable release is: 3.2.25 (Released on Jul 16, 2014) 52 | 53 | 54 | 官网地址:[这里](http://www.infradead.org/~tgr/libnl/) 55 | -------------------------------------------------------------------------------- /Linux/PF_RING/Active vs Passive Polling in Packet Processing (PF_RING).md: -------------------------------------------------------------------------------- 1 | # [Active vs Passive Polling in Packet Processing](http://www.ntop.org/pf_ring/active-vs-passive-polling-in-packet-processing/) 2 | 3 | 时常有 PF_RING 用户问到:应该使用 **passive polling** 技术(即调用 `pfring_poll()`)还是使用 `active polling` 技术(即基本等价于实现了一个 **active loop** ,直到下一个待处理 packet 出现;学院派的人们可能会回答说 (passive) polling 就是正确答案;这个回答从很多方面来说都是有道理的,包括从节省 CPUs 耗电的角度;但不幸的是,在实际中故事会有所不同; 4 | 5 | 如果你打算在无事可做时,避免浪费 CPU 时钟周期(cycles),即没有 packet 待处理时,你应该调用 `pfring_poll()` 或 `poll`/`select` 以告知系统在发现有 packet 处理时唤醒程序;而如果你创建的是 **active polling loop** ,你可能就会实现如下代码逻辑 6 | 7 | ```c 8 | while() { usleep(1); } 9 | ``` 10 | 11 | 这种实现能够(理论上)减少 CPU loop ,令其稍微休息一下(1 微秒);这会是一种很好的实践,如果 `usleep()` 或 `nanosleep()` 真正持续的时间确实如你所指定的值时;不幸的是,结果并不是这样;这些函数均通过系统调用实现的 sleep 功能;我们知道,简单的系统调用的代价是非常低的(例如,你可以基于这里的[测试程序](https://github.com/tsuna/contextswitch/blob/master/timesyscall.c)进行相关测试),并且在通常情况下[低于 100 nsec/call](http://blog.tsunanet.net/2010/11/how-long-does-it-take-to-make-context.html),即和 1 usec sleep 相比可以忽略不计;下面让我们基于下面的简单程序(sleep.c)来具体测量一下 `usleep()` 和 `nanosleep()` 的精确度到底是多少; 12 | 13 | ```c 14 | #include 15 | #include 16 | #include 17 | 18 | double delta_time_usec(struct timeval *now, struct timeval *before) { 19 | time_t delta_seconds; 20 | time_t delta_microseconds; 21 | 22 | delta_seconds = now->tv_sec - before->tv_sec; 23 | 24 | if(now->tv_usec > before->tv_usec) 25 | delta_microseconds = now->tv_usec - before->tv_usec; 26 | else 27 | delta_microseconds = now->tv_usec - before->tv_usec + 1000000; /* 1e6 */ 28 | 29 | return((double)(delta_seconds * 1000000) + (double)delta_microseconds); 30 | } 31 | 32 | int main(int argc, char* argv[]) { 33 | int i, n = argc > 1 ? atoi(argv[1]) : 100000; 34 | static struct timeval start, end; 35 | struct timespec req, rem; 36 | int how_many = 1; 37 | 38 | gettimeofday(&start, NULL); 39 | for (i = 0; i < n; i++) 40 | usleep(how_many); 41 | gettimeofday(&end, NULL); 42 | 43 | printf("usleep(1) took %f usecs\n", delta_time_usec(&end, &start) / n); 44 | 45 | gettimeofday(&start, NULL); 46 | for (i = 0; i < n; i++) { 47 | req.tv_sec = 0, req.tv_nsec = how_many; 48 | nanosleep(&req, &rem); 49 | } 50 | gettimeofday(&end, NULL); 51 | 52 | printf("nanosleep(1) took %f usecs\n", delta_time_usec(&end, &start) / n); 53 | } 54 | ``` 55 | 56 | 不同机器上的运行结果会些许差异,但基本在 60 usec 左右; 57 | 58 | ```shell 59 | # ./sleep 60 | usleep(1) took 56.248760 usecs 61 | nanosleep(1) took 65.165280 usecs 62 | ``` 63 | 64 | 这意味着当使用 `usleep()` 和 `nanosleep()` 进行 1 微秒 sleep 时,实际上 sleep 了大概 60 微秒;这个并不令人觉得奇怪,已被许多人发现了[[1](http://stackoverflow.com/questions/12823598/effect-of-usleep0-in-c-on-linux)] [[2](https://lists.freebsd.org/pipermail/freebsd-arch/2012-March/012417.html)]; 65 | 66 | 而这种结果在实际中意味着什么呢?我们知道,**若线速为 10G ,那么将会每隔 67 nsec 接收到一个 packet ,即 60 usec 的 sleep 将会接收大约 895 个 packets** ,因此你必须设计好缓冲(buffers)以便处理这种情况;这个情况还意味着,在要求严苛的场景中,你只能选择使用纯粹的 **active polling** 方式(即不能在你的 active packet poll 中调用任何形式的 usleep/nanosleep 函数),例如当你从两块网络适配器上接收 time-merging packets 时; 67 | 68 | 结论就是:**Active polling** 并不优雅,但在进行 packets 的高速处理时,这种方式可能是必须的,以便获得好的/准确的结果;PF_RING 应用同时支持 passive 和 active polling ;例如,在 `pfcount` 中你可以使用 `-a` 标识强制要求使用 active packet polling ,在增大 CPU 负载(100%)的前提下,(在一些情况下)增加 packet 捕获性能(即当你使用 active polling 时,请确保你将你的应用保定到一个 CPU 核心上;在 `pfcount` 中你可以通过 `-g` 达成); -------------------------------------------------------------------------------- /Linux/PF_RING/IRQ Balancing.md: -------------------------------------------------------------------------------- 1 | # [IRQ Balancing](http://www.ntop.org/pf_ring/irq-balancing/) 2 | 3 | 在 Linux 中,中断(interrupts)由内核自动进行处理;尤其需要说明的是,还存在一个名为 `irqbalancer` 的进程负责在多个处理器中进行中断的均衡;不幸的是,该默认行为是让全部处理器共同进行中断处理,而结果却是总体性能并非最优,尤其在多核系统中;这是因为拥有多 RX queues 的现代 NICs 在满足缓存一致性(cache coherency)原则前提下,能够工作于最佳状态;这意味着属于 ethX-RX queue Y 的中断必须被发送给 1 个核心或者最多 1 个核心及其相应的 Hyper-Threaded (HT) ;如果多处理器同时针对了相同的 RX queue 进行处理,则会导致缓存(cache)失效,性能下降;由于这个原因,IRQ balancing 成为了性能的关键;这也就是我为何建议针对相同的中断仅使用 1 或 2 个核心(对应 HT 情况)进行处理;由于在 Linux 上中断(默认)通常被发送给全部处理器的现状,即对应 `/prox/irq/X/smp_affinity` 被设置为 `ffffffff` 的情况,正如我上面所说的,最好避免这种全部处理器参与处理所有中断的方式;例如 4 | 5 | ```shell 6 | ~# grep eth /proc/interrupts 7 | 191: 0 0 3 0 0 0 2 310630615 454 0 0 0 0 0 2 0 PCI-MSI-edge eth5-rx-3 8 | 192: 0 3 0 0 0 2 0 314774529 0 0 0 0 0 2 0 0 PCI-MSI-edge eth5-rx-2 9 | 193: 3 0 0 0 2 309832652 454 0 0 0 0 0 2 0 0 0 PCI-MSI-edge eth5-rx-1 10 | 194: 0 0 0 2 0 314283930 0 0 0 0 0 2 0 0 0 3 PCI-MSI-edge eth5-TxRx-0 11 | 195: 0 0 1 0 1 0 0 0 0 0 1 0 0 0 1 0 PCI-MSI-edge eth5 12 | 196: 0 3 0 311226806 0 0 0 0 0 2 0 0 0 13 | ``` 14 | 15 | 其中 16 | 17 | ``` 18 | # cat /proc/irq/19[12345]/smp_affinity 19 | 00008080 20 | 00008080 21 | 00002020 22 | 00002020 23 | ffffffff 24 | ``` 25 | 26 | 该设置允许最大化性能,尤其在使用了 **PF_RING** 和 **TNAPI** 时;当手动调整中断设置时,请去使能 `irqbalancer` ,因为 `irqbalancer` 会按照其自己希望的方式恢复中断处理行为,进而“危害”你所做的努力; 27 | 28 | 进一步阅读: 29 | 30 | - [SMP affinity and proper interrupt handling in Linux](http://www.alexonlinux.com/smp-affinity-and-proper-interrupt-handling-in-linux) 31 | - [Why interrupt affinity with multiple cores is not such a good thing](http://www.alexonlinux.com/why-interrupt-affinity-with-multiple-cores-is-not-such-a-good-thing) -------------------------------------------------------------------------------- /Linux/PF_RING/Introducing PF_RING DNA.md: -------------------------------------------------------------------------------- 1 | # [Introducing PF_RING DNA (Direct NIC Access)](http://www.ntop.org/pf_ring/introducing-pf_ring-dna-direct-nic-access/) 2 | 3 | 在此隆重宣布 PF_RING DNA (Direct NIC Access) 已经可用了,在 Linux 下,和基于 PF_RING (non-DNA) 进行 packet 捕获比较发现,其能够极大的提高性能(高达 80%); 4 | 5 | ![PF_RING DNA](https://raw.githubusercontent.com/moooofly/ImageCache/master/Pictures/PF_RING%20DNA%20\(Direct%20NIC%20Access\).png "PF_RING DNA") 6 | 7 | 8 | PF_RING 通过 Linux NAPI 从 NICs 进行 packets 的 polling ,这意味着 NAPI 会从 NIC 中拷贝 packets 到 PF_RING 的环形缓冲区(circular buffer),之后用户态应用程序再从该环形缓冲区中进行 packets 读取(polling);在这种情况下,存在两次 poll 操作:应用程序和 NAPI 各一次;这导致了 CPU cycles 被这些 polling 所耗费;**优点**就是 PF_RING 能够将 incoming packets 同时分发到多个环形缓冲区中(即对应多个应用程序); 9 | 10 | **PF_RING DNA (Direct NIC Access)** 是一种**映射 NIC memory 和 registers 到用户态**的方案,因为从 NIC 拷贝 packets 到 DMA ring 中的操作是由 NIC **NPU (Network Process Unit)** 完成的,非 NAPI 完成;这必然带来了更好的性能表现,因为 CPU cycles 仅被用于 consuming packets ,未被浪费在从网络适配器上进行 packets 搬移动作上;而**缺点**就是一次只能有一个应用程序可以打开 DMA ring ,或者换句话说,用户态应用程序需要相互“沟通”以便进行 packets 的分发(distribute); 11 | 12 | 简单来说,**如果您喜欢灵活性,那么你应该使用 PF_RING ,如果你想要追求纯粹的速度快,那么 PF_RING DNA 是解决方案**;需要注意的是,在 DNA 模式下,NAPI polling 不会发生,因此诸如 reflection 和 packet filtering 等 PF_RING 特性不再被支持; 13 | -------------------------------------------------------------------------------- /Linux/PF_RING/Introducing PF_RING ZC.md: -------------------------------------------------------------------------------- 1 | # Introducing PF_RING ZC (Zero Copy) 2 | 3 | > 原文地址:[这里](http://www.ntop.org/pf_ring/introducing-pf_ring-zc-zero-copy/) 4 | 5 | 在将近 18 个月的开发后,我们高兴的宣布 [PF_RING ZC (Zero Copy)](http://www.ntop.org/products/packet-capture/pf_ring/pf_ring-zc-zero-copy/) 发布了;基于从 DNA 和 libzero 处学到的经验教训,我们决定从零开始重新设计一个全新的、提供有一致性保证的(consistent)、zero-copy API ,用以实现广受欢迎的网络模式;设计目标是能够提供一套简单 API 用以保证网络应用程序开发者能够获得线速性能(从 1 到 multi-10 Gbit);我们已经帮你隐藏了全部内部和底层细节,以打造 developer-centric API 而非 network/hardware-centric API ; 6 | 7 | 对于熟悉 DNA 和 Libzero 到用户来说,ZC 和它们的主要差别在于: 8 | 9 | - 我们统一了 in-kernel(之前的 PF_RING-aware drivers)和 kernel-bypass(之前的 DNA)驱动的实现;现在,你可以通过 “`-i eth0`”(in-kernel 处理模式)和 “`-i zc:eth0`”(kernel bypass)打开相同的设备;尤其是,你可以运行时决定使用哪种操作模式; 10 | - 全部的 drivers memory 被映射为(mapped)[huge-pages](https://github.com/ntop/PF_RING/blob/dev/doc/README.hugepages.md) 以获取更好的性能; 11 | - 如果你通过 “`zc:ethX`” 打开设备,则所有操作都以 zero-copy 模式完成;你能通过简单测试看到具体效果(这里 eth3 为一个 10 Gbit 接口,运行了 PF_RING-aware [ixgbe](https://github.com/ntop/PF_RING/tree/dev/drivers/intel/ixgbe/ixgbe-4.1.5-zc/src) 驱动);第一个命令发送可达 0.82 Gbit ,而第二个可达 10 Gbit; 12 | ``` 13 | # ./zsend -i eth3 -c 3 -g 0 14 | # ./zsend -i zc:eth3 -c 3 -g 0 15 | ``` 16 | - ZC 具有 [KVM](https://en.wikipedia.org/wiki/Kernel-based_Virtual_Machine) 友好性,意味着你能够从运行在 VM 中的应用和线程上以 10 Gbit 线速发送/接收 packets ,而无需使用类似 `PCIe passthrough` 这种技术;需要注意的是,同一种应用可以不做任何修改的运行在 VM 和物理机上:我们真的真的让 VM 和 ZC 之间成为了好基友; 17 | - 与其它网络框架类似,例如 [Click Modular Router](http://read.cs.ucla.edu/click/click) ,我们提供了诸如 queue, pool, worker 这类简单组件用于保证通过几行代码构建应用程序; 18 | - API 已经被简化和重写过了;例如,仅使用 6 行代码你就能够创建一个 traffic aggregator 和 balancer (详见[示例程序](https://github.com/ntop/PF_RING/blob/dev/userland/examples_zc/README.examples)); 19 | - 当工作在 kernel-bypass 模式下时,我们允许你和 IP stack 进行交互,并向其发送 packets 或从其获取 packets ;这可以简化既需要满足线速要求,又(有时)需要和主机 IP stack 交互的应用程序的开发过程; 20 | - 当和低速(low-speed)设备进行交互时(例如 WiFi 适配器),我们能够采用 one-copy-mode 方式进行操作,或者允许未被提供 accelerate drivers 的 NICs 同样从 ZC 中受益:当 packet 进入 ZC 时,仅存在一次拷贝行为,然后没有然后了; 21 | - 针对 no-for-profit 群众和研究机构,我们免费提供产品供使用;针对商业客户,我们简化了 license 模型,因此仅需要一个 license(不再是之前的两个,一个针对 DNA ,一个针对 Libzero ,因此现在您可以享受更低的 license 费用); 22 | - 我们期望这项技术能够普及起来,因此你只会在使用 accelerated drivers 时需要 license ,而对于所有其它东东(例如 KVM 和 one-copy 支持),你都能够免费使用,无需 license ; 23 | 24 | 如果你想要测试 PF_RING ZC ,最好的方式是:阅读这个 [quick start guide](https://github.com/ntop/PF_RING/blob/dev/userland/examples_zc/README.quickstart) ; 25 | 26 | 27 | ## FAQ 28 | 29 | Q. **PF_RING ZC 的性能如何?** 30 | A. 线速,任意 packet 大小,multi 10 Gbit ;你可以使用各种 apps 进行测试,例如 `zcount` 和 `zsend` ; 31 | 32 | Q. **是否仍旧对 DNA 和 Libzero 进行支持?** 33 | A. 就目前而言,我们会继续支持 DNA/Libzero ,尽管未来会是 PF_RING ZC 的天下,因为后者提供了许多新特性和一致的 API ; 34 | 35 | Q. **PF_RING ZC 是否会支持 legacy applications ,例如那些基于 libpcap 开发的应用?** 36 | A. 会的,一切和其前任 DNA 一样,我们支持 pcap-based 应用程序,以及诸如基于 PF_RING DAQ 实现的 Snort 等其它 apps ; 37 | 38 | Q. **我应该如何打开一个 PF_RING ZC/libpcap 中的 queue ?** 39 | A. 你可以使用如下语法实现:“`zc:@`” ;例如:`pcount -i zc:4@0` 40 | 41 | Q. **What adapters feature native ZC drivers?** 42 | A. 我们当前支持了 Intel 适配器(1 和 10 Gbit)使用 zero-copy 模式,以及所有基于 1-copy 模式的其它适配器;需要记住的是,一旦 packets 被搬移到了 ZC 的世界,你就能够将它们以 zero-copy 模式传递给任意数量的应用程序、线程和 VMs 了;重点是,你只需在入口处支付 "copy ticket" ; 43 | 44 | Q. **How do you position ZC with respect to other technologies such as DPDK?** 45 | A. DPDK 主要面向的是贴近硬件的应用开发者,即对 X86 架构细节很熟悉的人,能够并愿意使用十六进制的 PCI ID (例如 0d:01.0)调用网络接口;对于 PF_RING ZC 的使用者来说,设备调用可以通过其名字(例如 eth1)完成,PF_RING ZC 负责管理所有底层(low-level)细节信息,因此你就可以无阻碍的运行你已有的 pcap-based 应用;ZC 是一种开发者友好的技术; 46 | -------------------------------------------------------------------------------- /Linux/PF_RING/PF_RING User's Guide.md: -------------------------------------------------------------------------------- 1 | # PF_RING User's Guide 2 | 3 | > 原文地址:[这里](https://github.com/ntop/PF_RING/wiki) 4 | 5 | PF_RING 的定位是高速的 packet 捕获库,其可将常见的商用(commodity)PC 转变成高效、廉价的网络测量设备(network measurement box),适用于 packet 和活动 traffic 的分析和操控;更进一步,PF_RING 打开了一个全新的市场,因为其实现了基于数行代码令诸如 traffic balancers 或 packet filters 这类高效率应用程序的创建成为了可能; 6 | 7 | 更多信息详见 [Vanilla PF_RING](https://github.com/moooofly/MarkSomethingDown/blob/master/Linux/Vanilla%20PF_RING.md) 和 [PF_RING ZC](https://github.com/moooofly/MarkSomethingDown/blob/master/Linux/PF_RING%20ZC.md) ; 8 | 9 | 针对 PF_RING 所支持的 NICs 的比较,详见[这里](https://github.com/ntop/PF_RING/wiki/Drivers-and-Modules); 10 | 11 | 12 | PF_RING 用户手册目录: 13 | 14 | * [Vanilla PF_RING](https://github.com/moooofly/MarkSomethingDown/blob/master/Linux/Vanilla%20PF_RING.md) 15 | * [PF_RING ZC](https://github.com/moooofly/MarkSomethingDown/blob/master/Linux/PF_RING%20ZC.md) 16 | * [Source Code Compilation/Installation](https://github.com/moooofly/MarkSomethingDown/blob/master/Linux/PF_RING%20Installation.md) 17 | * [Packages Installation](https://github.com/ntop/PF_RING/blob/dev/doc/README.apt_rpm_packages.md) 18 | * [Drivers/Modules](https://github.com/ntop/PF_RING/wiki/Drivers-and-Modules) 19 | * [Accolade](https://github.com/ntop/PF_RING/blob/dev/doc/README.accolade.md) 20 | * [Endace DAG](https://github.com/ntop/PF_RING/blob/dev/doc/README.dag.md) 21 | * [Exablaze](https://github.com/ntop/PF_RING/blob/dev/doc/README.exablaze.md) 22 | * [Fiberblaze](https://github.com/ntop/PF_RING/blob/dev/doc/README.fiberblaze.md) 23 | * [Myricom](https://github.com/ntop/PF_RING/blob/dev/doc/README.myricom.md) 24 | * [Napatech](https://github.com/ntop/PF_RING/blob/dev/doc/README.napatech.md) 25 | * [Stack](https://github.com/ntop/PF_RING/blob/dev/doc/README.stack.md) 26 | * [Timeline](https://github.com/ntop/PF_RING/blob/dev/doc/README.timeline.md) 27 | * [nBPF](https://github.com/ntop/PF_RING/blob/dev/userland/nbpf/README.md) 28 | * [FM10K](https://github.com/ntop/PF_RING/blob/dev/userland/nbpf/README.fm10k.md) 29 | * VM Support 30 | * [PCI Passthrough](https://github.com/ntop/PF_RING/blob/dev/doc/README.virsh_hostdev.md) 31 | * [ZC on QEMU/KVM](https://github.com/ntop/PF_RING/blob/dev/doc/README.kvm_zc.md) 32 | * 3rd Party Integration 33 | * [Bro](https://github.com/ntop/PF_RING/blob/dev/doc/README.bro.md) 34 | * [Suricata](https://github.com/ntop/PF_RING/blob/dev/doc/README.suricata.md) 35 | * [Wireshark](https://github.com/ntop/PF_RING/blob/dev/userland/wireshark/extcap/README.md) 36 | * Misc 37 | * [RSS](https://github.com/moooofly/MarkSomethingDown/blob/master/Linux/RSS_Receive%20Side%20Scaling.md) 38 | * [Hugepages](https://github.com/ntop/PF_RING/blob/dev/doc/README.hugepages.md) 39 | * [Docker](https://github.com/ntop/PF_RING/blob/dev/doc/README.docker.md) 40 | * [DNA to ZC Migration](https://github.com/ntop/PF_RING/blob/dev/doc/README.DNA_to_ZC.md) 41 | * [API Documentation](http://www.ntop.org/pfring_api/files.html) 42 | -------------------------------------------------------------------------------- /Linux/PF_RING/PF_RING and Transparent Mode.md: -------------------------------------------------------------------------------- 1 | # [PF_RING and Transparent Mode](http://www.ntop.org/pf_ring/pf_ring-and-transparent-mode/) 2 | 3 | PF_RING 被设计用以增强 packet 捕获性能;这意味着需要在 RX path 上进行加速,而常常被使用的一种方式就是减少从适配器到用户态 packet 所经过的“旅途”;这可以通过允许驱动程序将 packet 直接从 NIC 推送到 PF_RING 实现,即不再经过通常的 kernel path ;基于这个原因,PF_RING 引入了一个名为 “transparent mode” 的选项,其目的就是用于调节(tune)packets 从 NIC 搬移到 PF_RING 的方式;该选项(可以在基于 `insmod` 添加 PF_RING 模块时指定)可以设置如下三种值: 4 | 5 | - **`insmod pf_ring.ko transparent_mode=0`** 6 | 默认值,意味着 packets 是通过标准内核机制(NAPI)发送到 PF_RING 中的(即经过标准 kernel path);在该设置下,packets 会被发送给 PF_RING 和所有其它内核组件(不确定这里理解的是否正确);所有 NIC drivers 都支持该模式; 7 | 8 | - **`insmod pf_ring.ko transparent_mode=1`** 9 | 在该模式下,packets 是由 NIC driver 直接发送到 PF_RING 中的,但 packets 同样会被传递给其它内核组件(通过发送 packets 到 NAPI 实现);在该模式下,packet 捕获能被加速的原因是,packets 从 NIC driver 中被拷贝出去时,无需经过常规的 kernel path ;需要注意的是,为了使能该模式,你必须使用支持 PF_RING 的 NIC driver ;可用的 PF_RING-enabled drivers 已放在了 `drivers/` 目录中; 10 | 11 | - **`insmod pf_ring.ko transparent_mode=2`** 12 | 在该模式下,packets 是由 NIC driver 直接发送给 PF_RING 的,但不会发给所有其它内核组件(因为会拖慢 packet 捕获过程);需要注意的是: 13 | - 为了使能该模式,你必须使用支持 PF_RING 的 NIC driver ; 14 | - Packets 在被投递给(delivered)PF_RING 后不会再被发送到 kernel ;这意味着你将无法从基于 PF_RING-aware drivers 的 NICs 获取到活动性信息(connectivity); 15 | - 该模式是最快的方式,因为 packets 会以最快的速度拷贝给 PF_RING ,并在得到处理后立即丢弃; 16 | 17 | ------ 18 | 19 | # [PF_RING and transparent_mode](http://www.ntop.org/pf_ring/pf_ring-and-transparent_mode/) 20 | 21 | 许多 PF_RING 用户都知道为了不对 Linux kernel 打补丁,从 PF_RING 4.x 开始 packets 是通过 NAPI 机制进行接收的;这意味着 packet 的 journey 与标准 Linux 中的路径一样;因此,相对 vanilla Linux 的性能改进也是很微小的(< 5%),尽管 PF_RING 允许完成很多标准 AF_PACKET 之外的事; 22 | 23 | 为了大幅改进的性能,PF_RING 支持了一个名为 `transparent_mode` 的参数,可在进行内核模块加载时使用,如 `insmod pf_ring.ko transparent_mode=X` ,其中 X 的值可以为 0, 1 或 2 ;具体含义会随着你所 hook 的 PF_RING-based 应用(例如 `pfcount` )的、接口 NIC driver 的不同而有所变化;因此,很可能在一个接口上你使用的是标准驱动,而在另外的接口上你使用的是 PF_RING-aware 驱动;当前,所有支持的 PF_RING-aware 驱动都保存在 `PF_RING/drivers` 目录下,除了 `TNAPI` ;需要注意的是,针对 DNA 驱动的情况,由于 kernel 被完全旁路掉了,故 `transparent_mode` 参数将不起作用; 24 | 25 | 26 | Mode | Standard driver | PF_RING-aware driver | Packet Capture Acceleration 27 | ---|---|---|--- 28 | 0 | Packets are received through Linux NAPI | Packets are received through Linux NAPI | Same as Vanilla Linux 29 | 1 | Packets are received through Linux NAPI | Packets are passed to NAPI (for sending them to PF_RING-unaware applications) and copied directly to PF_RING for PF_RING-aware applications (i.e. PF_RING does not need NAPI for receiving packets) | Limited 30 | 2 | The driver sends packets only to PF_RING so PF_RING-unaware applications do not see any packet | The driver copies packets directly to PF_RING only (i.e. NAPI does not receive any packet) | Extreme 31 | 32 | 33 | -------------------------------------------------------------------------------- /Linux/PF_RING/PF_RING 家族史.md: -------------------------------------------------------------------------------- 1 | # PF_RING 家族史 2 | 3 | > 参考自:[这里](http://jasonzhuo.com/pfring-and-jnetpcap/) 4 | 5 | ## PF_RING 简介 6 | 7 | PF_RING 是 Luca Deri 发明的、基于提高内核处理数据包效率,进而改善网络数据包捕获程序(如 libpcap 和在其上的 tcpdump 等)的东东。PF_RING 是一种新型的网络 socket ,它可以极大的改进包捕获的速度。 8 | 9 | ### 术语 10 | 11 | - **NAPI**:NAPI 是 Linux 新的网卡数据处理 API ,NAPI 是一种综合了中断与轮询两种方式的技术;NAPI 在高负载的情况下可以产生更好的性能,它避免了为每个传入的数据帧都产生中断。详情可以参考[这里](http://blog.csdn.net/zhangskd/article/details/21627963); 12 | - **Zero copy (ZC)**:简单一点来说,零拷贝就是一种避免 CPU 将数据从一块存储拷贝到另外一块存储的技术; 13 | - **NPU**:网络处理单元; 14 | - **DMA**:即 Direct Memory Access ,直接内存存取;它允许不同速度的硬件装置来沟通,而不需要依赖于 CPU 的大量中断负载; 15 | - **Linux 网络栈**:如下图所示,它简单地为用户空间的应用程序提供了一种访问内核网络子系统的方法; 16 | 17 | ![Linux 网络栈](https://raw.githubusercontent.com/moooofly/ImageCache/master/Pictures/Linux%20%E7%BD%91%E7%BB%9C%E6%A0%88.gif "Linux 网络栈") 18 | 19 | 20 | ## libpcap 抓包原理 21 | 22 | libpcap 的包捕获机制就是**在数据链路层加一个旁路处理**。当一个数据包到达网络接口时,libpcap 首先利用已经创建的 Socket 从链路层驱动程序中获得该数据包的拷贝,再通过 **Tap 函数**将数据包发给 **BPF 过滤器**。BPF 过滤器根据用户已经定义好的过滤规则对数据包进行逐一匹配,匹配成功则放入内核缓冲区(一次拷贝),并传递给用户缓冲区(又一次拷贝),匹配失败则直接丢弃。如果没有设置过滤规则,所有数据包都将放入内核缓冲区,并传递给用户层缓冲区。 23 | 24 | ![Libpcap 的包捕获机制](https://raw.githubusercontent.com/moooofly/ImageCache/master/Pictures/Libpcap%20%E7%9A%84%E5%8C%85%E6%8D%95%E8%8E%B7%E6%9C%BA%E5%88%B6.png "Libpcap 的包捕获机制") 25 | 26 | 在高速复杂网络环境下 **libpcap 丢包的原因**主要有以下两个方面: 27 | 28 | - Cpu 处于频繁中断状态,造成接收数据包效率低下; 29 | - 数据包被多次拷贝,浪费了大量时间和资源。从网卡驱动到内核,再从内核到用户空间; 30 | 31 | 32 | ### 为啥用 PF_RING 呢 33 | 34 | 随着信息技术的发展,1 Gbit/s,10 Gbit/s 以及 100 Gbit/s 的网络会越来越普及,那么**零拷贝技术**也会变得越来越普及,这是因为网络链接的处理能力比 CPU 的处理能力的增长要快得多。高速网络环境下,CPU 就有可能需要花费几乎所有的时间去拷贝要传输的数据,而没有能力再去做别的事情,这就产生了性能瓶颈。 35 | 36 | ## PF_RING 驱动家族 37 | 38 | ### PF_RING DNA (Direct NIC Access) 39 | 40 | 对于那些希望在 CPU 利用率为 0%(拷贝包到主机)的情况下,想要最大化数据包捕获速度的用户来说,可以使用 **DNA (Direct NIC Access)** 驱动;它允许数据直接从网络接口上读取,它以**零拷贝**的方式**同时绕过 Linux 内核和 PF_RING 模块**。 41 | 42 | 左图解释:**Vanilla PF_RING** 从 NIC 上通过 Linux NAPI 获取数据包拷贝,拷贝到 PF_RING 的 环状缓存空间。然后用户空间的应用程序会从该环状缓存空间中读取数据包。从图中可以看出 Vanilla PF_RING 方式有**两次 polling 操作**:一次是从 NIC 到 PF_RING 环状缓存空间(Linux 内核里面),另外一次从 PF_RING 环状缓存空间到用户程序。 43 | 44 | 左图中的实现(即 Vanilla PF_RING)相对于传统方式来说,由于 Application 使用的是**基于 `mmap` 的 libpcap 版本**,会较标准版本的 libpcap 效率更高。**libpcap 标准版**是目前使用最多的、用于从内核拷贝数据包到用户层的库,而 libpcap-mmap 是 libpcap 的一个改进版本。**传统 libpcap** 使用固定大小的**存储缓冲器**和**保持缓冲器**来完成数据包从内核到用户层的传递,而 **libpcap-mmap** 设计了一个大小可以配置的循环缓冲器,允许用户程序和内核程序同时对该循环缓冲器的不同数据区域进行直接的读取。其次,PF_RING 使用的是 NAPI ,而不是(标准)传统 libpcap 中基于 **DMA** 方式(调用系统函数 `netif_rx()`)将数据包从网卡拷贝到内核缓存。 45 | 46 | 右图解释:在 DNA 模式下,会通过 NIC 的 NPU 拷贝数据包到**网卡上的缓存空间**。然后直接通过 DMA 方式到用户层,同时**绕过了 PF_RING 模块和 Linux 内核缓存**。官网已经证明了 DNA 方式能有更快的处理速率 Performance 。 47 | 48 | ![PF_RING DNA (Direct NIC Access)](https://raw.githubusercontent.com/moooofly/ImageCache/master/Pictures/PF_RING%20DNA%20\(Direct%20NIC%20Access\).png "PF_RING DNA (Direct NIC Access)") 49 | 50 | 让人多少有点遗憾的是,该方式并不是可以随意使用的;根据其 License 说明,提供免费下载但是以二进制形式提供测试版本的库(也就是说使用 5 分钟或者达到一定包的处理数量之后软件就停了),如果需要长期使用,需要购买解锁的代码。 51 | 52 | ``` 53 | ERROR: You do not seem to have a valid DNA license for eth0 [Intel 1 Gbit e1000e family]. We're now working in demo mode with packet capture and transmission limited to 0 day(s) 00:05:00 54 | ``` 55 | 56 | 关于传统数据发送的整个过程,可以看《[Linux 中的零拷贝技术](https://www.ibm.com/developerworks/cn/linux/l-cn-zerocopy1/)》; 57 | 58 | ### PF_RING-aware drivers (ZC support) 59 | 60 | 根据官方手册介绍: 61 | 62 | > An interface in ZC mode provides the same performance as DNA. 63 | 64 | PF_RING ZC 和 PF_RING DNA 实际上都是**绕过 Linux 内核和 PF_RING 模块**的方式,因此在这些模式下 Linux 内核将看不到任何数据包。 65 | 66 | ### PF_RING ZC 67 | 68 | 关于 PF_RING ZC,PF_RING DNA,PF_RING-aware drivers 之间的关系是有点乱的,不太容易分清楚。 69 | 70 | > "It can be considered as the successor of DNA/LibZero that offers a single and consistent API implementing simple building blocks (queue, worker and pool) that can be used from threads, applications and virtual machines." 71 | > 72 | > "PF_RING ZC comes with a new generation of PF_RING aware drivers." 73 | 74 | ### 相互关系 75 | 76 | - PF_RING ZC 的 API 更友好; 77 | - PF_RING ZC 模块可以看做是 DNA/LibZero 的后继者; 78 | - PF_RING ZC 和 PF_RING DNA 都是**绕过 Linux 内核和 PF_RING 模块**的方式,在这些模式下 Linux 内核将看不到任何数据包; 79 | 80 | 81 | ## PF_RING 工作模式 82 | 83 | PF_RING 有三种工作模式(对应 `transparent_mode` 的不同值): 84 | 85 | - 为 0 时,走的是 Linux 标准的 NAPI 包处理流程; 86 | - 为 1 时,包既走 Linux 标准包处理流程,也 copy 给 PR_RING 一份; 87 | - 为 2 时,驱动只将包拷贝给 PF_RING ,内核不会接收到这些包; 88 | 89 | 1 和 2 模式需要 PF_RING-aware 的网卡驱动支持。 90 | 91 | 另外: 92 | 93 | - 默认为 `transparent=0` ,数据包通过标准的 linux 接口接收,任何驱动都可以使用该模式; 94 | - `transparent=1`(用于 Vanilla PF_RING 和 PF_RING-aware 驱动程序),数据包分别拷贝到 PF_RING 和标准 linux 网络协议栈各一份; 95 | - `transparent=2`(用于 PF_RING-aware 驱动程序),数据包仅拷贝到 PF_RING ,而不会拷贝到标准的 linux 网络协议栈(即 tcpdump 不会看到任何数据包); 96 | 97 | 不要同时使用模式 1 和模式 2 到 Vanilla 驱动,否则将会抓到任何数据包。 98 | 99 | ## PF_RING 包过滤 100 | 101 | Vanilla PF_RING 支持传统的 BPF 过滤器,由于 DNA 模式下,不再使用 NAPI Poll ,所以 PF_RING 的数据包过滤功能就不支持了;目前可以使用硬件层数据包过滤的只有 intel 的 82599 网卡支持。 -------------------------------------------------------------------------------- /Linux/PF_RING/PF_RING 杂七杂八.md: -------------------------------------------------------------------------------- 1 | # PF_RING 杂七杂八 2 | 3 | ## [How to capture from a bond interface using PF_RING ZC?](http://www.ntop.org/support/faq/how-to-capture-from-a-bond-interface-using-pf_ring-zc/) 4 | 5 | 由于 PF_RING ZC 是一种内核旁路(kernel-bypass)技术,并且应用程序会直接访问网卡,因此不可能从 bond 设备上进行捕获操作,然而你能够在 ZC 模式下直接从多个接口上聚合(aggregate)traffic ,详见示例 `zbalance_ipc -i zc:ethX,zc:ethY` ; 6 | 7 | ## [ZC is faster than DNA because ZC does no copy, but DNA does?](http://www.ntop.org/support/faq/zc-is-faster-than-dna-because-zc-does-no-copy-but-dna-does/) 8 | 9 | 性能是相近的,但基于 Zero-Copy 的 ZC 提供了更高的灵活性(提供了 sw queues, multi-process 和 multi-vm 支持等等); 10 | 11 | ## [Do DNA and ZC have any relationship , dependence, or they are completely isolated technologies?](http://www.ntop.org/support/faq/do-dna-and-zc-have-any-relationship-dependence-or-they-are-completely-isolated-technologies-2/) 12 | 13 | 完全不相关; 14 | 15 | ## [What is the PF_RING ZC distribution format?](http://www.ntop.org/support/faq/why-is-the-pf_ring-dna-distribution-format/) 16 | 17 | PF_RING ZC 由两部分构成:kernel drivers 和 user-space library;内核驱动以源码格式作为 PF_RING 的一部分发布,而用户空间库以二进制格式发布,并且要求 per-MAC licenses ; 18 | 19 | 20 | ## [Modern Packet Capture and Analysis: Multi-Core, Multi-Gigabit, and Beyond](http://www.ntop.org/pf_ring/modern-packet-capture-and-analysis-multi-core-multi-gigabit-and-beyond/) 21 | 22 | - 对于每一个想要使用 PF_RING 获取 packet 捕获加速能力的人来说,都应该阅读这个 [pdf 文档](http://luca.ntop.org/IM2009_Tutorial.pdf); 23 | - 如今,packet 捕获过程中的最大成本耗费已经受限于 packet 分析速度了; 24 | - 由于上述原因,您应该将 PF_RING 作为框架用以创建简单、但强大的 traffic 监控应用程序; 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /Linux/PF_RING/PF_RING.xmind: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moooofly/MarkSomethingDown/3ed8d77b34dfb893b865932086065265876e3bc6/Linux/PF_RING/PF_RING.xmind -------------------------------------------------------------------------------- /Linux/PF_RING/PF_RING_homepage.md: -------------------------------------------------------------------------------- 1 | # PF_RING 2 | 3 | > 原文地址:[这里](http://www.ntop.org/products/packet-capture/pf_ring/) 4 | 5 | ## High-speed packet capture, filtering and analysis. 6 | 7 | PF_RING™ 是一种新型网络 socket ,能够极大到提高 packet 捕获速度,其具有以下特性: 8 | 9 | - 可用于 kernel 2.6.32 及之后的版本; 10 | - 无需对 kernel 打 patch :只需加载 kernel 模块; 11 | - 采用(常用的)商用网络适配器就可提供 10 Gbit 的 [Hardware Packet Filtering](http://www.ntop.org/products/packet-capture/pf_ring/hardware-packet-filtering/) 能力; 12 | - 支持用户空间 [ZC](http://www.ntop.org/products/packet-capture/pf_ring/pf_ring-zc-zero-copy/) (新一代 DNA, Direct NIC Access) drivers ;在通过 NIC NPU (Network Process Unit) 将 packets 推到(pushing to)用户空间时,或者从用户空间获取(getting from)时,即便处于极端的 packet 捕获/传输速度情况下,也不需要任何形式的 kernel 干预;使用 10Gbit ZC driver 后,对于任何大小的 packet ,你都可以按照 wire-speed 发送或接收; 13 | - [PF_RING ZC](http://www.ntop.org/products/packet-capture/pf_ring/pf_ring-zc-zero-copy/) 库可用于以 zero-copy 方式跨 threads, applications, Virtual Machines 进行 packets 分布; 14 | - 设备驱动无关(independent); 15 | - 支持 Myricom, Intel 及 Napatech 的网络适配器; 16 | - Kernel-based 的 packet 捕获和抽样; 17 | - 支持 Libpcap ,可无缝集成已存在 pcap-based 应用; 18 | - 除 BPF 外,还可以指定数以百计的 header filters ; 19 | - 支持内容检视(Content inspection)功能,因此只有满足 payload filter 规则的 packets 才能通过; 20 | - 可以通过 PF_RING™ 插件支持高级 packet 解析和内容过滤; 21 | 22 | 更多 PF_RING™ 的内部实现可以查看[用户手册](http://www.ntop.org/support/documentation/documentation/); 23 | 24 | 25 | > - Napatech 是提供网络管理和安全应用数据交付解决方案的全球领导者。随着数据量增多、复杂性增大,组织必须对流经其网络的信息进行监控、编译和分析。产品使用专利技术,能高速捕获和处理大量数据,同时保证性能并实现实时可见性; 26 | > - Myricom 是著名的网络设备供应商,是为垂直市场应用提供高性能、低延时优化以太网解决方案的行业领导者;Myricom 在低延时、高包速率、垂直应用优化方面做的很好;Myri-10G 网络适配器具有低延迟、高带宽及 CPU 资源占用低的特点,能提供终极性能的以太网及 Myricom 专业软件平台; 27 | 28 | ## Vanilla PF_RING™ 29 | 30 | PF_RING™ 是基于 Linux NAPI 从 NICs 中进行 packets 轮询;这意味着 NAPI 会从 NIC 中拷贝 packets 到 PF_RING™ 的 circular buffer ,之后用户态应用程序再从该 ring 中读取这些 packets ;在这种场景下,存在两次轮询动作,即应用和 NAPI 各一次,这就会导致一些 CPU 时钟周期在轮询中被耗费掉了;而这种实现方式的好处就是:PF_RING™ 能够将进入的 packets 同时分发到多个 rings 中(对应多个应用); 31 | 32 | ![vanilla_pf_ring](https://raw.githubusercontent.com/moooofly/ImageCache/master/Pictures/vanilla_pf_ring.png "vanilla_pf_ring") 33 | 34 | ## PF_RING™ Modules 35 | 36 | PF_RING™ 实现了模块化架构(modular architecture),因此它能够使用除 PF_RING™ 这个 kernel 模块外的额外组件;当前,可用的其他模块包括: 37 | 38 | - ZC module. 39 | 详情查看 [ZC](http://www.ntop.org/products/packet-capture/pf_ring/pf_ring-zc-zero-copy/) 页面说明; 40 | - Accolade module. 41 | 该模块在 PF_RING™ 中为 Accolade cards 增加了本地支持; 42 | - Endace module. 43 | 该模块在 PF_RING™ 中为 Endace DAG cards 增加了本地支持; 44 | - Exablaze module. 45 | 该模块在 PF_RING™ 中为 Exablaze cards 增加了本地支持; 46 | - Fiberblaze module. 47 | 该模块在 PF_RING™ 中为 Fiberblaze cards 增加了本地支持; 48 | - Myricom module. 49 | 该模块在 PF_RING™ 中为 Myricom 10 Gbit cards 增加了本地支持; 50 | - Napatech module. 51 | 该模块在 PF_RING™ 中为 Napatech cards 增加了本地支持; 52 | - Stack module. 53 | 该模块可用于向 linux 网络协议栈中 inject packets ; 54 | - Timeline module. 55 | 该模块可通过使用 PF_RING™ API 从 `n2disk` dump set 中无缝提取 traffic ; 56 | - Sysdig module. 57 | 该模块使用 sysdig 内核模块捕获系统事件; 58 | 59 | ![PF_RING](https://raw.githubusercontent.com/moooofly/ImageCache/master/Pictures/PF_RING-modules.jpeg "PF_RING") 60 | 61 | ## Who needs PF_RING™? 62 | 63 | 一般来讲,任何需要面对 pps 比较高(many)情况的都需要;术语 ‘many’ 的含义针对你所使用的、用于 traffic 分析的不同硬件含义有所不同;可能从 1,2GHz ARM 上的 80k pkt/sec 变化成 low-end 2,5GHz Xeon 上的 14M pkt/sec 及以上的速度; PF_RING™ 不仅为你提供了更快的 packets 捕获速度,还保证了 packets 捕获的高效(减少对 CPU cycles 的浪费); 64 | -------------------------------------------------------------------------------- /Linux/PF_RING/Quick Start Guide (PF_RING).md: -------------------------------------------------------------------------------- 1 | # Quick Start Guide 2 | 3 | > 原文地址:[这里](https://github.com/ntop/PF_RING/blob/dev/userland/examples_zc/README.quickstart) 4 | 5 | - 加载 PF_RING 内核模块 6 | 7 | ```shell 8 | $ cd PF_RING/kernel; make 9 | $ insmod pf_ring.ko 10 | ``` 11 | 12 | - 加载 PF_RING ZC-aware 驱动,用于 zero-copy Direct NIC Access ,以及任何其它工作在 1-copy 模式(zc 设备模拟)下的驱动;PF_RING ZC-aware 驱动位于 `drivers/PF_RING_aware` 目录下(带有 '`-zc`' 后缀) 13 | 14 | ``` 15 | $ cd PF_RING/drivers/PF_RING_aware/intel/ixgbe/ixgbe-3.18.7-zc/src; make 16 | $ ./load_driver.sh 17 | ``` 18 | 19 | - 使能并挂在足够的 hugepages ,因为内存分配时需要(详情阅读 `PF_RING/README.hugepages`);注意:hugepages 可以通过用来加载驱动程序的 `load_driver.sh` 脚本自动初始化; 20 | 21 | ``` 22 | $ echo 1024 > /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages 23 | $ mkdir /dev/hugepages 24 | $ mount -t hugetlbfs nodev /dev/hugepages 25 | ``` 26 | 27 | - 运行众多 PF_RING ZC 示例应用程序之一;请为每一个应用程序使用一个唯一的 cluster id(除非你使用的时 multi-process 应用); 28 | 29 | ``` 30 | $ cd PF_RING/userland; make 31 | $ cd examples_zc 32 | $ ./zcount -i zc:eth1 -c 1 33 | ``` 34 | 35 | 如果你的 eth1 和 eth2 时 cross connected 的,你可以执行 36 | 37 | ``` 38 | $ ./zcount -i zc:eth1 -c 1 39 | $ ./zsend -i zc:eth2 -c 2 40 | ``` 41 | 42 | 详情参考应用程序的 help (-h) 描述; 43 | -------------------------------------------------------------------------------- /Linux/PF_RING/Receive Side Scaling (PF_RING).md: -------------------------------------------------------------------------------- 1 | # RSS (Receive Side Scaling) 2 | 3 | > 原文地址:[这里](https://github.com/ntop/PF_RING/blob/dev/doc/README.RSS.md) 4 | 5 | 几乎所有 Intel(以及其它厂商)的 NICs 都支持 RSS ,这意味着**可以基于硬件针对 packets 进行哈希运算以便在多条 RX queues 中进行负载分布(distribute)**; 6 | 7 | 为了配置 queues 数量,你可以在调用 `insmod` 时使用 `RSS` 参数(如果你是基于 packages 安装的 PF_RING ZC drivers ,则可以使用配置文件进行配置,详情参见 `README.apt_rpm_packages` 说明),并传递一个逗号分隔的数字(每个接口上的 queue 数目)列表(每个接口对应一个列表),例如: 8 | 9 | 针对每个接口使能与处理器数量相同的 queue : 10 | 11 | ``` 12 | insmod ixgbe.ko RSS=0,0,0,0 13 | ``` 14 | 15 | 每个接口使能 4 个 RX queues : 16 | 17 | ``` 18 | insmod ixgbe.ko RSS=4,4,4,4 19 | ``` 20 | 21 | 去使能 multiqueue 功能(每个接口 1 个 RX queue): 22 | 23 | ``` 24 | insmod ixgbe.ko RSS=1,1,1,1 25 | ``` 26 | 27 | 另外,还可以运行时基于 `ethtool` 配置 RX queues 数量: 28 | 29 | ``` 30 | ethtool --set-channels combined 1 31 | ``` 32 | 33 | RSS 基于 IP-based 或 IP/Port-based (TCP) 哈希函数在指定数目的 RX queues 上进行负载分发,同时会结合一个 indirection 表:`queue = indirection_table[hash(packet)]` ;你可以通过如下命令查看 indirection table 的内容: 34 | 35 | ``` 36 | ethtool -x 37 | ``` 38 | 39 | 可以使用 `ethtool` 进行 indirection table 配置:即针对每一个 RX queue 简单设置一个 weights 值;例如,如果我们希望全部 traffic 都走向 queue 0 中,则我们可以通过如下命令配置具有 4 个 RX queues 的卡: 40 | 41 | ``` 42 | ethtool -X weight 1 0 0 0 43 | ``` 44 | 45 | ## Naming convention 46 | 47 | 为了打开指定接口上的 queue ,你必须通过 "@" 后缀指定 queue ID ,例如: 48 | 49 | ``` 50 | pfcount -i zc:eth1@0 51 | ``` 52 | 53 | 需要注意的是,如果你对一个具有多个 RSS queues 的接口进行配置,并且使用 `zc:eth1` 形式按照使用 ZC 模式打开,则等同于 `zc:eth1@0` 形式打开;这种方式不适用于标准内核模式,因为其对接口进行了抽象并从 eth1 上进行捕获,而这意味着从所有 queues 进行捕获;发生这种情况对原因在于 ZC 是一种 kernel-bypass 技术,因此不存在抽象层,故应用将直接打开接口上的 queue ,即对应了当 RSS=1 时的 full interface ; -------------------------------------------------------------------------------- /Linux/PF_RING/Vanilla PF_RING.md: -------------------------------------------------------------------------------- 1 | # Vanilla PF_RING 2 | 3 | > 原文地址:[Vanilla PF_RING](https://raw.githubusercontent.com/ntop/PF_RING/dev/doc/README.vanilla.md) 4 | 5 | ------ 6 | 7 | Vanilla PF_RING 的构成: 8 | 9 | 1. 内核加速模块(the accelerated kernel module),在 low-level 层次上提供了将 packet 拷贝到 PF_RING rings 的功能; 10 | 2. 用户空间 PF_RING SDK ,为用户空间应用程序提供了针对 PF_RING 的透明支持; 11 | 12 | PF_RING 实现了一种 socket 类型,基于该 socket 类型实现了用户空间应用程序直接与 PF_RING 内核模块进行“对话”的能力; 13 | 14 | 应用程序可以通过获取到的 PF_RING 句柄发起各种 API 调用; 15 | 16 | 该句柄可以绑定到: 17 | 18 | 1. 物理网络接口; 19 | 2. 某个 RX queue ,仅在 multi-queue 网络适配器上允许; 20 | 3. 名为 'any' 的虚拟接口,即所有系统接口上的收发包均可被获取; 21 | 22 | 正如上面所说,packets 的(用户态)读取发生在主存环形缓冲区(memory ring)中(创建时分配内存);而 incoming packets 是由内核(驱动)模块负责拷贝到该环形缓冲区的,之后再被用户空间应用所读取;内存的分配和释放并非基于每个 packet 进行,一旦某个 packet 被从环形缓冲区中读取走了,那么之前环形缓冲区中用于保存该 packet 的空间将被用作安放后续其它的 packets ;这就意味着,如果应用想要维护一个 packet archive ,则必须自行保存读取到的所有 packets ,因为 PF_RING 不会为应用做保存; 23 | 24 | ## Packet Filtering 25 | 26 | PF_RING 既支持 legacy **BPF** filters(即那些被 pcap-based 应用,如 tcpdump ,所支持的 filters 规则),也支持两种额外类型的 filters(取名为 **wildcard** 和 **precise** filters ,分别对应了一部分或全部 filter elements 被指定的情况),提供给开发者很多选择可能; 27 | 28 | Filters 是在 PF_RING 模块内部起作用的,即位于 kernel 中;一些现代适配器,例如 Intel 82599-based 或 Silicom Redirector 的 NICs ,支持了基于硬件的 filters ,PF_RING 同样通过特定的 API 调用进行了支持(例如 `pfring_add_hw_rule`);另外,PF_RING filters (除 hw filters 外)能够指定 action ,用于告知 PF_RING 内核模块在发现匹配 filter 的 packet 出现时,将执行何种 action ; 29 | 30 | Actions 包括 31 | 32 | - pass/don’t pass the filter to the user space application 33 | - stop evaluating the filter chain, or 34 | - reflect packet. 35 | 36 | 在 PF_RING 中,`packet reflection` 指的是传输(不做修改)匹配 filter 的 packet 到指定网络接口的能力(此处不包括接收到该 packet 的接口);整个 reflection 功能实现在 PF_RING 内核模块之中,而对于用户空间应用程序来说,唯一能够请求的活动就是设置 filter specification ,因此,是无法针对 packet 进行任何其它处理的; 37 | 38 | ## Packet Clustering 39 | 40 | PF_RING 还能够进一步提升 packet capture 应用的性能,基于已实现的两种机制:**balancing** 和 **clustering** ;这些机制允许一些应用程序(愿意处理一部分划分出来的 packets)只处理整个 packet stream 中的一部分,而将所有其它包发送到 cluster 中的其他成员来处理;这意味着,打开了 PF_RING sockets 的不同应用程序均能够将自身绑定到指定的 cluster Id 上(通过 `pfring_set_cluster`),进而成为包处理“劳动力”,以便对数据包的一部分进行分析处理; 41 | 42 | 在 cluster sockets 中进行 packets 划分的方法是通过 cluster policy 进行指定的,可以指定为(默认值)**per-flow**(即所有的 packets 都归属于相同的五元组 ``)或 **round-robin** ; 43 | 44 | 这意味着,如果你选择的是 per-flow balancing ,那么所有归属相同 flow 的 packets 都将被发送给同一个应用程序;若选择的是 round-robin ,那么所有的应用都将收到相同数量的 packets ,但是不保证归属于相同 queue 的 packets 一定被单独一个应用所接收;因此一方面来讲,per-flow balancing 允许保留(preserve)应用逻辑,因为在这种情况下,应用将只会接收所有 packets 的子集,但保证了 traffic 的一致性(consistent);而另一方面,如果你恰好遇到了某条特定的 flow 汇聚了几乎全部的 traffic 情况,那么处理该 flow 的应用程序将会出现 over-flooded 问题,并且此时 traffic 分布也将严重不均衡; 45 | -------------------------------------------------------------------------------- /Linux/PacketCapture/Comparing and Improving Current Packet Capturing Solutions based on Commodity Hardware.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moooofly/MarkSomethingDown/3ed8d77b34dfb893b865932086065265876e3bc6/Linux/PacketCapture/Comparing and Improving Current Packet Capturing Solutions based on Commodity Hardware.pdf -------------------------------------------------------------------------------- /Linux/PacketCapture/Modern Packet Capture and Analysis_Multi-Core, Multi-Gigabit, and Beyond.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moooofly/MarkSomethingDown/3ed8d77b34dfb893b865932086065265876e3bc6/Linux/PacketCapture/Modern Packet Capture and Analysis_Multi-Core, Multi-Gigabit, and Beyond.pdf -------------------------------------------------------------------------------- /Linux/PacketCapture/NAPI 模式-中断和轮询的折中以及一个负载均衡的问题.md: -------------------------------------------------------------------------------- 1 | # NAPI模式--中断和轮询的折中以及一个负载均衡的问题 2 | 3 | > 原文地址:[这里](http://blog.csdn.net/dog250/article/details/5302853) 4 | > 5 | > 此文解释了很多问题,推荐阅读!! 6 | 7 | 处理外部事件是 cpu 必须要做的事,因为 cpu 和外设的不平等性导致外设的事件被 cpu 当作是外部事件,其实它们是平等的,只不过冯氏机器不这么认为罢了; 8 | 9 | 既然要处理外部事件,那么就需要一定的方法,方法不止一种,大致有**中断**和**轮询**,以及一种混杂又复杂的方式,即 **DMA** 方式。中断是 cpu 被动处理的一种方式,也就是说 cpu 不知道何时中断,只要有了中断就会通知 cpu ,而 cpu 此时必须停下一切来处理,而轮询是 cpu 主动查询并处理的过程,cpu 隔一会查询一下外设看有没有事情可做。 10 | 11 | 我们看一下这两种方式,中断看似很高效,但是却会遗漏一些数据,避免遗漏的机制要么由硬件实现,要么由上层的软件实现;而轮询就没有中断高效了,它会做很多徒劳的操作,而且必须引入暂存机制,就是说由于 cpu 不可能在每次查询硬件的时候正好有事情可做,为了不使请求遗漏,随时到来的请求必须暂存在一个私有的区域内;只要这些都做好了,轮询是不会造成请求遗漏的;**中断模式在中断高频触发的场景中会造成大量遗漏和竞争**,毕竟只有一个 cpu ,同一个时间点只能有一个请求被处理,而轮询由于是 cpu 通过分批打包处理请求的,因此不会遗漏。 12 | 13 | 以上论述有点像我讨论过的基于 inotify 和 rsync 实现的文件同步,inotify 的实现就是中断,很显然有遗漏,而 rsync 实现的就是轮询,显然没有遗漏;cpu 主动做的事情它自己最明白了,但是它要是被动应对就不会这么明白了,它只是按照规则应对罢了,丝毫不会存在任何策略。如果中断过于频繁也是不好的,因为 cpu 必须处理中断,这会导致 cpu 没有时间做正经事,此时最好用轮询,但是在外设活动很缓和的时候,用轮询就不合适了,因为询也是白询,此时比较适合用中断;可是**系统怎么知道何时外设活跃何时外设缓和呢?**啊哈,可以用智能预测算法嘛,以历史值为依据!不,不能那样的,因为这是在内核,内核不是秀算法的地方,我另外的文章强调过这一点。那么怎么办?好办,还是约定,就是将中断和轮询相结合,这就是 Linux 网卡驱动中的 **NAPI 的方式**,它的设计十分巧妙,就是**在第一个包到来的时候中断,然后关闭中断开始轮询,等某一次轮询完毕后发现没有数据了,那么内核默认此次数据已经传输完毕,短时间内不会再有数据了,那么停止轮询,重新开启中断**,这样会减少很多次的中断,虽然某次轮询完毕发现没有数据并不能代表 1ms 以后不会再有数据,但是刚才说了,要想使算法简单,必须做一个合理的约定,人性化的约定,如果说加上判定什么情况下百分之九十五的可能不需要轮询了并不是不可能,只是维护那个算法的开销太大,它直接抵消了算法带来的优势。用人的思想考虑,如果一个饭店的服务员不停的从厨房接菜然后送到餐桌,注意是不停的,10秒一趟,但是突然隔了半分钟没有厨房的人吆喝接菜,如果你是服务员,难道你还会去窗口等菜吗?反正我不会,我会蹲下来稍微休息一下,即使刚蹲下来就会有新活我也愿意赌一把,虽然输得可能性 很大很大。 14 | 15 | 如此一来,我们看一下 **NAPI 解决了什么问题**,第一,它限制了中断的数量,一旦有中断过来就停掉中断改为轮询,这样就不会造成 cpu 被频繁中断,第二,cpu 不会做无用功,就是所谓的无用的轮询,因为只有在中断来了才改为轮询,中断来了说明有事可做;看看 NAPI 将中断和轮询结合的是多么巧妙啊。以往的实现中,**在硬件网卡中断中将 skb 排入队**,然后**在软中断中出队**并交由上层处理,一切配合的看起来那么好,可是在遇到**突发快速小包**传输的时候就会导致频繁中断,因为是突发的包,因此不能用轮询,因为是快速小包,因此不适合用中断,最终二者巧妙结合,各取优势,优势互补,绝了!这个框架适合一切的网卡模式,因此就将传统的网卡收发机制也纳入到了 NAPI 框架,很简单,就是用原来的逻辑实现 dev 的 poll 回调函数即可,至于传统的非 NAPI 方案,完全可以用一个桩子代替。 16 | 17 | cpu 利用率和频繁的中断问题通过 NAPI 机制解决了,但是这又引入了一个新的问题,就是这**可能造成 cpu 利用率的失衡**,这个怎么理解呢?NAPI 启动之后,网卡的(硬件)中断就会变得很少,要知道中断均衡的目前实现是基于中断数量的均衡,它根本不管中断数量均衡之后引起的 softirq 导致的 cpu 使用率是否均衡;softirq 的均衡也是一样,比如一个是磁盘 softirq ,一个是网卡的 NAPI 的 softirq ,前者瞬间就可以完成,但是来得频繁,而后者要轮询网卡并且处理协议栈,很耗时但是来得不频繁,可是 balancer 不管这么多,它只是觉得磁盘的 softirq 太多了,而从数量均衡的角度将更多的 softirq 发布到 softirq 少的 cpu 上,它根本不在乎这些更多的 softirq 是否会带来更高的 cpu 负载。**NAPI 削弱了中断/软中断均衡的作用**,毕竟它的主导在轮询,轮询会占用很多的处理器资源,而导致中断和软中断数量很少。中断或者软中断(特别是软中断)数量在 cpu 间的均衡可能造成各个 cpu 负载的严重不均衡,因为**各个硬中断几乎都是瞬间完成的**,硬中断不能耽搁太久的,但是**各个不同软中断的任务量却是千差万别的**,因此绝对不能按照数量来均衡软中断,然而**一般都是硬中断触发软中断,(并且)它们都在同一个 cpu 上**,因此如果想简单的实现 NAPI 在多 cpu 上的 cpu 使用率均衡,那么必须重新实现硬件的负载均衡机制,这样可以吗?不!因此这样会使得两个部分耦合过重,因此必须让硬中断的均衡和 cpu 的均衡解耦合,其实现在的内核就是这么做的,所以才会造成 cpu 使用率不均衡,**硬件中断的均衡和 cpu 均衡的解耦合带来的好处就是我们可以对软中断均衡做文章**,而硬中断的负载均衡还是用数量均衡实现,软中断彻底从硬件中断中解放出来,不再是直接在处理硬中断的 cpu 上触发软中断,而是可以在任何 cpu 上触发软中断,由于不同软中断的任务量千差万别,因此我们定义一个**软中断的“权值”**,然后按照不同软中断这个权值和数量的积的和来均衡软中断,这样的话,我想各个 cpu 的负载就均衡了,现在问题是,各个不同的软中断的“权值” 的计算问题,呵呵。累了,有时间再说。一个论坛上一哥们儿写了一个 patch,很有创意,比我这里的软中断均衡的粒度要小得多,这个补丁不是均衡软中断,而是将软中断进一步也分成了上下两部分,和 cpu 相关的**上半部**必须加急处理,这样不会对 cpu 造成太大负载,仍然用硬件中断均衡,并且由硬件中断的 cpu 触发软件中断,这部分不变;而软中断的下半部就需要均衡了,该补丁为每一个 cpu 创立了一个工作队列,然后将 `ip_rcv` 这种操作的 cpu 相关的工作放到软中断的上半部,其实就是从一个 cpu 的 skb 队列中抽取一个 skb ,然后将这个 skb 随机放到这些工作队列中进行处理,和整个软中断均衡有何不同吗?大大不同。软中断均衡针对的是一个 `poll_list` 里面的所有的 skb ,而这哥们儿的补丁针对的是一个 skb ,粒度十分小,但是没有测试,是不是太小了呢?这其实也是一个模式方法,逐步的将粒度精细化,类似将中断分成上半部和下半部的做法是放之四海而皆准的,这是一种哲学,也是一种风格。如果你说你没有见过 linux 的这种方式,那么只要你上过枯燥的计算机课或者读过枯燥的教科书或者你是天才你就知道一个叫做生产者/消费者的模型,它其实和 linux 的中断的上半部和下半部很类似,上半部是生产者,只管将环境搭建好,数据准备好,然后触发下半部,其实就是唤醒消费者,这个思想在多线程并发中很著名,而并发就是为了提高系统吞吐量,在 SMP 环境中也是为了并发,因此我们何尝不用用生产者/消费者模型呢?它也是一种低耦合的各司其职的模型。如果 你想不到 NAPI 的中断+轮询的方式,那么你听说过 linux 下怎样做文件同步的吗?`rsync` + `inotify` 的方式听说过吗?如果没有就赶快 google 一下吧。`rsync` + `inotify` 其实就是中断+轮询,`rsync` 是轮询,而 `inotify` 是中断,这个同步方案十分高效,保证只有在 `inotify` 监控到文件变化的时候才开始轮询,平时就睡觉,`inotify` 不再需要监控到具体的文件,因为它只负责告知事件,具体工作由 `rsync` 完成,`inotify` 只需要告诉一端文件变化了即可,那岂不是要全部同步了即使你只改了一个字符,别忘了 `rsync` 的算法,这就是另一篇文章了。所以不要再 觉得 linux 内核深不可测了,它的特点只有一个就是简单,比起用户应用那些复杂的算法,内核的算法一向简单易懂,其实内核的每一个机制,都可以在用户空间找到原型的。 18 | 19 | 可是 cpu 对 NAPI 处理的均衡真的有意义吗?用户难道就不能忍受一个 cpu 占用 100% 而另一个 0% 吗?表面上看是那样的,但是如果考虑 cache 或者切换代价的话就不一样了,性能因素不仅仅是 cpu 使用率,而是还有别的,如果一件事的开销过大,即使 cpu 使用率再均衡也是划不来的。这就好像初学者用 `free` 命令看内存时总是吓一大跳。特别是在 NAPI 处理网络数据包的操作中,比如 TCP 的 IP 包的分段重组问题,一旦乱序就要重传,这种情况下,一个 linux 主机如果只是作为一台路由器的话,那么进入系统的一个 TCP 包的不同分段如果被不同的 cpu 处理并向一个网卡转发了,那么同步问题会很麻烦的,如果你不做同步处理,那么很可能后面的段被一个 cpu 先发出去了,那么在真正的接收方接收到乱序的包后就会请求重发,这是不希望的,因此还是一个 cpu 串行处理好,这也许是 TCP/IP 协议栈的缺陷,但是没有办法,协议是那样的,只能那样去应对。**在大流量下,由于 NAPI 的缘故,网卡的中断被关闭了,此时那个第一次被中断的 cpu 正在 poll 这个网卡,因此所有的流量都会聚集到这个 cpu 上**,这可能是一个设计的缺陷吧。 -------------------------------------------------------------------------------- /Linux/PacketCapture/Packetbeat 配置之 Traffic 捕获选项.md: -------------------------------------------------------------------------------- 1 | # Packetbeat 之 Traffic 捕获选项设置 2 | 3 | > 原文地址:[这里](https://www.elastic.co/guide/en/beats/packetbeat/current/capturing-options.html) 4 | 5 | 存在两种部署 Packetbeat 的方式: 6 | 7 | - 在使用专用服务器(dedicated servers)时,可以通过镜像端口或 tap 设备来获取 traffic ; 8 | - 直接部署在你的应用服务器(application servers)上; 9 | 10 | 第一种方式的巨大优势在于:针对你的应用服务器不会产生任何额外的开销;但其要求专用网络设备(dedicated networking gear)的支持,而这也正是在云端部署时通常不具备的; 11 | 12 | 在上述两种情况下,sniffing 性能(从网络上进行被动包读取)非常重要;对于专用服务器的情况,更好的 sniffing 性能意味着对硬件本身的要求可以更低;对于 Packetbeat 被安装在已经部署好的应用服务器的情况,更好的 sniffing 性能则意味着更低的额外开销; 13 | 14 | 当前,Packetbeat 支持多种选项控制 traffic 捕获行为: 15 | 16 | - `pcap` - 底层使用 **libpcap** 库,在大多数平台上均能工作,但不是三种选项中最快的; 17 | - `af_packet` - 底层使用 memory mapped sniffing 机制(即 mmap() + socket API ,注册一种新的 socket 类型 `PACKET_MMAP`);该选项比 **libpcap** 更快,并且对 kernel 模块没有额外要求,但该选项是特定于 Linux 的; 18 | - `pf_ring` - 基于 ntop.org 的[项目](http://www.ntop.org/products/packet-capture/pf_ring/)实现;该选项提供了最快的 sniffing 速度;但是其要求应用程序的重新编译,且对 kernel 模块有要求;另外该方案是也特定于 Linux 的; 19 | 20 | 选项 `pf_ring` 实现了采用标准硬件上就可以达到 Gbps 级别的 sniffing 速度;但其要求基于 ntop 库重新编译 Packetbeat ,因此当前并未被 Elastic 以官方形式支持; 21 | 22 | 选项 `af_packet` 被称作 "memory-mapped sniffing" ,其利用 Linux 自身的[特性](http://lxr.free-electrons.com/source/Documentation/networking/packet_mmap.txt)实现;该选项对于专用服务器和将 Packetbeat 部署在当前应用服务器上的情况来说,可能是最佳 sniffing 模式; 23 | 24 | 该选项(`af_packet`)的实现方式为:程序针对 kernel 空间和用户空间的相同内存区域进行映射,并在该映射区域中实现一个简单的 circular buffer ,之后 kernel 会将 packets 写入该 circular buffer 之中,用户空间程序再从中进行读取;(用户空间程序会)先通过 `poll` 系统调用获取首个可用包的通知,之后的其它包就可以简单的通过内存访问方式进行读取; 25 | 26 | 该选项没有 `pf_ring` 方式快(在其开始丢包前,最快可达 200k pps),但该选项的使用不要求(程序的)重新编译和 kernel 模块的支持;因此仍可以将其视作针对 **libpcap** 的重要改进; 27 | 28 | 基于 `af_packet` 的 sniffer 还可以进一步调优:使用更多的内存以达到更高的性能;因为 circular buffer 的 size 越大,系统调用的需求量就会越少,也就意味着更少的 CPU 周期被消耗;该 buffer 的默认大小为 30 MB ,但是你可以按如下方式进行增大调整: 29 | 30 | ``` 31 | packetbeat.interfaces.device: eth0 32 | packetbeat.interfaces.type: af_packet 33 | packetbeat.interfaces.buffer_size_mb: 100 34 | ``` 35 | 36 | 更多配置信息详见 [Network Device Configuration](https://www.elastic.co/guide/en/beats/packetbeat/current/configuration-interfaces.html) ; 37 | -------------------------------------------------------------------------------- /Linux/PacketCapture/Programming with libpcap - Sniffing the Network From Our Own Application.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moooofly/MarkSomethingDown/3ed8d77b34dfb893b865932086065265876e3bc6/Linux/PacketCapture/Programming with libpcap - Sniffing the Network From Our Own Application.pdf -------------------------------------------------------------------------------- /Linux/PacketCapture/libpcap_An Architecture and Optimization Methodology for Packet Capture.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moooofly/MarkSomethingDown/3ed8d77b34dfb893b865932086065265876e3bc6/Linux/PacketCapture/libpcap_An Architecture and Optimization Methodology for Packet Capture.pdf -------------------------------------------------------------------------------- /Linux/PacketCapture/抓包分析之 “TCP Previous segment not captured”.md: -------------------------------------------------------------------------------- 1 | # 抓包分析之 “TCP Previous segment not captured” 2 | 3 | 标签(空格分隔): tcp 丢包 retransmission 4 | 5 | --- 6 | 7 | 8 | 前两天遇到了这样一个奇怪的现象:向某个服务发起 HTTP 请求,会概率性的出现丢包现象; 9 | 10 | 抓包截图如下: 11 | 12 | ![HTTP 请求正常情况](https://raw.githubusercontent.com/moooofly/ImageCache/master/Pictures/HTTP%20%E8%AF%B7%E6%B1%82%E6%AD%A3%E5%B8%B8%E6%83%85%E5%86%B5.png "HTTP 请求正常情况") 13 | 14 | > 在正常情况下,服务器在接收到 HTTP 请求后会迅速进行回应;并且 TCP 连接关闭是客户端侧发起的; 15 | 16 | ![HTTP 请求异常情况](https://raw.githubusercontent.com/moooofly/ImageCache/master/Pictures/HTTP%20%E8%AF%B7%E6%B1%82%E5%BC%82%E5%B8%B8%E6%83%85%E5%86%B5.png "HTTP 请求异常情况") 17 | 18 | > 在异常情况下,能够看到服务器在 20s 后主动关闭了 TCP 连接,并且 wireshark 的专家信息告诉我们,存在没有抓到的数据包(TCP Previous segment not captured); 19 | 20 | 需要注意的是:上述两个截图是通过 curl 连续不断进行测试时抓到的,问题复现概率非常高;因为服务器在云端,因此只能在本地客户端侧进行抓包分析; 21 | 22 | 针对异常情况的数据包,分析如下: 23 | 24 | 1. 196 号包说明服务器认为自己已经完成了服务请求,但客户端却没有主动关闭连接,于是在 20s 后只好主动将连接关闭;196 号包显示 "TCP Previous segment not captured" 并且包中 "Seq=1011" ,而我们抓到的上一个服务器侧发出包需要为 "Seq=1" ,说明其中有 1010 字节的包我们确实没抓到; 25 | 2. 197 号包说明客户端在收到 "Seq=1011" 后认为自己收到了一个乱序包,因此试图通过 "TCP Dup ACK 192#1" 和 "Ack=1" 试图让服务器重传缺失的 1010 子节; 26 | 3. 198 号包说明客户端发现 196 包携带了 "FIN" 标志,因此(在过了大约 6s 后)进行了四次握手的连接关闭; 27 | 4. 199 号包说明客户端由于某种原因还进行了一次针对 "FIN" 的 "TCP Spurious Retransmission" ; 28 | 29 | 从上面的分析可以看出,虽然异常包存在好几个,但最为关键的是 "TCP Previous segment not captured" ;因为问题是概率性出现,并且数据包大小也属于常规;另外据相关人员说,服务器侧没有 CPU 等异常,并且网卡流量也在正常范围内;因此,问题看起来就如同间歇式“抽风”一般;那么,一般什么情况会导致 "TCP Previous segment not captured" 的出现呢? 30 | 31 | 在抓包分析时,可能会看到上述信息情况有: 32 | 33 | - 在 tcp session 的中间阶段进行抓包,导致部分信息的缺失(属于正常情况,无法避免); 34 | - 抓包处理速度无法满足数据包到来的速度(可以通过 capture filter 进行调整); 35 | - 交换机、路由器和防火墙等在某些情况下会导致上述问题; 36 | - 杀毒软件、恶意软件监测程序等也可能导致上述问题; 37 | - 过于老旧的 TCP 协议栈实现可能存在相关 bug ; 38 | 39 | 40 | 另外,查阅 Wireshark 官网,存在如下解释说明: 41 | 42 | > **TCP Previous segment lost** - Occurs when a packet arrives with a sequence number greater than the "next expected sequence number" on that connection, indicating that one or more packets prior to the flagged packet did not arrive. This event is a good indicator of packet loss and will likely be accompanied by "TCP Retransmission" events. 43 | 44 | 45 | 总之,目前尚无法确定问题出现的原因,但怀疑和防火墙等设备有关,后续有进展后再更新结论~~ 46 | 47 | ---------- 48 | 49 | > 网上找到的通用分析说明 50 | 51 | 正如告警信息所描述的那样,这种情况常见于抓包行为起始于一个 tcp session 的中间阶段的情况;如果真实情况确实是由于 acks 丢失所致,那么你需要去相对于你的 host 的 upstream 去查看包是怎么丢失的; 52 | 53 | 非常可能出现的一种情况是,tshark 的抓包速度无法跟上数据包到来的速度,然后,额,理所当然的会丢掉一些东东(metrics);在抓包停止的时候,会有相应的信息告诉你是否存在 "**kernel dropped packet**" 的情况,以及 drop 了多少的信息;默认情况下,tshark 会 disable 掉 dns 查询,而 tcpdump 默认则不会;如果你使用 tcpdump 进行抓包,则需要使用 "-n" 开关来禁止 dns 查询以减少额外开销;如果你面临 disk IO 不足问题,那么你可以将抓包内容写到诸如 /dev/shm 等内存区中;但这种用法需要当心,因为一旦你等抓包内容过大,将会导致机器进入 swapping 困境之中; 54 | 55 | 一种常见的情况是,你的应用使用了一些长时间运行的 tcp session ,在后续启动抓包行为时,就必然会丢失这类 tcp session 的一部分信息; 56 | 57 | 具体来说,一些比较典型的、我所见过的、会导致 duplicate/missing acks 的情况有: 58 | 59 | - **Switches** - 通常情况下不太可能,但有些时候交换机处于 sick 状态时会出现这种问题; 60 | - **Routers** - 比交换机出现问题的可能性要高,但也不是非常高; 61 | - **Firewall** - 比路由器出现问题的可能要高,常见原因和资源耗尽有关(license, cpu, etc); 62 | - **Client side filtering software** - 反病毒软件,恶意软件探测软件等; 63 | 64 | 如果在 busy interface 上针对全部网络流量进行 unfiltered 模式的抓包,那么很大概率会在停止 tshark 时看到大量的数据包显示为 'dropped' ,因为这种情况下,tshark 需要针对全部抓包进行排序操作;一旦设置了合适的 capture filter 以减少针对非目标包的捕获,则出现 'dropped' 的概率大大降低; 65 | 66 | 67 | ---------- 68 | 69 | > 下图是网友给出的一种特殊情况:TCP 协议栈 bug 导致的序列号错误; 70 | 71 | ![tcp 连接关闭时由于协议栈bug导致的认为数据包丢失](https://raw.githubusercontent.com/moooofly/ImageCache/master/Pictures/tcp%20%E8%BF%9E%E6%8E%A5%E5%85%B3%E9%97%AD%E6%97%B6%E7%94%B1%E4%BA%8E%E5%8D%8F%E8%AE%AE%E6%A0%88bug%E5%AF%BC%E8%87%B4%E7%9A%84%E8%AE%A4%E4%B8%BA%E6%95%B0%E6%8D%AE%E5%8C%85%E4%B8%A2%E5%A4%B1.png "tcp 连接关闭时由于协议栈bug导致的认为数据包丢失") 72 | 73 | 包地址:[这里](https://www.cloudshark.org/captures/c256982bb42d) 74 | 75 | 从上述抓包中明显可以看出,来自 server 地址 82.117.201.86 的包明显没有遵循 TCP RFC 进行协议栈实现:在关闭 tcp 会话的时候,FIN 包应该携带下一个 expected 序列包,并且在该 FIN 包被 ACKed 时,相应的 ACK 包需要针对 FIN 所占用的一字节( one phantom byte)进行确定;然而,上述包的实际情况是,server 发送的 FIN 包中带有的序列号已经跨过了一字节的长度;这种行为明显是错误的,因此客户端此时正确的发送了一个 duplicate ACK 以请求获取正确序列号的包; 76 | 77 | 因此,导致上述抓包的可能原因,要么确实存在一字节数据被发送,之后丢失的情况,要么就是 server 端的 TCP 协议栈存在 bug ; 78 | 79 | "tcp previous segment not captured" 是 Wireshark 软件提供的专家信息,用于告知在当前包捕获中缺少了本应出现的某些包;该告警信息在之前被描述为 "tcp previous segment lost" ;该告警的基本含义为:或者是包真的没有出现过(丢包),或者是 Wireshark 的抓包动作不够快,以致没有将包到来的情况记录下来; 80 | 81 | 82 | ---------- 83 | 84 | 参考文章: 85 | 86 | - [Understanding [TCP ACKed unseen segment] [TCP Previous segment not captured]](http://stackoverflow.com/questions/18325522/understanding-tcp-acked-unseen-segment-tcp-previous-segment-not-captured) 87 | - [TCP previous segment not captured, why?](https://ask.wireshark.org/questions/12943/tcp-previous-segment-not-captured-why) 88 | 89 | 90 | -------------------------------------------------------------------------------- /Linux/Performance/Broken Linux Performance Tools (NETFLIX 2016).pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moooofly/MarkSomethingDown/3ed8d77b34dfb893b865932086065265876e3bc6/Linux/Performance/Broken Linux Performance Tools (NETFLIX 2016).pdf -------------------------------------------------------------------------------- /Linux/Performance/High Performance Browser Networking - Velocity.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moooofly/MarkSomethingDown/3ed8d77b34dfb893b865932086065265876e3bc6/Linux/Performance/High Performance Browser Networking - Velocity.pdf -------------------------------------------------------------------------------- /Linux/Performance/High Performance Browser Networking - Velocity.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moooofly/MarkSomethingDown/3ed8d77b34dfb893b865932086065265876e3bc6/Linux/Performance/High Performance Browser Networking - Velocity.pptx -------------------------------------------------------------------------------- /Linux/Performance/Linux Performance Tools.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moooofly/MarkSomethingDown/3ed8d77b34dfb893b865932086065265876e3bc6/Linux/Performance/Linux Performance Tools.pdf -------------------------------------------------------------------------------- /Linux/Performance/Linux Performance and Tuning Guidelines.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moooofly/MarkSomethingDown/3ed8d77b34dfb893b865932086065265876e3bc6/Linux/Performance/Linux Performance and Tuning Guidelines.pdf -------------------------------------------------------------------------------- /Linux/Performance/Tuning TCP and Nginx on ec2.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moooofly/MarkSomethingDown/3ed8d77b34dfb893b865932086065265876e3bc6/Linux/Performance/Tuning TCP and Nginx on ec2.pdf -------------------------------------------------------------------------------- /Linux/Performance/协议栈优化总结.md: -------------------------------------------------------------------------------- 1 | # 协议栈优化总结 2 | 3 | 4 | ---------- 5 | 6 | 7 | - [Optimizing Your Linux Stack for Maximum Mobile Web Performance](https://blog.cloudflare.com/optimizing-the-linux-stack-for-mobile-web-per/) 8 | - [优化 Linux 协议栈提升移动互联网性能](http://lib.csdn.net/article/linux/32532) 9 | - [High Performance Browser Networking](https://docs.google.com/presentation/d/1f2J_HrzMNvVHhsB3f7DKJFPl2N0Q_QR2ZEECWQu6oV8/present?slide=id.p19) (Google 大神给出的简版 PPT) 10 | - [High Performance Browser Networking](https://hpbn.co/) (在线电子书) 11 | - [TCP IW10 links](https://developers.google.com/speed/protocols/tcpm-IW10?csw=1) (协议栈优化中与 IW10 相关的所有文档) 12 | - [Increasing the TCP initial congestion window](https://lwn.net/Articles/427104/) (关于 TCP 初始拥塞窗口的解释) 13 | - [TCP: increase default initial receive window](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=356f039822b8d802138f7121c80d2a9286976dbd) (来自 kernel git 的说明) 14 | - [RFC6928: Increasing TCP's Initial Window](https://datatracker.ietf.org/doc/rfc6928/?include_text=1) 15 | - [Experimental Evaluation of Increasing TCP Initial Congestion Window to 10 Segments](https://research.csc.ncsu.edu/netsrv/?q=content/iw10) 16 | - [Increasing TCP’s Initial Window](https://www.ietf.org/proceedings/10mar/slides/iccrg-4.pdf) 17 | - [rfc3390: Increasing TCP's Initial Window](https://tools.ietf.org/html/rfc3390) 18 | - [Proportional Rate Reduction for TCP](https://tools.ietf.org/html/draft-mathis-tcpm-proportional-rate-reduction-01) 19 | - [Tuning initcwnd for optimum performance](https://www.cdnplanet.com/blog/tune-tcp-initcwnd-for-optimum-performance/) 20 | - [Optimizing TCP slow start](https://blog.habets.se/2011/10/Optimizing-TCP-slow-start.html) 21 | - [增大tcp init_cwnd](http://idning.github.io/tcp_ip_increasing_init_cwnd.html) 22 | - [浅谈TCP优化](http://itindex.net/detail/46633-tcp-%E4%BC%98%E5%8C%96) 23 | - [TCP的初始cwnd和ssthresh](http://blog.csdn.net/zhangskd/article/details/7608343) 24 | - [TCP拥塞控制窗口有效性验证机制](http://blog.csdn.net/zhangskd/article/details/7609465) 25 | - [Part 1: Lessons learned tuning TCP and Nginx in EC2](http://engineering.chartbeat.com/2014/01/02/part-1-lessons-learned-tuning-tcp-and-nginx-in-ec2/) 26 | - [Part 2: Lessons learned tuning TCP and Nginx in EC2](http://engineering.chartbeat.com/2014/02/12/part-2-lessons-learned-tuning-tcp-and-nginx-in-ec2/) 27 | -------------------------------------------------------------------------------- /Linux/Ring Buffer.md: -------------------------------------------------------------------------------- 1 | # Ring Buffer 2 | 3 | ## [Linux TCP队列相关参数的总结](https://yq.aliyun.com/articles/4252) 4 | 5 | **Ring Buffer** 位于 NIC 和 IP 层之间(准确的说位于 NIC driver 中),是一个典型的 FIFO 环形队列。Ring Buffer 没有包含数据本身,而是包含了指向 `sk_buff`(socket kernel buffers)的描述符。 6 | 可以使用 `ethtool -g eth0` 查看当前 **Ring Buffer** 的设置: 7 | 8 | ``` 9 | root@vagrant-ubuntu-trusty:~] $ ethtool -g eth0 10 | Ring parameters for eth0: 11 | Pre-set maximums: 12 | RX: 4096 13 | RX Mini: 0 14 | RX Jumbo: 0 15 | TX: 4096 16 | Current hardware settings: 17 | RX: 256 18 | RX Mini: 0 19 | RX Jumbo: 0 20 | TX: 256 21 | 22 | root@vagrant-ubuntu-trusty:~] $ 23 | ``` 24 | 25 | 可以通过 `ifconfig` 观察接收和传输队列的运行状况: 26 | 27 | ``` 28 | eth0 Link encap:Ethernet HWaddr 08:00:27:4a:c4:2f 29 | inet addr:10.0.2.15 Bcast:10.0.2.255 Mask:255.255.255.0 30 | inet6 addr: fe80::a00:27ff:fe4a:c42f/64 Scope:Link 31 | UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 32 | RX packets:2567 errors:0 dropped:0 overruns:0 frame:0 33 | TX packets:1640 errors:0 dropped:0 overruns:0 carrier:0 34 | collisions:0 txqueuelen:1000 35 | RX bytes:208893 (208.8 KB) TX bytes:198997 (198.9 KB) 36 | ``` 37 | 38 | 其中 39 | 40 | - RX errors:收包总的错误数; 41 | - `RX dropped`:表示数据包**已经进入了 Ring Buffer** ,但是**由于内存不够等系统原因,导致在拷贝到内存的过程中被丢弃**。 42 | - `RX overruns`:**表示数据包没到 Ring Buffer 就被网卡物理层给丢弃了**,而 CPU 无法及时的处理中断是造成 Ring Buffer 满的原因之一,例如中断分配的不均匀。 43 | 44 | 当 dropped 数量持续增加,建议增大 Ring Buffer ,使用 `ethtool -G` 进行设置。 45 | 46 | ### 数据包的接收 47 | 48 | ![](https://raw.githubusercontent.com/moooofly/ImageCache/master/Pictures/%E6%95%B0%E6%8D%AE%E5%8C%85%E6%8E%A5%E6%94%B6%E8%B7%AF%E5%BE%84.jpeg) 49 | 50 | 从下往上经过了三层:网卡驱动、系统内核空间,最后到用户态空间的应用。Linux 内核使用 sk_buff 数据结构描述一个数据包。当一个新的数据包到达,NIC 调用 DMA engine ,通过 **Ring Buffer** 将数据包放置到内核内存区。**Ring Buffer** 的大小固定,它不包含实际的数据包,而是包含了指向 sk_buff 的描述符。当 **Ring Buffer** 满的时候,新来的数据包将给丢弃。一旦数据包被成功接收,NIC 发起中断,由内核的中断处理程序将数据包传递给 IP 层。经过 IP 层的处理,数据包被放入队列等待 TCP 层处理。每个数据包经过 TCP 层一系列复杂的步骤,更新 TCP 状态机,最终到达 recvBuffer ,等待被应用接收处理。有一点需要注意,数据包到达 recvBuffer ,TCP 就会回 ACK 确认,即 TCP 的 ACK 表示数据包已经被操作系统内核收到,但并不确保应用层一定收到数据(例如这个时候系统 crash),因此一般建议应用协议层也要设计自己的确认机制。 51 | 52 | ### 数据包的发送 53 | 54 | ![](https://raw.githubusercontent.com/moooofly/ImageCache/master/Pictures/%E6%95%B0%E6%8D%AE%E5%8C%85%E5%8F%91%E9%80%81%E8%B7%AF%E5%BE%84.jpeg) 55 | 56 | 和接收数据的路径相反,数据包的发送从上往下也经过了三层:用户态空间的应用、系统内核空间、最后到网卡驱动。应用先将数据写入 TCP sendbuffer ,TCP 层将 sendbuffer 中的数据构建成数据包转交给 IP 层。IP 层会将待发送的数据包放入队列 QDisc 。数据包成功放入 QDisc 后,指向数据包的描述符 sk_buff 被放入 **Ring Buffer** 输出队列,随后网卡驱动调用 DMA engine 将数据发送到网络链路上。 57 | 58 | 59 | ---------- 60 | 61 | ## [How can I increase the ring buffer size of my NIC?](https://superuser.com/questions/284677/how-can-i-increase-the-ring-buffer-size-of-my-nic) 62 | 63 | The NIC ring buffer maximum size is determined by how much memory is available on the NIC. Typically you do not adjust this setting, this is very much a system administration task and an advanced one at that. 4MB is quite large for a NIC ring buffer. Intel NICs tend to cap at this amount. Broadcom NICs tend to cap at less than one quarter that amount, 1020KB. It is extremely unlikely, unless you have a 10GigE NIC, that you can go above 4096KB in the NIC's internal ring buffer. But we would need the exact model to know for sure as it is a hardware limitation. 64 | 65 | 66 | ---------- 67 | 68 | ## [NIC ring buffers](https://www.ibm.com/support/knowledgecenter/en/SSQPD3_2.6.0/com.ibm.wllm.doc/nicringbuffers.html) 69 | 70 | Ring buffers on the NIC are important to **handle bursts of incoming packets especially if there is some delay when the hardware interrupt handler schedules the packet receiving software interrupt (softirq)**. NIC ring buffer sizes vary per NIC vendor and NIC grade (that is, server or desktop). By increasing the Rx/Tx ring buffer size as shown below, you can decrease the probability of discarding packets in the NIC during a scheduling delay. The tool used to change ring buffer settings is the Linux utility, `ethtool`. 71 | 72 | ``` 73 | ethtool -g eth1 74 | ethtool -G eth1 rx 4096 tx 4096 75 | ethtool -g eth1 76 | ``` 77 | 78 | **These settings will be lost after a reboot**. To persist these changes across reboots reference the NIC vendor documentation for the ring buffer parameter(s) to set in the NIC device driver kernel module. 79 | -------------------------------------------------------------------------------- /Linux/The Page Cache.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moooofly/MarkSomethingDown/3ed8d77b34dfb893b865932086065265876e3bc6/Linux/The Page Cache.pdf -------------------------------------------------------------------------------- /Linux/WAL 原理与实践.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | # Write-ahead logging 5 | 6 | https://en.wikipedia.org/wiki/Write-ahead_logging 7 | 8 | 在计算机科学中,write-ahead logging (WAL) 是一种为数据库系统提供了原子性和持久性 (ACID 中的 A 和 D)的技术族; 9 | 10 | 在使用了 WAL 的系统中,所有修改操作在被 apply 前都会被写入日志文件;通常情况下,redo 和 undo 信息都会被保存在该日志中; 11 | 12 | 上述处理方式可以通过一个例子进行解释说明; 13 | 假定某程序在执行某操作的过程中,突然发生了断电异常;在重启后,程序最好能够知道之前执行的操作是否已成功完成,还是只成功了一半,亦或失败了;如果使用了 write-ahead log ,程序就能够通过检查对应的日志文件,确定出异常断电时执行操作的预期结果和实际结果的差异;基于比较结果,程序就能够确定需要 undo 掉哪些操作,完成哪些操作,或者只是维持原状; 14 | 15 | WAL 能够以 in-place 方式对数据库进行更新;另外一种实现原子更新的方式是基于 shadow paging ,该方式并非 in-place ;以 in-place 方式进行更新的主要优势在于可以有效的减少 index 和 block list 的修改; 16 | 17 | 文件系统通常会使用一种 WAL 的变体,专用于文件系统元数据的保存,通常称为 journaling ; 18 | 19 | 20 | 21 | # 产品中的使用 22 | 23 | ## kafka 24 | 25 | kafka 使用磁盘文件保存收到的消息。它使用一种类似于 WAL(write ahead log)的机制来实现对磁盘的顺序读写,然后再定时的将消息批量写入磁盘。消息的读取基本也是顺序的。这正符合 MQ 的顺序读取和追加写特性; 26 | 27 | ## InfluxDB 28 | 29 | 30 | ## etcd 31 | 32 | Write Ahead Log(预写式日志)是 etcd 用于持久化存储的日志格式。除了在内存中存有所有数据的状态以及节点的索引以外,etcd 还通过 WAL 进行持久化存储。在 WAL 中,所有的数据提交前都会事先记录日志。而 Snapshot 是 etcd 为了防止 WAL 文件中数据过多而创建的数据状态快照;Entry 表示存储的具体日志内容。 33 | 34 | etcd 的存储分为**内存存储**和**持久化(硬盘)存储**两部分;内存存储除了顺序化的记录下所有用户对节点数据变更的记录外,还会对用户数据进行索引、建堆等方便查询的操作。而持久化存储则使用了预写式日志(WAL, Write Ahead Log)进行记录存储。 35 | 36 | **在 WAL 的体系中,所有数据在提交之前都会进行日志记录。**在 etcd 的持久化存储目录中,有两个子目录。一个是 WAL ,存储着所有事务的变化记录;另一个则是 snapshot ,用于存储某一个时刻etcd 所有目录的数据。通过 WAL 和 snapshot 相结合的方式,etcd 可以有效的进行数据存储和节点故障恢复等操作。 37 | 38 | **既然有了 WAL 实时存储了所有的变更,为什么还需要 snapshot 呢?**随着使用量的增加,WAL 存储的数据会暴增,为了防止磁盘很快就爆满,etcd 默认每 10000 条记录做一次 snapshot ,经过snapshot 以后的 WAL 文件就可以删除。而通过 API 可以查询的 etcd 历史操作默认为 1000 条。 39 | 40 | **WAL(Write Ahead Log)最大的作用是记录了整个数据变化的全部历程。**在 etcd 中,所有数据的修改在提交前,都要先写入到 WAL 中。 41 | 42 | 使用 WAL 进行数据的存储使得 etcd 拥有两个重要功能: 43 | 44 | - **故障快速恢复**: 当你的数据遭到破坏时,就可以通过执行所有 WAL 中记录的修改操作,快速从最原始的数据恢复到数据损坏前的状态; 45 | - **数据回滚(undo)/重做(redo)**:因为所有的修改操作都被记录在 WAL 中,需要回滚或重做,只需要反向或正向执行日志中的操作即可; 46 | 47 | WAL 与 snapshot 在 etcd 中的命名规则: 48 | 在 etcd 的数据目录中,WAL 文件以 `$seq-$index.wal` 的格式存储。最初始的 WAL 文件是0000000000000000-0000000000000000.wal,表示是所有 WAL 文件中的第 0 个,初始的 Raft 状态编号为 0 。运行一段时间后可能需要进行日志切分,把新的条目放到一个新的 WAL 文件中。 49 | 50 | snapshot 的存储命名则比较容易理解,以 `$term-$index.wal` 格式进行命名存储。term 和 index就表示存储 snapshot 时数据所在的 raft 节点状态,当前的任期编号以及数据项位置信息。 51 | 52 | 从代码逻辑中可以看到,WAL 有两种模式:**读(read)模式**和**数据添加(append)模式**;两种模式不能同时成立。一个新创建的 WAL 文件处于 append 模式,并且不会进入到 read 模式。一个本来存在的 WAL 文件被打开的时候必然是 read 模式,并且只有在所有记录都被读完的时候,才能进入 append 模式,进入 append 模式后也不会再进入 read 模式。这样做有助于保证数据的完整与准确。 53 | 54 | 55 | 56 | ## mongodb 57 | 58 | 按照 Mongodb 默认的配置,WiredTiger 的写操作会先写入 Cache ,并持久化到 WAL(Write ahead log),每 60s 或 log 文件达到 2GB 时会做一次 Checkpoint ,将当前的数据持久化,产生一个新的快照。Wiredtiger 连接初始化时,首先将数据恢复至最新的快照状态,然后根据 WAL 恢复数据,以保证存储可靠性。 59 | 60 | 61 | ## HBase 62 | 63 | 64 | ## SQLite 65 | 66 | SQLite 在 3.7.0 开始引入 WAL 技术,全称叫 Write Ahead Log(预写日志); 67 | 68 | 其原理是:修改并不直接写入到数据库文件中,而是写入到另外一个称为 WAL 的文件中;如果事务失败,WAL 中的记录会被忽略,撤销修改;如果事务成功,它将在随后的某个时间被写回到数据库文件中,提交修改; 69 | 70 | WAL 使用**检查点**将修改写回数据库,默认情况下,当 WAL 文件发现有 1000 页修改时,将自动调用检查点。这个页数大小可以自行配置。 71 | 72 | WAL技术带来以下优点: 73 | - 读写操作不再互相阻塞,一定程度上解决了 SQLite 在处理高并发上的性能瓶颈; 74 | - 大多数场景中,带来很大的性能提升; 75 | 76 | 以下为[官网信息](http://www.sqlite.org/wal.html)摘录: 77 | 78 | SQLite 实现原子提交和回滚的方式是基于 rollback journal ;从 3.7.0 版本开始,一种新的 "Write-Ahead Log" 选项出现了(缩写为 "WAL"); 79 | 80 | 使用 WAL 取代 rollback journal 在一些方面有优有劣; 81 | 82 | 优势为: 83 | - WAL 在大多数场景下都是非常快的; 84 | - WAL 提供了更好的并发性能,因为 readers 不会阻塞 writers ,并且 writer 也不会阻塞 readers ;读和写可以并发进行; 85 | - 基于 WAL ,磁盘 I/O 操作更加倾向于顺序读写; 86 | - WAL 使用了 many fewer fsync() 操作,因此更加不容易受系统中 fsync() 调用问题的影响; 87 | 88 | 劣势为: 89 | - WAL 通常会要求 VFS 支持共享内存原语;(例外:[WAL without shared memory](http://www.sqlite.org/wal.html#noshm)) unix 和 windows 中内置的 VFS 支持该特性,但针对定制操作系统的、第三方扩展 VFS 可能就不支持; 90 | - 所有使用数据库的进程必须位于相同的主机上,WAL 无法工作于跨网络文件系统中; 91 | - 包含针对多个关联(ATTACHed)数据库的变更的事务,对于每个单独的数据库而言都是原子的, 但将所有数据库作为整来看时(跨数据库时),则不是原子的; 92 | - 在读非常多,写非常少的应用场景中,WAL 方式可能会比传统 rollback-journal 方式稍慢一点点(大概 1% 或 2%); 93 | 94 | 传统的 rollback journal 方式会将一份原始未经改变的数据库内容写入写入单独的 rollback journal 文件中,之后再将变更内容直接写到数据库文件中;在发生 crash 或 ROLLBACK 时,保留在 rollback journal 中的原始内容将被重放到数据库文件里,以便将数据库文件重置回原始状态;而 COMMIT 操作会在 rollback journal 文件删除时触发; 95 | 96 | WAL 方式有所不同;原始内容被保留在数据库文件中,而变更被 append 到单独的 WAL 文件中;COMMIT 行为可以通过将某个标志 commit 的特殊记录值 append 到 WAL 文件的方式进行记录;因此,COMMIT 行为可能发生于未将任何内容写入原始数据库的情况下;这也就允许 readers 能够继续在最初未改变的数据库上继续操作,与此同时,发生的变更会同时被 commit 到 WAL 中;多个事务可以被 append 到单个 WAL 文件到尾部; 97 | 98 | 关于 Checkpoint 的说明: 99 | 100 | 很显然,每个人都会想将所有 append 到 WAL 文件中的事务回写到原始数据库中;将 WAL 文件中的事务回写到数据库的行为称为 "checkpoint" ; 101 | 102 | 另外一种判别 way to think about the difference between rollback and write-ahead log is that in the rollback-journal approach, there are two primitive operations, reading and writing, whereas with a write-ahead log there are now three primitive operations: reading, writing, and checkpointing. 103 | 104 | By default, SQLite does a checkpoint automatically when the WAL file reaches a threshold size of 1000 pages. (The SQLITE_DEFAULT_WAL_AUTOCHECKPOINT compile-time option can be used to specify a different default.) Applications using WAL do not have to do anything in order to for these checkpoints to occur. But if they want to, applications can adjust the automatic checkpoint threshold. Or they can turn off the automatic checkpoints and run checkpoints during idle moments or in a separate thread or process. 105 | 106 | 107 | ## Berkeley DB 108 | 109 | Write-ahead-logging is the term that describes the underlying implementation that Berkeley DB uses to ensure recoverability. What it means is that before any change is made to a database, information about the change is written to a database log. 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | -------------------------------------------------------------------------------- /Linux/Wire Speed.md: -------------------------------------------------------------------------------- 1 | # Wire Speed 2 | 3 | ## [What is "Wire Speed" and what does it mean?](https://www.hayai.in/faq/wire-speed-and-does-it-mean) 4 | 5 | Wire speed is what it sounds like: the speed at which the wire between your router and our equipment operates. 6 | 7 | What "wire speed" means in real terms varies depending on which type of network you're connected to, but typically here's what you can expect: 8 | 9 | - 100 mbit/s for FTTB and Hayai Plus 10 | - 1 gbit/s for Hayai Plus 1000 and FTTH** 11 | - 1 gbit/s, n*1 gbit/s, 2.5 gbit/s, n*2.5 gbit/s, 10 gbit/s or n*10 gbit/s (cumulative, with either 100mbit/s or 1gbit/s to individual users) for certain multi-tenant, business & wholesale connections 12 | 13 | The speeds above don't mean you'll get that to every server everywhere in the world. When we offer services at "wire speed", it means we are not artificially restricting the speed between us and you - the data will simply come and go at the maximum rate that the equipment will allow. The actual speeds you get will vary due to various conditions, such as: time of day, activity on the local network, activity on the remote network, conditions and routing on networks outside of Hayai's control, where the remote host is located and so on). 14 | 15 | **You will need a gigabit network interface to achieve gigabit speeds -- you will not get anywhere near a gigabit if you are connected to the router via wifi (even with the latest 802.11ac devices) or if you have a "fast ethernet" (100mbit/s) network interface. You'll also want to have an SSD because traditional hard drives just aren't fast enough. 16 | 17 | Or, if you don't have gigabit ethernet or an SSD and aren't looking to upgrade, you'll be able to use several devices simultaneously at full speed and (probably) still have bandwidth to spare. 18 | 19 | 20 | ---------- 21 | 22 | 23 | ## [wire speed](http://searchnetworking.techtarget.com/definition/wire-speed) 24 | 25 | Wire speed refers to the rate of data transfer a given telecommunication technology provides at the physical wire level. Wire-speed, an adjective, describes any hardware box or function that tends to support this data transfer rate without slowing it down. It's common to refer to functions embedded in microchips rather than in software programming as working at wire speed. Switches,, routers, and other devices are sometimes described by their manufacturers as operating at wire speed. Data encryption and decryption and hardware emulation are software functions that might run at wire speed (or close to it) when embedded in a microchip. 26 | 27 | 28 | ---------- 29 | 30 | 31 | ## [Wire speed](https://en.wikipedia.org/wiki/Wire_speed) 32 | 33 | 34 | ---------- 35 | 36 | 37 | ## [blah blah](https://learningnetwork.cisco.com/thread/60459) 38 | 39 | The term at wire speed, or the adjective wire speed, describes any computer system or hardware device that is able to achieve a throughput equal to the maximum throughput of the communication standard. This requires that the CPU capacity, bus capacity, network switching capacity, etc., are sufficient. Network switches, routers, and similar devices are sometimes described as operating at wire speed. Data encryption and decryption and hardware emulation are software functions that might run at wire speed (or close to it) when embedded in a microchip. 40 | 41 | The wire speed is rarely achieved in connections between computers due to CPU limitations, disk read/write overhead, or contention for resources. However, it is still a useful concept for estimating the theoretical best throughput, and how far the real-life performance falls short of the maximum. 42 | 43 | -------------------------------------------------------------------------------- /Linux/esm 系统监控说明.md: -------------------------------------------------------------------------------- 1 | # 系统监控说明 2 | 3 | ## CPU Load 和 CPU Utilization 4 | 5 | 详见:《[CPU Utilization 和 CPU Load Average](https://github.com/moooofly/MarkSomethingDown/blob/master/Linux/CPU%20Utilization%20%E5%92%8C%20CPU%20Load.md)》 6 | 7 | 若进程创建过多线程(上万),也会导致系统慢的一塌糊涂,但可能没有什么 CPU 使用,内存也没什么占用,IO 也没有多少,但 load 非常高; 8 | 9 | ## CPU steal 10 | 11 | - 由于服务商在提供虚拟机时存在 CPU 超卖问题,因此和其他人共享 CPU 使用的情况是可能的; 12 | - 当发生 CPU 使用碰撞情况时,CPU 的使用取决于调度优先级;优先级低的进程会出现一点点 steal 值;若 steal 出现大幅升高,则说明由于超卖问题,把主机 CPU 占用满了; 13 | - 不使用虚拟机时一般不用关心该指标;使用虚拟机时,steal 代表超卖的幅度,一般不为 0 ; 14 | 15 | ## CPU softirq 和 CPU IRQ 16 | 17 | - 核心:发生中断时会打断当前“指令流水线”去处理中断; 18 | - 中断花费时间越长,代码被打断程度越严重; 19 | - 中断越频繁,一般来说上下文切换越频繁(每次中断都要发生很多切换); 20 | - 中断越频繁,中断消耗的 CPU 时间越长; 21 | - IRQ 多说明被物理设备打断的次数越多;一般来说,主要是由于网卡上包量非常大导致(网卡 pps 越高,中断数越大,导致软硬中断所要求的 CPU 处理时间越长,导致性能下降);因为在服务器上一般不会有那么多其它硬件事件发生; 22 | - IRQ 达到一定值后一定会导致用户进程调度被延迟,没有办法避免; 23 | - 需要关注中断发生在哪颗 CPU 上;大部分中断都是发生在 0 核心上,50% 左右; 24 | - 目前使用 Intel 网卡(替代了原来的 Broadcom 网卡)为多队列网卡,即能中断到多少 CPU 核心就中断到多少;但事实上,并不会全部占用(一般为前xx个); 25 | - CPU 节能功能会导致 Linux 在调度时尽量将所有任务往一个 CPU 核心上调度;副作用就是可能导致你的目标任务发生调度延迟; 26 | - 包量导致的延迟计算公式:100w pps --> 中断 100w 次 --> 延迟 50ms(每次中断的上下文切换时间成本为 50ns) 27 | - 基于 DMA 解决小包问题只是优化策略,并不解决根本问题; 28 | - pps 上升,也会造成 softirq 的上升,虽然内核调度策略会尽量将 softirq 往空核上调度,但空核不足时,一样处理不了; 29 | - 网卡限制:缓冲区大小限制,最低 8k ,最高不确定;缓冲区大小影响 DMA 聚合的极限,超过极限会导致丢包; 30 | 31 | linux 将中断分为两部分: 32 | 33 | - 硬中断:进入**底半部**中断处理过程,完成一些和硬件直接相关的中断处理过程,例如按键; 34 | - 软中断:进入**顶半部**中断处理过程,完成相应的处理流程,例如按键后的处理流程; 35 | 36 | 37 | ## Cache 和 Dirty 38 | 39 | - 尚未(操作系统层面)被 flush 的写入数据,可以被读取,对应 dirty cache ; 40 | - C 语言中的 flush 是针对缓存在进程中的数据的(只有程序执行 flush 后,数据才从进程里“出去”,别的进程才能看到),即 C 调用 flush 后不代表数据落盘,还需要调用 sync 进行落盘; 41 | - 若在内核 sync 之前修改了写入内容,此时的状态为“数据已写入系统”,对应 dirty cache 概念,若量极大,说明有大量数据堆积在内存里有丢失风险,可能原因是硬盘写入速度太慢; 42 | 43 | cache 和 buffer 44 | 45 | - 可以近似认为是一样的东西; 46 | - cache 对应块对象,底层是 block 结构,4k 级别; 47 | - buffer 对应文件对象,底层是 dfs 结构; 48 | - 可以粗略认为 cache + buffer 即总的缓存池; 49 | 50 | ## Slab 51 | 52 | 内核使用的所有内存片: 53 | 54 | - 可回收 reclaimable 55 | - 不可回收 unreclaimable 56 | 57 | 历史 bug:内核中使用了过多的内存片,导致内存大量被内核占用,应用无法得到所需要的内存,进而导致 IO 性能下降; 58 | 59 | ## Memory Util 60 | 61 | ``` 62 | used = total - free - buffer - cache - slab reclaimable 63 | util = used / total 64 | ``` 65 | 66 | > slab 统计信息已被计算到内存使用情况里; 67 | 68 | - 经验值:如果 util 超过 50% 则认为是有问题的(但并不一定导致问题); 69 | - 可能的问题原因,超过 50% 后,可用部分不足,会导致 IO 性能下降; 70 | - 若是 IO 密集型的应用,在 util 超过 50% 后一定要注意;若非 IO 密集型,则内存使用 util 可以更高,例如 redis ,即使达到 90% 也没问题(纯内存用法); 71 | - 内存占用看 Top 3 即可; 72 | 73 | ## Swap 74 | 75 | - 应该关掉; 76 | - 1G 的 swap 需要 10s ; 77 | - 在开了 1G swap 的情况下,若系统出现了 OOM 情况时,会导致 10s 内什么响应都没有; 78 | - 100m swap 对系统的帮助不大; 79 | - 若有些数据库必须要使用 swap ,当 swap usage 一直在涨时,就是有问题了;若存在 swap ,则应该一直保持在低值,一直涨一定有问题; 80 | 81 | 82 | ## Disk 83 | 84 | - storage util: 用来关注磁盘是否满了; 85 | - storage inode util: 小文件过多,导致 inode 耗光; 86 | - device/disk util: 磁盘总 IO 量和理论上可进行 IO 量的比值;一般来说,util 越高,IO 时间越长,IO 压力越大;有时该指标需要结合 IO 个数一起分析; 87 | - 一个盘,在 1s 内有 50% 的时间在做 IO ,则 disk util 为 50% ; 88 | - 当 disk util 达到 100% 时,表示的不是 IO 性能低,而是 IO 需要排队,此时 CPU 使用看起来是狂掉的(下跌);此时 CPU 的 iowait 会升高; 89 | 90 | 91 | 机械盘 IOPS 为 100-500 ; 92 | SSD 的 IOPS 为 几千 ; 93 | 94 | 95 | ## network 96 | 97 | Network - In 进数据量 98 | Network - Out 出数据量 99 | 100 | Network Util - In 网络当前进流量/网络理论总流量值 101 | Network Util - Out 网络当前出流量/网络理论总流量值 102 | 103 | Network Speed 会由于 bond 显示为 2G ; 104 | 105 | 虚拟机没有 Network Speed 这个值,因此也就算不出 Network Util ; 106 | 107 | 108 | ## TCP 109 | 110 | - `FIN_WAIT_1` 出现表示对端系统不正常,非应用不正常,因为 ack 是 TCP 协议栈自动回复的;`FIN_WAIT_1` 会在 75s 后自动消失; 111 | - `FIN_WAIT_2` 出现说明对方处于 `CLOSE_WAIT` 的不正常状态,不会被自动回收,对应 orphans socket;系统会在 orphans 数量超限后找最老的干掉;处于 FIN_WAIT_2 状态的 socket 会一直卡在这个状态,容易产生业务问题; 112 | - `TIME_WAIT` 关注业务行为是否符合预期; 113 | - `CLOSE_WAIT` 可以直接怀疑业务有问题; 114 | - retransmit segs 指标对于丢包、对方性能不足,网卡性能不足等问题,非常敏感;这个值应该在 0~1% 上下浮动(经验值); 115 | - 线上丢包率应该在万分之一到万分之三(自然背景丢包率),上限为 1%; 116 | - RTO 也敏感,但面板上没有;表示和对端之间的平均响应延迟; 117 | 118 | 重传率浮动的原因:随着发包数目上升,报文发送速度越快,中间丢包概率就越大,甚至将中间网络设备打满,进而导致丢包;丢包又会导致发包速度降低,丢包可能又会随着降低;所以才会浮动; 119 | 120 | 丢包率问题对打开了 bbr 的机器不适合,该算法不会影响丢包率,对于开了 bbr 得机器,哪怕链路用满,丢包率也不会上升;线上默认为 cubic ; 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | -------------------------------------------------------------------------------- /Linux/flume 本地接收 UDP 日志丢失问题.md: -------------------------------------------------------------------------------- 1 | # flume 本地接收 UDP 日志丢失问题 2 | 3 | ## 思路 4 | 5 | - 通过 127.0.0.1 来发送 6 | - 数据交互环节 7 | - 应用发日志到内核协议栈 8 | - 内核协议栈处理 9 | - 内核协议栈发日志到 flume 10 | - 通过 dropwatch 观察发包时丢包路径分布 11 | - 针对丢包最多的点查看内核源码进行分析 12 | - 通过 systemtap 脚本跟踪内核源码中和丢包相关的关键参数 13 | - 确定 sysctl 配置的内核参数和上述变量的关系 14 | - 分析 systemtap 输出结果(得出:只要发送端跟接收端的速度不匹配,情况一直会出现) 15 | - 通过 strace 查看 flume 的处理性能(估算真实能够处理的能力接近 8000/s 左右) 16 | 17 | ## dropwatch 相关 18 | 19 | - dropwatch 的 man 手册 20 | 21 | ``` 22 | NAME 23 | dropwatch - kernel dropped packet monitoring utility 24 | 25 | SYNOPSIS 26 | dropwatch [-l | list] 27 | 28 | DESCRIPTION 29 | dropwatch dropwatch is an interactive utility for monitoring and recording packets that are dropped by the kernel 30 | 31 | OPTIONS 32 | -l | list 33 | Select the translation method to use when a drop alert arrives. By default the raw instruction pointer of a drop location is output, but by the use of the -l option, we can assign a translation method so that the instruction pointer can be translated 34 | into function names. Currently supported lookup methods are: 35 | 36 | kas - use /proc/kallsyms to lookup instruction pointers to function mappings 37 | 38 | INTERACTIVE COMMANDS 39 | start Tells the kernel to start reporting dropped packets 40 | 41 | stop Tells the kernel to discontinue reporting dropped packets 42 | 43 | exit Exits the dropmonitor program 44 | 45 | help Displays summary of all commands 46 | 47 | set alertlimit 48 | Sets a triggerpoint to stop monitoring for dropped packets after alerts have been received 49 | ``` 50 | 51 | - dropwatch 使用 52 | 53 | ``` 54 | [root@xg-ops-elk-lvs-1 ~]# dropwatch -l kas 55 | Initalizing kallsyms db 56 | dropwatch> start 57 | Enabling monitoring... 58 | Waiting for activation ack.... 59 | Waiting for activation ack.... 60 | Waiting for activation ack.... 61 | Waiting for activation ack.... 62 | Failed activation request, error: Resource temporarily unavailable 63 | Shutting down ... 64 | [root@xg-ops-elk-lvs-1 ~]# 65 | ``` 66 | 67 | 68 | > TO BE CONTINUED 69 | 70 | ------ 71 | 72 | 73 | 74 | # linux 系统 UDP 丢包问题分析思路 75 | 76 | > http://cizixs.com/2018/01/13/linux-udp-packet-drop-debug 77 | -------------------------------------------------------------------------------- /Linux/insmod 和 modprobe.md: -------------------------------------------------------------------------------- 1 | # insmod 和 modprobe 2 | 3 | 4 | `insmod` 与 `modprobe` 都是用于载入 kernel 模块的,差别在于 `modprobe` 能够根据配置文件自动处理 module 间的载入依赖问题。 5 | 6 | 比方你要载入 a module,但是 a module 要求系统要先载入 b module 时,直接用 `insmod` 挂入通常都会出现错误讯息,不过 `modprobe` 倒是能够知道先载入 b module 后才载入 a module,如此依赖关系就会满足。 7 | 8 | 不过 `modprobe` 获取 module 之间依赖关系是通过读取 `/lib/modules/$(uname -r)/modules.dep` 文件得知的,而该文件的内容是通过 `depmod` 所建立的。若在载入过程中发生错误,在 `modprobe` 会卸载整组的模块。 9 | 10 | `modprobe` 在加载模块的时候,会检查模块里是否存在一些 symbols 在内核里没有定义,如果有这样的 symbols ,`modprobe` 函数会搜索其他模块,看其他模块里有没有相关的 symbols ;如果有,则将此模块也一起加载,这样的话,就算模块里有一些没有定义的 symbols 也能成功加载。但如果用 `insmod` 去加载的话,遇到这种情况就会加载失败。会出现 "unresolved symbols" 信息。 11 | 12 | 13 | 在用法上: 14 | 15 | - `insmod` 一次只能加载特定的一个设备驱动,且需要驱动的具体地址,如 `insmod /path/to/drv.ko` ; 16 | - `modprobe` 则可以一次将有依赖关系的驱动全部加载到内核。无需指定驱动的具体地址,如 `modprob drv` ,但需要在安装时按照 `make modues_install` 的方式进行驱动模块的安装,即驱动模块被安装在 `/lib/modules/$(uname -r)/xxx` 下。 17 | 18 | 19 | lsmod 命令可以用来查看当前已经被加载的模块,它是通过读出 `/proc/modules` 这个虚拟文件来实现上述功能的。关于当前已加载模块的更多信息可以在 `/sys/module//xxx` 中查看; 20 | 21 | -------------------------------------------------------------------------------- /Linux/linux 系统调优之 drop_caches.md: -------------------------------------------------------------------------------- 1 | # linux 系统调优之 drop_caches 2 | 3 | 查阅[资料](http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/Documentation/sysctl/vm.txt?id=HEAD#n189)如下: 4 | 5 | ```shell 6 | ============================================================== 7 | 8 | drop_caches 9 | 10 | Writing to this will cause the kernel to drop clean caches, as well as 11 | reclaimable slab objects like dentries and inodes. Once dropped, their 12 | memory becomes free. 13 | 14 | To free pagecache: 15 | echo 1 > /proc/sys/vm/drop_caches 16 | To free reclaimable slab objects (includes dentries and inodes): 17 | echo 2 > /proc/sys/vm/drop_caches 18 | To free slab objects and pagecache: 19 | echo 3 > /proc/sys/vm/drop_caches 20 | 21 | This is a non-destructive operation and will not free any dirty objects. 22 | To increase the number of objects freed by this operation, the user may run 23 | `sync' prior to writing to /proc/sys/vm/drop_caches. This will minimize the 24 | number of dirty objects on the system and create more candidates to be 25 | dropped. 26 | 27 | This file is not a means to control the growth of the various kernel caches 28 | (inodes, dentries, pagecache, etc...) These objects are automatically 29 | reclaimed by the kernel when memory is needed elsewhere on the system. 30 | 31 | Use of this file can cause performance problems. Since it discards cached 32 | objects, it may cost a significant amount of I/O and CPU to recreate the 33 | dropped objects, especially if they were under heavy use. Because of this, 34 | use outside of a testing or debugging environment is not recommended. 35 | 36 | You may see informational messages in your kernel log when this file is 37 | used: 38 | 39 | cat (1234): drop_caches: 3 40 | 41 | These are informational only. They do not mean that anything is wrong 42 | with your system. To disable them, echo 4 (bit 3) into drop_caches. 43 | 44 | ============================================================== 45 | ``` 46 | 47 | 关键点: 48 | 49 | - Writing to drop_caches will cause the kernel to drop clean **caches**, as well as 50 | reclaimable **slab objects** like **dentries** and **inodes**. 51 | - This is a non-destructive operation and **will not free any dirty objects**. 52 | - use outside of a testing or debugging environment is not recommended. 53 | 54 | 55 | 问题: 56 | 57 | - slab objects 中的 dentries 和 inodes 对应什么? 58 | - 通过 echo 修改 drop_caches 的值为 3 后,是否意味着一直处于 "**free slab objects and pagecache**" 状态? 59 | - 什么时候需要设置 drop_caches 进行进行清理?如何清理? 60 | - what's in the buffers and cache? 61 | - 如何进行 swap 清理? 62 | 63 | 64 | 针对问题一: 65 | 66 | > A **dentries** is a data structure that represents a directory. 67 | > An **inode** in your context is a data structure that represents a file. 68 | > 69 | 70 | 71 | 针对问题二: 72 | 73 | > It isn't sticky - you just write to the file to make it drop the caches and then it immediately starts caching again. 74 | > 75 | > Basically when you write to that file you aren't really changing a setting, you are issuing a command to the kernel. The kernel acts on that command (by dropping the caches) then carries on as before. 76 | > 77 | > The value you can read from /proc/sys/vm/drop_caches is whatever you put last, but it's not used anywhere, only the action of writing matters. The source code is in [fs/drop_caches.c](http://lxr.linux.no/linux+v3.0/fs/drop_caches.c). 78 | 79 | 针对问题三: 80 | 81 | > A common case to "**manually flush**" those caches is purely for **benchmark** comparison: your first benchmark run may run with "empty" caches and so give poor results, while a second run will show much "better" results (due to the pre-warmed caches). By flushing your caches before any benchmark run, you're removing the "warmed" caches and so your benchmark runs are more "fair" to be compared with each other. 82 | > 83 | > 可以使用如下命令进行清理: 84 | >> `free && sync && echo 3 > /proc/sys/vm/drop_caches && free` 85 | 86 | 针对问题四: 87 | 88 | > Take a look at [linux-ftools](https://code.google.com/p/linux-ftools/) if you'd like to analyze the contents of the buffers & cache. 89 | 90 | 91 | 针对问题五: 92 | 93 | > `swapoff -a` -- disable swap 94 | > `swapon -a` -- re-enable swap 95 | 96 | 97 | 参考: 98 | 99 | - [Setting /proc/sys/vm/drop_caches to clear cache](http://unix.stackexchange.com/questions/17936/setting-proc-sys-vm-drop-caches-to-clear-cache) 100 | - [How do you empty the buffers and cache on a Linux system?](http://unix.stackexchange.com/questions/87908/how-do-you-empty-the-buffers-and-cache-on-a-linux-system) 101 | - [what are pagecache, dentries, inodes?](http://stackoverflow.com/questions/29870068/what-are-pagecache-dentries-inodes) 102 | 103 | 104 | 105 | 106 | 107 | -------------------------------------------------------------------------------- /Linux/nf_conntrack 超限问题.md: -------------------------------------------------------------------------------- 1 | # nf_conntrack 超限问题 2 | 3 | > 背景:基于 C/S 模型进行大并发连接测试; 4 | 5 | ## 问题表现 6 | 7 | 当 server 侧连接数达到 262138 后,无法再建立新的连接,此时通过 dmesg 或者 `/var/log/kern.log` 可以看到 8 | 9 | ``` 10 | [35470.975678] nf_conntrack: table full, dropping packet 11 | [35704.617801] nf_conntrack: table full, dropping packet 12 | [35706.621871] nf_conntrack: table full, dropping packet 13 | [35710.633918] nf_conntrack: table full, dropping packet 14 | [35718.649976] nf_conntrack: table full, dropping packet 15 | ``` 16 | 17 | 在 client 侧也是一样的现象; 18 | 19 | 发生问题后,通过其他机器 ping 该机器会时通时不通,使用 ssh 登录的情况也一样; 20 | 21 | 22 | ## 故障原因 23 | 24 | **用来跟踪连接信息的哈希表满了**; 25 | 26 | 在 Ubuntu 16.04.3 LTS (Linux 4.4.0-87-generic x86_64) 上,未进行配置调整前,`nf_conntrack` 的默认值为(对应之前建立了 26w+ 连接后报错的情况): 27 | 28 | ``` 29 | $ cat /proc/sys/net/netfilter/nf_conntrack_max 30 | 262144 31 | ``` 32 | 33 | 可以通过如下命令查看 `nf_conntrack` 的当前使用状况 34 | 35 | ``` 36 | $ cat /proc/sys/net/netfilter/nf_conntrack_count 37 | ``` 38 | 39 | 背景知识: 40 | 41 | - `nf_conntrack`/`ip_conntrack` 跟 NAT 有关,用来**跟踪连接条目**,它会使用一个**哈希表**来记录 established 的记录。`nf_conntrack` 在 2.6.15 被引入,而 `ip_conntrack` 在 2.6.22 被移除;如果该哈希表满了,就会出现 42 | "nf_conntrack: table full, dropping packet" 信息; 43 | - `nf_conntrack` 工作在 3 层,支持 IPv4 和 IPv6,而 `ip_conntrack` 只支持 IPv4。目前,大多的 ip_conntrack_* 已被 nf_conntrack_* 取代,很多 ip_conntrack_* 仅仅是个 alias ; 44 | 45 | 46 | ## 系统配置 47 | 48 | ``` 49 | $ vi /etc/sysctl.conf 50 | ... 51 | net.nf_conntrack_max = 1048576 52 | net.netfilter.nf_conntrack_max = 1048576 53 | ``` 54 | 55 | 56 | ---------- 57 | 58 | 59 | ## 其他 60 | 61 | > 以下内容针对 CentOS6/CentOS7 62 | 63 | - 内核参数 `net.nf_conntrack_max` 系统默认值为 "65536" ,当 `nf_conntrack` 模块被 load ,且服务器上连接超过这个设定的值时,系统会主动丢掉新连接包,直到连接小于此设置值才会恢复。同时内核参数 `net.netfilter.nf_conntrack_tcp_timeout_established` 系统默认值为 "432000" ,代表 `nf_conntrack` 中保存的 TCP 连接记录的默认时间是 5 天,(保存时间过长)致使 `nf_conntrack` 的值减不下来,丢包持续时间长; 64 | - `nf_conntrack` 模块在**首次 load** 或**重新 load** 时,内核参数 `net.nf_conntrack_max` 会重新设置为默认值 "65536" ,并且不会调用 `sysctl` 设置为我们的预设值; 65 | - 触发 `nf_conntrack` 模块**首次 load** 比较隐蔽,**任何调用 iptables NAT 功能的操作都会触发**。当系统没有 load `nf_conntrack` 模块时(即 `lsmod |grep conntrack` 时无输出时),调用 `iptables` NAT 相关命令(例如 `iptables -L -t nat`)就会触发 nf_conntrack 模块 load ,致使 `net.nf_conntrack_max` 重设为 "65536" 。 66 | - 触发 `nf_conntrack` 模块重新 load 的操作很多,CentOS6 中 `service iptables restart` ,CentOS7 中 `systemctl restart firewalld` 都会触发设置重置,致使 `net.nf_conntrack_max` 重设为 "65536" 。 67 | 68 | ### 解决办法 69 | 70 | - 通过系统初始化脚本创建配置文件 `/etc/modprobe.d/nf_conntrack.conf` ,写入内容为 `options nf_conntrack hashsize=262144` ;(这种方法)通过设置 `nf_conntrack` 模块的挂接参数 `hashsize` ,进而设置 net.nf_conntrack_max 的值为 "2097152"(因为 nf_conntrack_max=hashsize*8),保证后续新初始化服务器配置正确; 71 | - 通过xxx方式将配置文件 `/etc/modprobe.d/nf_conntrack.conf` 推送到所有目标机器,内容为 `options nf_conntrack hashsize=262144` ,保证 `nf_conntrack` 模块在首次 load 或重新 load 时,`net.nf_conntrack_max` 内核参数被设置为预期的 "2097152" ; 72 | - 更新系统初始化脚本,设置 `net.netfilter.nf_conntrack_tcp_timeout_established=1800` ,减少 `nf_conntrack` 连接表中 TCP 连接的记录维持时间; 73 | 74 | 75 | ### 测试命令 76 | 77 | - `nf_conntrack` 模块在首次 load 时初始化默认值为 "65536" 78 | 79 | ``` 80 | [root@localhost ~]# systemctl stop firewalld 81 | [root@localhost ~]# lsmod |grep nf_conntrack 82 | [root@localhost ~]# sysctl -a |grep nf_conntrack 83 | 84 | 85 | [root@localhost ~]# iptables -L -t nat 86 | Chain PREROUTING (policy ACCEPT) 87 | target prot opt source destination 88 | 89 | Chain INPUT (policy ACCEPT) 90 | target prot opt source destination 91 | 92 | Chain OUTPUT (policy ACCEPT) 93 | target prot opt source destination 94 | 95 | Chain POSTROUTING (policy ACCEPT) 96 | target prot opt source destination 97 | 98 | 99 | [root@localhost ~]# lsmod |grep nf_conntrack 100 | nf_conntrack_ipv4 19108 1 101 | nf_defrag_ipv4 12729 1 nf_conntrack_ipv4 102 | nf_conntrack 111302 3 nf_nat,nf_nat_ipv4,nf_conntrack_ipv4 103 | 104 | 105 | [root@localhost ~]# sysctl -a |grep net.nf_conntrack_max 106 | net.nf_conntrack_max = 65536 107 | ``` 108 | 109 | - 设置 `net.nf_conntrack_max = 2097152` ,重启 firewalld 服务,`nf_conntrack_max` 重新被初始化为 "65536" ; 110 | 111 | ``` 112 | [root@localhost ~]# systemctl start firewalld 113 | [root@localhost ~]# sysctl net.nf_conntrack_max=2097152 114 | net.nf_conntrack_max = 2097152 115 | [root@localhost ~]# sysctl -a |grep net.nf_conntrack_max 116 | net.nf_conntrack_max = 2097152 117 | 118 | [root@localhost ~]# systemctl restart firewalld 119 | [root@localhost ~]# sysctl -a |grep net.nf_conntrack_max 120 | net.nf_conntrack_max = 65536 121 | ``` 122 | 123 | - 设置配置文件 `/etc/modprobe.d/nf_conntrack.conf` ,内容为 `options nf_conntrack hashsize=262144` ,保证 `net.nf_conntrack_max =2097152` 124 | 125 | ``` 126 | [root@localhost ~]# cat /etc/modprobe.d/nf_conntrack.conf 127 | options nf_conntrack hashsize=262144 128 | 129 | [root@localhost ~]# systemctl stop firewalld 130 | 131 | [root@localhost ~]# iptables -L -t nat 132 | Chain PREROUTING (policy ACCEPT) 133 | target prot opt source destination 134 | 135 | Chain INPUT (policy ACCEPT) 136 | target prot opt source destination 137 | 138 | Chain OUTPUT (policy ACCEPT) 139 | target prot opt source destination 140 | 141 | Chain POSTROUTING (policy ACCEPT) 142 | target prot opt source destination 143 | 144 | [root@localhost ~]# sysctl -a |grep net.nf_conntrack_max 145 | net.nf_conntrack_max = 2097152 146 | 147 | [root@localhost ~]# systemctl restart firewalld 148 | [root@localhost ~]# sysctl -a |grep net.nf_conntrack_max 149 | net.nf_conntrack_max = 2097152 150 | ``` 151 | -------------------------------------------------------------------------------- /Linux/run queue.md: -------------------------------------------------------------------------------- 1 | # run queue 2 | 3 | > In modern computers many processes run at once. **Active processes** are placed in an array called a `run queue`, or `runqueue`. The run queue may contain **priority** values for each process, which will be used by the **scheduler** to determine which process to run next. To ensure each program has a fair share of resources, each one is run for some **time period** (`quantum`) before it is paused and placed back into the run queue. When a program is stopped to let another run, the program with the highest priority in the run queue is then allowed to execute. 4 | > 5 | > Processes are also removed from the run queue when they ask to sleep, are waiting on a resource to become available, or have been terminated. 6 | 7 | 关键: 8 | 9 | - **Active processes** 被放在称作 `run queue` 的 array 中; 10 | - run queue 中可能会包含针对每个 process 的 **priority** 值; 11 | - Processes 被**从 run queue 中移出**的情况: 12 | - **Processes 主动要求 sleep 时** ; 13 | - **Processes 等待指定 resource 变成可用状态时**; 14 | - **Processes 被终止运行时**; 15 | 16 | > In the Linux operating system (prior to kernel 2.6.23), **each CPU in the system is given a run queue**, which maintains both an **active** and **expired** array of processes. Each array contains **140** (one for each **priority level**) pointers to doubly linked lists, which in turn reference all processes with the given priority. The scheduler selects the next process from the active array with highest priority. When a process' quantum expires, it is placed into the expired array with some priority. When the active array contains no more processes, the scheduler swaps the active and expired arrays, hence the name `O(1) scheduler`. 17 | 18 | 关键: 19 | 20 | - **每一个 CPU 都有一个 run queue** ; 21 | - 每一个 run queue 都由 **active array** 和 **expired array** 构成; 22 | - 每一个 array 中包含 **140** 个指针,分别指向对应不同 **priority** 的双向链表; 23 | - scheduler 从 active array 中获取 process 进行执行,时间片用完之后,放回 expired array ; 24 | - scheduler 通过交换 active array 和 expired array 实现了所谓的 `O(1) scheduler` ; 25 | 26 | 27 | > In UNIX or Linux, the `sar` command is used to check the run queue. The `vmstat` UNIX or Linux command can also be used to determine the number of processes that are **queued to run** or **waiting to run**. These appear in the 'r' column. 28 | 29 | 30 | ---------- 31 | 32 | ## 只言片语 33 | 34 | > Each process __using__ or __waiting__ for CPU (the __ready queue__ or __run queue__) increments the load number by 1. Each process that terminates decrements it by 1. Most UNIX systems count only processes in the running (on CPU) or runnable (waiting for CPU) states. However, Linux also includes processes in uninterruptible sleep states (usually waiting for disk activity), which can lead to markedly different results if many processes remain blocked in I/O due to a busy or stalled I/O system. 35 | 36 | ⚠️ 经过反复确认:ready queue 和 run queue 是同一个东西,只是叫法不同而已; 37 | 38 | ---------- 39 | 40 | 41 | 42 | ## 参考 43 | 44 | - [Run_queue from Wikipedia](https://en.wikipedia.org/wiki/Run_queue) 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /Linux/关于 TCP 协议中的 timestamp 问题.md: -------------------------------------------------------------------------------- 1 | # 关于 TCP 协议中的 timestamp 问题 2 | 3 | 之前和同事聊抓包分析过程中,进行应用层 request-response 耗时计算时,时间戳从哪里获取的问题时,扯出了“TCP 协议是否带有时间戳”的问题;我认为 TCP 协议已经带有 timestamp(因为我记得看到过),而另外一个人认为没有; 4 | 5 | 今天在看到另外一篇文章时,看到和 timestamp 相关的信息,遂成此文; 6 | 7 | 8 | ## RFC 793 9 | 10 | ### Options 11 | 12 | > An Option field may contain several options, and each option may be several octets in length. The options are used primarily in testing situations; for example, to carry **timestamps**. Both the Internet Protocol and TCP provide for options fields. 13 | 14 | ## RFC 1137 15 | 16 | 解释了当 TIME-WAIT 状态不足时将会发生什么; 17 | 18 | ## RFC 1323 19 | 20 | 实现了 TCP 拓展规范,以保证网络繁忙状态下的高可用。除此之外,另外,它定义了一个新的 TCP 选项,即两个四字节的 timestamp fields 时间戳字段,第一个是 TCP 发送方的当前时钟时间戳,而第二个是从远程主机接收到的最新时间戳; 21 | 22 | 23 | ## wiki:TCP timestamps 24 | 25 | **TCP timestamps**, defined in **RFC 1323**, can help TCP determine in which order packets were sent. TCP timestamps are not normally aligned to the system clock and start at some random value. Many operating systems will increment the timestamp for every elapsed millisecond; however the RFC only states that the ticks should be proportional. 26 | 27 | There are two timestamp fields: 28 | 29 | - a 4-byte **sender timestamp** value (my timestamp) 30 | - a 4-byte **echo reply timestamp** value (the most recent timestamp received from you). 31 | 32 | TCP timestamps are used in an algorithm known as Protection Against Wrapped Sequence numbers, or **PAWS** (see RFC 1323 for details). **PAWS is used when the receive window crosses the sequence number wraparound boundary**. In the case where a packet was potentially retransmitted it answers the question: "Is this sequence number in the first 4 GB or the second?" And the timestamp is used to break the tie. 33 | 34 | Also, the Eifel detection algorithm ([RFC 3522](https://tools.ietf.org/html/rfc3522)) uses TCP timestamps to determine if retransmissions are occurring because packets are lost or simply out of order. 35 | 36 | 37 | ## sysctl 配置 38 | 39 | linux 上 tcp_timestamps 默认开启 40 | 41 | ``` 42 | root@vagrant-ubuntu-trusty:~] $ sysctl -a|grep tcp_timestamps 43 | net.ipv4.tcp_timestamps = 1 44 | ``` 45 | 46 | 47 | ## 参考 48 | 49 | - [RFC 793](http://www.rfc-editor.org/rfc/rfc793.txt) 50 | - [RFC 1137](http://www.rfc-editor.org/rfc/rfc1137.txt) 51 | - [RFC 1323](http://www.rfc-editor.org/rfc/rfc1323.txt) 52 | - [wiki: Transmission Control Protocol](https://en.wikipedia.org/wiki/Transmission_Control_Protocol) 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /Linux/吞吐量 Throughput.md: -------------------------------------------------------------------------------- 1 | # 吞吐量 Throughput 2 | 3 | > When used in the context of communication networks, such as Ethernet or packet radio, throughput or network throughput is the rate of successful message delivery over a communication channel. The data these messages belong to may be delivered over a physical or logical link, or it can pass through a certain network node. Throughput is usually measured in **bits per second** (`bit/s` or `bps`), and sometimes in **data packets per second** (`p/s` or `pps`) or **data packets per time slot**. 4 | 5 | 吞吐量的度量单位有三种: 6 | 7 | - bps 8 | - pps 9 | - ppt 10 | 11 | > The throughput of a communication system may be affected by various factors, including the **limitations of underlying analog physical medium**, **available processing power of the system components**, and **end-user behavior**. When various protocol overheads are taken into account, useful rate of the transferred data can be significantly lower than the maximum achievable throughput; the useful part is usually referred to as `goodput`. 12 | 13 | 影响吞吐量的因素: 14 | 15 | - **底层物理介质的限制**; 16 | - **系统组件的可用处理能力**; 17 | - **端用户本身的行为**; 18 | 19 | 考虑到上述因素可能导致的额外开销,实际吞吐量可能远低于理论上可达的最大吞吐量,前者通常被称为“goodput”(有效吞吐量); 20 | 21 | 22 | ---------- 23 | 24 | > Sometimes, when we talk about **device performance** we are talking in terms of **packets per second** (`pps`) and **bits per second** (`bps`). But in latter case it's not quite correct to say "this device can do one hundred megabits ber second" **because router/switch/whatever performance is greatly depends on packet size** and if you want to mention device performance in a more accurate and professional way you would say "this device can do one hundred megabits per second at 64 bytes packet size" 25 | 26 | 设备性能和包大小有关系;因此正确描述设备性能的表达方式为:在 xxx 字节包大小情况下,可以达到 xxx bps ; 27 | 28 | > Often vendors such as our favorite **Cisco** specify device performance as **packets per second**, so we don't need to bother about packet size mentioning because pps is rather a characteristic of device's (processor, bus, ASICs) computing power. Packets per second more or less still the same with different packets size. But it is not very convinient to deal with pps in a real life because we have to know "real" device performance in our network. So we have to do two things: 29 | > 30 | > 1) Determine the average packet size which is specific for our network. For example traffic profile for our network could be 30% ftp-data (large packet at 1500 bytes) and 70% VoIP-data (a lot of small packets at 64 bytes) so our average packet size is about 800 bytes. 31 | > 32 | > 2) Calculate with simple formula how much there will be Megabits per second (Mbps) if our average packet size is 800 bytes and device performance is, lets say, 100 kpps (one hundred thousand of packets per second) 33 | > 34 | > The second step is not a big deal for a real professional, but we live in 21st century, aren't we? Unfortunately I didn't found any bps to pps converter/calculator anywhere online so I decided to make it myself (though I'm not a programmer). 35 | 36 | 知名设备厂商通常会基于 pps 数值展示设备性能,而这是从计算能力角度出发的;而有些场景中,我们更想要确定真正的设备性能,此时需要 37 | 38 | - **确定目标网络上的平均包大小**;例如,经过网络分析后可知,存在 30% 的 ftp 数据(即对应 1500 字节的大数据包)和 70% 的 VoIP 数据(即对应大量 64 字节的小数据包),因此,平均包大小在 800 字节左右; 39 | - **基于简单的公式换算**,就能得出当前吞吐量为多少 Mbps ,假如当前平均包大小为 800 字节,且设备性能假定为 100kpps 的话;则有 `100 * 1024 * 800 * 8 / 1024 = 640000 kbps = 62.5 Mbps` 40 | 41 | 需要注意的是:上述计算不能当作公式使用,因为设备性能(pps)是和包大小相关的,且这种相关性并非线性关系; 42 | 43 | 44 | > P.S. There is one more thing I need to say. There are at least three well know packet size: the least one - **64 bytes** (toughest case for device, usually referred with **router/switch** performance), the biggest one **1500 bytes** (sometimes 1400 bytes) usually referred with **firewall/VPN** performance and the so-called "real" one - **IMIX** at **427 bytes**, which represents an average packet size somewhere in the Internet (but I saw values in between 300-900 bytes) 45 | 46 | 三种常用作基准的包大小: 47 | 48 | - **64** 字节:常用于讨论 router/switch 的设备性能; 49 | - **1500** 字节(有时也用 1400 字节):常用于讨论 firewall/VPN 的设备性能; 50 | - **427** 字节:常用于讨论 [IMIX](https://en.wikipedia.org/wiki/Internet_Mix) ,代表了 typical Internet traffic ; 51 | 52 | > 在线计算工具:[这里](http://www.ccievault.net/index.php/tools) 53 | 54 | 55 | ---------- 56 | 57 | 58 | 参考: 59 | 60 | - [wiki/Throughput](https://en.wikipedia.org/wiki/Throughput) 61 | - [Bits per second to packets per second converter](http://www.ccievault.net/index.php/articles/37-cvnarticles/58-bps2pps) 62 | - [How many Packets per Second per port are needed to achieve Wire-Speed?](https://kb.juniper.net/InfoCenter/index?page=content&id=KB14737) 63 | 64 | 65 | -------------------------------------------------------------------------------- /Linux/如何实现内核旁路.md: -------------------------------------------------------------------------------- 1 | # 如何实现内核旁路 2 | 3 | > 原文地址:[这里](https://blog.cloudflare.com/kernel-bypass/) 4 | 5 | 不幸的是,对于一些更特别的工作负载,Vanilla Linux 内核的网络处理速度是不够的。举个例子,在 CloudFlare,我们持续地处理洪水般的数据包。**Vanilla Linux 处理速度仅能达到约 1M pps** ,这在我们的工作环境下是不够的,尤其时网卡是有能力处理大量数据包的。**现代 10Gbps 网卡的处理能力通常能够达到至少 10M pps** 。 6 | 7 | ![hispeed](https://raw.githubusercontent.com/moooofly/ImageCache/master/Pictures/hispeed.jpg "hispeed") 8 | 9 | 很明显,能够在我们已有硬件基础上,“挤压”出更多 packets 处理能力的办法就是从 Linux 内核网络协议栈下手,即 "kernel bypass" 技术;本文就深入研究实现该技术的各种方式; 10 | 11 | ## 内核不给力 12 | 13 | 可以通过一个小试验令你确信解决 Linux 问题确实是必要的;首先我们看看在完美条件下,kernel 能够处理多少 packets ;因为传递 packets 到用户空间代价高昂,因此替代方案为一旦 packets 离开了 network driver 代码的处理范围,就直接丢弃;据我所知,Linux 上不修改内核源码前提下,丢弃数据包的最快方法是:在 `PREROUTING` iptables chain 上设置一些 DROP 规则。 14 | 15 | ``` 16 | $ sudo iptables -t raw -I PREROUTING -p udp --dport 4321 --dst 192.168.254.1 -j DROP 17 | $ sudo ethtool -X eth2 weight 1 18 | $ watch 'ethtool -S eth2|grep rx' 19 | rx_packets: 12.2m/s 20 | rx-0.rx_packets: 1.4m/s 21 | rx-1.rx_packets: 0/s 22 | ... 23 | ``` 24 | 25 | > 注意:实际操作现实结果有所不同; 26 | 27 | 如上所示,网卡接收速度可达 12M pps ;通过 `ethtool -X` 来调整网卡上的间接表(indirection table),可以将所有的数据包引向 RX queue #0 ;正如我们看到的,kernel 能够在单 CPU 的一个 queue 上达到 1.4M pps 的处理速度; 28 | 29 | 在单核上达到 1.4M pps 是一个相当不错的结果,但不幸的是,协议栈无法进行扩展。当数据包被分配到多核上时,这个成绩会急剧下降。让我们看看把数据包分到 4 个 RX queues 的结果。 30 | 31 | ``` 32 | $ sudo ethtool -X eth2 weight 1 1 1 1 33 | $ watch 'ethtool -S eth2|grep rx' 34 | rx_packets: 12.1m/s 35 | rx-0.rx_packets: 477.8k/s 36 | rx-1.rx_packets: 447.5k/s 37 | rx-2.rx_packets: 482.6k/s 38 | rx-3.rx_packets: 455.9k/s 39 | ``` 40 | 41 | 此时每个核的处理速度是 480k pps。这是个糟糕的消息。即使乐观地假设增加多个核心不会进一步地造成性能的下降,处理数据包的核心也要多达 20 个才能达到线速度。所以内核是不起作用的。 42 | 43 | ## 内核旁路前来救驾 44 | 45 | ![bypass-1](https://raw.githubusercontent.com/moooofly/ImageCache/master/Pictures/bypass-1.jpg "bypass-1") 46 | 47 | 关于 Linux 内核网络性能的局限早已[不是什么新鲜事](https://lwn.net/Articles/629155/)了。在过去的几年中,人们多次尝试解决这个问题。这里列出一些广为人知的内核旁路技术。 48 | 49 | ### PACKET_MMAP 50 | 51 | [Packet_mmap](https://www.kernel.org/doc/Documentation/networking/packet_mmap.txt) 是一种用于 fast packet sniffing 的 Linux API 。尽管它不是严格意义上的内核旁路技术,但它仍就在该列表中占有一席之地,该技术在 Vanilla kernels 中已经存在。 52 | 53 | ### PF_RING 54 | 55 | PF_RING 是另一种用来提升数据包捕获速度的知名技术。与 `packet_mmap` 不同,PF_RING 不在内核主线中,并且需要特殊模块支持。通过 ZC drivers 和 `transparent_mode = 2` 设置,**所有的 packets 将只会被传递给 PF_RING 客户端,而不会投给内核网络协议栈**。由于内核正是导致 packet 处理变慢的原因,该技术确保了最快的处理。 56 | 57 | ### Snabbswitch 58 | 59 | `Snabbswitch` 是一种基于 Lua 语言的网络框架,主要用来写 L2 应用。其工作方式为:完全接管网卡,并在用户空间实现了一种硬件驱动。其通过将设备寄存器 mmap 到 `sysfs` 上(sysfs 是 Linux 内核中设计较新的一种虚拟的基于内存的文件系统),在 PCI 设备级别上实现了[用户空间 IO (UIO)](https://lwn.net/Articles/232575/);这种方式实现了非常快地操作能力,但是也导致**数据包完全跳过了内核网络协议栈**。 60 | 61 | ### DPDK 62 | 63 | `DPDK` 是一个基于 C 语言实现的网络框架,专门为 Intel 芯片所创造。本质上和 `snabbswitch` 类似,因为它也是一套完整框架,并依[赖于 UIO](https://www.slideshare.net/garyachy/dpdk-44585840) 。 64 | 65 | ### Netmap 66 | 67 | `Netmap` 也是一个功能丰富的网络框架,但和 UIO 技术相比,其最终实现为多个内核模块;为了和网络硬件集成在一起,用户需要给内核网络驱动打补丁。增加复杂性的最大好处是有一个详细文档说明的、[设备厂商无关的和清晰的 API](https://www.freebsd.org/cgi/man.cgi?query=netmap&sektion=4) 。 68 | 69 | 70 | ## 方案选择 71 | 72 | 由于内核旁路技术的主要目的就是不再让内核处理数据包,所以我们可以排除 `packet_mmap` 方式。因为这种方式不会接管数据包,其只是一个用于数据包嗅探的快速接口。同样,不支持 ZC 模块的普通 `PF_RING` 也没有什么吸引力,因为其主要目标是对 libpcap 进行加速(libpcap 是 unix/linux 平台下的网络数据包捕获函数包,大多数网络监控软件都以它为基础)。 73 | 74 | 我们已经排除了两种技术,但不幸的是,对于我们遇到的工作负载情况,[剩余的解决方案](https://www.slideshare.net/shemminger/uio-final)中同样没有一种满足要求; 75 | 76 | 77 | 让我解释下为何这么说;为了实现内核旁路技术,剩余的技术:`Snabbswitch`、`DPDK` 和 `netmap` 需要接管(独占)整个网卡,不允许该网卡上的任何 traffic 到达(经过)内核。在 CloudFlare 中,我们不能接受让一个 offloaded 应用**独占整个网卡**。 78 | 79 | 不得不说,有很多人会使用上面的技术;在其他条件允许的情况下,独占一个网卡用于旁路可能是一个可以接受的方案。 80 | 81 | ## 无需独占网卡的技术 82 | 83 | ### Solarflare 之 EF_VI 84 | 85 | ![efvi-model](https://raw.githubusercontent.com/moooofly/ImageCache/master/Pictures/efvi-model.png "efvi-model") 86 | 87 | Solarflare 网卡支持 OpenOnload,一个神奇的网卡加速器。EF_VI 作为一个专用库,仅能用在 Solarflare 网卡上;在底层,每个 EF_VI 程序可以访问一条特定的 RX 队列,这条 RX 队列对内核不可见的。默认情况下,这个队列不接收数据,直到你创建了一个 EF_VI “过滤器”。这个过滤器只是一个隐藏的流控制规则。你用 ethtool -n 也看不到,但实际上这个规则已经存在网卡中了。对于 EF_VI 来说,除了分配 RX 队列并且管理流控制规则,剩下的任务就是提供一个API 让用户空间可以访问这个队列。 88 | 89 | ### Bifurcated driver(分叉驱动) 90 | 91 | ![dpdk-model](https://raw.githubusercontent.com/moooofly/ImageCache/master/Pictures/dpdk-model.png "dpdk-model") 92 | 93 | 虽然 EF_VI 是 Solarflare 所特有的,其他网卡还是可以复制这个技术。首先我们需要一个支持多队列的网卡,同时它还支持流控制和操作间接表。 94 | 95 | 有了这些功能,我们可以: 96 | 97 | - 正常启动网卡,让内核来管理一切。 98 | - 修改间接表以确保没有数据包流向任一 RX 队列。比如说我们选择 16 号 RX 队列。 99 | - 通过流控制规则将一个特定的网络流引到 16号 RX 队列。 100 | 101 | 完成这些,剩下的步骤就是提供一个用户空间的 API ,从 16 号 RX 队列上接收数据包,并且不会影响其他任何队列。 102 | 103 | 这个想法在 DPDK 社区被称为“分叉驱动”。它们打算在 2014 年创建分叉驱动,不幸的是 这个补丁 还没进入内核的主线。 104 | 105 | ### Virtualization approach(虚拟化方案) 106 | 107 | ![virt-model](https://raw.githubusercontent.com/moooofly/ImageCache/master/Pictures/virt-model.png "virt-model") 108 | 109 | 针对 intel 82599 还有另外一种选择。我们可以利用网卡上的虚拟化功能来实现内核旁路,而不需要通过分叉驱动程序。 110 | 111 | 首先我简单说下背景。有结果证明,在虚拟化世界中将数据包从主机传递到客户机,虚拟机通常是瓶颈。因此,这些年对虚拟化性能的需求与日俱增,通过软件模拟网络硬件的仿真技术成为了影响性能的主要障碍。 112 | 113 | 网卡厂商增加一些特性来加速虚拟客户端。其中一项虚拟化技术,要求网卡虚拟成多个 PCI 设备。虚拟客户端可以操作这些虚拟接口,无需与主机操作系统进行任何合作。 114 | 115 | ## 总结 116 | 117 | 实现内核旁路并没有那么简单。虽然已存在很多开源技术,但看起来全部都需要一块专用(dedicated)网卡。这里我们展示三种可以选择的框架: 118 | 119 | - EF_VI-style hidden RX queues 120 | - DPDK bifurcated driver 121 | - The VF hack 122 | 123 | 不幸的是,在我们所研究过的众多技术中,似乎只有 EF_VI 满足我们的实际环境。我热切期望一种开源内核旁路 API 的出现,唯一的要求是不需要一块专用的网卡。 -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # MarkSomethingDown 2 | 3 | “对我来说,博客首先是一种知识管理工具,其次才是传播工具。我的技术文章,主要用来整理我还不懂的知识。我只写那些我还没有完全掌握的东西,那些我精通的东西,往往没有动力写。炫耀从来不是我的动机,好奇才是。” by *阮一峰* 4 | -------------------------------------------------------------------------------- /RabbitMQ/AMQP & RabbitMQ.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moooofly/MarkSomethingDown/3ed8d77b34dfb893b865932086065265876e3bc6/RabbitMQ/AMQP & RabbitMQ.pdf -------------------------------------------------------------------------------- /RabbitMQ/Dissecting the Rabbitd: RabbitMQ Internal Architecture.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moooofly/MarkSomethingDown/3ed8d77b34dfb893b865932086065265876e3bc6/RabbitMQ/Dissecting the Rabbitd: RabbitMQ Internal Architecture.pdf -------------------------------------------------------------------------------- /RabbitMQ/HAProxy 使用姿势.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # 安装一些必要的包 4 | ```shell 5 | apt-get -y install libpcre3 libpcre3-dev 6 | apt-get -y install openssl libssl-dev 7 | apt-get -y install zlib1g-dev 8 | ``` 9 | 10 | > 注意:若想在 haproxy-1.6.7 中使能 lua 功能,则必须安装 lua5.3 版本,否则编译不通过; 11 | 12 | 在 Ubuntu 15.04 中默认只提供 lua5.2 版本,不符合要求; 13 | ```shell 14 | apt-get -y install lua5.2 liblua5.2-dev 15 | ``` 16 | 17 | # 源码安装 lua5.3 18 | ```shell 19 | wget http://www.lua.org/ftp/lua-5.3.3.tar.gz 20 | tar zxvf lua-5.3.3.tar.gz 21 | cd lua-5.3.3/ 22 | make linux 23 | make install 24 | ``` 25 | 26 | > 注意:按照上面的方式,默认会将 lua5.3 安装到如下路径中 27 | ```shell 28 | cd src && mkdir -p /usr/local/bin /usr/local/include /usr/local/lib /usr/local/man/man1 /usr/local/share/lua/5.3 /usr/local/lib/lua/5.3 29 | cd src && install -p -m 0755 lua luac /usr/local/bin 30 | cd src && install -p -m 0644 lua.h luaconf.h lualib.h lauxlib.h lua.hpp /usr/local/include 31 | cd src && install -p -m 0644 liblua.a /usr/local/lib 32 | cd doc && install -p -m 0644 lua.1 luac.1 /usr/local/man/man1 33 | ``` 34 | 35 | # 源码编译 haproxy-1.6.7 36 | ```shell 37 | wget http://haproxy.1wt.eu/download/1.6/src/haproxy-1.6.7.tar.gz 38 | tar zxvf haproxy-1.6.7.tar.gz 39 | cd haproxy-1.6.7/ 40 | make TARGET=linux2628 CPU=native USE_PCRE=1 USE_OPENSSL=1 USE_ZLIB=1 USE_LUA=1 41 | make install 42 | ``` 43 | 44 | > 注意:按照上面的方式,默认会将 haproxy 安装到如下路径中 45 | ```shell 46 | install -d "/usr/local/sbin" 47 | install haproxy "/usr/local/sbin" 48 | install -d "/usr/local/share/man"/man1 49 | install -m 644 doc/haproxy.1 "/usr/local/share/man"/man1 50 | install -d "/usr/local/doc/haproxy" 51 | for x in configuration proxy-protocol management architecture cookie-options lua linux-syn-cookies network-namespaces close-options intro; do \ 52 | install -m 644 doc/$x.txt "/usr/local/doc/haproxy" ; \ 53 | done 54 | ``` 55 | 56 | 安装成功后通过 `haproxy -vv` 可以看到如下输出信息 57 | ```shell 58 | HA-Proxy version 1.6.7 2016/07/13 59 | Copyright 2000-2016 Willy Tarreau 60 | 61 | Build options : 62 | TARGET = linux2628 63 | CPU = native 64 | CC = gcc 65 | CFLAGS = -O2 -march=native -g -fno-strict-aliasing -Wdeclaration-after-statement 66 | OPTIONS = USE_ZLIB=1 USE_OPENSSL=1 USE_LUA=1 USE_PCRE=1 67 | 68 | Default settings : 69 | maxconn = 2000, bufsize = 16384, maxrewrite = 1024, maxpollevents = 200 70 | 71 | Encrypted password support via crypt(3): yes 72 | Built with zlib version : 1.2.8 73 | Compression algorithms supported : identity("identity"), deflate("deflate"), raw-deflate("deflate"), gzip("gzip") 74 | Built with OpenSSL version : OpenSSL 1.0.1f 6 Jan 2014 75 | Running on OpenSSL version : OpenSSL 1.0.1f 6 Jan 2014 76 | OpenSSL library supports TLS extensions : yes 77 | OpenSSL library supports SNI : yes 78 | OpenSSL library supports prefer-server-ciphers : yes 79 | Built with PCRE version : 8.35 2014-04-04 80 | PCRE library supports JIT : no (USE_PCRE_JIT not set) 81 | Built with Lua version : Lua 5.3.3 82 | Built with transparent proxy support using: IP_TRANSPARENT IPV6_TRANSPARENT IP_FREEBIND 83 | 84 | Available polling systems : 85 | epoll : pref=300, test result OK 86 | poll : pref=200, test result OK 87 | select : pref=150, test result OK 88 | Total: 3 (3 usable), will use epoll. 89 | 90 | ``` 91 | 92 | 93 | 基于本地 RabbitMQ 节点构建集群的配置文件 94 | 95 | ```shell 96 | # HAProxy Config for Local RabbitMQ Cluster 97 | 98 | global 99 | log 127.0.0.1 local0 info 100 | maxconn 4096 101 | stats socket /tmp/haproxy.socket uid haproxy mode 770 level admin 102 | daemon 103 | 104 | defaults 105 | log global 106 | mode tcp 107 | option tcplog 108 | option dontlognull 109 | retries 3 110 | option redispatch 111 | maxconn 2000 112 | timeout connect 5s 113 | timeout client 120s 114 | timeout server 120s 115 | 116 | listen rabbitmq_local_cluster 117 | bind :5670 118 | mode tcp 119 | balance roundrobin 120 | server rabbit 127.0.0.1:5672 check inter 5000 rise 2 fall 3 121 | server rabbit_1 127.0.0.1:5673 check inter 5000 rise 2 fall 3 122 | server rabbit_2 127.0.0.1:5674 check inter 5000 rise 2 fall 3 123 | 124 | listen private_monitoring 125 | bind :8100 126 | mode http 127 | option httplog 128 | stats enable 129 | stats uri /stats 130 | stats refresh 5s 131 | 132 | ``` 133 | 134 | # 启动 135 | ```shell 136 | haproxy -f /etc/haproxy/haproxy_rmq_cluster.cfg 137 | ``` 138 | 139 | # 重新加载 140 | ```shell 141 | haproxy -f /etc/haproxy/haproxy_rmq_cluster.cfg -p $(pidof haproxy) -sf $(pidof haproxy) 142 | ``` 143 | 144 | 145 | -------------------------------------------------------------------------------- /RabbitMQ/README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # TODO 4 | 5 | 6 | ---------- 7 | 8 | # 故障排查 9 | 10 | - [2016-07-20 线上 RabbitMQ 问题排查](https://github.com/moooofly/MarkSomethingDown/blob/master/RabbitMQ/2016-07-20%20%E7%BA%BF%E4%B8%8A%20RabbitMQ%20%E9%97%AE%E9%A2%98%E6%8E%92%E6%9F%A5.md) 11 | - [2016-08-17 腾讯云网路故障+RabbitMQ 节点异常](https://github.com/moooofly/MarkSomethingDown/blob/master/RabbitMQ/2016-08-17%20%E8%85%BE%E8%AE%AF%E4%BA%91%E7%BD%91%E8%B7%AF%E6%95%85%E9%9A%9C%2BRabbitMQ%20%E8%8A%82%E7%82%B9%E5%BC%82%E5%B8%B8.md) 12 | - [2016-09-03 双节点 RabbitMQ 集群故障](https://github.com/moooofly/MarkSomethingDown/blob/master/RabbitMQ/2016-09-03%20%E5%8F%8C%E8%8A%82%E7%82%B9%20RabbitMQ%20%E9%9B%86%E7%BE%A4%E6%95%85%E9%9A%9C.md) 13 | 14 | ---------- 15 | 16 | 17 | # 插件使用 18 | 19 | ## management 插件 20 | 21 | - [RabbitMQ management 插件数据库重置代价问题](https://github.com/moooofly/MarkSomethingDown/blob/master/RabbitMQ/RabbitMQ%20management%20%E6%8F%92%E4%BB%B6%E6%95%B0%E6%8D%AE%E5%BA%93%E9%87%8D%E7%BD%AE%E4%BB%A3%E4%BB%B7%E9%97%AE%E9%A2%98.md) 22 | - [RabbitMQ management 插件相关配置解析](https://github.com/moooofly/MarkSomethingDown/blob/master/RabbitMQ/RabbitMQ%20management%20%E6%8F%92%E4%BB%B6%E7%9B%B8%E5%85%B3%E9%85%8D%E7%BD%AE%E8%A7%A3%E6%9E%90.md) 23 | - [RabbitMQ management 插件过载问题](https://github.com/moooofly/MarkSomethingDown/blob/master/RabbitMQ/RabbitMQ%20management%20%E6%8F%92%E4%BB%B6%E8%BF%87%E8%BD%BD%E9%97%AE%E9%A2%98.md) 24 | - [RabbitMQ management 插件过载问题(高级篇)](https://github.com/moooofly/MarkSomethingDown/blob/master/RabbitMQ/RabbitMQ%20management%20%E6%8F%92%E4%BB%B6%E8%BF%87%E8%BD%BD%E9%97%AE%E9%A2%98%EF%BC%88%E9%AB%98%E7%BA%A7%E7%AF%87%EF%BC%89.md) 25 | 26 | ## sharding 插件 27 | 28 | - [RabbitMQ 之 Sharding 插件](https://github.com/moooofly/MarkSomethingDown/blob/master/RabbitMQ/RabbitMQ%20%E4%B9%8B%20Sharding%20%E6%8F%92%E4%BB%B6.md) 29 | 30 | ## shovel 插件 31 | 32 | ## federation 插件 33 | 34 | 35 | ---------- 36 | 37 | # 资源告警 38 | 39 | - [RabbitMQ 中发生内存和磁盘告警时的行为](https://github.com/moooofly/MarkSomethingDown/blob/master/RabbitMQ/RabbitMQ%20中发生内存和磁盘告警时的行为.md) 40 | - [RabbitMQ 中的内存使用说明](https://github.com/moooofly/MarkSomethingDown/blob/master/RabbitMQ/RabbitMQ%20%E4%B8%AD%E7%9A%84%E5%86%85%E5%AD%98%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E.md) 41 | - [RabbitMQ 中的内存告警问题](https://github.com/moooofly/MarkSomethingDown/blob/master/RabbitMQ/RabbitMQ%20%E4%B8%AD%E7%9A%84%E5%86%85%E5%AD%98%E5%91%8A%E8%AD%A6%E9%97%AE%E9%A2%98.md) 42 | - [RabbitMQ 中的磁盘告警问题](https://github.com/moooofly/MarkSomethingDown/blob/master/RabbitMQ/RabbitMQ%20%E4%B8%AD%E7%9A%84%E7%A3%81%E7%9B%98%E5%91%8A%E8%AD%A6%E9%97%AE%E9%A2%98.md) 43 | - [RabbitMQ 之连接阻塞通知功能](https://github.com/moooofly/MarkSomethingDown/blob/master/RabbitMQ/RabbitMQ%20%E4%B9%8B%E8%BF%9E%E6%8E%A5%E9%98%BB%E5%A1%9E%E9%80%9A%E7%9F%A5%E5%8A%9F%E8%83%BD.md) 44 | 45 | 46 | ---------- 47 | 48 | # 功能特性 49 | 50 | - [RabbitMQ 之延迟队列](https://github.com/moooofly/MarkSomethingDown/blob/master/RabbitMQ/RabbitMQ%20%E4%B9%8B%E5%BB%B6%E8%BF%9F%E9%98%9F%E5%88%97.md) 51 | - [RabbitMQ 之 queue 长度限制](https://github.com/moooofly/MarkSomethingDown/blob/master/RabbitMQ/RabbitMQ%20%E4%B9%8B%20queue%20%E9%95%BF%E5%BA%A6%E9%99%90%E5%88%B6.md) 52 | 53 | 54 | ---------- 55 | 56 | 57 | # 系统状态 58 | 59 | - [RabbitMQ 之 rabbitmqctl status 输出分析](https://github.com/moooofly/MarkSomethingDown/blob/master/RabbitMQ/RabbitMQ%20%E4%B9%8B%20rabbitmqctl%20status%20%E8%BE%93%E5%87%BA%E5%88%86%E6%9E%90.md) 60 | - [RabbitMQ 之生产环境配置检查表](https://github.com/moooofly/MarkSomethingDown/blob/master/RabbitMQ/RabbitMQ%20%E4%B9%8B%E7%94%9F%E4%BA%A7%E7%8E%AF%E5%A2%83%E9%85%8D%E7%BD%AE%E6%A3%80%E6%9F%A5%E8%A1%A8.md) 61 | 62 | 63 | ---------- 64 | 65 | 66 | # 集群相关 67 | 68 | - [HAProxy 使用姿势](https://github.com/moooofly/MarkSomethingDown/blob/master/RabbitMQ/HAProxy%20%E4%BD%BF%E7%94%A8%E5%A7%BF%E5%8A%BF.md) 69 | - [RabbitMQ 集群启动相关问题](https://github.com/moooofly/MarkSomethingDown/blob/master/RabbitMQ/RabbitMQ%20%E9%9B%86%E7%BE%A4%E5%90%AF%E5%8A%A8%E7%9B%B8%E5%85%B3%E9%97%AE%E9%A2%98.md) 70 | 71 | 72 | ---------- 73 | 74 | 75 | # 模拟测试 76 | 77 | - [RabbitMQ 错误行为模拟测试](https://github.com/moooofly/MarkSomethingDown/blob/master/RabbitMQ/RabbitMQ%20%E9%94%99%E8%AF%AF%E8%A1%8C%E4%B8%BA%E6%A8%A1%E6%8B%9F%E6%B5%8B%E8%AF%95.md) 78 | 79 | 80 | ---------- 81 | 82 | # 杂七杂八 83 | 84 | - [RabbitMQ 使用问题记录](https://github.com/moooofly/MarkSomethingDown/blob/master/RabbitMQ/RabbitMQ%20%E4%BD%BF%E7%94%A8%E9%97%AE%E9%A2%98%E8%AE%B0%E5%BD%95.md) 85 | - [RabbitMQ 使用姿势简介](https://github.com/moooofly/MarkSomethingDown/blob/master/RabbitMQ/RabbitMQ%20%E4%BD%BF%E7%94%A8%E5%A7%BF%E5%8A%BF%E7%AE%80%E4%BB%8B.md) 86 | 87 | -------------------------------------------------------------------------------- /RabbitMQ/RabbitMQ Operations.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moooofly/MarkSomethingDown/3ed8d77b34dfb893b865932086065265876e3bc6/RabbitMQ/RabbitMQ Operations.pdf -------------------------------------------------------------------------------- /RabbitMQ/RabbitMQ in Action(v2.7.0).pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moooofly/MarkSomethingDown/3ed8d77b34dfb893b865932086065265876e3bc6/RabbitMQ/RabbitMQ in Action(v2.7.0).pdf -------------------------------------------------------------------------------- /RabbitMQ/RabbitMQ 中发生内存和磁盘告警时的行为.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | # Memory and Disk Alarms 5 | 6 | 在两种场景下,RabbitMQ 会为了避免自身崩溃而停止从客户端连接上进行消息读取: 7 | - 当**内存使用**超过配置阈值上限时; 8 | - 当**磁盘空闲空间**低于配置阈值下限时; 9 | 10 | 两种场景下,RabbitMQ 都会临时性的阻塞所有连接,即停止从客户端(发布消息的)连接上进行读取行为;针对每条连接的心跳监控功能也会同时被去使能;通过 `rabbitmqctl` 和 management 插件看到的所有(被 Producer 使用的)网络连接状态,或者变为 `blocking`(表明当前并未在这些连接上发布消息,而此时可以继续操作)或者变为 `blocked`(表明已经有消息发布在这些连接上,而此时处于 pause 状态) 11 | 12 | 当 RabbitMQ 运行于 cluster 中时,内存和磁盘告警的影响都是 cluster 范围的;如果 cluster 中的某个节点达到了阈值限制,则所有节点都会触发连接的阻塞; 13 | 14 | 这里的实现意图是:只停止 producer 但允许 consumer 不受影响的继续运行;然而,因为 AMQP 协议允许多个 producers 和 consumers 在同一个 channel 上工作;也允许在同一个连接上的不同 channel 中工作,因此上面的逻辑实现并不完美; 15 | 16 | 在实际场景中,上述策略对于大多数应用来说都不会导致任何问题,因为此时只会看到截流导致的延迟;无论如何,若设计考量上允许,基于独立的 AMQP 连接处理 producing 或 consuming 是明智的选择; 17 | 18 | 19 | > 相关阅读: 20 | > - [内存阈值工作方式](https://github.com/moooofly/MarkSomethingDown/blob/master/RabbitMQ/RabbitMQ%20%E4%B8%AD%E7%9A%84%E5%86%85%E5%AD%98%E5%91%8A%E8%AD%A6%E9%97%AE%E9%A2%98.md) 21 | > - [磁盘阈值工作方式](https://github.com/moooofly/MarkSomethingDown/blob/master/RabbitMQ/RabbitMQ%20%E4%B8%AD%E7%9A%84%E7%A3%81%E7%9B%98%E5%91%8A%E8%AD%A6%E9%97%AE%E9%A2%98.md) 22 | > - [客户端如何确定自己被阻塞了](https://github.com/moooofly/MarkSomethingDown/blob/master/RabbitMQ/RabbitMQ%20%E4%B9%8B%E8%BF%9E%E6%8E%A5%E9%98%BB%E5%A1%9E%E9%80%9A%E7%9F%A5%E5%8A%9F%E8%83%BD.md) 23 | 24 | ## Related concepts 25 | 26 | 当 RabbitMQ 的 fd 使用量接近了操作系统允许的限制值时,则会直接拒绝掉客户端的连接建立; 27 | 当客户端发布消息的速度快于 RabbitMQ 的处理能力时,则会进入[流控](http://www.rabbitmq.com/flow-control.html)处理过程; 28 | 29 | ---------- 30 | 31 | 官网原文:[这里](http://www.rabbitmq.com/alarms.html) 32 | 33 | -------------------------------------------------------------------------------- /RabbitMQ/RabbitMQ 中的内存使用说明.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | # 内存使用 5 | 6 | RabbitMQ 能够报告自身的内存使用情况,以便用户获知系统的哪部分正在使用内存; 7 | 8 | 需要注意的是,所有的指标值都是基于底层 Erlang VM 返回的大概值;但是你仍旧应该认为其足够准确; 9 | 10 | 你可以通过 `rabbitmqctl status` 命令获取内存使用情况报告; 11 | 12 | ![rabbitmqctl status 中的 memory 输出信息](https://raw.githubusercontent.com/moooofly/ImageCache/master/Pictures/rabbitmqctl%20status%20中输出的%20memory%20详情.png "rabbitmqctl status 中的 memory 输出信息") 13 | 14 | 或者通过 management 插件 Web UI 中的 node 详情页进行查看; 15 | 16 | ![web UI 中的 memory 输出信息](https://raw.githubusercontent.com/moooofly/ImageCache/master/Pictures/web%20UI%20上输出的memory%20详情.png "web UI 中的 memory 输出信息") 17 | 18 | 内存使用情况被划分为下面几类(相互直接没有覆盖): 19 | 20 | ## Connections 21 | 22 | 这部分内存由外部程序向 RabbitMQ 创建的 connection 和 channel 构成;在使能了某些插件的情况下,一些由 RabbitMQ 向外部业务发起的 connection 和 channel 占用的内存也将计算在内;若启用了 SSL ,那么也包括这部分使用的内存; 23 | 24 | ## Queues 25 | 26 | 由每条 queue 进程占用的内存构成;需要注意的是,queue 会在达到设置的内存压力阈值时,将 their contents 给 swap 到磁盘上;消息 body 不被统计在这里,而是会被算进 Binary 内存占用统计中; 27 | 28 | ## Plugins 29 | 30 | 被插件所占用的内存;这部分统计值不包括 Erlang client 所使用的部分(已被统计到 Connection 占用内存中),也不包括 management 插件数据库所使用的部分(该内存单独统计); 31 | 注意:RabbitMQ 会针对协议插件,如 STOMP 和 MQTT 统计每条 connection 使用的内存; 32 | 33 | ## Other process memory 34 | 35 | Memory belonging to processes not counted above, and memory assigned to "processes" by the Erlang VM, but not to any one process. Memory that has recently been garbage collected can show up here briefly. 36 | 37 | ## Mnesia 38 | 39 | mnesia 数据库会维护所有数据的一份内存拷贝(即使当前节点为磁盘节点);典型情况下,只有当存在大量 queues, exchanges, bindings, users 或 virtual hosts 时才会占用很大内存; 40 | 41 | ## Message store index 42 | 43 | 默认的消息存储实现会在内存中维护一份针对所有消息的索引,包括那些已经被 page out 到磁盘上的消息的索引; 44 | 45 | ## Management database 46 | 47 | 在使能了 management 插件的情况下,其使用的统计数据库占用的内存; 48 | 在 cluster 中,该数据库仅会出现某一个节点上; 49 | 50 | ## Other ETS tables 51 | 52 | 除了上面三种集合之外的其他内存表占用的内存; 53 | 需要注意的是,由于当前 Erlang 运行时版本中的 bug ,某些内存占用会被统计到这里,但同时也统计到其他表自身内存占用中; 54 | 55 | ## Binaries 56 | 57 | 在 Erlang VM 中由共享 binary 数据使用的内存;In-memory message bodies show up here. 58 | 59 | ## Code 60 | 61 | 代码本身占用的内存;该值基本不会有啥变化; 62 | 63 | ## Atoms 64 | 65 | 由 atom 占用的内存;该值基本不会有啥变化; 66 | 67 | ## Other system memory 68 | 69 | 被 Erlang 自身使用的其他内存;其中的一种就是可用文件描述符数目; 70 | 71 | 72 | ---------- 73 | 74 | 75 | 官网地址:[这里](http://www.rabbitmq.com/memory-use.html) -------------------------------------------------------------------------------- /RabbitMQ/RabbitMQ 中的内存告警问题.md: -------------------------------------------------------------------------------- 1 | 2 | # Memory Alarms 3 | 4 | 在启动了 RabbitMQ 后,若执行过 `rabbitmqctl set_vm_memory_high_watermark fraction` 命令,RabbitMQ server 会探测计算机上已安装 RAM 总量;默认情况下,当 RabbitMQ server 使用了超过 40% 的 RAM 内存时,会触发内存告警并阻塞住所有 connection ;一旦告警被解除(例如当 server 将消息 page out 到磁盘时,或者将消息 delivery 到客户端时)常规服务能力就能够恢复了; 5 | 6 | 内存阈值默认被设置为安装 RAM 的 **40%** ; 7 | 8 | > ⚠️ 该值并不会真正阻止 RabbitMQ server 使用超过 40% 的内存,而只是一个会令 publisher 开始被阻塞的点;在最坏的情况下,由于 Erlang 垃圾回收器的原因,可能会导致内存使用量被 double(默认情况下为 RAM 的 80%);因此强烈建议开启操作系统本身的 swap 或 page 功能; 9 | 10 | 在 32-bit 体系架构中,每个进程可用内存的限制为 2GB ;而常规实现的 64-bit 体系架构(即AMD64 和 Intel EM64T)中仅允许每个进程使用区区 256TB ;64-bit Windows 更进一步将其限制为8TB ;另外需要注意的是,就算在 64-bit 操作系统中,一个 32-bit 进程通常也只会使用最大 2GB 的地址空间; 11 | 12 | ## Configuring the Memory Threshold 13 | 14 | 可以通过配置文件调整触发**流控机制**的内存阈值;下面的示例中将阈值设置成默认的 0.4 : 15 | 16 | ```shell 17 | [{rabbit, [{vm_memory_high_watermark, 0.4}]}]. 18 | ``` 19 | 20 | 默认值 0.4 代表了 40% 的已安装 RAM 或者 40% 的可用虚拟地址空间(比前者更小);例如在一个32-bit 平台上,如果你安装了 4GB 的 RAM ,那么 40% 的 4GB 为 1.6GB ,但是在 32-bit 的 Windows 上,通常会限制进程只能使用 2GB 内存,因此这里实际得到的阈值为 2GB 的 40% ,即 820MB ; 21 | 22 | 另一种方案为,直接设置节点可用内存阈值为一个具体数值;下面的例子中设置阈值为 1073741824 字节(1024 MB) : 23 | 24 | ```shell 25 | [{rabbit, [{vm_memory_high_watermark, {absolute, 1073741824}}]}]. 26 | ``` 27 | 28 | 与上面相同的例子,但使用了内存单位 MiB: 29 | 30 | ```shell 31 | [{rabbit, [{vm_memory_high_watermark, {absolute, "1024MiB"}}]}]. 32 | ``` 33 | 34 | 如果上面设置的绝对数值超过了实际安装的 RAM 大小,或者可用的虚拟地址空间大小,阈值会被自动调整为两者中较小的那个值; 35 | 36 | 在 RabbitMQ server 启动时,内存使用限制信息会输出到 `RABBITMQ_NODENAME.log` 文件中: 37 | 38 | ```shell 39 | =INFO REPORT==== 29-Oct-2009::15:43:27 === 40 | Memory limit set to 2048MB. 41 | ``` 42 | 43 | 可以通过 `rabbitmqctl status` 命令查询内存阈值的具体数值; 44 | 45 | 可以在 broker 处于运行状态时进行阈值的修改,只需执行 `rabbitmqctl set_vm_memory_high_watermark fraction` 或者 `rabbitmqctl set_vm_memory_high_watermark absolute memory_limit` 命令; 46 | 47 | 可以在上述命令中直接使用内存单位(如 MiB); 48 | 49 | 通过上述命令进行变更后,修改在 broker 停止运行前一直有效;若想 broker 重启后仍然有效,需要将相应的配置写入到配置文件中; 50 | 51 | 在具有 hot-swappable RAM 的系统中,内存限制会有所不同,when this command is executed without altering the threshold, due to the fact that the total amount of system RAM is queried. 52 | 53 | ### Disabling all publishing 54 | 55 | 若设置 `set_vm_memory_high_watermark` 为 0 则会立刻触发内存告警 ,并且令所有的 publishing 行为立即停止(这对于希望实现全局范围内进行 publish 停止功能来说非常有用); 56 | 57 | 设置命令为 58 | ```shell 59 | rabbitmqctl set_vm_memory_high_watermark 0 60 | ``` 61 | 62 | ## Limited Address Space 63 | 64 | 当在 64 bit 的操作系统(或者 32 bit 带有 PAE 的操作系统)上将 RabbitMQ 运行在 32 bit 的 Erlang VM 中时,可访问的内存是受限的;服务器会检测到这种情况,并记录如下日志信息: 65 | 66 | ```shell 67 | =WARNING REPORT==== 19-Dec-2013::11:27:13 === 68 | Only 2048MB of 12037MB memory usable due to limited address space. 69 | Crashes due to memory exhaustion are possible - see 70 | http://www.rabbitmq.com/memory.html#address-space 71 | ``` 72 | 73 | 内存告警系统并不是完美的;尽管停止 publishing 行为通常会阻止任何后续内存使用,但仍有可能存在其他东东继续内存消耗;当发生这种情况时,通常物理内存会被耗尽,之后操作系统会开始进行 swap 操作;但是当运行在受限地址空间的情况下,内存使用超限将会导致 VM 崩溃; 74 | 75 | 因此,强烈建议在 64 bit 操作系统上只使用 64 bit Erlang VM ; 76 | 77 | 78 | ## Configuring the Paging Threshold 79 | 80 | 在 broker 真正达到内存使用上限并阻塞 publishing 行为前,会尝试通过 page out 方式将 queue 中内容换出到磁盘,以释放内存占用;page out 行为是同时针对 persistent 和 transient 消息的(persistent 消息已经存在于磁盘上了,page out 操作只是将其他信息从内存中清除干净); 81 | 82 | 默认情况下,page out 行为开始于 broker 的内存占用达到了阈值 50% 的时候;也就是说,当默认的高水位(阈值)设置为 0.4 时,内存使用量在达到 20% 后就会触发 page out 操作;可以通过 `vm_memory_high_watermark_paging_ratio` 配置项进行调整,默认值为 0.5 : 83 | 84 | ```shell 85 | [{rabbit, [{vm_memory_high_watermark_paging_ratio, 0.75}, 86 | {vm_memory_high_watermark, 0.4}]}]. 87 | ``` 88 | 89 | 上述配置会在内存使用达到 30% 时开始进行 page out 操作,达到 40% 时阻塞 publishing 行为 ; 90 | 91 | > ⚠️ 设置 `vm_memory_high_watermark_paging_ratio` 的值大于 1.0 是可以的;在这种情况下,queues 将不会将其内容 page 到磁盘上;在这种情况下,如果 memory alarm 被触发了,producer 会照上面所说的被阻塞; 92 | 93 | ## Unrecognised platforms 94 | 95 | 如果 RabbitMQ server 无法识别你的系统,其会在 `RABBITMQ_NODENAME.log` 文件中附加如下告警信息,其中假定系统安装了 1GB 的 RAM : 96 | 97 | ```shell 98 | =WARNING REPORT==== 29-Oct-2009::17:23:44 === 99 | Unknown total memory size for your OS {unix,magic_homebrew_os}. Assuming memory size is 1024MB. 100 | ``` 101 | 102 | 在这种情况下,`vm_memory_high_watermark` 配置值会被用作放大假定的 1GB RAM 的乘数;若 `vm_memory_high_watermark` 被设置为 0.4 ,RabbitMQ 的内存阈值将被设置为 410MB ,即无论何时 RabbitMQ 使用了超过 410MB 的内存,都会导致 producer 被阻塞;也就是说,当 RabbitMQ 无法识别你的平台时,如果你实际安装了 8GB RAM ,并且你想让 RabbitMQ 在内存使用超过 3GB 时阻塞 producer ,你就可以设置 `vm_memory_high_watermark` 为 3 ; 103 | 104 | 关于推荐 RAM 水位设置,可以参考 《[RabbitMQ 之生产环境配置检查表](https://github.com/moooofly/MarkSomethingDown/blob/master/RabbitMQ/RabbitMQ%20%E4%B9%8B%E7%94%9F%E4%BA%A7%E7%8E%AF%E5%A2%83%E9%85%8D%E7%BD%AE%E6%A3%80%E6%9F%A5%E8%A1%A8.md)》; 105 | 106 | 107 | ---------- 108 | 109 | 官网原文:[这里](http://www.rabbitmq.com/memory.html) -------------------------------------------------------------------------------- /RabbitMQ/RabbitMQ 中的磁盘告警问题.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # Disk Alarms 4 | 5 | RabbitMQ 能够在磁盘空闲空间低于某个阈值时阻塞 producer ;该实现方式很有必要,因为即使是非持久消息,也会在某些时候被 page out 到磁盘上;而磁盘空间的耗尽可能会导致服务的崩溃;默认情况下,RabbitMQ 会在空闲磁盘空间低于 50MB 时阻塞住 producer ,并阻止驻留内存的消息被 page out 到磁盘;这种行为能够减少,但无法消除由于磁盘空间耗尽导致崩溃的可能性;尤其需要注意的是,如果消息被 page out 到磁盘过快,则非常有可能耗尽磁盘空间,并在两次运行磁盘空间监控之间发生崩溃;一种更加保守的方式为设置阈值限制等于系统中已安装的内存量 ; 6 | 7 | 全局流控会在空闲磁盘空间低于配置的阈值时触发;drive 或 partition 上能够被 broker 的数据库使用的空闲空间量,会以至少 10 秒一次的频率被监控,从而决定是否触发或清除告警; 8 | 9 | 监控进程是伴随 broker 启动而启动的,并会在 broker 的日志文件中输出如下内容: 10 | 11 | ```shell 12 | =INFO REPORT==== 23-Jun-2012::14:52:41 === 13 | Disk free limit set to 953MB 14 | ``` 15 | 16 | 在无法识别的平台上,监控进程将不被启动,并在日志中输出如下内容: 17 | 18 | ```shell 19 | =WARNING REPORT==== 23-Jun-2012::15:45:29 === 20 | Disabling disk free space monitoring 21 | ``` 22 | 23 | 当在 cluster 中运行 RabbitMQ 时,磁盘告警为 cluster 范围的;只要 cluster 中有一个节点发生了低于阈值的情况,所有节点都会阻塞连接; 24 | 25 | RabbitMQ 会周期性检查空闲磁盘空间量;检查的频率和上次检查时的空闲量有关(这是为了保证磁盘告警能够在空闲空间耗尽时被及时触发);通常情况下,磁盘空间检查为 10 一次,但该频率会随着阈值的接近而增加;当非常接近阈值时,RabbitMQ 会以每秒 10 次的频率进行检查,此时会对系统负载有所影响; 26 | 27 | # Configuring the Disk Free Space Limit 28 | 29 | 磁盘空闲空间阈值可以通过 `disk_free_limit` 进行配置;默认要求在数据库所在分区上只要存在 50MB 的空闲空间;如下配置文件设置磁盘空间空闲阈值为 1GB : 30 | ```shell 31 | [{rabbit, [{disk_free_limit, 1000000000}]}]. 32 | ``` 33 | 34 | 或者你也可以使用具体的内存单位进行设置(kB, kiB, MB, MiB, GB, GiB 等): 35 | ```shell 36 | [{rabbit, [{disk_free_limit, "1GB"}]}]. 37 | ``` 38 | 39 | 还可以设置相对于 RAM 的磁盘空闲阈值;如下配置文件中设置了磁盘空闲阈值和机器中的 RAM 相同: 40 | ```shell 41 | [{rabbit, [{disk_free_limit, {mem_relative, 1.0}}]}]. 42 | ``` 43 | 44 | 该阈值可以通过 `rabbitmqctl set_disk_free_limit disk_limit` 或 `rabbitmqctl set_disk_free_limit mem_relative fraction` 命令进行运行时调整;变更的效果在 broker 关闭前一直有效;若想配置一直有效,请写入配置文件; 45 | 46 | 47 | ---------- 48 | 49 | 官网原文:[这里](http://www.rabbitmq.com/disk-alarms.html) 50 | 51 | -------------------------------------------------------------------------------- /RabbitMQ/RabbitMQ 之 Delayed messages.md: -------------------------------------------------------------------------------- 1 | # RabbitMQ 之 Delayed messages 2 | 3 | ## [How to create a delayed queue in RabbitMQ?](http://stackoverflow.com/questions/17014584/how-to-create-a-delayed-queue-in-rabbitmq) 4 | 5 | ## [Delayed message in RabbitMQ](http://stackoverflow.com/questions/4444208/delayed-message-in-rabbitmq) 6 | 7 | ## [Delayed messages](https://www.cloudamqp.com/docs/delayed-messages.html) 8 | 9 | ## [RabbitMQ delayed message exchange plugin with Node.JS](https://www.cloudamqp.com/blog/2016-02-05-rabbitmq_delayed_message_exchange_plugin_with_node_js.html) 10 | 11 | ## [How to schedule or delay messages with RabbitMQ using a Dead Letter Exchange](http://yuserinterface.com/dev/2013/01/08/how-to-schedule-delay-messages-with-rabbitmq-using-a-dead-letter-exchange/) 12 | 13 | ## [Delayed message delivery in RabbitMQ](https://ivanyu.me/blog/2015/02/16/delayed-message-delivery-in-rabbitmq/) 14 | 15 | ## [Sending Scheduled/delayed messages with RabbitMQ through java client](http://www.tothenew.com/blog/sending-scheduleddelayed-messages-with-rabbitmq-through-java-client/) 16 | 17 | ## [Scheduling Messages with RabbitMQ](https://www.rabbitmq.com/blog/2015/04/16/scheduling-messages-with-rabbitmq/) 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /RabbitMQ/RabbitMQ 之 queue 长度限制.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | # [Queue Length Limit](http://www.rabbitmq.com/maxlength.html) 6 | 7 | 8 | queue 的最大长度可以基于**消息数量**进行限制,也可以基于**总字节数**进行限制(由所有消息 body 的长度之和决定,忽略消息属性占用的长度和任何其他额外开销),或者基于两种方式一起进行限制; 9 | 10 | 对于任何给定的 queue ,其最大长度(无论任何类型)都可以由 client 使用 queue 参数进行定义,或者在 server 侧通过 [policies](http://www.rabbitmq.com/parameters.html#policies) 进行定义;当通过两种方式同时设置了最大长度时时,取其中的最小值; 11 | 12 | 在任何情况下,**ready** 消息数总是被计算在内的;**unacknowledged** 消息不会被计算到限制值内;`rabbitmqctl list_queues` 输出项中的 **messages_ready** 和 **message_bytes_ready** ,以及相应的 management API 可以展示的限制值; 13 | 14 | **当限制值被达到时,消息或者会被从 queue 的前端被丢弃或者被 dead-lettered 处理,以便为新消息留出空间**; 15 | 16 | ## Configuration using arguments 17 | 18 | 最大消息数目(非负整数)可以通过 `x-max-length` 参数在 queue 声明中进行设置; 19 | 20 | 最大消息字节数目(非负整数)可以通过 `x-max-length-bytes` 参数在 queue 声明中进行设置; 21 | 22 | 如果两种参数都设置了,则同时生效;先达到限定值的限制先起作用; 23 | 24 | 下面示例中的 Java 代码声明了最多允许保存 10 条消息的 queue : 25 | 26 | ```java 27 | Map args = new HashMap(); 28 | args.put("x-max-length", 10); 29 | channel.queueDeclare("myqueue", false, false, false, args); 30 | ``` 31 | 32 | ## Configuration using policy 33 | 34 | 若想通过 policy 指定最大长度,可以将 key `max-length` 和/或 `max-length-bytes` 添加到 policy 定义中,例如: 35 | 36 | | | | 37 | -------- | --- 38 | | rabbitmqctl | rabbitmqctl set_policy Ten "^one-meg$" '{"max-length-bytes":1000000}' --apply-to queues| 39 | | rabbitmqctl (Windows) | rabbitmqctl set_policy Ten "^one-meg$" "{""max-length-bytes"":1000000}" --apply-to queues | 40 | 41 | 上述命令确保了名为 one-meg 的 queue 能够保存不超过 1MB 的消息 body 大小; 42 | 43 | Policies 的设置还可以使用 management plugin 进行,详见 [policy documentation](http://www.rabbitmq.com/parameters.html#policies) ; 44 | 45 | -------------------------------------------------------------------------------- /RabbitMQ/RabbitMQ 之吞吐量最大化.md: -------------------------------------------------------------------------------- 1 | 2 | # [Maximize throughput with RabbitMQ](http://stackoverflow.com/questions/10030227/maximize-throughput-with-rabbitmq) 3 | 4 | 在我们的项目中,会使用 RabbitMQ 的 "**Task Queues**" 模式来传输数据; 5 | 6 | 在 **producer** 侧,我们基于 node.js 构建了一些 TCP server 负责接收高并发数据,以及将数据无任何修改的转发给 MQ ; 7 | 8 | 在 **consumer** 侧,我们使用 JAVA client 从 MQ 中获取、处理、应答数据; 9 | 10 | 所以**问题**集中在: 11 | - **如何获取最大的消息传输吞吐量?**(例如 400,000 msg/second) 12 | - **使用多少 queues 是最佳实践?** 13 | - **是否 queue 的数据越多即意味着更好的吞吐量和性能?** 14 | - 是否还有其他的点需要注意的?在该使用场景中是否有任何已知的最佳实践指导原则? 15 | 16 | Any comments are highly appreciated!! 17 | 18 | ---------- 19 | 20 | 为了获得 RabbitMQ 的**最佳性能**,可以遵循其作者给出的使用建议;详见 《[Sizing your Rabbits](http://www.rabbitmq.com/blog/2011/09/24/sizing-your-rabbits/)》: 21 | 22 | > - **RabbitMQ 中的 queues 在空状态下是最快的**; 23 | > - 当一个 queue 处于空状态,并且其下有 consumers 处于准备接收消息的状态时,只要有消息到达该 queue ,就会直接转发给相应的 consumer ; 24 | > - 对于 **persistent** 消息发送到 **durable** queue 的情况来说,没什么好说的,消息确实会落到磁盘上,但该动作是**异步**完成的,并且相应的消息都会 **buffered heavily**; 25 | > - 关键点在于:在上述场景中,RabbitMQ 需要进行 book-keeping 的内容几乎可以忽略不计,需要修改的 data structures 也非常少量,并且仅需要分配非常少量的内存; 26 | 27 | 如果你想要深入理解和 RabbitMQ queues 性能相关的更多内容,可以看看[这篇博客文章](http://www.rabbitmq.com/blog/2011/10/27/performance-of-queues-when-less-is-more/); 28 | 29 | ---------- 30 | 31 | According to a response I once got from the `rabbitmq-discuss` mailing group there are other things that you can try to **增加吞吐量** 和 **降低延迟**: 32 | 33 | - **Use a larger prefetch count**. Small values hurt performance. 34 | - A topic exchange is slower than a direct or a fanout exchange. 35 | - **Make sure queues stay short**. Longer queues impose more processing overhead. 36 | - If you care about latency and message rates then **use smaller messages**. **Use an efficient format** (e.g. avoid XML) or **compress the payload**. 37 | - Experiment with **HiPE**, which helps performance. 38 | - **Avoid transactions and persistence**. Also avoid publishing in `immediate` or `mandatory` mode. Avoid HA. Clustering can also impact performance. 39 | - You will achieve better throughput on a multi-core system if you have multiple queues and consumers. 40 | - Use at least `v2.8.1`, which introduces `flow control`. Make sure the memory and disk space alarms never trigger. 41 | - Virtualisation can impose a small performance penalty. 42 | - Tune your OS and network stack. Make sure you provide more than enough RAM. Provide fast cores and RAM. 43 | 44 | 45 | 一点个人看法: 46 | - **prefetch** 应该尽量调大; 47 | - topic 匹配性能问题已经在新版本中有所优化; 48 | - queue 中留存的消息应该尽量少(理想很丰满,现实很残酷); 49 | - 消息大小越小越能降低延迟,提高消息速率;而将小消息合并成大消息进行处理,能够增大吞吐量; 50 | - 对消息进行高效的表达(更精简的数据格式 or 压缩),能够提升传输性能(业务处理复杂度略微提高); 51 | - 可以试试 `HiPE` ,对性能提升有好处(在 **Erlang R17** 后 `HiPE` 已经相当稳定); 52 | - 事务肯定要禁止使用,可靠性通过其他方案解决; 53 | - `immediate` 已经被取消,存在其他等效方案;`mandatory` 适用于某些特定场景,是否使用应该视情况而定; 54 | - 避免 HA ?扯什么蛋!cluster 也会对性能有一定影响?嗯,这是一句没有错误的废话; 55 | - 在多核系统上跑 RabbitMQ 性能会比跑在单核上强(需要注意下 docker 等虚拟环境等使用情况); 56 | - `flow control` 功能从 `v2.8.1` 开始才有; 57 | - Virtualisation 也会对性能有一定影响,如果这里是指通过 management 插件实现的 Virtualisation ,那么性能问题已经被遇到了! 58 | 59 | ---------- 60 | 61 | You will increase the throughput with a **larger prefetch count** AND at the same time **ACK multiple messages** (instead of sending ACK for each message) from your consumer. 62 | 63 | But, of course, ACK with `multiple` flag on ([here](http://www.rabbitmq.com/amqp-0-9-1-reference.html#basic.ack)) requires extra logic on your consumer application ([here](http://lists.rabbitmq.com/pipermail/rabbitmq-discuss/2013-August/029600.html)). You will have to keep a list of delivery-tags of the messages delivered from the broker, their status (whether your application has handled them or not) and ACK every N-th delivery-tag (NDTAG) when all of the messages with delivery-tag less than or equal to NDTAG have been handled. 64 | 65 | 更大的 prefetch 数值 + 一次 ack 多条消息的组合必然可以提高吞吐量,但会增加一定的业务处理复杂度; 66 | 67 | -------------------------------------------------------------------------------- /RabbitMQ/RabbitMQ 之延迟队列.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | # Lazy Queues 5 | 6 | 从 RabbitMQ 3.6.0 版本开始,broker 中增加了 **Lazy Queues** 这个东东:这种 queue 基于 disk 保存尽量多的消息,并且尽在 consumers 进行消息请求时才将对应的内容加载到 RAM 中;这也就是 lazy 的真谛; 7 | 8 | lazy queues 存在的主要目标就是为了支持超长 queues 的存在(100w+ 消息);这种 queues 通常出现在 consumers 在较长时间内都无法从 queue 中取走消息的场景;问题出现原因是多样的:比如 consumers 处于离线状态;consumers 发生 crash ;或者由于维护的需要将其取消了等等; 9 | 10 | 默认情况下,queues 会在内存中对 publish 到 RabbitMQ 的消息进行缓存;该缓存主要用于尽快向 consumers 投递消息(⚠️ 持久化消息会在进入 broker 后被写入磁盘,同时在缓存中保留一份);无论何时,只要 broker 认为应该释放内存了,缓存中的消息就会被 page out 到 disk 上;将消息 Page 到 disk 到行为需要花费一定的时间,并阻塞 queue 进程本身,即在此过程中无法接收新消息;尽管我们在最新 RabbitMQ 版本中已经改进了 paging 算法,但在某些使用场景下仍旧不是很理想:例如 queue 存在 100w+ 消息需要 page out 到磁盘时; 11 | 12 | Lazy queues 在这种场景下可以发挥作用:移除了缓存的使用,仅在 consumers 请求时加载消息到内存中;Lazy queues 会将每一条发送到当前 queue 的消息立刻写入文件系统,完全消除了前面提到的缓存的使用;好处就是极大的减少了 queue 所需的 RAM 量,同时消除了 paging 问题;尽管 lazy queue 会增加 I/O 使用,但充其量也就等同于处理持久化消息的情况; 13 | 14 | 15 | # Using Lazy Queues 16 | 17 | 通过 `queue.declare` 或 policy 设置,Queues 可以通过在 `default` 模式或 `lazy` 模式下;如果出现同时在 policy 和 queue 声明参数中设置了 queue 模式的情况,则通过 queue 声名参数进行的设置具有更高的优先级;这就意味着,如果 queue 的模式是通过声明参数进行的指定,则只能通过先删除该 queue ,再重新声明的方式进行变更; 18 | 19 | ## Configuration using arguments 20 | 21 | queue 模式可以通过在 queue 声明中国年指定 `x-queue-mode` 参数的方式进行设置;有效模式为 "default" 和 "lazy" ;如果在声明的时候没有指定模式,则使用 "default" 模式;`default` 模式就是在 3.6.0 版本以前一直在使用的模式,因此此变更不会导致兼容问题; 22 | 23 | 在下面的例子中,通过 Java 代码声明了模式为 "lazy" 的 queue : 24 | 25 | ``` 26 | Map args = new HashMap(); 27 | args.put("x-queue-mode", "lazy"); 28 | channel.queueDeclare("myqueue", false, false, false, args); 29 | ``` 30 | 31 | ## Configuration using policy 32 | 33 | 若想通过 policy 方式设置 queue 模式,只需将 queue-length 作为 key 添加到 policy 定义中,例如: 34 | 35 | | | | | 36 | ----------------- | ---------------------------- | ------------------ 37 | | rabbitmqctl | rabbitmqctl set_policy Lazy "^lazy-queue$" '{"queue-mode":"lazy"}' --apply-to queues| 38 | | rabbitmqctl (Windows) | rabbitmqctl set_policy Lazy "^lazy-queue$" "{""queue-mode"":""lazy""}" --apply-to queues | 39 | 40 | 上述设置会令名为 lazy-queue 的 queue 工作在 lazy 模式下; 41 | 42 | Policies 也可以通过 management 插件进行定义,详情参见 [policy]() 文档; 43 | 44 | ## Changing queue modes 45 | 46 | 如果你是通过 policy 设置的 queue 模式,那么你就能够在无需删除后重建的情况下,直接运行时修改;如果你想要另之前设置的 lazy-queue 变回 default 模式,则你可以通过如下命令进行操作: 47 | 48 | | | | | 49 | ----------------- | ---------------------------- | ------------------ 50 | | rabbitmqctl | rabbitmqctl set_policy Lazy "^lazy-queue$" '{"queue-mode":"default"}' --apply-to queues| 51 | | rabbitmqctl (Windows) | rabbitmqctl set_policy Lazy "^lazy-queue$" "{""queue-mode"":""default""}" --apply-to queues | 52 | 53 | 54 | # Performance Considerations for Lazy Queues 55 | 56 | ## Disk Utilization 57 | 58 | 正如上面所提到的,lazy queues 会将每一条进入该 queue 的消息写入磁盘;这会导致 I/O 操作的增加,但是请记住,此时的行为和具有持久化属性的消息到来时的情况是一样的;注意,即使被 publish 的消息是 transient 消息,在使用 lazy queue 时一样会被写入磁盘;而对于处于 default 模式的 queues 来说,transient 消息只会在需要进行 page out 处理时才被写入磁盘; 59 | 60 | ## RAM Utilization 61 | 62 | lazy queues 使用的内存量远远小于 default queues ;尽管难于针对每一种场景给出具体的数字,但可以给出我们得到的一些结论:我们尝试发送了 10 million 消息到 queue 中,并且该 queue 不存在消费者;消息体大小为 1000 字节;default queues 需要占用 1.2GB 的 RAM,而 lazy queues 仅需要 1.5MB 的 RAM ; 63 | 64 | 对于 default queue 来说,其需要花费 801 秒来发送 10MM 消息,平均发送速率为 12469 msg/s ;而发送同样数目的消息到 lazy queue 时,时间消耗为 421 秒,平均发送速率为 23653 msg/s ;上述差别可以解释为:对于 default queue 来说,会时不时的发生将消息 page out 到 disk 到情况;一旦我们激活了一个 consumer ,在消息转发时 lazy queue 就会相应的产生大概 40MB 的 RAM 占用;平均消息接收速率变为 13938 msg/s ; 65 | 66 | 67 | 可以通过如下的 java 库进行上述测试的重放: 68 | 69 | ```shell 70 | ./runjava.sh com.rabbitmq.examples.PerfTest -e test -u test_queue \ 71 | -f persistent -s 1000 -x1 -y0 -C10000000 72 | ``` 73 | 74 | > ⚠️ 上述测试仅为简单测试用例,请确保使用你自己的 benchmark 进行测试; 75 | 76 | Don't forget to change the queue mode between benchmarks runs. 77 | 78 | 79 | ## Converting between queue modes 80 | 81 | 如果我们需要将一个 default queue 转变成 lazy queue ;我们将会面临相似的性能冲击:因为 queue 将需要将消息 page 到 disk 上;当我们将某个 queue 转成 lazy 模式时,首先会进行消息 page 到 disk 到操作,之后才会开始处理 publish, ack 和其他命令; 82 | 83 | 当某个 queue 从 lazy 模式切回 default 模式,对应的处理过程就如同服务被重启后 queue 的恢复过程;会按照 16384 条消息一组的方式,批量加载到之前提到的缓存中; 84 | 85 | 86 | ---------- 87 | 88 | 89 | 官网原文:[这里](http://www.rabbitmq.com/lazy-queues.html) -------------------------------------------------------------------------------- /RabbitMQ/RabbitMQ 之批处理问题说明.md: -------------------------------------------------------------------------------- 1 | 最近写了一篇关于 RabbitMQ 的[分析文章](https://github.com/moooofly/MarkSomethingDown/blob/master/RabbitMQ/2017-03-02%20%E7%BA%BF%E4%B8%8A%20RabbitMQ%20%E9%97%AE%E9%A2%98%E6%8E%92%E6%9F%A5.md),公司小伙伴对如下说法存有异议: 2 | 3 | > 消息大小越小越能降低延迟,提高消息速率;而将小消息合并成大消息进行处理,能够增大吞吐量; 4 | 5 | 核心问题在于:**将小消息合并为大消息进行处理,是否能够增大吞吐量,以及适用的场合是什么**; 6 | 7 | 我的观点为:采用批处理对提高吞吐量是有好处的,原因在于可以大大减少网络通信;但是否适合采用批处理方式,则需要区分具体的使用场景; 8 | 9 | 举例:假如我要发送 100 条消息,当按照一次一条的方式处理时,整体耗时一定是高于将 100 条消息打包后一次性进行发送的耗时的;但是,如果你的关注点在于“某一条消息的延迟”,那么对于“某一条消息”来说,由于批处理而导致的延迟可能会更大一些; 10 | 11 | 另外,可以参考下 Amazon Simple Queue Service 关于批处理的[说明](http://docs.amazonaws.cn/zh_cn/AWSSimpleQueueService/latest/SQSDeveloperGuide/throughput.html),内容摘录如下: 12 | 13 | > Amazon SQS API 中的批处理操作可通过一次处理多达 10 条消息来进一步优化吞吐量。 14 | > 15 | > 批处理的基本理念是:**在与服务的每次往返操作中执行更多工作,以及在批处理请求的多条消息中分配批处理操作的延迟时间,而不是接受单一消息的整个延迟时间**。由于每次往返操作都会执行更多工作,因此,批处理请求可以更高效地使用线程和连接,从而提高吞吐量。Amazon SQS 按请求收费,因此,如果由更少的请求来处理等量的消息,则费用可以大幅降低。此外,更少的线程和连接可以降低客户端资源使用率,并且可以通过使用更小或更少的主机执行相同的工作来降低客户端费用。 16 | > 17 | > 不过,**批处理确实会让应用程序变得有点复杂**。例如,应用程序必须先积累消息,然后才能发送消息,并且有时候必须花费较长的时间来等待响应,但是批处理在以下情况下可能很有效: 18 | > 19 | > - 您的应用程序正在短时间内生成大量消息,因此,延迟时间决不会很长。 20 | > - 消息使用者从队列中自行获取消息,这与典型的消息创建者相反,后者需要发送消息来响应它们无法控制的事件。 21 | > 22 | > 重要:即使批处理中单独的消息失败了,批处理请求也可能会成功。在提出批处理请求后,您应始终检查各条消息是否失败了,并在必要时重试。 23 | 24 | ---------- 25 | 26 | 另外一个需要提及的点是,RabbitMQ 中涉及到批处理的地方有两处: 27 | 28 | - Consumer 侧 Acknowledging Multiple Deliveries at Once; 29 | - Producer 侧使用 Publisher confirm 机制时,若 broker 设置 basic.ack 中 multiple 域为 true ; 30 | 31 | 差别在于:consumer 侧的批处理功能,需要业务自己实现相应逻辑,而 producer 侧的批处理功能,只需要理解 RabbitMQ 实现的批处理逻辑; 32 | 33 | 详见官网说明:[这里](http://www.rabbitmq.com/confirms.html); -------------------------------------------------------------------------------- /RabbitMQ/RabbitMQ 之连接阻塞通知功能.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | # Blocked Connection Notifications 5 | 6 | 在某些情况下,若 broker 触发资源阈值限制(内存或磁盘)时,客户端能够接收到连接阻塞通知信息,将会非常有必要; 7 | 8 | 这里我们会介绍一种 AMQP 协议扩展,基于该扩展 broker 就能够在发生连接阻塞时,发送 `connection.blocked` 方法给客户端;在阻塞解除时,发送 `connection.unblocked` ; 9 | 10 | 为了接收(并正确处理)上述通知(方法),客户端必须在自身的 `client-properties` 能力集中表明支持 `connection.blocked` ;官方支持的客户端已经默认支持了上述方法,并提供了注册的 handler 方法,用于处理 connection.blocked 和 connection.unblocked ; 11 | 12 | # Using Blocked Connection Notifications with Java Client 13 | 14 | 略 15 | 16 | # Using Blocked Connection Notifications with .NET Client 17 | 18 | 略 19 | 20 | # When Notifications are Sent 21 | 22 | `connection.blocked` 方法的发送时机为 RabbitMQ 首次触发资源阈值时;例如,当 RabbitMQ 节点检测到当前 RAM 已经达到阈值时,则会发送 `connection.blocked` 方法给所有已连接的、支持该特性的、作为 Producer 的客户端;如果在连接重回非阻塞状态前,当前节点又触发了磁盘空闲空间不足告警,则不会发送额外的 `connection.blocked` ; 23 | 24 | `connection.unblocked` 方法的发送时机为所有资源告警都被恢复时,之后连接将恢复到完全非阻塞状态; 25 | 26 | 27 | ---------- 28 | 29 | 官网原文:[这里](http://www.rabbitmq.com/connection-blocked.html) 30 | 31 | -------------------------------------------------------------------------------- /RabbitMQ/Troubleshooting RabbitMQ and services that use it.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moooofly/MarkSomethingDown/3ed8d77b34dfb893b865932086065265876e3bc6/RabbitMQ/Troubleshooting RabbitMQ and services that use it.pdf -------------------------------------------------------------------------------- /Redis/Redis Cluster(Redis 3.X)设计要点.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | # Redis Cluster(Redis 3.X)设计要点 5 | 6 | 7 | Redis 3.0.0 RC1 版本 10.9 号发布,[Release Note](https://raw.githubusercontent.com/antirez/redis/3.0/00-RELEASENOTES);该版本支持 Redis Cluster,相信很多同学期待已久,不过这个版本只是 RC 版本,要应用到生产环境,还得等等; 8 | 9 | Redis Cluster设计要点: 10 | 11 | ## 架构:无中心 12 | 13 | - Redis Cluster 采用无中心结构,每个节点都保存数据和整个集群的状态; 14 | - 每个节点都和其他所有节点连接,这些连接保持活跃; 15 | - 使用 `gossip` 协议传播信息以及发现新节点; 16 | - cluster 中的 node 不会为 client 代理请求,client 需要根据 node 返回的错误信息(`MOVED` 错误)重定向请求; 17 | 18 | ## 数据分布:预分桶 19 | 20 | - 预分配 16384 个桶(slot),根据 `CRC16(key) mod 16384` 的值,决定将一个 key 放到哪个桶中; 21 | - 每个 Redis 物理结点负责一部分桶的管理,当发生 Redis 节点的增减时,调整桶的分布即可; 22 | 23 | 例如,假设 Redis Cluster 由三个节点 A、B、C 构成,则 24 | - Node A 包含桶的编号可以为 0 ~ 5500 ; 25 | - Node B 包含桶的编号可以为 5500 ~ 11000 ; 26 | - Node C 包含桶的编号可以为 11001 ~ 16384 ; 27 | 28 | 当发生 Redis 节点的增减时,只需调整桶的分布; 29 | 30 | 预分桶的方案介于“**硬 Hash**”和“**一致性 Hash**”之间,牺牲了一定的灵活性,但相比“一致性Hash“,数据的管理成本大大降低; 31 | 32 | ## 可用性:Master-Slave 33 | 34 | - 为了保证服务的(高)可用性,Redis Cluster 采取的方案是的 Master-Slave ; 35 | - 每个 Redis node 可以有一个或者多个 Slave ;当 Master 挂掉时,会选举一个 Slave 成为新 Master ; 36 | - 每个 Redis node 包含(被分配)一定量的桶;只有当这些桶对应的 Master 和 Slave 都挂掉时,这部分桶中的数据才不可用; 37 | 38 | ## 写操作 39 | 40 | Redis Cluster 使用异步复制方式进行主从同步; 41 | 42 | 一个完整的写操作步骤: 43 | - client 写数据到 master 节点; 44 | - master 告诉 client "ok" ; 45 | - master 传播更新到 slave ; 46 | 47 | 存在数据丢失的风险: 48 | - 上述写步骤 1 和 2 成功后,master crash,而此时数据还没有传播到 slave ; 49 | - 由于分区导致同时存在两个 master ,client 向旧的 master 写入了数据; 50 | 51 | 当然,由于 Redis Cluster 存在超时及故障恢复机制,因此第 2 个风险基本上不可能发生; 52 | 53 | ## 数据迁移 54 | 55 | - Redis Cluster 支持在线增/减节点; 56 | - 基于桶的数据分布方式大大降低了迁移成本,只需将数据桶从一个 Redis Node 迁移到另一个 Redis Node 即可完成迁移; 57 | - 当桶从一个 Node A 向另一个 Node B 迁移时,Node A 和 Node B 都会有这个桶,Node A 上桶的状态设置为`MIGRATING` ,Node B 上桶的状态被设置为 `IMPORTING` ; 58 | - 当客户端请求时,所有在 Node A 上的请求都将由 A 来处理,所有不在 A 上的 key 都由 Node B 来处理。同时,Node A 上将不会创建新的 key ; 59 | 60 | ## 多 key 操作 61 | 62 | 当系统从单节点向多节点扩展时,多 key 操作总是一个非常难解决的问题;Redis Cluster 方案如下: 63 | - 不支持多 key 操作; 64 | - 如果一定要使用多 key 操作,请确保所有的 key 都在一个 slot 上,具体方法是使用“hash tag”方案 65 | 66 | > hash tag 方案是一种数据分布的例外情况 67 | 68 | 69 | ## Reference 70 | - [Redis cluster tutorial](http://redis.io/topics/cluster-tutorial) 71 | - [Redis cluster Specification](http://redis.io/topics/cluster-spec) 72 | 73 | 74 | ---------- 75 | 76 | 77 | 原文:[这里](http://blog.csdn.net/yfkiss/article/details/39996129) 78 | 79 | 80 | 81 | 82 | -------------------------------------------------------------------------------- /Redis/Redis 杂七杂八.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # HQ of the Redis community 4 | 5 | 社区地址:[这里](https://www.reddit.com/r/redis/) 6 | 7 | > Reddit(英语发音:/ˈrɛdɪt/)是一个娱乐、社交及新闻网站,注册用户可以将文字或链接在网站上发布,使它基本上成为了一个电子布告栏系统。注册用户可以对这些帖子进行投票,结果将被用来进行排名和决定它在首页或子页的位置。网站上的内容分类被称为“subreddits”。“subreddit”的内容包括新闻、电子游戏、电影、音乐、书籍、健身、食物和图片分享等。 8 | 9 | 10 | # 如何与 Redis community 交流 11 | 12 | 交流方式如下: 13 | - Join the [mailing list](https://groups.google.com/forum/#!forum/redis-db) (Subscribe via email). 14 | - Meet us at the #redis channel on Freenode ([web access link](http://webchat.freenode.net/?channels=redis)). 15 | - Check the Redis tag on Stack Overflow. 16 | - Follow [Redis news feed](https://twitter.com/redisfeed) and antirez on Twitter. 17 | 18 | 19 | > 相关信息补充说明: 20 | >> - [qwebirc](https://www.qwebirc.org/) 21 | >> - [QuakeNet](https://www.quakenet.org/) 22 | >> - [freenode](http://freenode.net/) 23 | >> - [fosscon](https://fosscon.us/) 24 | >> - [privateinternetaccess](https://chi.privateinternetaccess.com/) 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /nonsense/2016年12月02日 线上 zookeeper 异常情况问题纪要.md: -------------------------------------------------------------------------------- 1 | # 2016年12月02日 线上 zookeeper 异常情况问题纪要 2 | 3 | 标签(空格分隔): zookeeper 4 | 5 | --- 6 | 7 | 一句话总结:这次会议针对 zookeeper 事件进行了回顾,并将可能问题点进行了罗列,并给出了一些后续改进方案; 8 | 9 | ## 可能问题点 10 | 11 | 1. 办公网络变更(据说变更后 qcr 到办公网延迟变大,办公室到 xg 则正常); 12 | 2. 腾讯云本身存在一些问题(在 pps 打高后,同属 c 网段的两个相邻 ip 地址互 ping 延迟高达 100ms 以上;而一般情况下,互 ping 也有 8ms;据说目前使用单队列,最高 pps 在 60000 左右) 13 | 3. 应用发布无自检(导致xxxx); 14 | 4. zk 的 outstanding request 队列飙高; 15 | 16 | ## 后续解决方案 17 | 18 | 1. 建立新灾备; 19 | 2. 去除跨机房 zk 集群的使用(目前应该 xg 和 qcr 中的 zk 构成了一个大集群) 20 | 3. 在 应用 和 zk 之间增加 gateway 进行定制化处理(限流,检测异常连接等) 21 | 4. 应用自检脚本应该会提升为价值观; 22 | 5. zk 扩容(解决 outstanding request 队列飙高问题) 23 | 6. 在 qcr 重现 zk 问题 24 | 7. 完善发布工具(制定 checklist 或提供检测脚本) 25 | 26 | ## 对 sre 提出了点期待(尚未明确说明) 27 | 28 | 1. 在出问题时,能够进行系统状态留存(没有具体说留存哪些东东) 29 | 2. 异常网络流量重放(希望能够将异常情况下的网络流量抓下来,后续用于重放,当然也可以采用其它实现手段) 30 | 31 | ## 未提及的问题 32 | 33 | 1. 在网络延迟达到 100ms 的情况下,zk 集群是否存在脑裂问题(zk 的配置是否能够容忍 100ms 的延时问题) 34 | 2. python 的进程管理程序在判定 worker 进程在 30s 内未能从 zk 上将配置全部拉取成功后,会将 worker 进程杀死,但没有说明杀死的方式,以及 socket 的处理,不知道是否会对 zk 造成影响; 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /nonsense/Continuous Integration - 持续集成.md: -------------------------------------------------------------------------------- 1 | # Continuous Integration - 持续集成 2 | 3 | ## [使用 Travis 进行持续集成](http://www.liaoxuefeng.com/article/0014631488240837e3633d3d180476cb684ba7c10fda6f6000) 4 | 5 | 持续集成:Continuous Integration,简称 CI ,意思是,在一个项目中,任何人对代码库的任何改动,都会触发 CI 服务器自动对项目进行构建,自动运行测试,甚至自动部署到测试环境。这样做的好处就是,随时发现问题,随时修复。因为修复问题的成本随着时间的推移而增长,越早发现,修复成本越低。 6 | 7 | Travis CI 是在线托管的 CI 服务,用 Travis 来进行持续集成,不需要自己搭服务器,在网页上点几下就好,用起来更方便。最重要的是,它对开源项目是免费的。 8 | 9 | 因为 GitHub 和 Travis 是一对好基友,不用 GitHub 虽然也能用 Travis ,但是配置起来太麻烦。而且,作为开源项目,为什么不用 GitHub ? 10 | 11 | 需要编写一个 `.travis.yml` 文件来告诉 Travis 一些项目信息; 12 | 13 | > 是不是用了 CI 代码质量就有保证了? 14 | 15 | 这个问题的答案是:否。如果 CI 能提高代码质量,那软件公司只需要招实习生写代码外加 CI 就可以了,招那么贵的高级工程师浪费钱干啥? 16 | 17 | > 是不是用了 Travis 就实现了 CI ? 18 | 19 | 这个问题的答案还是:否。CI 是解决问题的手段而不是目的。问题是如何提高代码质量。我见过很多公司的项目,编译一次半小时(不是编译 Linux 内核那种),测试一次几个小时。不能在短时间内完成编译、测试的代码都有问题,导致 CI 形同虚设。这里的“短时间”是指 5 分钟以内。 20 | 21 | 22 | ## [使用 Jenkins 进行持续集成](http://www.liaoxuefeng.com/article/001463233913442cdb2d1bd1b1b42e3b0b29eb1ba736c5e000) 23 | 24 | 开源项目如何利用 Travis CI 进行持续集成;如果你的项目不是开源项目,可以自己搭建 CI 环境,即利用 Jenkins CI 进行持续集成; 25 | 26 | Jenkins官方网站:https://jenkins.io/ 27 | 28 | 虽然 Jenkins 提供了 Windows、Linux、OS X 等各种安装程序,但是,这些安装程序都没有 war 包好使。只需要运行命令: 29 | 30 | ``` 31 | java -jar jenkins.war 32 | ``` 33 | 34 | 浏览器登录:http://localhost:8080/ 35 | 36 | 37 | ## 其他 38 | 39 | - [Core Concepts for Beginners](https://docs.travis-ci.com/user/for-beginners) 40 | - [Getting started](https://docs.travis-ci.com/user/getting-started/) 41 | - [Building a Go Project](https://docs.travis-ci.com/user/languages/go) 42 | - [Customizing the Build](https://docs.travis-ci.com/user/customizing-the-build/) 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /nonsense/GitHub Access Token.md: -------------------------------------------------------------------------------- 1 | # GitHub Access Token 2 | 3 | ![octotree 被限速](https://raw.githubusercontent.com/moooofly/ImageCache/master/Pictures/Access%20Token%20problem%20when%20using%20octotree.png "octotree 被限速") 4 | 5 | Octotree 基于 [GitHub API](https://developer.github.com/v3/) 获取 repository metadata 信息;默认情况下,它基于 **unauthenticated requests** 访问 GitHub API ;然而,存在两种 requests 必须被鉴权的情况: 6 | 7 | - 访问一个 private repository 时 8 | - 超过了[针对 unauthenticated requests 的速率限制](https://developer.github.com/v3/#rate-limiting) 9 | 10 | 当发生上述两种情况时,Octotree 将要求你提供 [GitHub personal access token](https://help.github.com/articles/creating-a-personal-access-token-for-the-command-line/) ;如果你之前没有,可以先[创建一个](https://github.com/settings/tokens/new),再将其复制粘贴到对应的文本框中;注意,最小权限访问至少要设置为 `public_repo` 和 `repo`(如果你需要能够访问 private repositories 的话) 11 | 12 | ![Cache/Pictures/new personal access token - 1](https://raw.githubusercontent.com/moooofly/ImageCache/master/Pictures/new%20personal%20access%20token%20-%201.png "Cache/Pictures/new personal access token - 1") 13 | 14 | ![Cache/Pictures/new personal access token - 2](https://raw.githubusercontent.com/moooofly/ImageCache/master/Pictures/new%20personal%20access%20token%20-%202.png "Cache/Pictures/new personal access token - 2") 15 | 16 | 17 | - personal access token 的作用就和 OAuth access token 一样; 18 | - 可被用于基于 HTTPS 的 git 模式中,从而避免使用密码; 19 | - 可被用于基于 Basic Authentication 的 API 的鉴权; 20 | 21 | 22 | 23 | ---------- 24 | 25 | 26 | ## [Rate Limiting](https://developer.github.com/v3/#rate-limiting) 27 | 28 | 任意一个 API 请求所返回的 HTTP headers 中都包含了当前的 rate limit 状态值: 29 | 30 | ``` 31 | curl -i https://api.github.com/users/octocat 32 | HTTP/1.1 200 OK 33 | Date: Mon, 01 Jul 2013 17:27:06 GMT 34 | Status: 200 OK 35 | X-RateLimit-Limit: 60 36 | X-RateLimit-Remaining: 56 37 | X-RateLimit-Reset: 1372700873 38 | ``` 39 | 40 | | Header Name | Description | 41 | | -- | -- | 42 | | **X-RateLimit-Limit** | 每小时允许发起的最大请求数量 | 43 | | **X-RateLimit-Remaining** | 在当前 rate limit 窗口中仍允许发起的请求数量 | 44 | | **X-RateLimit-Reset** | 重置当前 rate limit 时间窗口的时间周期(以 UTC epoch seconds 为单位) | 45 | 46 | 如果超出了上述 rate limit ,则会收到如下错误返回信息: 47 | 48 | ``` 49 | HTTP/1.1 403 Forbidden 50 | Date: Tue, 20 Aug 2013 14:50:41 GMT 51 | Status: 403 Forbidden 52 | X-RateLimit-Limit: 60 53 | X-RateLimit-Remaining: 0 54 | X-RateLimit-Reset: 1377013266 55 | 56 | { 57 | "message": "API rate limit exceeded for xxx.xxx.xxx.xxx. (But here's the good news: Authenticated requests get a higher rate limit. Check out the documentation for more details.)", 58 | "documentation_url": "https://developer.github.com/v3/#rate-limiting" 59 | } 60 | ``` 61 | 62 | ## GitHub API rate limit 63 | 64 | ```shell 65 | Error: GitHub API rate limit exceeded for 220.166.254.65. (But here's the good news: Authenticated requests get a higher rate limit. Check out the documentation for more details.) 66 | Try again in 56 minutes 17 seconds, or create an personal access token: 67 | https://github.com/settings/tokens 68 | and then set it as HOMEBREW_GITHUB_API_TOKEN. 69 | ``` 70 | 71 | 解决办法: 72 | 73 | - 注册、登录 https://github.com ; 74 | - 访问 https://github.com/settings/tokens ; 75 | - 在 `Personal settings -> Personal access tokens` 中点击 "Generate new token" 创建 token ; 76 | - Make sure to copy your new personal access token now. You won't be able to see it again! 77 | - Personal access tokens function like ordinary OAuth access tokens. They can be used instead of a password for Git over HTTPS, or can be used to authenticate to the API over Basic Authentication. 78 | - 在 `~/.bashrc` 中添加 `HOMEBREW_GITHUB_API_TOKEN` 环境变量 79 | 80 | ```shell 81 | if [ -f /usr/local/bin/brew ]; then 82 | export HOMEBREW_GITHUB_API_TOKEN=xxxxxxxxxx 83 | fi 84 | ``` 85 | 86 | 87 | ## [Creating a personal access token for the command line](https://help.github.com/articles/creating-a-personal-access-token-for-the-command-line/) 88 | 89 | > You can create a personal access token and use it in place of a password when performing Git operations over HTTPS with Git on the command line or the API. 90 | 91 | 在以下场景中,personal access token 被用于鉴权 GitHub 访问: 92 | 93 | - 当你使用 [two-factor authentication](https://help.github.com/articles/about-two-factor-authentication) 时 94 | - 基于 SAML single sign-on (SSO) 访问组织中受保护的内容时;Tokens used with organizations that use SAML SSO must be authorized. 95 | 96 | ### Creating a token 97 | 98 | https://help.github.com/articles/creating-a-personal-access-token-for-the-command-line/#creating-a-token 99 | 100 | ### Using a token on the command line 101 | 102 | 一旦你拥有了 token ,你就可以在执行 Git operations over HTTPS 时使用 token 而不是密码; 103 | 104 | 例如,在命令行上你可以输入ß 105 | 106 | ``` 107 | git clone https://github.com/username/repo.git 108 | Username: your_username 109 | Password: your_token 110 | ``` 111 | 112 | Personal access tokens 只能被用于 HTTPS Git 操作;如果你的 repository 使用 SSH 形式的 remote URL ,那么你将需要[将 remote 从 SSH 切换成 HTTPS](https://help.github.com/articles/changing-a-remote-s-url/#switching-remote-urls-from-ssh-to-https) ; 113 | 114 | 如果你在使用过程中,没有被提示需要输入用户名和密码,则有可能你的密码信息已经被缓存在了你的电脑上;你可以通过[更新 Keychain](https://help.github.com/articles/updating-credentials-from-the-osx-keychain) ,将其中保存的旧密码替换成 token ; 115 | -------------------------------------------------------------------------------- /nonsense/HTTP 之 GET 在 body 中携带参数问题.md: -------------------------------------------------------------------------------- 1 | # HTTP 之 GET 在 body 中携带参数问题 2 | 3 | 在测试 Elasticsearch 时遇到下面这种测试命令: 4 | 5 | ``` 6 | curl -u elastic:changeme -XGET http://localhost:9200/_search\?pretty -d '{ "from": 30, "size":10}' 7 | ``` 8 | 9 | 可以看到这里指定的 `-XGET` ,但同时通过 `-d` 参数指定了数据内容: 10 | 11 | > 在 `man 1 curl` 中可以看到 12 | > 13 | > **`-d, --data `** 14 | > 15 | > (HTTP) Sends the specified data in a **POST** request to the HTTP server, in the same way that a browser does when a user has filled in an HTML form and presses the submit button. This will cause `curl` to pass the data to the server using the **content-type** `application/x-www-form-urlencoded`. 16 | > 17 | > `-d, --data` is the same as `--data-ascii`. `--data-raw` is almost the same but does not have a special interpretation of the `@` character. To post data purely binary, you should instead use the `--data-binary` option. To **URL-encode** the value of a form field you may use `--data-urlencode`. 18 | If any of these options is used more than once on the same command line, the data pieces specified will be merged together with a separating `&`-symbol. Thus, using '`-d name=daniel -d skill=lousy`' would generate a post chunk that looks like '`name=daniel&skill=lousy`'. 19 | > 20 | > If you start the data with the letter `@`, the rest should be a **file name** to read the data from, or `-` if you want `curl` to read the data from `stdin`. Multiple files can also be specified. Posting data from a file named 'foobar' would thus be done with `--data @foobar`. When `--data` is told to read from a file like that, carriage returns and newlines will be stripped out. If you don't want the `@` character to have a special interpretation use `--data-raw` instead. 21 | 22 | 这里就引出了一个矛盾点:在 `GET` 请求中通过 `-d` 发送数据是什么鬼?! 23 | 24 | 抓包发现确实可以这么使用: 25 | 26 | ![HTTP GET with data in body](https://raw.githubusercontent.com/moooofly/ImageCache/master/Pictures/HTTP%20GET%20with%20data%20in%20body.png "HTTP GET with data in body") 27 | 28 | 一般来讲,任何语言(特别是 javascript)实现的 HTTP 库都不允许 `GET` 请求中携带交互数据。因此,很多用户会惊讶于 `GET` 请求中居然会允许这么做。 29 | 30 | 真实情况是:在规定 HTTP 语义及内容的 [RFC 7231](http://tools.ietf.org/html/rfc7231#page-24) 中,并未限制 `GET` 请求中是否允许携带交互数据!所以,有些 HTTP 服务允许这种行为,而另外一些(特别是缓存代理)则不允许这种行为。 31 | 32 | Elasticsearch 的作者们倾向于使用 `GET` 提交查询请求,因为他们觉得这个 verb 相比 `POST` 来说,能更好的描述这种行为。然而,因为携带交互数据的 GET 请求并不被广泛支持,所以 search API 同样支持 `POST` 请求,即 33 | 34 | ``` 35 | POST /_search 36 | { 37 | "from": 30, 38 | "size": 10 39 | } 40 | ``` 41 | -------------------------------------------------------------------------------- /nonsense/Linux Man Pages in Dash.md: -------------------------------------------------------------------------------- 1 | # Linux Man Pages in Dash 2 | 3 | > Oct 21st, 2013 4 | 5 | > Dash works great as a man page browser, but I sometimes get requests to make extra docsets containing the man pages of various flavours of Linux. 6 | 7 | > I’ve decided not to pursue these requests, because: 8 | 9 | > - Updates for these docsets would be a nightmare, as man pages change a lot, individually. 10 | > - I’d have to choose which man pages to include and which not to. I’d never be able to guess which obscure man page a user might want. 11 | 12 | > The current `Man Pages` docset solves these issues by indexing the man pages that are actually on your Mac. 13 | 14 | Dash 作为 man 手册浏览工具已经做的很好了,但是还是经常会收到针对不同种类 Linux 添加额外 docsets 的需求; 15 | 16 | 但我最终决定不处理类似的请求,因为: 17 | 18 | - man 手册经常会发生变更,且都是独立变更; 19 | - 不得不选择包含哪些 man 页面,以及不包含哪些 man 页面;我无法猜测哪些费解的 man 页面是一个用户可能需要的; 20 | 21 | 当前提供的 `Man Pages` docset 通过索引你的 Mac 机器上实际安装的 man 手册的方式解决了上述问题; 22 | 23 | ## The workaround 24 | 25 | > You can copy the man pages from any Linux box to your Mac and Dash will index them as part of the regular Man Pages docset. 26 | 27 | > Step by step instructions: 28 | 29 | > - Log into your Linux box 30 | > - Run man -w to list the folders that contain man pages 31 | > - Copy these folders to your Mac 32 | > - Optional, but highly recommended: use a batch renamer to rename all of the man page files to have a common prefix. This will help you differentiate between the default macOS man pages and the Linux ones 33 | > - Move the man pages anywhere on your MANPATH, or any folder from man -w 34 | 35 | > That’s it! 36 | 37 | 你可以将任意 Linux 中的 man 手册拷贝到你的 Mac 上,之后 Dash 就能够将其作为 `Man Pages` docset 的一部分进行索引了; 38 | 39 | 操作步骤如下: 40 | 41 | - 登录到你的 Linux 机器上; 42 | - 运行 `man -w` 查看包含 man 手册页面的文件夹; 43 | - 拷贝这些文件夹到你的 Mac 中; 44 | - 可选的,但却是极力推荐的方式:使用一个批量重命名工具对所有 man 手册文件进行加前缀重命名;这样你才能区分出哪些是 macOS 默认的 man 手册,哪些是 Linux 中的 man 手册; 45 | - 将 man 手册移动到 MANPATH 环境变量中指定的路径里,或者移动到 man -w 命令输出的文件夹里; 46 | -------------------------------------------------------------------------------- /nonsense/Mac 挂在 NTFS 移动硬盘 ReadOnly 问题解决.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 参考:[这里](http://blog.csdn.net/sunbiao0526/article/details/8566317) 4 | 5 | 6 | ```shell 7 | sunfeideMacBook-Pro:data sunfei$ diskutil info /Volumes/Seagate\ Backup\ Plus\ Drive/ 8 | 9 | Device Identifier: disk2s1 10 | Device Node: /dev/disk2s1 11 | Whole: No 12 | Part of Whole: disk2 13 | Device / Media Name: Untitled 1 14 | Volume Name: Seagate Backup Plus Drive 15 | Mounted: Yes 16 | Mount Point: /Volumes/Seagate Backup Plus Drive 17 | File System Personality: NTFS 18 | Type (Bundle): ntfs 19 | Name (User Visible): Windows NT File System (NTFS) 20 | Partition Type: Windows_NTFS 21 | OS Can Be Installed: No 22 | Media Type: Generic 23 | Protocol: USB 24 | SMART Status: Not Supported 25 | Volume UUID: F7F4131A-1567-4A15-9D2F-68A69496DA0D 26 | Total Size: 1.0 TB (1000203836928 Bytes) (exactly 1953523119 512-Byte-Units) 27 | Volume Free Space: 785.6 GB (785610182656 Bytes) (exactly 1534394888 512-Byte-Units) 28 | Device Block Size: 512 Bytes 29 | Allocation Block Size: 4096 Bytes 30 | Read-Only Media: No 31 | Read-Only Volume: Yes 32 | Device Location: External 33 | Removable Media: No 34 | 35 | sunfeideMacBook-Pro:data sunfei$ 36 | 37 | 38 | sunfeideMacBook-Pro:data sunfei$ hdiutil eject /Volumes/Seagate\ Backup\ Plus\ Drive/ 39 | 40 | "disk2" unmounted. 41 | "disk2" ejected. 42 | 43 | sunfeideMacBook-Pro:data sunfei$ 44 | 45 | 46 | sunfeideMacBook-Pro:data sunfei$ sudo mkdir /Volumes/MyHD 47 | Password: 48 | sunfeideMacBook-Pro:data sunfei$ ll /Volumes/ 49 | total 8 50 | lrwxr-xr-x 1 root admin 1 6 5 12:04 Macintosh HD -> / 51 | drwxr-xr-x+ 2 root admin 68 6 6 00:28 MyHD 52 | sunfeideMacBook-Pro:data sunfei$ 53 | 54 | 55 | sunfeideMacBook-Pro:data sunfei$ sudo mount_ntfs -o rw,nobrowse /dev/disk2s1 /Volumes/MyHD/ 56 | sunfeideMacBook-Pro:data sunfei$ 57 | 58 | 59 | sunfeideMacBook-Pro:data sunfei$ mount 60 | 61 | /dev/disk1 on / (hfs, local, journaled) 62 | devfs on /dev (devfs, local, nobrowse) 63 | map -hosts on /net (autofs, nosuid, automounted, nobrowse) 64 | map auto_home on /home (autofs, automounted, nobrowse) 65 | /dev/disk2s1 on /Volumes/MyHD (ntfs, local, noowners, nobrowse) 66 | 67 | sunfeideMacBook-Pro:data sunfei$ 68 | 69 | ``` 70 | -------------------------------------------------------------------------------- /nonsense/Python 使用小结.md: -------------------------------------------------------------------------------- 1 | # Python 使用小结 2 | 3 | - 只使用 python 进行逻辑构建,作为粘合剂使用; 4 | - 安装特定版本时,需要安装配套的文档;在 python 中微小的变更都可能导致函数不可用;使用错误文档,容易抓瞎; 5 | - Jupyter 玩起来;用于私人环境,用户能拿到所有权限,不建议给别人用,可以放在虚拟机中; 6 | - IPython 必备; 7 | - 在 python 交互环境中执行 python 文件中的程序; 8 | 9 | ```python 10 | ➜ Python python 11 | Python 2.7.13 (default, Dec 17 2016, 23:03:43) 12 | [GCC 4.2.1 Compatible Apple LLVM 8.0.0 (clang-800.0.42.1)] on darwin 13 | Type "help", "copyright", "credits" or "license" for more information. 14 | >>> 15 | >>> import os 16 | >>> os.system('python test.py') 17 | 1+2 18 | 0 19 | >>> 20 | >>> 21 | >>> import test 22 | 1+2 23 | >>> 24 | ``` 25 | 26 | - 使用三引号引用双引号和单引号 27 | 28 | ```python 29 | >>> '''I'm "Dad"''' 30 | 'I\'m "Dad"' 31 | >>> 32 | ``` 33 | 34 | - 缩进:python 建议缩进统一使用四个空格实现; 35 | - 只有 if..elif..else 没有 switch ; 36 | - for 的潜台词是“枚举”,本质上是一种语法糖; 37 | - python 中的 lambda 主要用于延迟调用; 38 | - python 中的限制:只允许定义一行的 lambda ; 39 | - python 中不提倡使用 getter 和 setter ; 40 | 41 | 42 | ---------- 43 | 44 | 45 | ## Python2 v.s. Python3 46 | 47 | ### print 问题 48 | 49 | - python2 中 `print` 为关键字;允许使用 `print 'xxx'` 关键字用法和 `print('xxx')` 函数用法; 50 | - python3 中 `print` 为函数;只允许使用 `print('xxx')` 函数用法; 51 | 52 | ### input 和 raw_input 53 | 54 | ```python 55 | # input 是 python3 写法,raw_input 是对应的 python2 写法。 56 | try: 57 | input = raw_input 58 | except NameError: 59 | pass 60 | ``` 61 | 62 | > python2 中的 input 有使用风险; 63 | 64 | ### 缩进问题 65 | 66 | - P2 允许空格和 Tab 混用; 67 | - P3 不能混合使用 Tab 和空格; 68 | 69 | ### 字符串问题(Unicode) 70 | 71 | - python2 通过 `u'xxx'` 表示 Unicode ;通过 `'xxx'` 表示普通字符串; 72 | - python3 默认认为所有字符串都为 Unicode; 73 | 74 | ### 比较问题 75 | 76 | - python2 下允许数字和字符进行大小比较; 77 | - python3 下禁止; 78 | 79 | > 建议:不混合使用; 80 | 81 | ### 除法问题 / 82 | 83 | - python2 中 "/" 是整数除法; 84 | - python3 中 "/" 是浮点除法; 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /nonsense/Tmux 快捷键.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | | Ctrl+b | | 激活控制台;此时以下按键生效 | 5 | ---|---|--- 6 | | 系统操作 | ? | 列出所有快捷键;按q返回 | 7 | | | d | 脱离当前会话;这样可以暂时返回Shell界面,输入tmux attach能够重新进入之前的会话 | 8 | | | D | 选择要脱离的会话;在同时开启了多个会话时使用 | 9 | | | Ctrl+z | 挂起当前会话 | 10 | | | r | 强制重绘未脱离的会话 | 11 | | | s | 选择并切换会话;在同时开启了多个会话时使用 | 12 | | | : | 进入命令行模式;此时可以输入支持的命令,例如kill-server可以关闭服务器 | 13 | | | [ | 进入复制模式;此时的操作与vi/emacs相同,按q/Esc退出 | 14 | | | ~ | 列出提示信息缓存;其中包含了之前tmux返回的各种提示信息 | 15 | | | ? | 列出所有快捷键;按q返回 | 16 | | | ? | 列出所有快捷键;按q返回 | 17 | | | ? | 列出所有快捷键;按q返回 | 18 | | | ? | 列出所有快捷键;按q返回 | 19 | ---|---|--- 20 | | 窗口操作 | c | 创建新窗口 | 21 | | | & | 关闭当前窗口 | 22 | | | 数字键 | 切换至指定窗口 | 23 | | | p | 切换至上一窗口 | 24 | | | n | 切换至下一窗口 | 25 | | | l | 在前后两个窗口间互相切换 | 26 | | | w | 通过窗口列表切换窗口 | 27 | | | , | 重命名当前窗口;这样便于识别 | 28 | | | . | 修改当前窗口编号;相当于窗口重新排序 | 29 | | | f | 在所有窗口中查找指定文本 | 30 | ---|---|--- 31 | | 面板操作 | " | 将当前面板平分为上下两块 | 32 | | | % | 将当前面板平分为左右两块 | 33 | | | x | 关闭当前面板 | 34 | | | ! | 将当前面板置于新窗口;即新建一个窗口,其中仅包含当前面板 | 35 | | | Ctrl+方向键 | 以1个单元格为单位移动边缘以调整当前面板大小 | 36 | | | Alt+方向键 | 以5个单元格为单位移动边缘以调整当前面板大小 | 37 | | | Space | 在预置的面板布局中循环切换;依次包括even-horizontal、even-vertical、main-horizontal、main-vertical、tiled | 38 | | | q | 显示面板编号 | 39 | | | o | 在当前窗口中选择下一面板 | 40 | | | 方向键 | 移动光标以选择面板 | 41 | | | { | 向前置换当前面板 | 42 | | | } | 向后置换当前面板 | 43 | | | Alt+o | 逆时针旋转当前窗口的面板 | 44 | | | Ctrl+o | 顺时针旋转当前窗口的面板 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /nonsense/iTerm2 下使用 rz sz 命令.md: -------------------------------------------------------------------------------- 1 | # iTerm2 下使用 rz/sz 命令 2 | 3 | > 参考:[ZModem integration for iTerm 2](https://github.com/mmastrac/iterm2-zmodem) 4 | 5 | 6 | 步骤: 7 | 8 | - Install `lrzsz` on OSX: `brew install lrzsz` 9 | - Save the `iterm2-send-zmodem.sh` and `iterm2-recv-zmodem.sh` scripts in `/usr/local/bin/` 10 | - Set up Triggers (Perferences -> Profiles -> your Profile -> Advanced -> Triggers -> Edit) in iTerm 2 like so: 11 | ``` 12 | Regular expression: rz waiting to receive.\*\*B0100 13 | Action: Run Silent Coprocess 14 | Parameters: /usr/local/bin/iterm2-send-zmodem.sh 15 | Instant: checked 16 | 17 | Regular expression: \*\*B00000000000000 18 | Action: Run Silent Coprocess 19 | Parameters: /usr/local/bin/iterm2-recv-zmodem.sh 20 | Instant: checked 21 | ``` -------------------------------------------------------------------------------- /nonsense/shell 使用常见问题.md: -------------------------------------------------------------------------------- 1 | # shell 使用常见问题 2 | 3 | 标签(空格分隔): shell 4 | 5 | --- 6 | 7 | ## 如何解决 ubuntu 默认不提供 root 用户问题 8 | 9 | Ubuntu 默认安装时,并没有给 root 用户设置口令,也没有启用 root 帐户; 10 | 11 | 设置 root 用户密码(也用于重置密码),即开启 root 帐号 12 | 13 | ```shell 14 | $ sudo passwd root # 设置 root 用户密码 15 | $ su - root # 切换成 root 用户 16 | ``` 17 | 18 | 如果要再次禁用 root 帐号(锁定帐户),可以执行 19 | 20 | ```shell 21 | # sudo passwd -l root 22 | ``` 23 | 24 | 如果要再次启动 root 账号(需要以前锁定过,否则无效),可以执行 25 | 26 | ```shell 27 | sudo passwd -u root 28 | ``` 29 | 30 | 31 | ## bash v.s. dash 32 | 33 | - dash — command interpreter (shell) 34 | 35 | > `dash` is the standard command interpreter for the system. The current 36 | > version of `dash` is in the process of being changed to conform with the 37 | > POSIX 1003.2 and 1003.2a specifications for the shell. This version 38 | > has many features which make it appear similar in some respects to the 39 | > **Korn** shell, but it is not a **Korn** shell clone (see ksh(1)). Only fea‐ 40 | > tures designated by POSIX, plus a few Berkeley extensions, are being 41 | > incorporated into this shell. 42 | 43 | 44 | - bash - GNU Bourne-Again SHell 45 | 46 | > `Bash` is an `sh`-compatible command language interpreter that executes 47 | > commands read from the standard input or from a file. `Bash` also 48 | > incorporates useful features from the **Korn** and **C** shells (`ksh` and 49 | > `csh`). 50 | > 51 | > `Bash` is intended to be a conformant implementation of the Shell and 52 | > Utilities portion of the IEEE POSIX specification (IEEE Standard 53 | > 1003.1). `Bash` can be configured to be POSIX-conformant by default. 54 | 55 | 如今 Ubuntu 系统中,`/bin/sh` 默认已经指向 `dash` ,这是一个不同于 `bash` 的 shell ,它主要是为了执行脚本而出现,而不是交互;它速度更快,但功能相比 `bash` 要少很多,语法严格遵守 POSIX 标准; 56 | 57 | ```shell 58 | root@vagrant-ubuntu-trusty:~# ll /bin/sh 59 | lrwxrwxrwx 1 root root 4 Jan 17 07:14 /bin/sh -> dash* 60 | root@vagrant-ubuntu-trusty:~# 61 | ``` 62 | 63 | 如果想切换 `/bin/sh` 的默认指向(不建议修改),则执行 64 | ```shell 65 | sudo dpkg-reconfigure dash 66 | ``` 67 | 68 | > 想要进行修改的理由:脚本兼容性问题;因为 `bash` 和 `dash` 对 shell 脚本语法对兼容性有所不同; 69 | 70 | 71 | ## shell 脚本执行问题 72 | 73 | > 参考:[这里](http://stackoverflow.com/questions/31473298/i-am-puzzled-with-the-differences-between-sh-xxx-sh-and-xxx-sh-for-running/31473406)以及[这里](https://www.cyberciti.biz/faq/run-execute-sh-shell-script/) 74 | 75 | 一般情况下,在编写好 shell 脚本后,会按照如下方式执行脚本 76 | 77 | ```shell 78 | # chmod +x script-name-here.sh 79 | # 如下任选一种 80 | # ./script-name-here.sh -- 1 81 | # sh script-name-here.sh -- 2 82 | # bash script-name-here.sh -- 3 83 | ``` 84 | 85 | - 1 的成功执行,要求 `.sh` 脚本必须有可执行权限; 86 | - 1 和 2 的区别在于:1 执行时,解释器使用的是 "shebang" 行上指定的内容;2 执行时,解释器使用的是 `sh` 所链接到的 shell ; 87 | - 2 和 3 的区别在于:`sh` 可能链接到 `bash` 上,也可能链接到其他 shell 上; 88 | 89 | 90 | 91 | ### 使用 `sudo bash xxx.sh` 的原因 92 | 93 | 一般情况下,通过 shell 脚本安装应用程序时,你会需要 root 权限才能保证安装过程的顺利进行;而 root 权限在许多 Linux 和 UNIX like 系统中默认是不允许直接使用的; 94 | 95 | 通过 `sudo bash xxx.sh` 方式,可以基于用户自身密码获取 root 权限,以 root shell 运行脚本; 96 | 97 | 当然,如果知道 root 密码的话,也可以如下操作(不建议这么使用) 98 | 99 | ```shell 100 | $ su - root 101 | # bash xxx.sh 102 | ``` 103 | 104 | 105 | ## shell 切换问题 106 | 107 | > 参考:[Change Shell To Bash](https://www.cyberciti.biz/faq/how-to-change-shell-to-bash/) 108 | 109 | ### 确定指定 user 的默认 shell 110 | 111 | ```shell 112 | $ grep /etc/passwd 113 | ``` 114 | 115 | ### 确认当前系统中提供了哪些 shell 116 | 117 | ```shell 118 | $ cat /etc/shells 119 | ``` 120 | 121 | ### 进行不同 shell 切换 122 | 123 | 简单一句话就是:想使用哪种 shell 就直接输入其名字; 124 | 125 | 例如从 bash 切到 dash 时,输入 126 | 127 | ```shell 128 | # dash 129 | ``` 130 | 131 | ### 改变指定 user 的默认 shell 132 | 133 | 可用命令形式 134 | 135 | ```shell 136 | chsh 137 | chsh -s /bin/bash 138 | chsh -s /bin/bash 139 | ``` 140 | 141 | 实际操作 142 | 143 | ```shell 144 | vagrant@vagrant-ubuntu-trusty:~$ cat /etc/passwd|grep "vagrant" 145 | vagrant:x:1000:1000:,,,:/home/vagrant:/bin/bash 146 | vagrant@vagrant-ubuntu-trusty:~$ 147 | vagrant@vagrant-ubuntu-trusty:~$ chsh 148 | Password: 149 | Changing the login shell for vagrant 150 | Enter the new value, or press ENTER for the default 151 | Login Shell [/bin/bash]: /bin/dash 152 | vagrant@vagrant-ubuntu-trusty:~$ 153 | vagrant@vagrant-ubuntu-trusty:~$ cat /etc/passwd|grep "vagrant" 154 | vagrant:x:1000:1000:,,,:/home/vagrant:/bin/dash 155 | vagrant@vagrant-ubuntu-trusty:~$ 156 | ``` 157 | 158 | > 若想确定效果,则需要先 logout 再 login ; 159 | 160 | ### 查找指定 shell 的完整路径 161 | 162 | ```shell 163 | # type -a bash 164 | ``` 165 | 166 | 或者 167 | 168 | ```shell 169 | # which bash 170 | ``` 171 | 172 | 173 | -------------------------------------------------------------------------------- /nonsense/thoughtbot 的 Git 使用规范.md: -------------------------------------------------------------------------------- 1 | # [Git Protocol](https://github.com/thoughtbot/guides/tree/master/protocol/git) 2 | 3 | A guide for programming within version control. 4 | 5 | ## Maintain a Repo 6 | 7 | * 避免在源码控制中包含特定于开发机器或 process 的文件; 8 | * 在 merge 完成后,请删除 local 和 remote 上的 feature branches ; 9 | * 在 feature branch 开展开发工作; 10 | * 经常 rebase 以保证及时将 upstream 上发生的变更纳入到本地; 11 | * 基于 [pull request] 进行 code reviews ; 12 | 13 | [pull request]: https://help.github.com/articles/using-pull-requests/ 14 | 15 | ## Write a Feature 16 | 17 | - 基于 master 分支(最新代码)创建一个本地 feature branch ; 18 | 19 | ``` 20 | git checkout master 21 | git pull 22 | git checkout -b 23 | ``` 24 | 25 | - 经常 rebas码,以保证与 upstream 上的代码一致; 26 | 27 | ``` 28 | git fetch origin 29 | git rebase origin/master 30 | ``` 31 | 32 | 解决冲突; 33 | 34 | - 当 feature 开发完成、测试通过后,stage 所有变更; 35 | 36 | ``` 37 | git add --all 38 | ``` 39 | 40 | 之后进行 commit ; 41 | 42 | ``` 43 | git status 44 | git commit --verbose 45 | ``` 46 | 47 | 编写一份 [good commit message] ,示例格式如下: 48 | 49 | ``` 50 | Present-tense summary under 50 characters 51 | 52 | * More information about commit (under 72 characters). 53 | * More information about commit (under 72 characters). 54 | 55 | http://project.management-system.com/ticket/123 56 | ``` 57 | 58 | - 如果在 feature 开发中创建了不止一个 commit ,则 [use `git rebase` interactively](https://help.github.com/articles/about-git-rebase/) 59 | 以 squash 这些 commits ,使之成为更加内聚的 (cohesive)、更具可读性的 commits : 60 | 61 | ``` 62 | git rebase -i origin/master 63 | ``` 64 | 65 | - 推送该分支到你自己的远程仓库; 66 | 67 | ``` 68 | git push origin 69 | ``` 70 | 71 | - 提交 [GitHub pull request] ; 72 | 73 | 在项目的 chat room 中寻求 code review ; 74 | 75 | [good commit message]: http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html 76 | [GitHub pull request]: https://help.github.com/articles/using-pull-requests/ 77 | 78 | ## Review Code 79 | 80 | 除了 author 外的其他组员也要进行 pull request 的 review ;所有人都需要遵循 [Code Review](https://github.com/thoughtbot/guides/tree/master/code-review) 准则以免 miscommunication ; 81 | 82 | 所有人应该基于 GitHub 的 web 接口直接在代码行上进行评论和提问,也可以在项目专门的 chat room 中进行沟通; 83 | 84 | 针对 review 者自己进行变更的情况,可以 85 | 86 | ``` 87 | git checkout 88 | ./bin/setup 89 | git diff staging/master..HEAD 90 | ``` 91 | 92 | 在当前分支上进行小变更,进行 feature 测试,运行 tests,之后 commit 和 push ; 93 | 94 | 当满足要求后,在 pull request 时直接填写 `Ready to merge.` ; 95 | 96 | ## Merge 97 | 98 | **Rebase interactively**;将类似 "Fix whitespace" 这种 commits 进行 Squash ,将其变成一条或少量有价值的 commit(s) ;编辑 commit messages 以正确显示意图;运行测试; 99 | 100 | ``` 101 | git fetch origin 102 | git rebase -i origin/master 103 | ``` 104 | 105 | **Force push your branch**. 当你的 commit(s) 被 push 到 master 上时,这允许 GitHub 自动关闭你的 pull 106 | request 并将其标记为 merged ;这同样令 [find the pull request] 成为可能; 107 | 108 | ``` 109 | git push --force-with-lease origin 110 | ``` 111 | 112 | 查看新 commits 列表;查看发生变更的文件;Merge 分支内容到 master ; 113 | 114 | ``` 115 | git log origin/master.. 116 | git diff --stat origin/master 117 | git checkout master 118 | git merge --ff-only 119 | git push 120 | ``` 121 | 122 | 删除你的远程 feature branch ; 123 | 124 | ``` 125 | git push origin --delete 126 | ``` 127 | 128 | 删除你的本地 feature branch ; 129 | 130 | ``` 131 | git branch --delete 132 | ``` 133 | 134 | [find the pull request]: http://stackoverflow.com/a/17819027 135 | 136 | 137 | ---------- 138 | 139 | 140 | - [Git 使用规范流程](http://www.ruanyifeng.com/blog/2015/08/git-use-process.html) 141 | - [Git Interactive Rebase, Squash, Amend and Other Ways of Rewriting History](https://robots.thoughtbot.com/git-interactive-rebase-squash-amend-rewriting-history) -------------------------------------------------------------------------------- /nonsense/vim 使用_1_无插件.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | # 浏览目录 5 | 6 | 直接执行 `vim <目录名>` 7 | 进入 vim 后执行 `:E` 8 | 9 | 两种方式存在一定区别: 10 | 第一种是基于 NERD tree 实现的; 11 | 第二种是基于 Netrw Directory Listing 实现的; 12 | 13 | 14 | ---------- 15 | 16 | 17 | # 缓冲区 buffer 相关命令 18 | 19 | 查看位于缓冲区中的文件 `:ls` ; 20 | 切换缓冲区文件显示 `:buffer ` 或 `:buffer `; 21 | 22 | 切换缓冲区中下一个文件 `:bnext` 缩写 `:bn` ; 23 | 切换缓冲区中前一个文件 `:bprevious` 缩写 `:bp` ; 24 | 切换缓冲区中最后一个文件 `:blast` 缩写 `:bl` ; 25 | 切换缓冲区中第一个文件 `:bfirst` 缩写 `:bf` ; 26 | 27 | buffer 中用于标示文件状态的标记: 28 | 29 | ```shell 30 | – (非活动的缓冲区) 31 | a (当前被激活缓冲区) 32 | h (隐藏的缓冲区) 33 | % (当前的缓冲区) 34 | # (交换缓冲区) 35 | = (只读缓冲区) 36 | + (已经更改的缓冲区) 37 | ``` 38 | 39 | 注意: 40 | vim 命令支持 Tab 键补全; 41 | vim 命令支持命令缩写(同 gdb 模式); 42 | 43 | 44 | ---------- 45 | 46 | # 窗口分割(分屏) 47 | 48 | ### 命令行分屏启动 vim 49 | 50 | 垂直分屏 `vim -On file1 file2 file3` 51 | 水平分屏 `vim -on file1 file2 file3` 52 | 其中 n 为分屏数目,不指定 n 则根据文件数目进行分屏; 53 | 54 | > 注意: 55 | 执行 `vim file1 file2 file3` 时,只打开了一个窗口,file1 显示在窗口中,file1, file2 和 file3 均存在于 buffer 中; 56 | 执行 `vim -O file1 file2 file3` 时,会以分屏方式打开 3 个窗口,分别显示 3 个文件,与此同时,3 个文件也存在于 buffer 中; 57 | 58 | 59 | ### 基于窗口中的文件进行分屏 60 | 61 | `ctrl + W N` 以新的空 vim 文件进行分屏; 62 | 63 | `ctrl + W S` 上下分割当前打开的文件; 64 | `ctrl + W V` 左右分割当前打开的文件; 65 | `:sp filename` 上下分割,并打开一个新的文件; 66 | `:vsp filename` 左右分割,并打开一个新的文件; 67 | 68 | 69 | ### 基于当前目录进行分屏 70 | 71 | 在下边分屏浏览目录 `:Hexplore` 缩写 `:He` 72 | 在上边分屏浏览目录 `:Hexplore!` 缩写 `:He!` 73 | 在左边分屏浏览目录 `:Vexplore` 缩写 :`Ve` 74 | 在右边分屏浏览目录 `:Vexplore!` 缩写 :`Ve!` 75 | 76 | 77 | ### 关闭分屏窗口 78 | 79 | `ctrl + W C` 关闭光标所在分屏窗口(注意:窗口中显示的文件仍旧存在于 buffer 中); 80 | 81 | ### 在分屏间移动光标 82 | 83 | 若想在分屏间移动光标,先按 `ctrl + W` ,再按方向键: 84 | h 向左侧屏移动 85 | j 向下侧屏移动 86 | k 向上侧屏移动 87 | l 向右侧屏移动 88 | w 向下一个屏移动 89 | 90 | ### 分屏同步移动 91 | 92 | 要让两个分屏中的文件同步移动,需要到待同步移动的两个屏中都输入 `:set scb` 命令,解开同步移动输入 `:set scb!` 命令; 93 | 注:`:set scb` 是 `:set scrollbind` 的缩写; 94 | 95 | 96 | ### 分屏尺寸调整 97 | 98 | `ctrl + W <` 调整宽度(需要较新版本支持) 99 | `ctrl + W >` 调整宽度(需要较新版本支持) 100 | `ctrl + W =` 让所有屏一样高度 101 | `ctrl + W +` 增加光标所在屏高度 102 | `ctrl + W -` 减少光标所在屏高度 103 | 104 | ### 分屏转 Tab 页 105 | 106 | `ctrl + W T` 将当前分屏窗口转成 Tab 页; 107 | 108 | > 注意: 109 | >> - 上面的 T 为大写字母; 110 | >> - 上面的命令,只能将光标所在分屏窗口转成 Tab 页,若存在多个分屏窗口,则需要执行多次上述命令; 111 | >> - 标签转换为分屏[据说](http://stackoverflow.com/questions/14688536/move-adjacent-tab-to-split)没有内置的解法; 112 | 113 | 114 | ---------- 115 | 116 | 117 | # Tab 页浏览目录 118 | 119 | 120 | ### 分 Tab 页启动 vim 121 | 122 | 123 | 在 Shell 命令行下,可以使用 vim 的 -p 参数以 Tab 页方式打开多个文件:`vim -p file1 file2 ile3` 124 | 125 | `:tabe[dit] file1` 在 vim 中基于 Tab 页打开文件; 126 | `:bufdo tab split` 将 buffer 中的文件全部转成 Tab 页文件; 127 | 128 | 129 | ### 基于当前目录进行 Tab 分页 130 | 131 | `:Texplorer` 缩写 `:Te` ; 132 | 133 | ### 分页切换 134 | 135 | 若想在多个 Tab 页中切换,只需在 normal 模式下执行如下命令(注意,下述命令不需要加冒号): 136 | `gt` 切换到下一个 Tab 页; 137 | `gT` 切换到前一个 Tab 页; 138 | `{i} gt` 切换到指定 Tab 页,其中 i 是指定页对应的数字,从 1 开始计数;例如 5 gt 就是到第 5 页; 139 | `:tabmove {i}` 移动 Tab 页到目标位置,其中 i 是指 Tab 页目标位置,位置从 0 开始计数; 140 | `:tabs` 查看已打开 Tab 页情况; 141 | `:tabclose {i}` 关闭指定 Tab 页,若未指定 i 则关闭当前页; 142 | 143 | 144 | 145 | ---------- 146 | 147 | # 保存会话 148 | 149 | 150 | ---------- 151 | 152 | # Quickfix 153 | 154 | 155 | `:cp` 跳到上一个错误 156 | `:cn` 跳到下一个错误 157 | `:cl` 列出所有错误 158 | `:cc` 显示错误详细信息 159 | 160 | 161 | ---------- 162 | 163 | # 关键字补全 164 | 165 | 在 insert 模式下,可以按 `Ctrl + N`(Vim 会开始搜索当前目录下的代码,搜索完成后会出现一个下拉列表),再按 `Ctrl + P`,之后就可以通过上下光标键来进行选择; 166 | 167 | 更多的补齐,都在 Ctrl +X 下面: 168 | 169 | Ctrl + X 和 Ctrl + D 宏定义补齐 170 | Ctrl + X 和 Ctrl + ] 是Tag 补齐 171 | Ctrl + X 和 Ctrl + F 是文件名 补齐 172 | Ctrl + X 和 Ctrl + I 也是关键词补齐,但是关键后会有个文件名,告诉你这个关键词在哪个文件中 173 | Ctrl + X 和 Ctrl +V 是表达式补齐 174 | Ctrl + X 和 Ctrl +L 这可以对整个行补齐 175 | 176 | ---------- 177 | 178 | 179 | # 小技巧 180 | 181 | 182 | `guu` 或 `Vu` 可以把一整行字符变成全小写; 183 | `gUU` 或 `VU` 可以把一整行字符变成全大写; 184 | 按 `v` 键进入 virtual 模式,然后移动光标选择目标文本,再按 `u` 转小写,或者按 `U` 转大写; 185 | `ga` 查看光标处字符的 **ascii** 码; 186 | `g8` 查看光标处字符的 **utf-8** 编码; 187 | `gf` 打开光标处所指的文件(可用于打开 #include 头文件,但必须有路径) 188 | `*` 或 `#` 在当前文件中向下或向上搜索光标位置的单词; 189 | 190 | `Ctrl + O` 向后回退光标移动; 191 | `Ctrl + I` 向前追赶光标移动; 192 | 193 | ---------- 194 | 195 | 196 | # 参考 197 | 198 | 199 | - [无插件Vim编程技巧](http://coolshell.cn/articles/11312.html) 200 | - [Vim的分屏功能](http://coolshell.cn/articles/1679.html) 201 | - []() 202 | - []() 203 | -------------------------------------------------------------------------------- /nonsense/大二层网络.md: -------------------------------------------------------------------------------- 1 | # 大二层网络 2 | 3 | 标签(空格分隔): 大二层 网络 4 | 5 | --- 6 | 7 | ## [剖析大二层](http://www.h3c.com.cn/About_H3C/Company_Publication/IP_Lh/2012/06/Home/Catalog/201212/769073_30008_0.htm) 8 | 9 | 在**数据中心**和**云计算**的网络方案和技术讨论中,大二层已经成为热点话题,涌现了各种软件和硬件技术、直接和间接手段等,目的都是为了解决“**L2 over XX**”的问题。那么,为什么有这么多大二层技术?在数据中心方案规划和设计中该如何选择?本文进行一个总体的剖析,并在后续的文章中就主要技术与应用进行详细的分析和介绍。 10 | 11 | ### 为什么需要大二层 12 | 13 | #### 1. 虚拟化对数据中心提出的挑战 14 | 15 | **传统的三层数据中心架构结构的设计**是为了应付服务**客户端-服务器**应用程序的纵贯式大流量,同时使网络管理员能够对流量流进行管理。工程师在这些架构中采用**生成树协议(STP)**来优化客户端到服务器的路径和支持连接冗余。 16 | 17 | 虚拟化从根本上改变了数据中心网络架构的需求。最重要的一点就是,虚拟化引入了**虚拟机动态迁移技术**。从而**要求网络支持大范围的二层域**。从根本上改变了传统三层网络统治数据中心网络的局面。 18 | 19 | #### 2. 虚拟机迁移与数据中心二层网络的变化 20 | 21 | 在**传统的**数据中心服务器区**网络设计**中,通常**将二层网络的范围限制在网络接入层以下**(即**传统的二层网络**),避免出现大范围的二层广播域。 22 | 23 | 如图1所示,由于传统的数据中心服务器利用率太低,平均只有10%~15%,浪费了大量的电力能源和机房资源。虚拟化技术能够有效地提高服务器的利用率,降低能源消耗,降低客户的运维成本,所以虚拟化技术得到了极大的发展。但是,虚拟化给数据中心带来的不仅是服务器利用率的提高,还有网络架构的变化。具体的来说,虚拟化技术的一项伴生技术—**虚拟机动态迁移**(如VMware的VMotion)在数据中心得到了广泛的应用。简单来说,虚拟机迁移技术可以使数据中心的计算资源得到灵活的调配,进一步提高虚拟机资源的利用率。但是**虚拟机迁移要求虚拟机迁移前后的IP和MAC地址不变,这就需要虚拟机迁移前后的网络处于同一个二层域内部**。由于客户要求虚拟机迁移的范围越来越大,甚至是跨越不同地域、不同机房之间的迁移,所以使得数据中心二层网络的范围越来越大,甚至出现了专业的大二层网络这一新领域专题。 24 | 25 | ![](http://www.h3c.com.cn/res/201212/24/20121224_1501692_image001_769073_30008_0.jpg) 26 | 27 | #### 3. 传统网络的二层为什么大不起来 28 | 29 | 在数据中心网络中,“**区域**”对应VLAN的划分。 30 | 31 | - **相同VLAN内**的终端属于同一广播域,具有一致的VLAN-ID,二层连通; 32 | - **不同VLAN内**的终端需要通过网关互相访问,二层隔离,三层连通。 33 | 34 | 传统的数据中心设计,区域和VLAN的划分粒度是比较细的,这主要取决于“需求”和“网络规模”。 35 | 36 | 传统的数据中心主要是**依据功能进行区域划分**,例如WEB、APP、DB,办公区、业务区、内联区、外联区等等。不同区域之间通过网关和安全设备互访,保证不同区域的可靠性、安全性。同时,不同区域由于具有不同的功能,因此需要相互访问数据时,只要终端之间能够通信即可,并不一定要求通信双方处于同一VLAN或二层网络。 37 | 38 | (在)传统的数据中心网络技术(中), STP是二层网络中非常重要的一种协议。用户构建网络时,为了保证可靠性,通常会采用冗余设备和冗余链路,这样就**不可避免的形成环路**。而(当)二层网络处于同一个广播域下,广播报文在环路中会反复持续传送,**形成广播风暴**,瞬间即可导致端口阻塞和设备瘫痪。因此,为了防止广播风暴,就必须防止形成环路。这样,既要防止形成环路,又要保证可靠性,就只能将冗余设备和冗余链路变成备份设备和备份链路。**即冗余的设备端口和链路在正常情况下被阻塞掉,不参与数据报文的转发。只有当前转发的设备、端口、链路出现故障,导致网络不通的时候,冗余的设备端口和链路才会被打开,使得网络能够恢复正常。**实现这些自动控制功能的就是**STP(Spanning Tree Protocol,生成树协议)**。 39 | 40 | 由于**STP的收敛性能**等原因,**一般情况下STP的网络规模不会超过100台交换机**。同时由于STP需要阻塞掉冗余设备和链路,也降低了网络资源的带宽利用率。因此在实际网络规划时,从转发性能、利用率、可靠性等方面考虑,会**尽可能控制STP网络范围**。 41 | 42 | #### 4. 大二层也是为了流通的要求 43 | 44 | 随着数据大集中的发展和虚拟化技术的应用,数据中心的规模与日俱增,不仅对二层网络的区域范围要求也越来越大,在需求和管理水平上也提出了新的挑战。 45 | 46 | 数据中心区域规模和业务处理需求的增加,对于集群处理的应用越来越多,集群内的服务器需要在一个二层VLAN下。同时,虚拟化技术的应用,在带来业务部署的便利性和灵活性基础上,虚拟机的迁移问题也成为必须要考虑的问题。**为了保证虚拟机承载业务的连续性,虚拟机迁移前后的IP地址不变,因此虚拟机的迁移范围需要在同一个二层VLAN下。反过来即,二层网络规模有多大,虚拟机才能迁移有多远。** 47 | 48 | 传统的基于STP备份设备和链路方案已经不能满足数据中心规模、带宽的需求,并且**STP协议几秒至几分钟的故障收敛时间**,也不能满足数据中心的可靠性要求。因此,需要能够有新的技术,在满足二层网络规模的同时,也能够充分利用冗余设备和链路,提升链路利用率,而且数据中心的故障收敛时间能够降低到亚秒甚至毫秒级。 49 | 50 | ### 大二层需要有多大 51 | 52 | 既然二层网络规模需要扩大,那么大到什么程度合适?这取决于应用场景和技术选择。 53 | 54 | #### 1. 数据中心内 55 | 56 | 大二层首先需要解决的是数据中心内部的网络扩展问题,通过大规模二层网络和VLAN延伸,实现虚拟机在数据中心内部的大范围迁移。由于**数据中心内的大二层网络都要覆盖多个接入交换机和核心交换机**,主要有以下两类技术。 57 | 58 | - **虚拟交换机技术** 59 | 60 | 虚拟交换机技术的出发点很简单,属于**工程派**。既然**二层网络的核心是环路问题**,而环路问题是随着冗余设备和链路产生的,那么如果将相互冗余的两台或多台设备、两条或多条链路合并成一台设备和一条链路,就可以回到之前的单设备、单链路情况,环路自然也就不存在了。尤其是交换机技术的发展,虚拟交换机从低端盒式设备到高端框式设备都已经广泛应用,具备了相当的成熟度和稳定度。因此,**虚拟交换机技术成为目前应用最广的大二层解决方案**。 61 | 62 | 虚拟交换机技术的代表是**H3C公司的IRF**、**Cisco公司的VSS**,其特点是只需要交换机软件升级即可支持,应用成本低,部署简单。目前这些技术都是各厂商独立实现和完成的,只能同一厂商的相同系列产品之间才能实施虚拟化。同时,由于高端框式交换机的性能、密度越来越高,对虚拟交换机的技术要求也越来越高,目前框式交换机的虚拟化密度最高为4:1。**虚拟交换机的密度限制了二层网络的规模大约在1万~2万台服务器左右。** 63 | 64 | - **隧道技术** 65 | 66 | 隧道技术属于**技术派**,出发点是借船出海。二层网络不能有环路,冗余链路必须要阻塞掉,但三层网络显然不存在这个问题,而且还可以做**ECMP(等价链路)**,能否借用过来呢?通过**在二层报文前插入额外的帧头**,并且**采用路由计算的方式控制整网数据的转发**,不仅可以在冗余链路下防止广播风暴,而且可以做ECMP。这样可以将二层网络的规模扩展到整张网络,而**不会受核心交换机数量的限制**。 67 | 68 | 隧道技术的代表是**TRILL**、**SPB**,都是通过借用IS-IS路由协议的计算和转发模式,实现二层网络的大规模扩展。这些技术的特点是**可以构建比虚拟交换机技术更大的超大规模二层网络**(应用于大规模集群计算),但尚未完全成熟,目前正在标准化过程中。同时传统交换机不仅需要软件升级,还需要硬件支持。 69 | 70 | #### 2. 跨数据中心 71 | 72 | 随着数据中心多中心的部署,虚拟机的跨数据中心迁移、灾备,跨数据中心业务负载分担等需求,使得二层网络的扩展不仅是在数据中心的边界为止,还需要考虑跨越数据中心机房的区域,延伸到同城备份中心、远程灾备中心。 73 | 74 | **一般情况下,多数据中心之间的连接是通过路由连通的,天然是一个三层网络**。而要实现通过三层网络连接的两个二层网络互通,就必须实现“**L2 over L3**”。 75 | 76 | **L2oL3技术**也有许多种,例如传统的**VPLS(MPLS L2VPN)技术**,以及新兴的Cisco **OTV**、H3C **EVI技术**,都是借助隧道的方式,将二层数据报文封装在三层报文中,跨越中间的三层网络,实现两地二层数据的互通。这种隧道就像一个虚拟的桥,将多个数据中心的二层网络贯穿在一起。 77 | 78 | 另外,也有部分虚拟化和软件厂商提出了**软件的L2 over L3技术解决方案**。例如VMware的**VXLAN**、微软的**NVGRE**,在虚拟化层的vSwitch中将二层数据封装在UDP、GRE报文中,在物理网络拓扑上构建一层虚拟化网络层,从而摆脱对网络设备层的二层、三层限制。这些技术由于性能、扩展性等问题,也没有得到广泛的使用。 79 | 80 | ### 结束语 81 | 82 | 大规模二层网络的需求目前已经非常的清晰,各厂商都提出了有针对性的技术和方案,满足大二层的当前要求和未来扩展需求。但从实际应用情况来看,除了虚拟交换机技术在成熟度和应用性方面得到验证,其他的相关技术仍然在完善过程中。同时,业界也希望加快相关技术的标准化进程,从而加强各厂商设备的兼容性和互通性,降低用户的部署和维护成本。 83 | -------------------------------------------------------------------------------- /nonsense/如何向开源社区提问题.md: -------------------------------------------------------------------------------- 1 | # 如何向开源社区提问题 2 | 3 | > 原文地址:[这里](https://github.com/seajs/seajs/issues/545) 4 | 5 | 使用软件产品,或多或少都会遇到问题。对于商业产品,我们可以咨询客服寻求帮助。对于公司自己研发的产品,我们可以直接请教专家同事。但对于开源软件,在遇到问题时,如何才能及时有效地寻求帮助呢? 6 | 7 | 本文以开源类库 SeaJS 为例,说说我心目中的最佳实践。 8 | 9 | ## 提问前 10 | 11 | 遇到问题时,心里都很着急。在决定向开源社区提交问题前,最好先做做以下功课: 12 | 13 | ### 尝试从官方文档中找到答案 14 | 15 | 确保自己阅读过至少一次官方文档。这样在遇到问题时,如果能回忆起只言片语,就可以再去读一遍相关文档,问题往往也就解决了。 16 | 17 | ### Google 是你的朋友 18 | 19 | 对于成熟的开源项目,你遇到的问题,很可能别人也遇到过。这时通过 Google、StackOverflow 等网站的搜索服务,可以帮你快速定位并解决问题。永远记住,地球上的你并不孤单,包括你遇到的问题。 20 | 21 | ### 挖掘 Bug 宝藏 22 | 23 | 开源软件一般都会有自己的 Bug 管理方案,比如 WebKit、V8、jQuery、SeaJS 等等。从它们的官网上找到 Bug 管理地址,然后通过搜索看看有无你遇到的问题。对于活跃社区来说,这一招经常很管用。比如 jQuery 的 Bug Tracker,通过右上角的 Search Tickets 可以找到非常多有用的信息。一个运作良好的 Bug 库,经常是一座巨大的宝藏。SeaJS 是直接通过 GitHub Issues 来管理,你可以在 Issues 中找到很多信息。 24 | 25 | ### 求助身边的朋友 26 | 27 | 如果你使用的开源软件,在朋友圈或同事圈里也有人使用,那么抬起你的脚、或拿起你的电话,真挚诚恳的探讨不会遭遇拒绝,而会增进友谊。不要犹豫,你的内心渴望面对面交流,你的朋友也是。 28 | 29 | 如果以上 4 步都无法解决你遇到的问题,也别犹豫,立马向开源社区提交问题就好。 30 | 31 | ## 提问时 32 | 33 | 提问有很多种,比如你认识作者,直接面对面请教就行。下面探讨的是如何通过互联网的方式来问问题。 34 | 35 | ### 平和对等的心态 36 | 37 | 很多开源软件都是免费的,作者往往是业余时间出于兴趣在维护,没有义务回答社区问题。提问时,不要把自己摆在顾客的位置,比如 38 | 39 | > 项目马上要上线了,请务必帮忙解决 40 | > 这是我的邮箱,请及时联系我 41 | 42 | 另外,也不要把自己摆在乞食者的位置,比如 43 | 44 | > 冰天雪地跪求解答 45 | > 救命啊,我的网站挂了 46 | 47 | 在开源社区,一切皆是朋友。无论对方是 Linux 内核的作者,还是某个 jQuery 插件的作者,你和作者都是对等的。你的提问是在帮助开源软件完善。平和对等的心态,可以让你的问题赢得更多人的阅读和思考。 48 | 49 | ### 通过正确的途径提交 50 | 51 | 如果遇到问题的开源软件有专门的 Bug 管理系统,请最好到这些指定系统中提交。比如,对于前端开发工程师来说,下面这些 Tracker 系统很重要。 52 | 53 | - jQuery Tickets 54 | - WebKit Bugzilla 55 | - Mozilla Bugzilla 56 | 57 | 还有各个开源类库的 Issues 库,比如 SeaJS 的是:seajs/issues 58 | 59 | 最不好的途径是 60 | 61 | - QQ 、阿里旺旺、微信等群组。这些群组主要是用来工作或休闲的。对开源项目来说,在这些地方提问,作者一般不会关注,效率非常低。 62 | - 微博、Facebook 等社交网络。不少人在微博上通过 at 或私信询问 SeaJS 问题,这些我经常看不到。看到了,也不情愿回复。微博是扯淡、交流情感的地方,一般是写代码写累了,才去逛逛,很少会有在社交网络上回答技术问题的心情。 63 | 通过正确的途径提交问题,一般可以让你的问题得到及时准确的回复。 64 | 65 | ### 使用明确、有意义的标题 66 | 67 | 抱着平和对等的心态,找到合适的途径后,就得静下心来将遇到的问题写成文字。书写文字不是一件简单的事情,我们可以从遵循一些简单的规则开始。 68 | 69 | 首先是标题要简洁清晰,要言之有物。比如 70 | 71 | > 我遇到了一个 Ajax 问题 72 | > SeaJS 在我的浏览器上运行不了 73 | 74 | 上面的标题很糟糕,光看标题作者无法知道发生了什么事。当开源社区的问题很多时,上面这类标题,经常会让作者直接忽视或将优先级降到很低。更妥当的标题是 75 | 76 | > Ajax 请求未返回正确的 responseXML 77 | > SeaJS 2.0 在 IE6 上运行时抛错 78 | 79 | 明确、有意义的标题,可以帮助作者确定问题具体是什么类型、预估需要多少时间解决、是否现在马上解决等。一个好的标题,也有利于社区知识的沉淀和后期搜索。标题有如一个人的颜面衣着,虽然不是关键,但在嘈杂的信息社区中,这很重要。 80 | 81 | ### 遵循良好的模板 82 | 83 | 如果社区提供了问题模板,一定要仔细看下。比如 Google Code 社区,当你创建一个问题时,会自动提供以下模板: 84 | 85 | ``` 86 | What steps will reproduce the problem? 87 | 该问题的重现步骤是什么? 88 | 1. 89 | 2. 90 | 3. 91 | 92 | What is the expected output? What do you see instead? 93 | 你期待的结果是什么?实际看到的又是什么? 94 | 95 | 96 | What version of the product are you using? On what operating system? 97 | 你正在使用产品的哪个版本?在什么操作系统上? 98 | 99 | 100 | Please provide any additional information below. 101 | 如果有的话,请在下面提供更多信息。 102 | ``` 103 | 104 | 遵循这个模板去描述问题,经常能省很多事。作者一般也非常欢迎通过模板提交的问题。如果社区没有提供模板,也可以自己遵循以上模板来提交。 105 | 106 | 下面针对问题内容,具体说说一些需要注意的点。 107 | 108 | ### 语法正确、格式清晰 109 | 110 | 虽然我们不是作家,但正确的语法、清晰的格式,可以让读者赏心悦目,也就更有心情帮你一起思考解决问题。 111 | 112 | 对于很多需要代码来描述的问题,要尤其注意格式,比如 113 | ``` 114 | seajs.use('jquery',function($){$(document).ready(function() { /* ... */ })}); 115 | ``` 116 | 117 | 可读性不如 118 | ``` 119 | seajs.use('jquery', function($) { 120 | $(document).ready(function() { 121 | // ... 122 | }); 123 | }); 124 | ``` 125 | 126 | GitHub 的 Markdown 语法可以很好地支持代码排版、语法高亮等,建议书写代码时,一定要先阅读下说明:**GitHub Flavored Markdown**。这能让你的内容看起来很专业,社区也就更有意愿会去帮助你,否则糟糕的排版,经常带来的是发帖之后的石沉大海。 127 | 128 | ### 描述事实、而不是猜测 129 | 130 | 事实是指,依次进行了哪些操作、产生了怎样的结果。比如 131 | 132 | > 我在 Windows XP 下用 IE6 打开 seajs.org 后,点击“5 分钟上手 SeaJS”,这时浏览器弹出脚本错误提示,例子显示不正确。 133 | 134 | 上面是一段比较好的事实描述(更好的是把错误提示也截图上来),而不要像下面这样猜测: 135 | 136 | > SeaJS 在 IE6 下运行不正常,我怀疑是源码第 213 行有问题。 137 | 138 | 上面的描述,会让作者一头雾水、甚至很恼火。尽量避免猜测性描述,除非你能先描述事实,在事实描述清楚之后,再给出合理的猜测是欢迎的。 139 | 140 | 对于前端项目来说,如果能提供可重现错误的在线可访问代码,那是最好不过的。一旦你这么用心去做了,作者往往也会很用心地立马帮你解决。 141 | 142 | ### 描述目标、而不是过程 143 | 144 | 经常会有这种情况,提问者在脑袋里有个更高层次的目标,他们在自以为能达到目标的特定道路上卡住了,然后跑来问该怎么走。比如 145 | 146 | > SeaJS 的 parseMap 方法在遇到 map 的多个配置项同时匹配同一个路径时,应该允许用户指定是全部生效还是仅第一个匹配的配置项生效。 147 | 148 | 上面这个问题的背后,提问者实际上想解决的是如何通过 SeaJS 来做版本管理。提问者选择了通过 map 的方式来实现,但这过程中遇到了问题,因此跑过来继续怎么走。然而,如果只是描述过程,往往会把作者也绕进去。 149 | 150 | 实际情况却是,提问者选择的路本身就是一条崎岖之路,对于要解决的问题,实际上有更好的方式。这种情况下,描述清楚目标,讲清楚要干什么非常重要。 151 | 152 | 在描述自己是怎么做之前,一定要先描述要做什么。提问题时,What 往往比 How 更重要。 153 | 154 | ### 要有具体场景 155 | 156 | 无论在开源社区,还是微博、知乎等平台上,有一种非常常见的问题: 157 | 158 | > 如何维护 JavaScript 代码? 159 | > 如何使用 SeaJS 进行模块化开发? 160 | 161 | 这类问题还有很多,每每遇到,只能笑笑,然后悄悄地忽略掉。因此这类问题很难回答,就如下面这些问题一样: 162 | 163 | > 如何才能让生命有意义? 164 | > 如何打败淘宝? 165 | 166 | 这类提问者,一般比较浮躁,经常对问题本身也没有经过思考。踏实的提问者,不会让问题浮在空中无法回答,而会在具体场景中让问题落地: 167 | 168 | > 我的项目有 20 多个 JS 文件,接下来还会急剧增加。目前遇到以下问题……(省略五百字)…… 请问如何维护? 169 | 170 | ### 仔细检查、确保准确 171 | 172 | 是人都会犯错误,特别是在如此快节奏的互联网环境下。好不容易把问题描述清楚时,不要急着立刻提交。在提交前,至少保证从头到尾再仔细阅读一遍,比如语法错误、错别字、标点符号、排版等等。做到这些,不光是尊重别人,也是尊重自己。 173 | 174 | ## 提问后 175 | 176 | 提交问题后,建议通过邮件等方式订阅回复。互联网上最有效的沟通方式是异步沟通,不要期待作者马上回复,也不要心烦意乱着急地等待。出去看看天,数数云朵,你会逐步明白什么是风轻云淡。 177 | 178 | ### 尽可能补充信息 179 | 180 | 在接收到回复时,仔细阅读。最经常的情况是,社区回复的,经常不是你想要的。比如 181 | 182 | > 根据你的描述,问题无法重现。能否提供具体使用环境和重现步骤? 183 | 184 | 这时要淡定。仔细看看自己提交的问题描述是否足够清晰,如果有可补充的信息,尽量补充,以帮助作者能尽快定位问题。比如 185 | 186 | > 很抱歉,我前面有一步描述不正确,实际情况是我是在 IETester 中运行的…… 187 | 188 | 谦和淡定的交流,不光能帮助你解决问题,还有助于你结交更多朋友。 189 | 190 | ### 适当的总结 191 | 192 | 当问题终于解决时,建议对问题进行总结。可以编辑原帖,也可以通过博客等方式总结。你的总结,会让遇到同样问题的朋友们受益,并且对自己的技能也是一种提高。前端业界,无论国内还是国外,有很多牛人之所以成为牛人,很大程度上都是因为有总结思考的好习惯。 193 | 194 | ### 不要忘记感谢 195 | 196 | 最后,记得感谢。很多开源软件的作者,都是利用业余时间在创作代码。你的感谢,汇集许许多多大家的感谢,会让开源社区充满爱与力量。 197 | 198 | ## 延伸阅读 199 | 200 | - [如何有效地报告 Bug](http://www.chiark.greenend.org.uk/~sgtatham/bugs-cn.html) 201 | - [提问的智慧](http://www.wapm.cn/smart-questions/smart-questions-zh.html) 202 | - [回答的智慧](https://code.google.com/archive/p/cpyug/wikis/ZenForAsk.wiki) -------------------------------------------------------------------------------- /nonsense/如何在 ubuntu 上进行系统时间调整.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 本文简单介绍如何在 Ubuntu 上进行系统时间调整; 4 | 5 | ---------- 6 | 7 | 8 | ## 查看当前时间显示(变更前) 9 | ```shell 10 | # date 11 | Wed Jul 27 07:52:32 GMT 2016 12 | ``` 13 | 14 | ## 进行时区调整 15 | 16 | 例如将时区设置成 `Asia/Shanghai` ; 17 | 18 | ### 确定目标时区 19 | 20 | ```shell 21 | # tzselect 22 | Please identify a location so that time zone rules can be set correctly. 23 | Please select a continent, ocean, "coord", or "TZ". 24 | 1) Africa 25 | 2) Americas 26 | 3) Antarctica 27 | 4) Arctic Ocean 28 | 5) Asia 29 | 6) Atlantic Ocean 30 | 7) Australia 31 | 8) Europe 32 | 9) Indian Ocean 33 | 10) Pacific Ocean 34 | 11) coord - I want to use geographical coordinates. 35 | 12) TZ - I want to specify the time zone using the Posix TZ format. 36 | #? 5 37 | Please select a country whose clocks agree with yours. 38 | 1) Afghanistan 18) Israel 35) Palestine 39 | 2) Armenia 19) Japan 36) Philippines 40 | 3) Azerbaijan 20) Jordan 37) Qatar 41 | 4) Bahrain 21) Kazakhstan 38) Russia 42 | 5) Bangladesh 22) Korea (North) 39) Saudi Arabia 43 | 6) Bhutan 23) Korea (South) 40) Singapore 44 | 7) Brunei 24) Kuwait 41) Sri Lanka 45 | 8) Cambodia 25) Kyrgyzstan 42) Syria 46 | 9) China 26) Laos 43) Taiwan 47 | 10) Cyprus 27) Lebanon 44) Tajikistan 48 | 11) East Timor 28) Macau 45) Thailand 49 | 12) Georgia 29) Malaysia 46) Turkmenistan 50 | 13) Hong Kong 30) Mongolia 47) United Arab Emirates 51 | 14) India 31) Myanmar (Burma) 48) Uzbekistan 52 | 15) Indonesia 32) Nepal 49) Vietnam 53 | 16) Iran 33) Oman 50) Yemen 54 | 17) Iraq 34) Pakistan 55 | #? 9 56 | Please select one of the following time zone regions. 57 | 1) Beijing Time 58 | 2) Xinjiang Time 59 | #? 1 60 | 61 | The following information has been given: 62 | 63 | China 64 | Beijing Time 65 | 66 | Therefore TZ='Asia/Shanghai' will be used. 67 | Local time is now: Wed Jul 27 17:25:12 CST 2016. 68 | Universal Time is now: Wed Jul 27 09:25:12 UTC 2016. 69 | Is the above information OK? 70 | 1) Yes 71 | 2) No 72 | #? 1 73 | 74 | You can make this change permanent for yourself by appending the line 75 | TZ='Asia/Shanghai'; export TZ 76 | to the file '.profile' in your home directory; then log out and log in again. 77 | 78 | Here is that TZ value again, this time on standard output so that you 79 | can use the /usr/bin/tzselect command in shell scripts: 80 | Asia/Shanghai 81 | # 82 | ``` 83 | 84 | 85 | ### 基于图形界面进行时区调整 86 | 87 | 只需要在界面上进行简单选择即可; 88 | 89 | ```shell 90 | # dpkg-reconfigure tzdata 91 | 92 | Current default time zone: 'Asia/Shanghai' 93 | Local time is now: Wed Jul 27 17:04:51 CST 2016. 94 | Universal Time is now: Wed Jul 27 09:04:51 UTC 2016. 95 | 96 | # 97 | ``` 98 | 99 | ### 基于 timedatectl 进行时区调整 100 | 101 | 如果你使用的 Linux 系统支持 `Systemd`,则可以使用 `timedatectl` 命令进行系统范围时区设置。 102 | 103 | 在 Systemd 下有一个名为 `systemd-timedated` 的系统服务负责调整系统时钟和时区,可以使用 timedatectl 命令对此系统服务进行配置。 104 | 105 | 设置时区 106 | ```shell 107 | timedatectl set-timezone 'Asia/Shanghai' 108 | ``` 109 | 110 | 查看当前时间设定 111 | ```shell 112 | # timedatectl 113 | Warning: Ignoring the TZ variable. Reading the system's time zone setting only. 114 | 115 | Local time: Wed 2016-07-27 17:45:54 CST 116 | Universal time: Wed 2016-07-27 09:45:54 UTC 117 | RTC time: Wed 2016-07-27 09:45:54 118 | Time zone: Asia/Shanghai (CST, +0800) 119 | NTP enabled: yes 120 | NTP synchronized: yes 121 | RTC in local TZ: no 122 | DST active: n/a 123 | # 124 | ``` 125 | 126 | ## 防止系统重启后时区改变 127 | 128 | ### 用户级别设置时区 129 | 130 | 在 `.profile` 文件中添加 131 | ```shell 132 | TZ='Asia/Shanghai'; export TZ 133 | ``` 134 | 之后执行 `source .profile` 令设置生效;也可以重新进行 shell 登录; 135 | 136 | 137 | ### 系统级别设置时区 138 | 139 | ```shell 140 | rm -f /etc/localtime 141 | ln -s /usr/share/zoneinfo/Asia/Shanghai /etc/localtime 142 | ``` 143 | 或者(等效命令) 144 | ```shell 145 | ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime 146 | ``` 147 | > 注意:`Asia/Shanghai` 是根据上面 `tzselect` 确定的; 148 | 149 | 150 | ## 通过公网 NTP 服务器进行时间校准 151 | 152 | ```shell 153 | # ntpdate pool.ntp.org 154 | 27 Jul 15:56:36 ntpdate[8265]: adjust time server 115.28.122.198 offset 0.010742 sec 155 | ``` 156 | 157 | ## 查看当前时间显示(变更后) 158 | 159 | ```shell 160 | # date 161 | Wed Jul 27 15:58:03 CST 2016 162 | ``` 163 | 164 | ## 设置硬件时间和系统时间一致 165 | 166 | ```shell 167 | # /sbin/hwclock --systohc 168 | ``` 169 | -------------------------------------------------------------------------------- /nonsense/编程语言进化史.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moooofly/MarkSomethingDown/3ed8d77b34dfb893b865932086065265876e3bc6/nonsense/编程语言进化史.pdf --------------------------------------------------------------------------------