July 28, 2019
RabbitMQ常见面试题
"RabbitMq的消息类型(6种)、 消息确认机制\nRabbitMq中的概念及解释\nServer(Broker): 接收客户端连接,实现AMQP协议的消息队列和路由功能的进程; Virtual Host:虚拟主机的概念,类似权限控制组,一个Virtual Host里可以有多个Exchange和Queue。 Exchange: 交换机,接收生产者发送的消息,并根据Routing Key将消息路由到服务器中的队列Queue。 ExchangeType: 交换机类型决定了路由消息行为,RabbitMQ中有四种类型Exchange,分别是fanout、direct、topic 和 headers; Queue:消息队列,用于存储还未被消费者消费的消息; Message:由Header和body组成,Header是由生产者添加的各种属性的集合,包括Message是否被持久化、优先级是多少、由哪个Message Queue接收等;body是真正需要发送的数据内容; BindingKey:绑定关键字,将一个特定的 Exchange 和一个特定的 Queue 绑定起来。 2.对mq有哪些理 …"
July 28, 2019
rabbitmq消息队列的消息持久化机制
"首先阅读这篇文章: https://blog.csdn.net/yongche_shi/article/details/51500534\n之前其实已经写过一篇关于RabbitMQ持久化的 文章 ,但那篇文章侧重代码层面的写入流程,对于持久化操作何时发生以及什么时候会刷新到磁盘等问题其实都没有搞清楚,这篇文章着重于关注这些问题。\n消息什么时候需要持久化? 根据 官方博文 的介绍,RabbitMQ在两种情况下会将消息写入磁盘:\n消息本身在 publish 的时候就要求消息写入磁盘; 内存紧张 需要将部分内存中的消息转移到磁盘; 消息什么时候会刷到磁盘? 写入文件前会有一个Buffer,大小为1M(1048576),数据在写入文件时,首先会写入到这个Buffer,如果Buffer已满,则会将Buffer写入到文件(未必刷到磁盘); 有个固定的刷盘时间:25ms,也就是不管Buffer满不满,每隔25ms,Buffer里的数据及未刷新到磁盘的文件内容必定会刷到磁盘; 每次消息写入后,如果没有后续写入请求,则会直接将已写入的消息刷到磁盘:使用Erlang的receive x after 0来实 …"
July 26, 2019
docker exec 命令原理
"我们经常使用 docker exec 命令进入到一个容器里进行一些操作,那么这个命令是如果进入到容器里的呢?想必大家都知道用到了Namespace来实现,但至于底层实现原理是什么,想必都不是特别清楚吧。\n我们知道容器的本质其实就是一个进程,每个进程都有一个Pid,至于容器的Pid值可以通过 docker inspect container_id 来查看,我们这里是一个Python应用容器,我们看一下他的 Pid值\ndocker inspect --format \u0026#39;{{ .State.Pid }}\u0026#39; 4ddf4638572d 25686 而每个进程都有自己的Namespace,你可以通过查看宿主机的 proc 文件,看到这个 25686 进程的所有 Namespace 对应的文件\nls -l /proc/25686/ns total 0 lrwxrwxrwx 1 root root 0 Aug 13 14:05 cgroup -\u0026gt; cgroup:[4026531835] lrwxrwxrwx 1 root root 0 Aug 13 14:05 ipc -\u0026gt; …"
July 26, 2019
docker中的命名空间
"Namespace 的作用是“隔离”,它让应用进程只能看到该Namespace 内的“世界”;而 Cgroups 的作用是“限制”,它给这个“世界”围上了一圈看不见的墙。\n命名空间是 Linux 内核一个强大的特性。每个容器都有自己单独的命名空间,运行在其中的应用都像是在独立的操作系统中运行一样。命名空间保证了容器之间彼此互不影响。\n在docker中一共有以下几个命名空间,每个Namespace的发挥着不同的作用。\npid 命名空间 不同用户的进程就是通过 pid 命名空间隔离开的,且不同命名空间中可以有相同 pid。在同一个Namespace中只能看到当前命名空间的进程。所有的 LXC 进程在 Docker 中的父进程为Docker进程,每个 LXC 进程具有不同的命名空间。同时由于允许嵌套,因此可以很方便的实现嵌套的 Docker 容器。\nnet 命名空间 有了 pid 命名空间, 每个命名空间中的 pid 能够相互隔离,但是网络端口还是共享 host 的端口。网络隔离是通过 net 命名空间实现的, 每个 net 命名空间有独立的 网络设备, IP 地址, 路由表, …"
July 13, 2019
docker容器调试利器nicolaka/netshoot
"背景 在日常工作中,我们一般会将容器进行精简,将其大小压缩到最小,以此来提高容器部署效率,参考小米云技术 – Docker最佳实践:5个方法精简镜像。但有一个比较尴尬的问题就是对容器排障,由于容器里没有了我们日常工作中用到许多排障命令,如top、ps、netstat等,所以想排除故障的话,常用的做法是安装对应的命令,如果容器过多的话,再这样搞就有些麻烦了,特别是在一些安装包源速度很慢的情况。\n解决方案 今天发现一篇文章(简化 Pod 故障诊断:kubectl-debug 介绍)介绍针对此类问题的解决方案的,这里介绍的是一个叫做 kubectl-debug 的命令,由国内知名的PingCAP公司出品的,主要用在k8s环境中的。我们知道容器里主要两大技术,一个是用cgroup来实现容器资源的限制,一个是用Namespace来实现容器的资源隔离的)。(kubectl-debug 命令是基于一个工具包() 来实现的,其原理是利用将一个工具包容器添加到目标容器所在的Pod里,实现和目标容器的Network Namespace一致,从而达到对新旧容器进程的相互可见性,这样我们就可以直接在目标容器里 …"
July 12, 2019
基于docker环境实现Elasticsearch 集群环境
"最近搭建了es集群的时候,现在需要测试添加一个新的数据节点,项目是使用docker-compose命令来搭建的。\n以下基于最新版本 es7.2.0进行, 配置文件目录为 es, 所以docker 在创建网络的时候,网络名称会以 es_ 前缀开始,如本例中我们在docker-composer.yaml文件中指定了网络名称为esnet,但docker生成的实例名称为 es_esnet,至于网络相关的信息可以通过 docker network --help 查看。\n搭建es集群 // docker-compose.yaml 集群配置文件\nversion: \u0026#39;2.2\u0026#39; services: es01: image: docker.elastic.co/elasticsearch/elasticsearch:7.2.0 container_name: es01 environment: - node.name=es01 - node.master=true - node.data=true - discovery.seed_hosts=es02 - …"
July 11, 2019
golang内存对齐(进阶必看)
"先看一个结构体\n// 写法一 type T1 struct { a int8 b int64 c int16 } // 写法二 type T2 struct { a int8 c int16 b int64 } 对于这两个结构体,都有a、b、c三个定义完全一样的字段,只是在定义结构体的时候字段顺序不一样而已,那么两种写法有什么影响吗?\n对于新手来说,感觉着没有什么区别的,只是一个书写顺序不同而已,但对于go编译器来说,则有着很大的区别,特别是在不同架构上(32位/64位)的编译器,在一定程度上对内存的使用大小和执行效率有着一定的不同。这里的主要知识点就是golang语言中的内存对齐概念(alignment guarantee),\n类型的尺寸和结构体字节填充(structure padding) Go白皮书只对以下种类的类型的尺寸进行了明确规定。\n类型种类 尺寸(字节数) ------ ------ byte, uint8, int8 1 uint16, int16 2 uint32, int32, float32 4 uint64, int64 8 float64, complex64 …"
July 10, 2019
kafka常用术语
"官方网站:,中文: http://kafka.apachecn.org/\n注意它和其它消息系统(消息队列)在定义上的区别,以便更好的理解它的应用场景。Apache Kafka 是一款分布式流处理平台(Distributed Streaming Platform)。\n术语 消息:Record。消息实体,是通信的基本单位。 主题:Topic。主题是承载消息的逻辑容器,在实际使用中多用来区分具体的业务。 分区:Partition。一个有序不变的消息序列。每个主题Topic下可以有多个分区。 消息位移:Offset。表示分区中每条消息的位置信息,是一个单调递增且不变的值。 缓存代理,Broker。Kafka集群中的一台或多台服务器统称broker。 副本:Replica。Kafka 中同一条消息能够被拷贝到多个地方以提供数据冗余,这些地方就是所谓的副本。副本还分为领导者副本和追随者副本,各自有不同的角色划分。副本是在分区层级下的,即每个分区可配置多个副本实现高可用。 生产者:Producer。向主题发布新消息的应用程序。 消费者:Consumer。从主题订阅新消息的应用程序。 消费者位 …"
July 3, 2019
ES集群的高可用性之节点
"为了防止ES集群中单点问题,一般都需要对集群节点做高可用性,当发生单点问题时,也可以向外正常提供服务。这里主要记录一下节点的加入、离开和主节点选举。\n集群安装教程请参考:\n节点角色 集群是由多个节点组成的,每个节点都扮演着不同的角色,一般常用的有 Master、Data 和 client。节点角色介绍:\n节点角色配置参数: node.master: true node.data: false node.ingest: false\n在一个集群中,可以通过 查看到每个节点在集群中扮演的角色,一个节点可同时拥有多个角色,如值MDI,同时也是每个节点的默认值,其中的 Ingest 节点也称作预处理节点,不过在生产环境中一般将master 和 data节点分开的。所有节点默认都是支持 Ingest 操作的。节点组合参考:\n新节点的加入 随着数量大的增加,有时候我们不得进行机器的扩容,这时间就需要加入一些新的机器节点,用来提高访问速度。\n当一个新节点加入的时候,它通过读取 discovery.zen.ping.unicast.hosts 配置的节点获取集群状态,然后找到 master 节点,并向其 …"
July 2, 2019
docker容器 Exited (137)错误代码
"最近要搭建es集群,由于刚接触es不久,直接使用的docker构建,发现当用两个容器搭建好集群时,再添加新的es容器节点时,总是出现其它容器被kill的现象,查看容器日志未发现任何错误信息,导致一段时间非常的迷茫。\n起始认为是配置不当引起了,于是一直在配置这方面找问题,网上的有些教程是直接在物理机器上或者虚拟机上进行部署,而自己的环境是docker, 通过 docker-compose 来部署的,\u0008环境有些差异。\n有网友提醒有可能是由 OOM 引起的问题,因为代码是137, 使用命令 “docker inspect 容器ID” 查看了一下容器, status列显示”OOMKilled\u0026quot;: false” ,所以从这里查看的话,并非是 OOM 引起的,起初个人分析容器的启动过程,是在启动一个容器时,dockerd应该先检查内存是否足够,如果不足够的话,则启动新窗口失败才对,而不是先将已存在的窗口killed,再去启动新容器,所以仍将OOM的原因排除掉了。\n后来\u0008发现一篇文章 介绍到这个和 docker for mac 分配的内存大小有关系,试着将给 docker 分配的内存调整 …"