Jekyll2019-02-08T11:34:58+00:00http://diegoreico.com/feed.xmldiegoreicoMy Dev Blog & R4nd00m Th1ngsDiego Reiriz Coresdiegoreiriz@gmail.comInteresting FOSDEM 2019 Talks for people working with Data2019-08-02T00:00:00+00:002019-08-02T00:00:00+00:00http://diegoreico.com/conferences/fosdem2019talksforpeopleworkingwithdata<p>Last year I could attend to <a href="https://fosdem.org">FOSDEM</a> 2018 edition at Brussels and I was amazed with the number of cool talks that <a href="https://fosdem.org">FOSDEM</a> hosts at the same time (it’s pretty crazy! look at the <a href="https://fosdem.org/2019/schedule/day/saturday/">full schedule for 1 day</a>)</p>
<p>Unfortunetly, this year I couldn’t attend to <a href="https://fosdem.org">FOSDEM</a> 2019 edition, BUT I filtered all the uploaded talks to only select thoose ones relevant for people with interests on Data Science (like me). By the way, all the <a href="https://video.fosdem.org/">recordings are avaliable on the FOSDEM’s ftp web server</a> if you want to check them.</p>
<p><em><strong>Note: this list is subject to changes</strong></em></p>
<h2 id="ai---hpcdata-science-dev-room">AI - HPC/Data Science dev room</h2>
<ul>
<li><a href="http://mirror.onet.pl/pub/mirrors/video.fosdem.org/2019/UA2.118/8_principles_production_data_science.mp4">The state of machine learning operations in 2019: reproducibility, explainability, bias evaluation and beyond</a></li>
<li><a href="https://ftp.fau.de/fosdem/2019/UA2.118/beam_cross_language.mp4">Apache Beam: from zero to portability</a></li>
<li><a href="https://mirrors.dotsrc.org/fosdem/2019/UA2.118/condition_monitoring.mp4">Condition monitoring and transfer learning</a></li>
<li><a href="http://bofh.nikhef.nl/events/FOSDEM/2019/UA2.118/dl_parallel_db.mp4">Deep Learning on Massive Parallel Procesing Databases</a></li>
<li><a href="http://ftp.belnet.be/mirror/FOSDEM/2019/UA2.118/feature_store.mp4">Feature Store: a data management layer in ML pipelines</a></li>
<li><a href="http://mirror.onet.pl/pub/mirrors/video.fosdem.org/2019/UA2.118/nakadi.mp4">Nakadi Streaming Events for 100s of Teams</a></li>
<li><a href="https://mirror.as35701.net/video.fosdem.org/2019/UA2.118/rapids.mp4">RAPIDS: Datascience with GPUs</a></li>
<li><a href="https://ftp.fau.de/fosdem/2019/UA2.118/streaming_pipelines_neural_machine_translation.mp4">Streaming Pipelines for Neural Machine translation</a></li>
<li><a href="https://mirror.as35701.net/video.fosdem.org/2019/UA2.118/validating_big_data_jobs.mp4">Validating Big Data Jobs</a></li>
</ul>
<h2 id="geo">GEO</h2>
<ul>
<li><a href="https://mirror.as35701.net/video.fosdem.org/2019/AW1.126/geo_3geonames.mp4">3Geonomes.org</a></li>
<li><a href="https://ftp.heanet.ie/mirrors/fosdem-video/2019/AW1.126/geo_augmentedreality.mp4">Hikar - Augmented reality for hikers</a></li>
<li><a href="https://ftp.heanet.ie/mirrors/fosdem-video/2019/AW1.126/geo_boostgeometry.mp4">Latest Development in Boost Geometry</a></li>
<li><a href="http://bofh.nikhef.nl/events/FOSDEM/2019/AW1.126/geo_gpxtraces.mp4">Hundred* Thousand rides a day</a></li>
<li><a href="https://ftp.heanet.ie/mirrors/fosdem-video/2019/AW1.126/geo_osmdeeplearning.mp4">Improve OSM data quality with deep learning</a></li>
<li><a href="https://ftp.heanet.ie/mirrors/fosdem-video/2019/AW1.126/geo_osmqgis.mp4">OpenStreetMaps for emergency prep: The view from San Francisco</a></li>
<li><a href="https://ftp.heanet.ie/mirrors/fosdem-video/2019/AW1.126/geo_osmwikidata.mp4">Linking OpenStreetMap and Wikidata</a></li>
<li><a href="https://ftp.heanet.ie/mirrors/fosdem-video/2019/AW1.126/geo_streetview.mp4">OpenTrailView 360</a></li>
</ul>
<h2 id="databases">Databases</h2>
<ul>
<li><a href="https://ftp.heanet.ie/mirrors/fosdem-video/2019/H.1301/improve_sql.mp4">Improve your SQL</a></li>
</ul>
<h2 id="graphs">Graphs</h2>
<ul>
<li><a href="https://ftp.heanet.ie/mirrors/fosdem-video/2019/H.1308/graph_access_control_tinkerpop.mp4">Differentiated access control to graph data</a></li>
<li><a href="http://mirror.onet.pl/pub/mirrors/video.fosdem.org/2019/H.1308/graph_french_trade_study.mp4">Using networks to study 19th century French trade</a></li>
<li><a href="http://ftp.belnet.be/mirror/FOSDEM/2019/H.1308/graph_gephi_js.mp4">Gephi JS: exploring the dystopian future of a Javascript Gephi</a></li>
<li><a href="https://ftp.heanet.ie/mirrors/fosdem-video/2019/H.1308/graph_mgmt_config.mp4">Mgmt Config: a tale of three graphs</a></li>
<li><a href="https://ftp.heanet.ie/mirrors/fosdem-video/2019/H.1308/graph_multiplex_analysis_graphblas.mp4">Multiple Graph analyssis with GraphBlas</a></li>
<li><a href="https://ftp.heanet.ie/mirrors/fosdem-video/2019/H.1308/graph_real_time_streaming_kafka_neo4j.mp4">Leveraging realtime streaming with Neo4j-Streams</a></li>
<li><a href="https://ftp.heanet.ie/mirrors/fosdem-video/2019/H.1308/graph_usage_efl.mp4">Graph usage in EFL</a></li>
<li><a href="https://ftp.heanet.ie/mirrors/fosdem-video/2019/H.1308/graph_weaviate_knowledge_graph.mp4">Introduction of OSS Weaviate, the Descentralized Knowldege Graph</a></li>
</ul>
<h2 id="ml-on-code">ML on Code</h2>
<ul>
<li><a href="https://ftp.heanet.ie/mirrors/fosdem-video/2019/H.2213/ml_on_code_astor.mp4">Astor an automated code repair framework</a></li>
<li><a href="https://ftp.heanet.ie/mirrors/fosdem-video/2019/H.2213/ml_on_code_automatic_refactoring.mp4">How to build an automatic refactoring and migration toolkit</a></li>
<li><a href="https://ftp.heanet.ie/mirrors/fosdem-video/2019/H.2213/ml_on_code_code_review_suggestions.mp4">Suggesting Fixes during code review with ML</a></li>
<li><a href="https://ftp.heanet.ie/mirrors/fosdem-video/2019/H.2213/ml_on_code_coming.mp4">Coming: a tool for Mining Change Pattern Instances from Git Commits</a></li>
<li><a href="https://ftp.heanet.ie/mirrors/fosdem-video/2019/H.2213/ml_on_code_commit_message.mp4">Neural commit message suggester</a></li>
<li><a href="https://ftp.fau.de/fosdem/2019/H.2213/ml_on_code_deduplicating_pga.mp4">Deduplication of large amounts of code</a></li>
<li><a href="https://ftp.heanet.ie/mirrors/fosdem-video/2019/H.2213/ml_on_code_kotlin_anomalies.mp4">Code anomalies on kotlin programs</a></li>
<li><a href="http://ftp.belnet.be/mirror/FOSDEM/2019/H.2213/ml_on_code_mining_source_code.mp4">Mining source code^3</a></li>
<li><a href="https://mirror.cyberbits.eu/fosdem/2019/H.2213/ml_on_code_smelling_source.mp4">Smelling Source Code Using Deep Learning</a></li>
<li><a href="https://ftp.heanet.ie/mirrors/fosdem-video/2019/H.2213/ml_on_code_understanding.mp4">Understanding Source Code with Deep Learning</a></li>
</ul>
<h2 id="searching">Searching</h2>
<ul>
<li><a href="https://mirrors.dotsrc.org/fosdem/2019/K.3.201/apache_lucene_solr_8.mp4">Apache Lucene and Apache Solr 8</a></li>
<li><a href="https://mirror.as35701.net/video.fosdem.org/2019/K.3.201/elasticsearch_correctness_performance_validator.mp4">ElasticSearch Correctnes and perfOrmances Validator</a></li>
<li><a href="https://ftp.fau.de/fosdem/2019/K.3.201/learning_to_rank.mp4">Learning to Rank</a></li>
<li><a href="https://ftp.heanet.ie/mirrors/fosdem-video/2019/K.3.201/lucene_upgrade_jira_8.mp4">Lucene upgrade in Jira 8.0</a></li>
<li><a href="https://ftp.heanet.ie/mirrors/fosdem-video/2019/K.3.201/super_speedy_scoring_lucene.mp4">Super-Speedy scoring in Lucene 8</a></li>
</ul>
<h2 id="python">Python</h2>
<ul>
<li><a href="http://ftp.belnet.be/mirror/FOSDEM/2019/UD2.120/python_application_configuration.mp4">Mastering Application/service configuration</a></li>
<li><a href="http://mirror.onet.pl/pub/mirrors/video.fosdem.org/2019/UD2.120/python_matching_with_behavior_trees.mp4">Tree matchings with Behavior Trees</a></li>
<li><a href="https://ftp.heanet.ie/mirrors/fosdem-video/2019/UD2.120/python_memory_management.mp4">Memory management in Python</a></li>
</ul>Diego Reiriz Coresdiegoreiriz@gmail.comLast year I could attend to FOSDEM 2018 edition at Brussels and I was amazed with the number of cool talks that FOSDEM hosts at the same time (it’s pretty crazy! look at the full schedule for 1 day)Rocking with Flink on a Zeppelin2018-06-09T00:00:00+00:002018-06-09T00:00:00+00:00http://diegoreico.com/environments/runningflinkgclusterwithzeppelin<p>I recently started to use Apache Zeppelin, because I wanted a tool that allows me to work with notebooks using Scala + Apache Flink and as a plus, Apache Zeppelin provides you with autogenerated plots if you print you data as TSV file !!!!!!!</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>%table
t0 t1 t2 t3 t4 t5 t6 t7 t8 t9 t10 t11 t12 t13 t14
1 2 3 4 5 0 0 0 0 0 0 0 0 0 0
1 1 2 3 4 5 0 0 0 0 0 0 0 0 0
1 2 2 2 3 4 4 5 0 0 0 0 0 0 0
1 3 4 5 0 0 0 0 0 0 0 0 0 0 0
1 1 1 2 2 2 3 3 3 4 4 4 5 5 5
1 1 2 3 1 4 5 0 0 0 0 0 0 0 0
1 2 3 1 1 4 5 0 0 0 0 0 0 0 0
1 5 3 2 4 0 0 0 0 0 0 0 0 0 0
1 5 5 3 2 1 4 0 0 0 0 0 0 0 0
1 5 5 3 5 1 4 2 0 0 0 0 0 0 0
2 3 3 3 4 5 1 0 0 0 0 0 0 0 0
</code></pre></div></div>
<p><img src="/assets/images/flinkzeppelin/table.png" alt="table" />
<img src="/assets/images/flinkzeppelin/plot.png" alt="graph" /></p>
<p>If you print your data inside a notebook paragraph it will automatically allow you to do scatter plots, bar plots, pie charts, etc. and c’mon that’s freaking amazing, you don’t have to write you data in a DB/File/Thing and then plot the data using other tools, so you can have all your work in a single place and that’s nice.</p>
<p>So, if everything is nice, what am I doing here writting all this? By default, Zeppelin brings a Flink interpreter that you can use to run Flink workloads and when you execute it for the first time, it will start a Flink local minicluster in wich Zeppelin will run your workload and that’s great if you are doing small tests, but when the problem scales a bit that cluster isn’t enough. Also the Flink minicluster that brings Zeppelin is running Flink 1.1.3 and Flink 1.5 it’s already out. The sad part about this, it that i only had time to make it run with Flink 1.4.2, because until that version Flink’s jobs could be sended using an RPC port Job Manager’s port 6123, but since that version jobs should be sended using Flink’s REST API, so Zeppelin’s interpreter should be patched to use the REST API.</p>
<h2 id="creating-our-environmet">Creating our environmet</h2>
<p>Let’s get dirty and start to work a bit on all this, first of all we need to create the environment that we want to use, in this case it will be a Zeppelin Notebook Server, a Flink node running a Jobmanagar and two Flink nodes running Taskmanagers. With this in mind I’ve made the following docker-compose file:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>version: "3"
services:
#=============================
# FLINK
#=============================
jobmanager:
image: flink:1.4.2
expose:
- "6123"
ports:
- "6123:6123"
- "8081:8081"
command: jobmanager
environment:
- JOB_MANAGER_RPC_ADDRESS=jobmanager
taskmanager:
image: flink:1.4.2
expose:
- "6121"
- "6122"
depends_on:
- jobmanager
command: taskmanager
links:
- "jobmanager:jobmanager"
environment:
- JOB_MANAGER_RPC_ADDRESS=jobmanager
#=============================
# ZEPPELIN
#=============================
zeppelin:
image: apache/zeppelin:0.7.3
ports:
- "8080:8080"
</code></pre></div></div>
<p>Once we have this docker-compose file we can create our environment running the following docker-compose command</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>docker-compose up -d --scale taskmanager=2
</code></pre></div></div>
<p>So our environment should look like this:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code> Name Command State Ports
-----------------------------------------------------------------------------------------------------------------------
zeppelinflink15_jobmanager_1 /docker-entrypoint.sh jobm ... Up 0.0.0.0:6123->6123/tcp, 0.0.0.0:8081->8081/tcp
zeppelinflink15_taskmanager_1 /docker-entrypoint.sh task ... Up 6121/tcp, 6122/tcp, 6123/tcp, 8081/tcp
zeppelinflink15_taskmanager_2 /docker-entrypoint.sh task ... Up 6121/tcp, 6122/tcp, 6123/tcp, 8081/tcp
zeppelinflink15_zeppelin_1 /usr/bin/tini -- bin/zeppe ... Up 0.0.0.0:8080->8080/tcp
</code></pre></div></div>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>NOTE: my containers start with the prefix 'zeppelinflink15' because thats the name of the folder in which im working
</code></pre></div></div>
<p>If we access to <a href="http://localhost:8080">http://localhost:8080</a> we should have access to zeppeling UI</p>
<p><img src="/assets/images/flinkzeppelin/zeppelinui.png" alt="zeppelinUI" /></p>
<p>And if we access to <a href="http://localhost:8081">http://localhost:8081</a> we should be able to see Flink’s Web UI</p>
<p><img src="/assets/images/flinkzeppelin/flinkui.png" alt="FlinkUi" /></p>
<h2 id="setting-up-the-environment">Setting up the environment</h2>
<p>Once we have all the parts that we need, the next step is to configure Zeppelin to use our Flink cluster when we run a paragraph of code with the flink interpreter <code class="highlighter-rouge">%flink</code>. For this, we need to go to the <a href="http://localhost:8080/#/interpreter">interpreters section inside Zeppelin UI</a> and find the Flink interpreter <code class="highlighter-rouge">%flink</code></p>
<p><img src="/assets/images/flinkzeppelin/flinkinterpreter.png" alt="Default flink interpreter" /></p>
<p>Before changing anything in the interpreter I want to show you which libraries contains that interpreter, to understand wich changes we are gonna do. So let’s connect to the Zeppelin container that we have created with docker-compose using:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>NOTE: to obtain the name of the Zeppelin container use sudo docker-compose ps
</code></pre></div></div>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>docker exec -it zeppelinflink15_zeppelin_1 /bin/bash
</code></pre></div></div>
<p>Once inside the container we can run the following command to check the dependencies that is using the Flink interpreter</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ls interpreter/flink/
activation-1.1.jar
akka-actor_2.11-2.3.7.jar
akka-remote_2.11-2.3.7.jar
akka-slf4j_2.11-2.3.7.jar
akka-testkit_2.11-2.3.7.jar
aopalliance-1.0.jar
avro-1.7.6.jar
chill_2.11-0.7.4.jar
chill-java-0.7.4.jar
commons-beanutils-bean-collections-1.8.3.jar
commons-cli-1.3.1.jar
commons-codec-1.5.jar
commons-collections-3.2.1.jar
commons-compress-1.4.1.jar
commons-configuration-1.9.jar
commons-daemon-1.0.13.jar
commons-digester-1.8.1.jar
commons-el-1.0.jar
commons-io-2.4.jar
commons-lang-2.5.jar
commons-lang3-3.3.2.jar
commons-logging-1.1.1.jar
commons-math3-3.5.jar
commons-net-3.1.jar
config-1.2.1.jar
flink-annotations-1.1.3.jar
flink-clients_2.11-1.1.3.jar
flink-core-1.1.3.jar
flink-java-1.1.3.jar
flink-metrics-core-1.1.3.jar
flink-optimizer_2.11-1.1.3.jar
flink-runtime_2.11-1.1.3.jar
flink-scala_2.11-1.1.3.jar
flink-scala-shell_2.11-1.1.3.jar
flink-shaded-hadoop2-1.1.3.jar
flink-streaming-java_2.11-1.1.3.jar
flink-streaming-scala_2.11-1.1.3.jar
force-shading-1.1.3.jar
grizzled-slf4j_2.11-1.0.2.jar
gson-2.2.jar
guice-3.0.jar
jackson-annotations-2.4.0.jar
jackson-core-2.4.2.jar
jackson-core-asl-1.9.13.jar
jackson-databind-2.4.2.jar
jackson-mapper-asl-1.9.13.jar
javassist-3.18.2-GA.jar
javax.inject-1.jar
java-xmlbuilder-0.4.jar
jaxb-api-2.2.2.jar
jersey-core-1.9.jar
jetty-util-6.1.26.jar
jline-0.9.94.jar
jsch-0.1.42.jar
jsr305-1.3.9.jar
kryo-2.24.0.jar
log4j-1.2.17.jar
metrics-core-3.1.0.jar
metrics-json-3.1.0.jar
metrics-jvm-3.1.0.jar
minlog-1.2.jar
netty-3.8.0.Final.jar
netty-all-4.0.27.Final.jar
objenesis-2.1.jar
org.apache.sling.commons.json-2.0.6.jar
paranamer-2.3.jar
protobuf-java-2.5.0.jar
scala-compiler-2.11.7.jar
scala-library-2.11.7.jar
scala-parser-combinators_2.11-1.0.4.jar
scala-reflect-2.11.7.jar
scala-xml_2.11-1.0.4.jar
scopt_2.11-3.2.0.jar
servlet-api-2.5.jar
slf4j-api-1.7.10.jar
slf4j-log4j12-1.7.10.jar
snappy-java-1.0.5.jar
stax-api-1.0-2.jar
uncommons-maths-1.2.2a.jar
xmlenc-0.52.jar
xz-1.0.jar
zeppelin-flink_2.11-0.7.3.jar
zookeeper-3.4.6.jar
</code></pre></div></div>
<p>And in all that mess we can see that it is using Flink 1.1.3 for Scala 2.11:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ls interpreter/flink/ | grep "flink"
flink-annotations-1.1.3.jar
flink-clients_2.11-1.1.3.jar
flink-core-1.1.3.jar
flink-java-1.1.3.jar
flink-metrics-core-1.1.3.jar
flink-optimizer_2.11-1.1.3.jar
flink-runtime_2.11-1.1.3.jar
flink-scala_2.11-1.1.3.jar
flink-scala-shell_2.11-1.1.3.jar
flink-shaded-hadoop2-1.1.3.jar
flink-streaming-java_2.11-1.1.3.jar
flink-streaming-scala_2.11-1.1.3.jar
zeppelin-flink_2.11-0.7.3.jar
</code></pre></div></div>
<p>Now that we have ensured ourselves that we don’t have compatible libraries for our Flink Cluster, we have to add them to the interpreter in some way. I have choose to edit the <code class="highlighter-rouge">flink</code> interpreter using the UI and add the following dependencies supressing the Scala classes because we already have that libs loaded in the interpreter.</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>NOTE: the dependencies will be downloaded from mvn central repository
</code></pre></div></div>
<table>
<thead>
<tr>
<th>artifact</th>
<th>exclude</th>
</tr>
</thead>
<tbody>
<tr>
<td>org.apache.flink:flink-streaming-scala_2.11:1.4.2</td>
<td>org.scala-lang:scala-library,org.scala-lang:scala-reflect,org.scala-lang:scala-compiler</td>
</tr>
<tr>
<td>org.apache.flink:flink-scala_2.11:1.4.2</td>
<td>org.scala-lang:scala-library,org.scala-lang:scala-reflect,org.scala-lang:scala-compiler</td>
</tr>
<tr>
<td>org.apache.flink:flink-clients_2.11:1.4.2</td>
<td>org.scala-lang:scala-library,org.scala-lang:scala-reflect,org.scala-lang:scala-compiler</td>
</tr>
</tbody>
</table>
<p>And I have also changed the property <code class="highlighter-rouge">host</code> of the interpreter from <code class="highlighter-rouge">local</code> to <code class="highlighter-rouge">jobmanager</code>, with this change the Flink interpreter will access to the container inside our docker-compose, named as Jobmanager, instead of start a new Flink mini cluster when we run a Flink paragraph.</p>
<p>Image with all changes made</p>
<p><img src="/assets/images/flinkzeppelin/dependencies.png" alt="Dependencies" /></p>
<h2 id="testing">Testing</h2>
<p>With all changes made, now you should be able to run the following piece of code inside your Flink interpreter on top of your Flink cluster.</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>
val dataset = benv.fromCollection(List(
Array(1,2,3,4,5,0,0,0,0,0,0,0,0,0,0),
Array(1,1,2,3,4,5,0,0,0,0,0,0,0,0,0),
Array(1,2,2,2,3,4,4,5,0,0,0,0,0,0,0),
Array(1,3,4,5,0,0,0,0,0,0,0,0,0,0,0),
Array(1,1,1,2,2,2,3,3,3,4,4,4,5,5,5),
Array(1,1,2,3,1,4,5,0,0,0,0,0,0,0,0),
Array(1,2,3,1,1,4,5,0,0,0,0,0,0,0,0),
Array(1,5,3,2,4,0,0,0,0,0,0,0,0,0,0),
Array(1,5,5,3,2,1,4,0,0,0,0,0,0,0,0),
Array(1,5,5,3,5,1,4,2,0,0,0,0,0,0,0),
Array(2,3,3,3,4,5,1,0,0,0,0,0,0,0,0)
)
)
val results = dataset.collect()
var table = "%table\n"
table += "t0 \t t1 \t t2 \t t3 \t t4 \t t5 \t t6 \t t7 \t t8 \t t9 \t t10 \t t11 \t t12 \t t13 \t t14 \n"
for(result <- results){
for(item <- result){
table += item + "\t"
}
table += "\n"
}
println(table)
</code></pre></div></div>
<p>For that piece of code you should have the following output without any errors:</p>
<p><img src="/assets/images/flinkzeppelin/expectedOutput.png" alt="Dependencies" /></p>
<p>And that’s all, I hope that this post could be helpful for those working with Apache Zeppelin and Apache Flink and you can ping me on twitter @diegoreico if you want to talk about something related to this.</p>Diego Reiriz Coresdiegoreiriz@gmail.comI recently started to use Apache Zeppelin, because I wanted a tool that allows me to work with notebooks using Scala + Apache Flink and as a plus, Apache Zeppelin provides you with autogenerated plots if you print you data as TSV file !!!!!!!Conectando Apache Flink con Elasticsearch2017-06-12T00:00:00+00:002017-06-12T00:00:00+00:00http://diegoreico.com/development/conectandoapacheflinkconelasticsearch<p>Hace poco he empezado a utilizar el framework para desarrollo de aplicaciones en Streaming <strong>Apache Flink</strong>, el cuál es considerado como la 4ª generación de herramientas para el análisis de datos en un contexto de Big Data.</p>
<p><img src="https://a248.e.akamai.net/secure.meetupstatic.com/photos/event/9/2/8/d/600_455497517.jpeg" alt="https://a248.e.akamai.net/secure.meetupstatic.com/photos/event/9/2/8/d/600_455497517.jpeg" /></p>
<p>En general, la facilidad de uso del framework me ha parecido sorprendente, ya que permite realizar todo tipo de acciones distribuidas sobre nodos mediante el uso de funciones muy conocidas como pueden ser <strong>map</strong> y <strong>reduce</strong>, al mismo tiempo que permite realizar operaciones complejas sobre los datos en streaming, mediante el uso de varios tipos de ventanas.</p>
<p>Pero no todo en el framework va a ser bueno, en estos momentos la herramienta se encuentra en la <strong>versión 1.4</strong> y <strong>está creciendo</strong> a un ritmo bastante sorprendente, pero el problema reside en que ni la documentación de la herramienta, ni la comunidad, están creciendo al mismo ritmo que el framework. Esto lo pude observar cuando intenté realizar una operación que debería ser relativamente sencilla, la cual consistía en almacenar los <strong>datos procesados por un streaming</strong>, en un contenedor de <strong>Docker</strong> sobre el que se ejecutaba una imagen de <strong>elasticsearch 5.4</strong>. A pesar de que en la documentación del framework Apache Flink existe un apartado de <strong>conectores</strong>, en el que se documenta como conectar el framework a la plataforma elasticsearch, <strong>en mi caso no he conseguido hacer funcionar el conector</strong> tras haberlo intentado un par de veces y tras realizar alguna que otra búsqueda de ejemplos, parece que <strong>no soy el único</strong> que se ha encontrado con esta barrera.</p>
<h1 id="abordando-el-problema">Abordando el problema</h1>
<p>Para empezar, existen <strong>dos formas</strong> de conectarse a elasticsearch:</p>
<ol>
<li>Mediante la API Java que se expone en el puerto 9300 por defecto</li>
<li>Mediante la API REST que se expone en el puerto 9200 por defecto</li>
</ol>
<p>En una situación ideal, preferiría conectarme a elasticsearch mediante la API Java, pero he podido observar que las diferentes versiones de Apache Flink varían bastante y es necesario usar en cada versión los conectores específicos disponibles que ofrece el framework, para poder conectarnos a elasticsearch y esto genera unas dependencias en el proyecto con las que no me siento nada cómodo trabajando.</p>
<p>Entonces he optado por pasarme a mi segunda opción que es utilizar la API REST para conectarme a elasticsearch y de esta forma <strong>me olvido de los problemas de compatibilidad entre las diferentes versiones</strong> de elasticsearch con Apache Flink y sus conectores.</p>
<h1 id="manos-a-la-obra">Manos a la obra</h1>
<p>En mi caso estoy utilizando el framework <strong>Apache Flink</strong> en su versión <strong>1.3</strong>, con la versión <strong>2.10</strong> del lenguaje <strong>Scala</strong>.</p>
<p>Lo primero que he realizado es añadir como dependencia al proyecto la libreía <a href="https://github.com/scalaj/scalaj-http">scalaj-http</a> que actúa como un wrapper de <a href="https://docs.oracle.com/javase/8/docs/api/java/net/HttpURLConnection.html">java.net.HttpURLConnection</a> y añade bastante azucar sintáctico. Para ello basta con añadir a nuestro <strong>pom.xml</strong> la siguiente dependencia.</p>
<script src="https://gist.github.com/DiegoReiriz/518b3ad1323b6c1e8a9bce9b7e61e3a2.js"></script>
<p>Una vez que ya hemos añadido la dependencía, basta con realizar una simple petición POST contra la API de elasticsearch para insertar un dato, contra un <strong>índice que crearamos previamente</strong>. En este caso insertaremos un dato en el índice tfg:</p>
<script src="https://gist.github.com/DiegoReiriz/83df80346f932d347d581e1c5ca1f661.js"></script>
<p>Si queremos aplicar esto sobre los datos de nuestro streaming en Flink, bastaría con aplicar una operación map sobre el streaming:</p>
<script src="https://gist.github.com/DiegoReiriz/7f2b410c9950bccb379e4721bbe24f33.js"></script>
<p>Con esto, ya estaríamos insertando de <strong>forma sencilla</strong> nuestros datos en elasticsearch. Obviamente, esta <strong>no es la forma más eficiente</strong> de insertar los datos, ya que estamos generando una petición http por cada elemento de nuestro stream, cuando lo más razonable sería <strong>esperar a que se cumpla una ventana temporal</strong> o se <strong>acumule un volumen de datos</strong> considerable antes de realizar una insercción. Pero eso ya son cuestiones de diseño dependientes del comportamiento de cada sistema.</p>
<p>Por último, si queremos que esto tenga un toque <strong>un poco más profesional</strong>, en vez de formar en un String el JSON que queremos enviar en el cuerpo de la petición POST, sería conveniente utilizar un motor de renderizado de plantillas como puede ser <a href="https://mustache.github.io/">mustache</a> o <a href="https://pugjs.org/api/getting-started.html">pug</a>.</p>Diego Reiriz Coresdiegoreiriz@gmail.comHace poco he empezado a utilizar el framework para desarrollo de aplicaciones en Streaming Apache Flink, el cuál es considerado como la 4ª generación de herramientas para el análisis de datos en un contexto de Big Data.Entendiendo la importancia del paso de mensajes2017-05-24T00:00:00+00:002017-05-24T00:00:00+00:00http://diegoreico.com/development/importanciapasodemensajes<p>Esta vez me apetece hablar de un concepto de diseño de software, como es el paso de mensajes, que ha calado en múltiples niveles del desarrollo del mismo, así como en la organización y la comunicación de los sistemas informáticos.</p>
<h2 id="en-que-cosiste-el-paso-de-mensajes">En que cosiste el paso de mensajes?</h2>
<p>El paso de mensajes, lo podemos considerar como un tipo de arquitectura de software orientada a la comunicación de varios elementos, que se caracteriza por tener muy poco acoplamiento entre los elementos participes. Como su nombre indica, la idea detrás de esta arquitectura reside en la comunicación de los elementos mediante el envió de mensajes, en lugar de realizar una interacción directa entre ellos.</p>
<h2 id="el-paso-de-mensajes-en-su-versión-mas-simple">El paso de mensajes en su versión mas simple</h2>
<p>La idea detrás de esta forma de diseñar software es bastante sencilla y natural para nosotros como seres humanos, tenemos a un productor de mensajes, un canal/medio en el que se publican mensajes y uno o varios receptores.</p>
<p><img src="/assets/images/importanciapasodemensajes/mp0.png" alt="/assets/images/importanciapasodemensajes/mp0.png" /></p>
<p>En este tipo de diseños, el emisor no necesita realmente especificar quien es el destinatario del mensaje que quiere enviar, su única preocupación es producir un mensaje y publicarlo en el canal de comunicación adecuado. Mientras que en el lado del Receptor, este simplemente se tiene que preocupar de si el mensaje se dirige a él y si entiende el contenido del mensaje.
Si aplicamos esta idea al desarrollo de software, podríamos tener un código (java en este caso) como el siguiente:</p>
<script src="https://gist.github.com/DiegoReiriz/b62996ee9983060bc0460221dd092724.js"></script>
<script src="https://gist.github.com/DiegoReiriz/2206321423775b35f5489b12a7f11a32.js"></script>
<script src="https://gist.github.com/DiegoReiriz/8410eace6868f5bcd1312a8be6d1b2f7.js"></script>
<script src="https://gist.github.com/DiegoReiriz/5bf0ce54a2f6003f393ad23c55307fbb.js"></script>
<script src="https://gist.github.com/DiegoReiriz/ff60f6ce9f83d0ef02f33910a22a2034.js"></script>
<p><strong>Resultado</strong></p>
<blockquote>
<p>Consumidor: Acabo de recibir: Hello World!
Consumidor: Acabo de recibir: 123456</p>
</blockquote>
<h2 id="esto-nos-tiene-que-sonar">Esto nos tiene que sonar</h2>
<p>La implementación realizada anteriormente nos debería recordar al patrón de diseño Observer, donde un emisor mantiene una lista de Observadores que están a la espera de que el emisor emita algún tipo de evento.</p>
<p><img src="/assets/images/importanciapasodemensajes/mp1.gif" alt="/assets/images/importanciapasodemensajes/mp1.gif" /></p>
<p>La principal diferencia entre el diseño anterior y un patrón de diseño Observer puro, es que en nuestro diseño estamos desacoplando a los emisores y a los observadores mediante la introducción de un canal. Lo que realmente tenemos es una versión muy simple de un patrón de arquitectura de paso de mensajes, conocido como publica-subscribe.</p>
<p><img src="/assets/images/importanciapasodemensajes/mp2.jpg" alt="/assets/images/importanciapasodemensajes/mp2.jpg" /></p>
<h2 id="que-principales-ventajas-nos-proporcionan-este-tipo-de-diseños">Que principales ventajas nos proporcionan este tipo de diseños?</h2>
<ul>
<li><strong>Bajo acoplamiento</strong>: como se puede apreciar en la implementación que realicé anteriormente, el productor únicamente necesitar tener acceso al canal y publicar un mensaje, por lo tanto se desentiende de quienes están recibiendo el mensaje, como lo reciben y que hacen con el mismo.</li>
<li><strong>Alta escalabilidad</strong>: como se puede observar en el código proporcionado, “teóricamente” podemos aumentar el número de consumidores y productores de un canal de forma indiscriminada. Así mismo, podemos disponer de diferentes canales en función de su propósito y tanto un productor, como un consumidor, puede participar de forma activa en varios canales simultáneamente.</li>
<li><strong>Debuggear facilmente</strong>: resulta muy sencillo el desarrollo de pruebas sobre este tipo de sistemas, porque podemos substituir cualquier productor o consumidor de mensajes por uno falso para asegurarnos de que el sistema se comporta como nosotros esperamos. Así mismo, también podemos introducir consumidores que actúen como sniffers en los canales, de forma que estos registren todos los mensajes que se envían por el canal y mantengan un log.</li>
</ul>
<h2 id="que-damos-a-cambio">Que damos a cambio?</h2>
<p>Cuando aplicamos cualquier tipo de patrón de diseño, así como de arquitectura, siempre estamos sacrificando algo. En este caso, el rendimiento de nuestro programa/sistema será inferior al de uno en el que todos los elementos del mismo se conecten directamente, pero es un precio justo si consideramos todo lo que estamos ganando.</p>
<h2 id="evolucionando-el-diseño-base">Evolucionando el diseño base</h2>
<p>Lo realmente interesante respecto al patrón de arquitectura que se ha presentado, es su gran versatilidad, ya que sin complicarnos mucho la vida podemos implementar y combinar cualquiera de los patrones de comunicación que se nos ocurra.</p>
<p><img src="/assets/images/importanciapasodemensajes/mp3.png" alt="/assets/images/importanciapasodemensajes/mp3.png" /></p>
<p>Por otro lado, si simplemente modificamos el canal que forma parte de nuestro diseño actual, también podemos lograr comportamientos bastante interesantes. A continuación se muestran posibles modificaciones:</p>
<ul>
<li><strong>Adición de persistencia al canal</strong>: puede ser de gran utilidad que el canal registre y mantengan un número determinado de mensajes y que los consumidores elijan cuando consumirlos, dando lugar al famoso patrón productor-consumidor.</li>
</ul>
<p><img src="/assets/images/importanciapasodemensajes/mp4.jpg" alt="/assets/images/importanciapasodemensajes/mp4.jpg" /></p>
<ul>
<li><strong>Soporte de operaciones sobre el canal</strong>: independientemente de si el canal dispone o no de persistencia para los mensajes, es interesante barajar la opción del diseño de un canal que aplique una operación (normalmente una función pura) a todos los mensajes que este contiene, ya sea aplicándola a todos los elementos actuales almacenados en el canal o de forma individual cuando estos se añaden al mismo. El tipo de operaciones que se pueden realizar son de todo tipo: operaciones de filtrado, operaciones de ordenación, operaciones aritméticas (si fijamos el tipo de datos del canal), operaciones de transformación…</li>
</ul>
<p><img src="/assets/images/importanciapasodemensajes/mp5.png" alt="/assets/images/importanciapasodemensajes/mp5.png" /></p>
<ul>
<li><strong>Unión y división de canales</strong>: es interesante hacer que un mismo canal se pueda subdividir en varios bajo una condición, o justamente lo contrario, que varios canales agrupen sus mensajes.</li>
</ul>
<p><img src="/assets/images/importanciapasodemensajes/mp6.png" alt="/assets/images/importanciapasodemensajes/mp6.png" /></p>
<p>Otra opción que tenemos a la hora de evolucionar el diseño presentado, es la adición de un nuevo elemento, el broker. El principal propósito de este es coordinar las llamadas a servicios en arquitecturas orientadas a los mismos, además de poder validar si las peticiones cumplen con el formato esperado. Si queremos generalizar el comportamiento de este, para la situación que hemos planteado, podemos considerarlo como una fachada que elige a que canales se dirigen los mensajes. Donde en este caso, lo más probable es que los canales dispongan de una serie de acciones o filtros que adecuan el formato de los mensajes a los consumidores del canal.</p>
<p><img src="/assets/images/importanciapasodemensajes/mp7.png" alt="/assets/images/importanciapasodemensajes/mp7.png" /></p>
<p>Podría continuar sugiriendo más modificaciones sobre el diseño base, pero creo que ha quedado más que claro que el diseño es bastante versátil y al final todo consiste en adaptarlo a las necesidades que tengamos en cada caso.</p>
<h2 id="donde-se-usa">Donde se usa?</h2>
<p>Actualmente el diseño presentado se usa a varios niveles y cada producto/software/sistema lo implementa a su manera, pero los conceptos clave acaban siendo los mismos en todos o presentando pequeñas variaciones. A continuación se muestran algunos ejemplos:</p>
<ul>
<li><strong>ReactiveX</strong>: framework disponible en múltiples lenguajes de programación, que combina el patrón observer, con el patrón iterator y programación funcional. http://reactivex.io/</li>
<li><strong>Apache Kafka</strong>: plataforma de streaming distribuido. https://kafka.apache.org</li>
<li><strong>RabbitMQ</strong>: broker de mensajes. https://www.rabbitmq.com/</li>
<li><strong>Message Passing Interface (MPI)</strong>: sistema de paso de mensajes orientado a la computación paralela. https://www.open-mpi.org/</li>
</ul>
<h2 id="epílogo">Epílogo</h2>
<p>Gracias por leer todo este rollo que he soltado y que hago en mis ratos libres! Al final, para mi esto es una forma de aportar un poco de mis conocimientos con la finalidad de que puedan llegar a ser útiles para otros, al igual que yo he leído gran cantidad de posts publicados por gente que sabe mucho más que yo.</p>
<p>Se acepta cualquier sugerencia, impertinencia, improperio, comentario, etc. siempre que sea con fundamento y afán de mejorar/corregir/aumentar el contenido de este artículo.</p>Diego Reiriz Coresdiegoreiriz@gmail.comEsta vez me apetece hablar de un concepto de diseño de software, como es el paso de mensajes, que ha calado en múltiples niveles del desarrollo del mismo, así como en la organización y la comunicación de los sistemas informáticos.