KAFKA跨主机部署网络不通解决思路
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
KAFKA跨主机部署网络不通解决思路的更多相关文章
- kubernetes跨网段pod网络不通问题
kubernetes跨网段问题 k8s的master是10.10.10.0网段,新加了一些node,网段是172.16.100.0网段,造成容器直接网络不能相互访问. 部署k8s的时候也部署了flan ...
- Ubuntu网络不通解决办法
如下问题: 尝试和Host主机互ping也不通, Ubuntu: vmware 桥接模式 IP:192.168.1.202/24 gateway:192.168.1.1 Host主机:网络正常 IP: ...
- Exsi6.6主机网络不通解决办法
Exsi虚拟机网络偶尔不通,防火墙性能不足 解决办法,断开网络连接再重连
- (转) docker跨主机 macvlan 网络配置
原文链接 https://github.com/alfredhuang211/study-docker-doc/blob/master/docker%E8%B7%A8%E4%B8%BB%E6%9C%B ...
- u-boot-2014-04 网络不通解决一例
不久前我移植了u-boot-214-04到Tq2440的板子上,基本功能都有了,网卡也可以使用了.有一天打算把u-boot-2010-06也也一直到tq2440上,移植完后发现u-boot-214-0 ...
- Docker系列04—跨主机网络方案(overlay/weave)
在前面详细讲解了几种网络模式:none,host,bridge,container.他们解决了单个主机间的容器的通信问题,并不能实现多个主机容器之间的通信. 跨主机网络方案包括两大类: 1,docke ...
- centos7下安装docker(15.6docker跨主机网络---Weave)
Weave是weaveworks开发的容器网络解决方案.weave创建的虚拟网络可以将部署在多个主机上的容器连接起来.对于容器来说,weave就像一个巨大的网络交换机,容器可以直接通信,无需NAT和端 ...
- centos7下安装docker(15.1跨主机网络)
之前学习了单个host上的网络,我们知道单个host上的网络有:none,host,bridge和joined,他们解决了单个host上面的容器通信的问题:接下来我们讨论跨主机间容器通信的方案 跨主机 ...
- Docker跨主机网络——overlay
前言 在Docker网络--单host网络一文中,我为大家总结了Docker的单机网络相关知识和操作,单机网络比较容易.本文我为大家总结Docker跨主机通信相关知识.同样本文大部分内容以CloudM ...
随机推荐
- 关闭 synactive guixt. 在sap gui的右上角一个标志里,将 active guixt 选项去掉即可。
关闭 synactive guixt. 在sap gui的右上角一个标志里,将 active guixt 选项去掉即可.
- allegro17.2 gerber 步骤
1.Manufacture -> NC -> Drill Customization... 先点击 Auto generate symbols,出来对话框后点击 YES .然后在Symbo ...
- iOS上传图片和视频(base64和file)
前言:iOS开发中经常会使用到图片和视频上传及保存到相册,下面我讲介绍视频图片的两种上传服务器的方法.以阿里云的OSS服务器为例. 友情提示:上传图片方法在APP中使用很广泛,最好单独写一个图片上传的 ...
- jmeter-PC注册遇到的问题与解决
2019-04-26问题:
- Xamarin.Forms FlexLayout 布局扩展+ 模板扩展+弹性换行
Binding a FlexLayout to a Collection In May we published a doc on the new FlexLayout control that’ ...
- STM32F103单片机解密资料
STM32F103单片机解密资料下载 一.STM32 32位ARM Cortex MCU 基于ARM® Cortex® M 处理器内核的 32位闪存微控制器STM32产品家族,为MCU用户开辟了一个全 ...
- java操作对比两个字符串,将差异数据提取出来
记录瞬间 在实际的工作中,需要解决生成两次字符串结果进行对比的问题,将存在差异的字符串直接给出来. 当然,前提是需要将对比的两次结果,进行前期处理 比如: a_str = "@com/ene ...
- 《ASP.NET Core In Action》读书笔记系列三 ASP.NET Core如何处理请求的?
在本节中,您将看到ASP.NET Core应用程序如何运行的,从请求URL开始到页面呈现在浏览器中. 为此,您将看到 一个HTTP请求在Web服务器中是如何被处理的.ASP.NET Core如何扩展该 ...
- css3 样式过度器 Transition
transition 简写属性,用于在一个属性中设置四个过渡属性. 1. transition 把鼠标指针放到 div 元素上,其宽度会从 100px 逐渐变为 300px: eg: div{wi ...
- C博客作业06--结构体&文件
1.本章学习总结 1.1思维导图 1.2本章学习体会 学习了结构和文件,又是懵懵的课了,我的天啊.结构还好,题目集一出就做了,不是很难,感觉掌握的还可以,不过这只是感觉而已,等到真正来写大作业的时候又 ...