Spark Streaming with Kafka in Scala - scala

I'm trying to build a Kafka consumer in Scala using IntelliJ to read messages from a Kafka topic and save them on hdfs. I'm using spark 1.6.2, kafka_2.10-0.10, scala 2.10.5 with hdp 2.5.3. I'm getting the error below:
Exception in thread "main" java.lang.NoSuchMethodError: kafka.consumer.SimpleConsumer.<init>(Ljava/lang/String;IIILjava/lang/String;Lorg/apache/kafka/common/protocol/SecurityProtocol;)V
From my research on here, I've learned that it's a jar/dependency issue but I'm still not able to resolve it.

You have to make sure that kafka libraries are available for Spark runtime. There are several ways to make sure of this:
Invoking spark shell or spark-submit with --jars "/location/of/your/kafka-jar"
Copy kafka related jars into your spark installation's "jars" folder. (Note: If you running on cluster, you have to copy these jars to all the nodes. So, I recommend above method where spark does this for you internally)

Related

Serialization issues when connecting to Spark cluster

I have a Spark app written in Scala that is writing and reading from Parquet files.
The app exposes an HTTP API, and when it receives requests, sends work to a Spark cluster through a long-lived context that is persisted through the app's life.
It then returns the results to the HTTP client.
This all works fine when I'm using a local mode, with local[*] as master.
However, as soon as I'm trying to connect to a Spark cluster, I'm running into serialization issues.
With Spark's default serializer, I get the following:
java.lang.ClassCastException: cannot assign instance of scala.collection.immutable.List$SerializationProxy to field org.apache.spark.sql.execution.FilterExec.otherPreds of type scala.collection.Seq in instance of org.apache.spark.sql.execution.FilterExec.
If I enable Kryo serializer, I get java.lang.IllegalStateException: unread block data.
This happens when trying to read from the Parquet files, however I don't believe it has anything to do with the Parquet files themselves, simply with the serialization of the code that's being sent over to the Spark cluster.
From a lot of internet searches, I've gathered that this could be caused by incompatibilities between Spark versions, or even Java versions.
But the versions being used are identical.
The app is written in Scala 2.12.8 and ships with Spark 2.4.3.
The Spark cluster is running Spark 2.4.3 (the version compiled with Scala 2.12).
And the machine on which both the Spark cluster and the app are running is using openJDK 1.8.0_212.
According to another internet search, the problem could have been because of a mismatch in the spark.master URL.
So I've set spark.master in spark-defaults.conf to the same value I'm using within the app to connect to it.
However, this hasn't solved the issue and I am now running out of ideas.
I am not entirely sure what the underlying explanation is, but I fixed it by copying my application's jar into Spark's jars directory. Then I was still encountering an error, but a different one: something about a Cats/kernel/Eq class missing. So I added cats-kernel's jar into Spark's jars directory.
And now everything works. Something I read in another Stack Overflow thread may explain it:
I think that whenever you do any kind of map operation using a lambda which is referring to methods/classes of your project, you need to supply them as an additional jar. Spark does serializes the lambda itself, but is not pulling together its dependencies. Not sure why the error message is not informative at all.

How to mock data for cassandra when using spark cassandra connector in spark streaming testing?

I have a code written entirely in scala which uses spark streaming to get json data from kafka topic and then dump it to cassandra and another kafka topic after some processing. Now I need to write an unit test for this code. I need help on how to write such a test and how we can mock data when I am using spark cassandra connector.
You can use spark-cassandra-connector-embedded that is developed together with connector itself. Just add the Maven or SBT dependency to your project, like, this for SBT:
"com.datastax.spark" %% "spark-cassandra-connector-embedded" % {latest.version}

Support multiple Spark distributions on Yarn cluster

I run multiple spark jobs on a cluster via $SPARK_HOME/bin/spark-submit --master yarn --deploy-mode cluster.
When a new version of Spark goes live I'd like to somehow roll out a new distribution over the cluster alongside with the old one and then gradually migrate all my jobs one by one.
Unfortunately, Spark relies on $SPARK_HOME global variable so I can't figure out how to achieve it.
It would be especially useful when Spark for Scala 2.12 is out.
It is possible to run any number of Spark distributions on YARN cluster. I've done it a lot of times on my MapR cluster, mixing 1-3 different versions, as well as setting up official Apache Spark there.
All you need is to tweak conf/spark-env.sh (rename spark-env.sh.template) and just add a line:
export SPARK_HOME=/your/location/of/spark/spark-2.1.0

scala spark cassandra installation

How many ways are there to run Spark? If I just declare dependencies in build.sbt, Spark is supposed to be downloaded and works?
But if I want to run Spark locally (download the Spark tar file, winutils...), how can I specify in scala code that I want to run my code against the local Spark and not against the dependencies downloaded in the IntelliJ?
In order to connect Spark to Cassandra, do I need a local installation of Spark? I read somewhere it's not possible to connect from a "programmatically" Spark to a local Cassandra database
1) Spark runs in a slightly strange way, there is your application (the Spark Driver and Executors) and there is the Resource Manager (Spark Master/Workers, Yarn, Mesos or Local).
In your code you can run against the in process manager (local) by specifying the master as local or local[n]. The Local mode requires no installation of Spark as it will be automatically setup in the process you are running. This would be using the dependencies you downloaded.
To run against a Spark Master which is running locally, you use a spark:// url that points at your particular local Spark Master instance. Note that this will cause executor JVMS to start separate from your application necessitating the distribution of application code and dependencies. (Other resource managers have there own identifying urls)
2) You do not need a "Resource Manager" to connect to C* from Spark but this ability is basically for debugging and testing. To do this you would use the local master url. Normal Spark usage should have an external Resource Manager because without an external resource manager the system cannot be distributed.
For some more Spark Cassandra examples see
https://github.com/datastax/SparkBuildExamples

Should the worker also need Hadoop installed for Spark?

I have setup scala,Hadoop & spark & started the master node successfully.
I just installed scala & spark & started the worker(slave) too. So what I am confused is shouldn't Haddop be setup in worker too for running tasks?
This link from the official Apache Spark shows how to configure a spark cluster. And the requirements are clearly explained here that both scala and hadoop are required.