Kafka的部署不仅需要集群可用,同时需要对orderer节点可连,这就是为什么有的时候,kafka集群本身没问题,但是orderer却总是报错。

为了试验kafka剥离方案的可行性,跨阿里云网络和内网进行部署。

部署环境如下:

K8s部署在阿里云环境上,192.168.8.108可连外网,作为master;192.168.8.107不能连外网,作为slave;

Kafka集群部署在内网192.168.9.21等集群上,都可以连外网。

因为orderer节点会起在slave机器上,也就是107这台机器,它无法直连外网。因此,通过nginx转发来保证orderer可以连上kafka集群,如下图所示。

那么advertised listeners的配置就尤为重要,毕竟这是kafka节点保存在zookeeper集群中的brokers元信息,orderer最终是通过这些地址去访问kafka的。

如果将kafka0的KAFKA_ADVERTISED_LISTENERS地址设为192.168.9.21:9092,虽然集群创建正常,但是orderer无法连上云象的内网地址,也就是无法连上kafka。所以,选择将kafka0的KAFKA_ADVERTISED_LISTENERS地址设为192.168.8.108:9092,然后在108上设置nginx代理,连接到 公网IP:9092,这样就可以连上kafka节点了。

尝试Setupbaas 发现orderer仍然报错kafka集群异常,但是kafka的启动日志没有任何异常。

setup的流程很长,还要清理环境,用kafkaclient来调试会方便很多。 fabric用的go语言client是sarama,简单改一下里面的producer就可以起一个简单的client,来测试kafka集群是否可用了。

用producer向kafka写入数据,发现报错信息如下:

报错说明,现在这个partiton没有leader,我们知道kafka每个partiton都会有一个leader,负责client的读写。

为了确认测试用的partition到底有没有leader,通过kafka内部的kafka-topic.sh来查看详细信息。

结果发现,topic首先是创建成功了,partition leader也是存在的,那么为什么client没有获取到该partition的leader信息呢?

带着疑问,查看sarama的部分源码,发现传给kafkaclient(例如orderer里面的producer)的addrlist只是作为seedbrokers,从seedbrokers里面尝试去连接kafka server来获取metadata。

这个metadata里面包括了,注册在zk里面的所有brokers的信息, kafkaclient实际上是与这些brokers进行交互的,所以即使seedbroker填的不全,有时候也不影响kafka集群的使用。

根据报错信息,可以发现GetMetadata返回的信息里面有ErrLeaderNotAvailable报错。

由上图可知,GetMetadata向kafkabroker发送了获取metadata的请求,并且key是3。

查看kafka源码,可以找到kafkaAPI如何处理key为3的请求。




GetMetadata在zk里面创建了topic,并且标记为无leader状态,每个新建的topic都是处于LEADER_NOT_AVAILABLE的状态的,那问题应该出现在metadata的更新上面,负责管理各个partition状态的组件是controller,是不是controller哪里出了问题了?

难道kafka启动日志里有报错被忽略了吗?搜索Controller相关log,发现并没有报错。


ZookeeperLeaderElector: 主要用于KafkController Leader选举,选举出Controller是broker1,但是后续却没有给出controller报错信息。

实际上,controller作为kafka的组件,日志另有输出,报错如下,确实是访问不到broker的地址。

controller是随机选择一个kafka节点上启动的,为了同步副本状态,controller需要连接上每一个kafka节点,因为advertised listener地址在容器里访问不到,所以controller与各个broker的连接出现异常。

进入容器查看网络连接情况,通过netstat –ae发现其中一个kafka有不正常的连接。

通过zkCli.sh发现,这正是controller所在的kafka,可以坐实是controller的问题了。

问题的原因找到了,但是为什么用kafka自带的脚本查出来的topic状态确实正常的呢?

查看该脚本调用的函数,发现改脚本调用的函数查询的数据居然来自于zk,并不是从kafka中获得。因为所有kafka连接zk并不存在问题,所以可以得出一致的topic 描述,看来使用这个脚本去查看topic状态也得慎重。

所以表面上可以创建topic,partition也存在leader终于有了解释。

Client在GetMetadata的时候,第一次创建了无主topic,在retry的时候,kafkaclient获取的metadata信息是来自于kafka的MetadataCache,因为controller的原因partitionState没有更新,所以返回的topic信息仍然有LEADER_NOT_AVAILABLE报错。

但是为什么正常情况,却没有返回这个LEADER_NOT_AVIALABLE呢?

在每个Broker的KafkaServer对象中都会创建MetadataCache组件, 负责缓存所有的metadata信息。


可见查询partitionMetadata时,是通过partitionState来判断存活的brokers里面是否有leader。如果有partitionState未更新,就返回LEADER_NOT_AVIALABLE的metadata,否则就可以返回最新的metadata。

Controller是如何更新partitionState的呢?

集群所有partition状态是由PartitionStateMachine来管理的。



由以上代码可见,partitionState更新需要通过ControllerChannelManager。ControllerChannelManager负责维护Controller Leader与集群中其他broker之间连接,是管理这个集群的基础。

然而,ControllerChannelManager在启动时就出问题了,连不上其他的broker,所以无法所有的kafka metadata都没能更新。controller必须连上advertised listeners,包括其自身所在的broker。

问题解决方案:

如果将kafka0的KAFKA_ADVERTISED_LISTENERS地址设为public.ip.net:9092,阿里云192.168.8.107上倒是可以通过修改host文件,把public.ip.net解析成192.168.8.108。这样,107在访问public.ip.net时,会连到108并通过nginx转发到192.168.9.21:9092。orderer需要连kafka集群的话,需要在k8s容器里添加host才行。

问题总结:

1、advertised listeners不仅需要让orderer可连接,还需要让每个可能成为controller的kafkabroker容器可连才行。

2、这种表面可以创建topic,实际集群无法使用的情况,可以考虑查看controller的日志。

3、kafka自带的kafka-topic脚本,描述的是zk里面的信息,并不一定于kafka里面的数据一致,需要慎重使用。

转载请注明出处:https://www.cnblogs.com/zooqkl

  1.  

KAFKA跨主机部署网络不通解决思路的更多相关文章

  1. kubernetes跨网段pod网络不通问题

    kubernetes跨网段问题 k8s的master是10.10.10.0网段,新加了一些node,网段是172.16.100.0网段,造成容器直接网络不能相互访问. 部署k8s的时候也部署了flan ...

  2. Ubuntu网络不通解决办法

    如下问题: 尝试和Host主机互ping也不通, Ubuntu: vmware 桥接模式 IP:192.168.1.202/24 gateway:192.168.1.1 Host主机:网络正常 IP: ...

  3. Exsi6.6主机网络不通解决办法

    Exsi虚拟机网络偶尔不通,防火墙性能不足 解决办法,断开网络连接再重连

  4. (转) docker跨主机 macvlan 网络配置

    原文链接 https://github.com/alfredhuang211/study-docker-doc/blob/master/docker%E8%B7%A8%E4%B8%BB%E6%9C%B ...

  5. u-boot-2014-04 网络不通解决一例

    不久前我移植了u-boot-214-04到Tq2440的板子上,基本功能都有了,网卡也可以使用了.有一天打算把u-boot-2010-06也也一直到tq2440上,移植完后发现u-boot-214-0 ...

  6. Docker系列04—跨主机网络方案(overlay/weave)

    在前面详细讲解了几种网络模式:none,host,bridge,container.他们解决了单个主机间的容器的通信问题,并不能实现多个主机容器之间的通信. 跨主机网络方案包括两大类: 1,docke ...

  7. centos7下安装docker(15.6docker跨主机网络---Weave)

    Weave是weaveworks开发的容器网络解决方案.weave创建的虚拟网络可以将部署在多个主机上的容器连接起来.对于容器来说,weave就像一个巨大的网络交换机,容器可以直接通信,无需NAT和端 ...

  8. centos7下安装docker(15.1跨主机网络)

    之前学习了单个host上的网络,我们知道单个host上的网络有:none,host,bridge和joined,他们解决了单个host上面的容器通信的问题:接下来我们讨论跨主机间容器通信的方案 跨主机 ...

  9. Docker跨主机网络——overlay

    前言 在Docker网络--单host网络一文中,我为大家总结了Docker的单机网络相关知识和操作,单机网络比较容易.本文我为大家总结Docker跨主机通信相关知识.同样本文大部分内容以CloudM ...

随机推荐

  1. BIO, NIO 和 Epoll (转载)

    很好的文章 https://eklitzke.org/blocking-io-nonblocking-io-and-epoll

  2. [svc]简单理解什么是rpc调用?跟restapi有何区别?

    什么是rpc调用 restapi调用方式是对数据的crud. 常见的我们写flash写个api,或者借助django drf写个标准的resetapi,一个url可以借助httpget post pu ...

  3. datetime模块处理时间

    python常用的处理时间的库有:datetime,time,calendar.datetime库包括了date(储存日期:(年.月.日),time(储存时间:(小时.分.秒和微秒),timedelt ...

  4. centos7 vmd-1.9.3安装

    1. 下载安装包 安装包下载地址是http://www.ks.uiuc.edu/Research/vmd/,选择自己合适的版本,我下载1.9.3版本 2. 安装必要库 yum install free ...

  5. table的thead,tbody,tfoot

    为了让大表格(table)在下载的时候可以分段的显示,就是说在浏览器解析HTML时,table是作为一个整体解释的,使用tbody可以优化显示. 如果表格很长,用tbody分段,可以一部分一部分地显示 ...

  6. OI养老专题01:约瑟夫问题

    有M个人,其编号分别为1-M.这M个人按顺序排成一个圈.现在给定一个数N,从第一个人开始依次报数,数到N的人出列,然后又从下一个人开始又从1开始依次报数,数到N的人又出列...如此循环,直到最后一个人 ...

  7. Firefox 安装 Adobe Flashplayer

    3. 安装Adobe Flash Player: Adobe Flash Player的安装比较容易,只要将对应的文档复制到正确的的位置即可,具体的操作 如下: (1) 将libflashplayer ...

  8. HashMap 源码分析

    static final int DEFAULT_INITIAL_CAPACITY = 16;  默认容量 static final int MAXIMUM_CAPACITY = 1073741824 ...

  9. angular4 使用swiper 首次加载问题(一)

    angular 在使用外部插件swiper 还是有不少小坑的,下面来聊一聊.angular在使用swiper 的一些坑 一开始觉得使用外部引入的方式比较好,就在外部定义了.简单快捷方便, 但是在开发后 ...

  10. 关于Xocd升级 cocopoads无法使用的解决

    最近由于工作原因,升级了下Xcode,以前是8.1现在升级到了8.3,导致无法使用了cocopoads,研究了好久终于找到了解决办法. 先描述下我的几个问题吧. 1.当运行cocopoads的时候出现 ...