Why Kafka consumer freezes on Node failure while Producer stays unaffected? - google-cloud-platform

I am new to Kafka and trying to create a Kafka cluster with 3 nodes for High Availability.
I have followed this guide and I have done the setup on Google Compute Instance (GCP VMs).
I tried creating topics with different --replication-factor.
Here is an example with replication-factor=3. I have tried the values 1 and 2 as well.
# With replication factor-3
bin/kafka-topics.sh --create \
--bootstrap-server xxx.xx.xx.xxx:9092,yy.yyy.yyy.yy:9092,zzz.zz.zz.zzz:9092 \
--replication-factor 3 --partitions 1 --topic sample-topic
This is what my consumer code looks like:
from kafka import KafkaConsumer
consumer = KafkaConsumer(
'sample-topic',
bootstrap_servers=[
'yyy.yy.yy.yyy'
],
client_id="sample-client-name",
auto_offset_reset="earliest",
group_id="sample-group-name")
for message in consumer:
print(message)
This is what my producer code looks like:
from time import sleep
from kafka import KafkaProducer
producer = KafkaProducer(
bootstrap_servers=[
'xxx.xx.xx.xxx', 'yyy.yy.yy.yyy', 'zzz.zz.zz.zzz'])
for i in range(1000):
message = str.encode("Message: " + str(i))
producer.send('sample-topic', value=message)
print("sent: {}".format(i))
sleep(5)
[xxx.xx.xx.xxx, yyy.yy.yy.yyy, zzz.zz.zz.zzz above are the IP addresses of the VMs]
Initially, the setup works pretty well. Now I start stopping the VMs (always keeping 2 VMs alive. Whenever I want to stop another VM I make sure at least two VMs are alive).
The producer code had the same bootstrap_servers as consumer code. I have tried keeping only 1 and 2 servers inside bootstrap_servers but it fails the same way for at least one of the VM going down( tried keeping all three VMs down one after another, making sure I'll have 2 VMs working).
Kafka consumers freeze because of stopping the VMs (only one VM down at a time, other two are brought up before stopping the targeted VM)
Is there any configuration I am missing? How to make the consumer stay intact like the producer?

If I read that linked post correctly, it doesn't mention that offsets.topic.replication.factor will have to be increased as well.
Otherwise, stopping the broker that holds the single replica will cause consumers fail to commit / lookup offsets

Related

Distributing tasks over HTTP using SpringBoot non-blocking WebClient (performance question?)

I have a large number of tasks - N, needs to be distributed to multiple http worker nodes via load balancer. Though there exists multiple nodes - n, combining all nodes we have a max-concurrency setting - x.
Always
N > x > n
One node can run those tasks in multiple threads. Mean time consumption for each task is about 50 sec to 1 min. Using Web-Client to distribute tasks and Mono response from Workers.
There exists a distributor and designed the process as follows:
1. Remove a task from queue.
2. Send the task via POST request using Web-Client and subscribe immediately with a subscriber instance
3. Holt new subscription when max concurrency reached to x
4. When any one of the above distributed task completes it calls on-accept(T) method of the subscriber.
5. If task queue is not empty, remove and send the next task / (x+1) task.
6. Keep track of total number completed tasks.
7. If all tasks completed & queue empty set Completable Future object as complete
8. Exit
The above process works fine. Tested with N=5000, n=10 & x=25.
Now the confusion is in this design we always have x number of concurrent subscriptions. As soon as one ends we create another until all tasks are completed. What is the impact of this in large scale production environment? If number of concurrent subscription (the value of x > 10,000) increases via the HTTP(s) load balancer is that going to have serious impact on performance and network latency? Our expected production volume will be something like below:
N=200,000,000
n=100
x=10,000
I will be grateful if some one with knowledge of Reactor and Web-Client expertise comment of this approach. Our main concern is having too many concurrent subscriptions.

Kafka Multi broker setup with ec2 machine: Timed out waiting for a node assignment. Call: createTopics

I am trying to setup kafka with 3 broker nodes and 1 zookeeper node in AWS EC2 instances. I have following server.properties for every broker:
kafka-1:
broker.id=0
listeners=PLAINTEXT_1://ec2-**-***-**-17.eu-central-1.compute.amazonaws.com:9092
advertised.listeners=PLAINTEXT_1://ec2-**-***-**-17.eu-central-1.compute.amazonaws.com:9092
listener.security.protocol.map=,PLAINTEXT_1:PLAINTEXT
inter.broker.listener.name=PLAINTEXT_1
zookeeper.connect=ec2-**-***-**-105.eu-central-1.compute.amazonaws.com:2181
kafka-2:
broker.id=1
listeners=PLAINTEXT_2://ec2-**-***-**-43.eu-central-1.compute.amazonaws.com:9093
advertised.listeners=PLAINTEXT_2://ec2-**-***-**-43.eu-central-1.compute.amazonaws.com:9093
listener.security.protocol.map=,PLAINTEXT_2:PLAINTEXT
inter.broker.listener.name=PLAINTEXT_2
zookeeper.connect=ec2-**-***-**-105.eu-central-1.compute.amazonaws.com:2181
kafka-3:
broker.id=2
listeners=PLAINTEXT_3://ec2-**-***-**-27.eu-central-1.compute.amazonaws.com:9094
advertised.listeners=PLAINTEXT_3://ec2-**-***-**-27.eu-central-1.compute.amazonaws.com:9094
listener.security.protocol.map=,PLAINTEXT_3:PLAINTEXT
inter.broker.listener.name=PLAINTEXT_3
zookeeper.connect=ec2-**-***-**-105.eu-central-1.compute.amazonaws.com:2181
zookeeper:
tickTime=2000
dataDir=/var/lib/zookeeper
clientPort=2181
When I ran following command in zookeeper I see that they are connected
I also telnetted from any broker to other ones with broker port they are all connected
However, when I try to create topic with 2 replication factor I get Timed out waiting for a node assignment
I cannot understand what is incorrect with my setup, I see 3 nodes running in zookeeper, but having problems when creating topic. BTW, when I make replication factor 1 I get the same error. How can I make sure that everything is alright with my cluster?
It's good that telnet checks the port is open, but it doesn't verify the Kafka protocol works. You could use kcat utility for that, but the fix includes
listeners are set to either PLAINTEXT://:9092 or PLAINTEXT://0.0.0.0:9092 for every broker, which means using the same port
Removing the number from the listener mapping and advertised listeners property such that each broker is the same
I'd also recommend looking at using Ansible/Terraform/Cloudformation to ensure you consistently modify the cluster rather than edit individual settings manually

Capacity-Scheduler Not Running multiple Jobs submitted in different queues

So we are new to Capacity scheduler. We are spinning up an AWS Cluster where we want to add capacity scheduler configuration to have the jobs running simultaneously in different different queue.
The issue is, even though we are managing to create a stable cluster with the scheduler config, but then we are unable to submit the jobs parallely in each queue.
By referring to the below link , we created the configurations by providing he respective values.
https://hadoop.apache.org/docs/current/hadoop-yarn/hadoop-yarn-site/CapacityScheduler.html
With all parameters added as given in the above link, the cluster fails while bootstrapping.
yarn.scheduler.capacity.maximum-am-resource-percent=0.2
yarn.scheduler.capacity.maximum-applications=10000
yarn.scheduler.capacity.node-locality-delay=40
yarn.scheduler.capacity.root.accessible-node-labels=*
yarn.scheduler.capacity.root.acl_administer_queue=yarn
yarn.scheduler.capacity.root.capacity=100
yarn.scheduler.capacity.root.default.acl_submit_applications=yarn
yarn.scheduler.capacity.root.default.capacity=50
yarn.scheduler.capacity.root.default.maximum-capacity=100
yarn.scheduler.capacity.root.default.state=RUNNING
yarn.scheduler.capacity.root.default.user-limit-factor=2
yarn.scheduler.capacity.root.queues=bt,default,opt
yarn.scheduler.capacity.queue-mappings-override.enable=false
yarn.scheduler.capacity.root.bt.acl_administer_queue=*
yarn.scheduler.capacity.root.bt.acl_submit_applications=*
yarn.scheduler.capacity.root.bt.capacity=25
yarn.scheduler.capacity.root.bt.maximum-capacity=100
yarn.scheduler.capacity.root.bt.minimum-user-limit-percent=100
yarn.scheduler.capacity.root.bt.ordering-policy=fair
yarn.scheduler.capacity.root.bt.ordering-policy.fair.enable-size-based-weight=false
yarn.scheduler.capacity.root.bt.priority=0
yarn.scheduler.capacity.root.bt.state=RUNNING
yarn.scheduler.capacity.root.bt.user-limit-factor=1
yarn.scheduler.capacity.root.default.acl_administer_queue=yarn
yarn.scheduler.capacity.root.default.minimum-user-limit-percent=25
yarn.scheduler.capacity.root.default.ordering-policy=fair
yarn.scheduler.capacity.root.default.ordering-policy.fair.enable-size-based-weight=false
yarn.scheduler.capacity.root.default.priority=0
yarn.scheduler.capacity.root.opt.acl_administer_queue=*
yarn.scheduler.capacity.root.opt.acl_submit_applications=*
yarn.scheduler.capacity.root.opt.capacity=25
yarn.scheduler.capacity.root.opt.maximum-capacity=25
yarn.scheduler.capacity.root.opt.minimum-user-limit-percent=100
yarn.scheduler.capacity.root.opt.ordering-policy=fair
yarn.scheduler.capacity.root.opt.ordering-policy.fair.enable-size-based-weight=false
yarn.scheduler.capacity.root.opt.priority=0
yarn.scheduler.capacity.root.opt.state=RUNNING
yarn.scheduler.capacity.root.opt.user-limit-factor=1
yarn.scheduler.capacity.root.priority=0
Some how with above configuration we are able to create a cluster but some issues which we are facing are:
1. The job runs perfectly fine in default queue and if submitted in other queues, its stuck in ACCEPTED state.
2. Only one job is getting submitted at a time and other jobs are still waiting in EMR steps instead of running under different different queues.
P.S: The jobs we are submitting on to the EMRs are spark jobs triggered from Lambda function.

Kafka consumer get "Marking the coordinator dead" error when using group-ids

I have a Kafka cluster running on Kubernetes (on AWS). Each broker has a corresponding external loadbalancer (ELB) and afaict, Kafka's advertised.listeners have been set appropriately so that the ELB's DNS names get returned when clients query for broker information. Most of the setup is similar to the one mentioned here.
I created a kafka consumer without specifying any group-id. With this consumer, reading messages from a topic worked just fine. However, if I set a group-id when creating the kafka consumer, I get back the following error messages:
2018-01-30 22:04:16,763.763.313055038:kafka.cluster:140735643595584:INFO:74479:Group coordinator for my-group-id is BrokerMetadata(nodeId=2, host=u'a17ee9a8a032411e8a3c902beb474154-867008169.us-west-2.elb.amazonaws.com', port=32402, rack=None)
2018-01-30 22:04:16,763.763.804912567:kafka.coordinator:140735643595584:INFO:74479:Discovered coordinator 2 for group my-group-id
2018-01-30 22:04:16,764.764.270067215:kafka.coordinator.consumer:140735643595584:INFO:74479:Revoking previously assigned partitions set([]) for group my-group-id
2018-01-30 22:04:16,866.866.26291275:kafka.coordinator:140735643595584:INFO:74479:(Re-)joining group my-group-id
2018-01-30 22:04:16,898.898.787975311:kafka.coordinator:140735643595584:INFO:74479:Joined group 'my-group-id' (generation 1) with member_id kafka-python-1.3.5-e31607c2-45ec-4461-8691-260bb84c76ba
2018-01-30 22:04:16,899.899.425029755:kafka.coordinator:140735643595584:INFO:74479:Elected group leader -- performing partition assignments using range
2018-01-30 22:04:16,936.936.614990234:kafka.coordinator:140735643595584:WARNING:74479:Marking the coordinator dead (node 2) for group my-group-id: [Error 15] GroupCoordinatorNotAvailableError.
2018-01-30 22:04:17,069.69.8890686035:kafka.cluster:140735643595584:INFO:74479:Group coordinator for my-group-id is BrokerMetadata(nodeId=2, host=u'my-elb.us-west-2.elb.amazonaws.com', port=32402, rack=None)
my-elb.us-west-2.elb.amazonaws.com:32402 is accessible from the client. I used kafkacat and set my-elb.us-west-2.elb.amazonaws.com:32402 as the broker address, it was able to list topics, consume topics, etc.
Any ideas what might be wrong?
Marking the coordinator dead happens when there is a Network communication error between the Consumer Client and the Coordinator (Also this can happen when the Coordinator dies and the group needs to rebalance). There are a variety of situations (offset commit request, fetch offset, etc) that can cause this issue. So to find the root cause issue you need to set the logging level to trace and debug :
logging.level.org.apache.kafka=TRACE
The problem was with 3 config settings in the server.properties that were set incorrectly.
The default minimum in-sync replicas was 2 (min.insync.replicas=2). However, the internal topic settings had a replication factor of 1 (offsets.topic.replication.factor=1).
When a consumer connected with a group-ip, it's corresponding entry had to be made the __consumer_offsets topic. When, this topic was updated, only a single replica was written. This threw errors that the number of in-sync replicas was below the required number.
org.apache.kafka.common.errors.NotEnoughReplicasException: Number of insync replicas for partition __consumer_offsets-42 is [1], below required minimum [2]
I changed the required number of in-sync replicas to 1 and things started working fine.

Celery and fanout - ensuring unique queue per worker?

I'm trying to do something in celery that should be fairly simple, but can't see an obvious configuration for.
I've got a master host and a number of slave hosts. The master host runs a Django application that sometimes has to instruct the slaves to do things asynchronously. The task needs to be carried out by all the slaves, and there is no return type.
Celery appears to be an obvious choice. My knowledge of RabbitMQ tells me that I should have a scenario where a single fanout exchange should exist on rMQ and each celery worker should create an exclusive queue and bind to this exchange. Then, every task request published by the master will be queued into each worker and then executed by every slave.
However, looking through all the celery docs, they seem geared around the scenario where each worker carrying out the same task binds to the same queue. This won't work with a fanout exchange type, as fanout simply creates one message per connected queue.
If I was using pika and pure python, I'd simply call something like channel.queue_declare(exclusive=True) and then bind that to my exchange, ensuring that each client has its own queue and gets a copy of the message.
How do you do this in celery?
This is short, as I'm on my phone. See the celery docs -> Userguide -> Routing. You want the Broadcast entity in Kombu which do what you describe, and there's a section about it in the routing guide.