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 ...
随机推荐
- (4.11)mysql备份还原——mysql闪回技术(基于binlog)
0.闪回技术与工具简介 mysql闪回工具比较流行三大类: [0.1]官方的mysqlbinlog:支持数据库在线/离线,用脚本处理binlog的输出,转化成对应SQL再执行.通用性不好,对正则.se ...
- Hydra(爆破神器)
PS:这款暴力密码破解工具相当强大,支持几乎所有协议的在线密码破解,其密码能否被破解关键在于字典是否足够强大.对于社会工程型渗透来说,有时能够得到事半功倍的效果.本文仅从安全角度去探讨测试,使用本文内 ...
- C++实验三
part2 graph.h #ifndef GRAPH_H#define GRAPH_H// 类Graph的声明 class Graph { public: Graph(char ch, int n) ...
- leafLet入门教程兼leafLet API中文文档参考
英文文档参考:https://leafletjs.com/reference-1.3.4.html#popup 博客参考:https://blog.csdn.net/qq_36595013/artic ...
- ShellExecute 打开网页、目录、邮箱
#include <Windows.h> #include <tchar.h> int WINAPI _tWinMain(HINSTANCE hInstance, HINSTA ...
- laravel----------Client error: `POST http://47.98.116.219/oauth/token` resulted in a `401 Unauthorized` response: {"error":"invalid_client","message":"Client authentication failed"}
1.设备没有授权,原因是 这个client_id的值就是数据库wk_oauth_clients 的主键ID,查看下表是否有这条数据
- Vue渐进式JavaScript 框架
1. Vue简介 1.1 初步了解Vue.js框架 Vue.js (读音 /vjuː/,类似于 view) 是一种轻量级前端MVVM框架.同时吸收了React(组件化)和Angular(灵活指令页面 ...
- 华为AR-111S路由器GRE协议设置
一.GRE的定义: gre(generic routing encapsulation,通用路由封装)协议是对某些网络层协议(如ip 和ipx)的数据报进行封装,使这些被封装的数据报能够在另一个网络层 ...
- day21 python之模块和包
一 模块 1 什么是模块? 常见的场景:一个模块就是一个包含了python定义和声明的文件,文件名就是模块名字加上.py的后缀. 但其实import加载的模块分为四个通用类别: 1 使用python编 ...
- WinForm中 Asp.Net Signalr消息推送测试实例
p{ text-align:center; } blockquote > p > span{ text-align:center; font-size: 18px; color: #ff0 ...