This is an automated email from the ASF dual-hosted git repository.

nkruber pushed a commit to branch asf-site
in repository https://gitbox.apache.org/repos/asf/flink-web.git

commit 9dba6e8756560ed0ad00c482bc06932a70e63a17
Author: Nico Kruber <[email protected]>
AuthorDate: Wed Jul 17 15:00:35 2019 +0200

    [Blog] style-tuning for Network Stack Vol. 1
---
 _posts/2019-06-05-flink-network-stack.md    | 151 ++++++++++++------------
 content/2019/06/05/flink-network-stack.html | 172 +++++++++++++++------------
 content/blog/feed.xml                       | 174 +++++++++++++++-------------
 3 files changed, 266 insertions(+), 231 deletions(-)

diff --git a/_posts/2019-06-05-flink-network-stack.md 
b/_posts/2019-06-05-flink-network-stack.md
index 6e26fbd..f7c36d9 100644
--- a/_posts/2019-06-05-flink-network-stack.md
+++ b/_posts/2019-06-05-flink-network-stack.md
@@ -5,16 +5,27 @@ date: 2019-06-05T08:45:00.000Z
 authors:
 - Nico:
   name: "Nico Kruber"
-  
+
 
 excerpt: Flink’s network stack is one of the core components that make up 
Apache Flink's runtime module sitting at the core of every Flink job. In this 
post, which is the first in a series of posts about the network stack, we look 
at the abstractions exposed to the stream operators and detail their physical 
implementation and various optimisations in Apache Flink.
 ---
 
+<style type="text/css">
+.tg  {border-collapse:collapse;border-spacing:0;}
+.tg td{padding:10px 
20px;border-style:solid;border-width:1px;overflow:hidden;word-break:normal;}
+.tg th{padding:10px 
20px;border-style:solid;border-width:1px;overflow:hidden;word-break:normal;background-color:#eff0f1;}
+.tg .tg-wide{padding:10px 30px;}
+.tg .tg-top{vertical-align:top}
+.tg .tg-center{text-align:center;vertical-align:center}
+</style>
+
 Flink’s network stack is one of the core components that make up the 
`flink-runtime` module and sit at the heart of every Flink job. It connects 
individual work units (subtasks) from all TaskManagers. This is where your 
streamed-in data flows through and it is therefore crucial to the performance 
of your Flink job for both the throughput as well as latency you observe. In 
contrast to the coordination channels between TaskManagers and JobManagers 
which are using RPCs via Akka, the network [...]
 
 This blog post is the first in a series of posts about the network stack. In 
the sections below, we will first have a high-level look at what abstractions 
are exposed to the stream operators and then go into detail on the physical 
implementation and various optimisations Flink did. We will briefly present the 
result of these optimisations and Flink’s trade-off between throughput and 
latency. Future blog posts in this series will elaborate more on monitoring and 
metrics, tuning parameters [...]
 
-# Logical View
+{% toc %}
+
+## Logical View
 
 Flink’s network stack provides the following logical view to the subtasks when 
communicating with each other, for example during a network shuffle as required 
by a `keyBy()`.
 
@@ -54,42 +65,34 @@ Batch jobs may also produce results in a blocking fashion, 
depending on the oper
 The following table summarises the valid combinations:
 <br>
 <center>
-<style type="text/css">
-.tg  {border-collapse:collapse;border-spacing:0;}
-.tg td{font-family:Arial, sans-serif;font-size:14px;padding:10px 
30px;border-style:solid;border-width:1px;overflow:hidden;word-break:normal;border-color:black;}
-.tg th{font-family:Arial, 
sans-serif;font-size:14px;font-weight:normal;padding:10px 
30px;border-style:solid;border-width:1px;overflow:hidden;word-break:normal;border-color:black;}
-.tg 
.tg-wwp9{font-size:15px;background-color:#9b9b9b;border-color:#343434;text-align:left}
-.tg .tg-sogj{font-size:15px;text-align:left}
-.tg .tg-cbs6{font-size:15px;text-align:left;vertical-align:top}
-</style>
 <table class="tg">
   <tr>
-    <th class="tg-wwp9">Output Type</th>
-    <th class="tg-wwp9">Scheduling Type</th>
-    <th class="tg-wwp9">Applies to…</th>
+    <th>Output Type</th>
+    <th>Scheduling Type</th>
+    <th>Applies to…</th>
   </tr>
   <tr>
-    <td class="tg-sogj" rowspan="2">pipelined, unbounded</td>
-    <td class="tg-sogj">all at once</td>
-    <td class="tg-sogj">Streaming jobs</td>
+    <td rowspan="2">pipelined, unbounded</td>
+    <td>all at once</td>
+    <td>Streaming jobs</td>
   </tr>
   <tr>
-    <td class="tg-sogj">next stage on first output</td>
-    <td class="tg-sogj">n/a¹</td>
+    <td>next stage on first output</td>
+    <td>n/a¹</td>
   </tr>
   <tr>
-    <td class="tg-sogj" rowspan="2">pipelined, bounded</td>
-    <td class="tg-sogj">all at once</td>
-    <td class="tg-sogj">n/a²</td>
+    <td rowspan="2">pipelined, bounded</td>
+    <td>all at once</td>
+    <td>n/a²</td>
   </tr>
   <tr>
-    <td class="tg-sogj">next stage on first output</td>
-    <td class="tg-sogj">Batch jobs</td>
+    <td>next stage on first output</td>
+    <td>Batch jobs</td>
   </tr>
   <tr>
-    <td class="tg-cbs6">blocking</td>
-    <td class="tg-cbs6">next stage on complete output</td>
-    <td class="tg-cbs6">Batch jobs</td>
+    <td>blocking</td>
+    <td>next stage on complete output</td>
+    <td>Batch jobs</td>
   </tr>
 </table>
 </center>
@@ -105,7 +108,7 @@ Additionally, for subtasks with more than one input, 
scheduling start in two way
 
 <br>
 
-# Physical Transport
+## Physical Transport
 
 In order to understand the physical data connections, please recall that, in 
Flink, different tasks may share the same slot via [slot sharing groups]({{ 
site.DOCS_BASE_URL 
}}flink-docs-release-1.8/dev/stream/operators/#task-chaining-and-resource-groups).
 TaskManagers may also provide more than one slot to allow multiple subtasks of 
the same task to be scheduled onto the same TaskManager.
 
@@ -113,37 +116,29 @@ For the example pictured below, we will assume a 
parallelism of 4 and a deployme
 <br>
 
 <center>
-<style type="text/css">
-.tg  {border-collapse:collapse;border-spacing:10;}
-.tg td{font-family:Arial, sans-serif;font-size:15px;padding:10px 
80px;border-style:solid;border-width:1px;overflow:hidden;word-break:normal;border-color:black;}
-.tg th{font-family:Arial, 
sans-serif;font-size:15px;font-weight:normal;padding:10px 
80px;border-style:solid;border-width:1px;overflow:hidden;word-break:normal;border-color:black;}
-.tg 
.tg-266k{background-color:#9b9b9b;border-color:inherit;text-align:left;vertical-align:center}
-.tg .tg-c3ow{border-color:inherit;text-align:center;vertical-align:center}
-.tg .tg-0pky{border-color:inherit;text-align:left;vertical-align:center}
-</style>
 <table class="tg">
   <tr>
-    <th class="tg-266k"></th>
-    <th class="tg-266k">B.1</th>
-    <th class="tg-266k">B.2</th>
-    <th class="tg-266k">B.3</th>
-    <th class="tg-266k">B.4</th>
+    <th></th>
+    <th class="tg-wide">B.1</th>
+    <th class="tg-wide">B.2</th>
+    <th class="tg-wide">B.3</th>
+    <th class="tg-wide">B.4</th>
   </tr>
   <tr>
-    <td class="tg-0pky">A.1</td>
-    <td class="tg-c3ow" colspan="2" rowspan="2">local</td>
-    <td class="tg-c3ow" colspan="2" rowspan="2">remote</td>
+    <th class="tg-wide">A.1</th>
+    <td class="tg-center" colspan="2" rowspan="2">local</td>
+    <td class="tg-center" colspan="2" rowspan="2">remote</td>
   </tr>
   <tr>
-    <td class="tg-0pky">A.2</td>
+    <th class="tg-wide">A.2</th>
   </tr>
   <tr>
-    <td class="tg-0pky">A.3</td>
-    <td class="tg-c3ow" colspan="2" rowspan="2">remote</td>
-    <td class="tg-c3ow" colspan="2" rowspan="2">local</td>
+    <th class="tg-wide">A.3</th>
+    <td class="tg-center" colspan="2" rowspan="2">remote</td>
+    <td class="tg-center" colspan="2" rowspan="2">local</td>
   </tr>
   <tr>
-    <td class="tg-0pky">A.4</td>
+    <th class="tg-wide">A.4</th>
   </tr>
 </table>
 </center>
@@ -164,7 +159,7 @@ The results of each subtask are called [ResultPartition]({{ 
site.DOCS_BASE_URL }
 
 The total number of buffers on a single TaskManager usually does not need 
configuration. See the [Configuring the Network Buffers]({{ site.DOCS_BASE_URL 
}}flink-docs-release-1.8/ops/config.html#configuring-the-network-buffers) 
documentation for details on how to do so if needed.
 
-## Inflicting Backpressure (1)
+### Inflicting Backpressure (1)
 
 Whenever a subtask’s sending buffer pool is exhausted — buffers reside in 
either a result subpartition's buffer queue or inside the lower, Netty-backed 
network stack — the producer is blocked, cannot continue, and experiences 
backpressure. The receiver works in a similar fashion: any incoming Netty 
buffer in the lower network stack needs to be made available to Flink via a 
network buffer. If there is no network buffer available in the appropriate 
subtask's buffer pool, Flink will stop re [...]
 
@@ -179,7 +174,7 @@ To prevent this situation from even happening, Flink 1.5 
introduced its own flow
 
 <br>
 
-# Credit-based Flow Control
+## Credit-based Flow Control
 
 Credit-based flow control makes sure that whatever is “on the wire” will have 
capacity at the receiver to handle. It is based on the availability of network 
buffers as a natural extension of the mechanisms Flink had before. Instead of 
only having a shared local buffer pool, each remote input channel now has its 
own set of **exclusive buffers**. Conversely, buffers in the local buffer pool 
are called **floating buffers** as they will float around and are available to 
every input channel.
 
@@ -196,11 +191,11 @@ Credit-based flow control will use 
[buffers-per-channel]({{ site.DOCS_BASE_URL }
 
 <sup>3</sup>If there are not enough buffers available, each buffer pool will 
get the same share of the globally available ones (± 1).
 
-## Inflicting Backpressure (2)
+### Inflicting Backpressure (2)
 
 As opposed to the receiver's backpressure mechanisms without flow control, 
credits provide a more direct control: If a receiver cannot keep up, its 
available credits will eventually hit 0 and stop the sender from forwarding 
buffers to the lower network stack. There is backpressure on this logical 
channel only and there is no need to block reading from a multiplexed TCP 
channel. Other receivers are therefore not affected in processing available 
buffers.
 
-## What do we Gain? Where is the Catch?
+### What do we Gain? Where is the Catch?
 
 <img align="right" src="{{ site.baseurl 
}}/img/blog/2019-06-05-network-stack/flink-network-stack5.png" width="300" 
height="200" alt="Physical-transport-credit-flow-checkpoints-Flink's Network 
Stack"/>
 
@@ -213,36 +208,40 @@ There is one more thing you may notice when using 
credit-based flow control: sin
 <br>
 
 <center>
-<style type="text/css">
-.tg  {border-collapse:collapse;border-spacing:0;}
-.tg td{font-family:Arial, sans-serif;font-size:14px;padding:10px 
30px;border-style:solid;border-width:1px;overflow:hidden;word-break:normal;border-color:black;}
-.tg th{font-family:Arial, 
sans-serif;font-size:14px;font-weight:normal;padding:10px 
30px;border-style:solid;border-width:1px;overflow:hidden;word-break:normal;border-color:black;}
-.tg .tg-0vnf{font-size:15px;text-align:center}
-.tg .tg-rc1r{font-size:15px;background-color:#9b9b9b;text-align:left}
-.tg .tg-sogj{font-size:15px;text-align:left}
-</style>
 <table class="tg">
   <tr>
-    <th class="tg-rc1r">Advantages</th>
-    <th class="tg-rc1r">Disadvantages</th>
+    <th>Advantages</th>
+    <th>Disadvantages</th>
   </tr>
   <tr>
-    <td class="tg-sogj">• better resource utilisation with data skew in 
multiplexed connections <br><br>• improved checkpoint alignment<br><br>• 
reduced memory use (less data in lower network layers)</td>
-    <td class="tg-sogj">• additional credit-announce messages<br><br>• 
additional backlog-announce messages (piggy-backed with buffer messages, almost 
no overhead)<br><br>• potential round-trip latency</td>
+    <td class="tg-top">
+    • better resource utilisation with data skew in multiplexed connections 
<br><br>
+    • improved checkpoint alignment<br><br>
+    • reduced memory use (less data in lower network layers)</td>
+    <td class="tg-top">
+    • additional credit-announce messages<br><br>
+    • additional backlog-announce messages (piggy-backed with buffer messages, 
almost no overhead)<br><br>
+    • potential round-trip latency</td>
   </tr>
   <tr>
-    <td class="tg-0vnf" colspan="2">• backpressure appears earlier</td>
+    <td class="tg-center" colspan="2">• backpressure appears earlier</td>
   </tr>
 </table>
 </center>
 <br>
 
-> _NOTE:_ If you need to turn off credit-based flow control, you can add this 
to your `flink-conf.yaml`: `taskmanager.network.credit-model: false`. 
-> This parameter, however, is deprecated and will eventually be removed along 
with the non-credit-based flow control code.
+<div class="alert alert-info" markdown="1">
+<span class="label label-info" style="display: inline-block"><span 
class="glyphicon glyphicon-info-sign" aria-hidden="true"></span> Note</span>
+If you need to turn off credit-based flow control, you can add this to your 
`flink-conf.yaml`:
+
+`taskmanager.network.credit-model: false`
+
+This parameter, however, is deprecated and will eventually be removed along 
with the non-credit-based flow control code.
+</div>
 
 <br>
 
-# Writing Records into Network Buffers and Reading them again
+## Writing Records into Network Buffers and Reading them again
 
 The following picture extends the slightly more high-level view from above 
with further details of the network stack and its surrounding components, from 
the collection of a record in your sending operator to the receiving operator 
getting it:
 <br>
@@ -257,7 +256,7 @@ After creating a record and passing it along, for example 
via `Collector#collect
 On the receiver’s side, the lower network stack (netty) is writing received 
buffers into the appropriate input channels. The (stream) tasks’s thread 
eventually reads from these queues and tries to deserialise the accumulated 
bytes into Java objects with the help of the [RecordReader]({{ 
site.DOCS_BASE_URL 
}}flink-docs-release-1.8/api/java/org/apache/flink/runtime/io/network/api/reader/RecordReader.html)
 and going through the [SpillingAdaptiveSpanningRecordDeserializer]({{ 
site.DOCS_BASE_ [...]
 <br>
 
-## Flushing Buffers to Netty
+### Flushing Buffers to Netty
 
 In the picture above, the credit-based flow control mechanics actually sit 
inside the “Netty Server” (and “Netty Client”) components and the buffer the 
RecordWriter is writing to is always added to the result subpartition in an 
empty state and then gradually filled with (serialised) records. But when does 
Netty actually get the buffer? Obviously, it cannot take bytes whenever they 
become available since that would not only add substantial costs due to 
cross-thread communication and synch [...]
 
@@ -268,7 +267,7 @@ In Flink, there are three situations that make a buffer 
available for consumptio
 * a special event such as a checkpoint barrier is sent.<br>
 <br>
 
-### Flush after Buffer Full
+#### Flush after Buffer Full
 
 The RecordWriter works with a local serialisation buffer for the current 
record and will gradually write these bytes to one or more network buffers 
sitting at the appropriate result subpartition queue. Although a RecordWriter 
can work on multiple subpartitions, each subpartition has only one RecordWriter 
writing data to it. The Netty server, on the other hand, is reading from 
multiple result subpartitions and multiplexing the appropriate ones into a 
single channel as described above. Thi [...]
 <br>
@@ -281,7 +280,7 @@ The RecordWriter works with a local serialisation buffer 
for the current record
 <sup>4</sup>We can assume it already got the notification if there are more 
finished buffers in the queue.
 <br>
 
-### Flush after Buffer Timeout
+#### Flush after Buffer Timeout
 
 In order to support low-latency use cases, we cannot only rely on buffers 
being full in order to send data downstream. There may be cases where a certain 
communication channel does not have too many records flowing through and 
unnecessarily increase the latency of the few records you actually have. 
Therefore, a periodic process will flush whatever data is available down the 
stack: the output flusher. The periodic interval can be configured via 
[StreamExecutionEnvironment#setBufferTimeout [...]
 <br>
@@ -294,12 +293,12 @@ In order to support low-latency use cases, we cannot only 
rely on buffers being
 <sup>5</sup>Strictly speaking, the output flusher does not give any guarantees 
- it only sends a notification to Netty which can pick it up at will / 
capacity. This also means that the output flusher has no effect if the channel 
is backpressured.
 <br>
 
-### Flush after special event
+#### Flush after special event
 
 Some special events also trigger immediate flushes if being sent through the 
RecordWriter. The most important ones are checkpoint barriers or 
end-of-partition events which obviously should go quickly and not wait for the 
output flusher to kick in.
 <br>
 
-### Further remarks
+#### Further remarks
 
 In contrast to Flink < 1.5, please note that (a) network buffers are now 
placed in the subpartition queues directly and (b) we are not closing the 
buffer on each flush. This gives us a few advantages:
 
@@ -310,13 +309,13 @@ In contrast to Flink < 1.5, please note that (a) network 
buffers are now placed
 However, you may notice an increased CPU use and TCP packet rate during low 
load scenarios. This is because, with the changes, Flink will use any 
*available* CPU cycles to try to maintain the desired latency. Once the load 
increases, this will self-adjust by buffers filling up more. High load 
scenarios are not affected and even get a better throughput because of the 
reduced synchronisation overhead.
 <br>
 
-## Buffer Builder & Buffer Consumer
+### Buffer Builder & Buffer Consumer
 
 If you want to dig deeper into how the producer-consumer mechanics are 
implemented in Flink, please take a closer look at the [BufferBuilder]({{ 
site.DOCS_BASE_URL 
}}flink-docs-release-1.8/api/java/org/apache/flink/runtime/io/network/buffer/BufferBuilder.html)
 and [BufferConsumer]({{ site.DOCS_BASE_URL 
}}flink-docs-release-1.8/api/java/org/apache/flink/runtime/io/network/buffer/BufferConsumer.html)
 classes which have been introduced in Flink 1.5. While reading is potentially 
only *per bu [...]
 
 <br>
 
-# Latency vs. Throughput
+## Latency vs. Throughput
 
 Network buffers were introduced to get higher resource utilisation and higher 
throughput at the cost of having some records wait in buffers a little longer. 
Although an upper limit to this wait time can be given via the buffer timeout, 
you may be curious to find out more about the trade-off between these two 
dimensions: latency and throughput, as, obviously, you cannot get both. The 
following plot shows various values for the buffer timeout starting at 0 (flush 
with every record) to 100m [...]
 <br>
@@ -330,7 +329,7 @@ As you can see, with Flink 1.5+, even very low buffer 
timeouts such as 1ms (for
 
 <br>
 
-# Conclusion
+## Conclusion
 
 Now you know about result partitions, the different network connections and 
scheduling types for both batch and streaming. You also know about credit-based 
flow control and how the network stack works internally, in order to reason 
about network-related tuning parameters and about certain job behaviours. 
Future blog posts in this series will build upon this knowledge and go into 
more operational details including relevant metrics to look at, further network 
stack tuning, and common antip [...]
 
diff --git a/content/2019/06/05/flink-network-stack.html 
b/content/2019/06/05/flink-network-stack.html
index 2445ec5..c1e0fcd 100644
--- a/content/2019/06/05/flink-network-stack.html
+++ b/content/2019/06/05/flink-network-stack.html
@@ -173,11 +173,43 @@
       <article>
         <p>05 Jun 2019 Nico Kruber </p>
 
+<style type="text/css">
+.tg  {border-collapse:collapse;border-spacing:0;}
+.tg td{padding:10px 
20px;border-style:solid;border-width:1px;overflow:hidden;word-break:normal;}
+.tg th{padding:10px 
20px;border-style:solid;border-width:1px;overflow:hidden;word-break:normal;background-color:#eff0f1;}
+.tg .tg-wide{padding:10px 30px;}
+.tg .tg-top{vertical-align:top}
+.tg .tg-center{text-align:center;vertical-align:center}
+</style>
+
 <p>Flink’s network stack is one of the core components that make up the 
<code>flink-runtime</code> module and sit at the heart of every Flink job. It 
connects individual work units (subtasks) from all TaskManagers. This is where 
your streamed-in data flows through and it is therefore crucial to the 
performance of your Flink job for both the throughput as well as latency you 
observe. In contrast to the coordination channels between TaskManagers and 
JobManagers which are using RPCs via Akk [...]
 
 <p>This blog post is the first in a series of posts about the network stack. 
In the sections below, we will first have a high-level look at what 
abstractions are exposed to the stream operators and then go into detail on the 
physical implementation and various optimisations Flink did. We will briefly 
present the result of these optimisations and Flink’s trade-off between 
throughput and latency. Future blog posts in this series will elaborate more on 
monitoring and metrics, tuning paramet [...]
 
-<h1 id="logical-view">Logical View</h1>
+<div class="page-toc">
+<ul id="markdown-toc">
+  <li><a href="#logical-view" id="markdown-toc-logical-view">Logical 
View</a></li>
+  <li><a href="#physical-transport" 
id="markdown-toc-physical-transport">Physical Transport</a>    <ul>
+      <li><a href="#inflicting-backpressure-1" 
id="markdown-toc-inflicting-backpressure-1">Inflicting Backpressure (1)</a></li>
+    </ul>
+  </li>
+  <li><a href="#credit-based-flow-control" 
id="markdown-toc-credit-based-flow-control">Credit-based Flow Control</a>    
<ul>
+      <li><a href="#inflicting-backpressure-2" 
id="markdown-toc-inflicting-backpressure-2">Inflicting Backpressure (2)</a></li>
+      <li><a href="#what-do-we-gain-where-is-the-catch" 
id="markdown-toc-what-do-we-gain-where-is-the-catch">What do we Gain? Where is 
the Catch?</a></li>
+    </ul>
+  </li>
+  <li><a href="#writing-records-into-network-buffers-and-reading-them-again" 
id="markdown-toc-writing-records-into-network-buffers-and-reading-them-again">Writing
 Records into Network Buffers and Reading them again</a>    <ul>
+      <li><a href="#flushing-buffers-to-netty" 
id="markdown-toc-flushing-buffers-to-netty">Flushing Buffers to Netty</a></li>
+      <li><a href="#buffer-builder--buffer-consumer" 
id="markdown-toc-buffer-builder--buffer-consumer">Buffer Builder &amp; Buffer 
Consumer</a></li>
+    </ul>
+  </li>
+  <li><a href="#latency-vs-throughput" 
id="markdown-toc-latency-vs-throughput">Latency vs. Throughput</a></li>
+  <li><a href="#conclusion" id="markdown-toc-conclusion">Conclusion</a></li>
+</ul>
+
+</div>
+
+<h2 id="logical-view">Logical View</h2>
 
 <p>Flink’s network stack provides the following logical view to the subtasks 
when communicating with each other, for example during a network shuffle as 
required by a <code>keyBy()</code>.</p>
 
@@ -226,42 +258,34 @@
 <p>The following table summarises the valid combinations:
 <br /></p>
 <center>
-<style type="text/css">
-.tg  {border-collapse:collapse;border-spacing:0;}
-.tg td{font-family:Arial, sans-serif;font-size:14px;padding:10px 
30px;border-style:solid;border-width:1px;overflow:hidden;word-break:normal;border-color:black;}
-.tg th{font-family:Arial, 
sans-serif;font-size:14px;font-weight:normal;padding:10px 
30px;border-style:solid;border-width:1px;overflow:hidden;word-break:normal;border-color:black;}
-.tg 
.tg-wwp9{font-size:15px;background-color:#9b9b9b;border-color:#343434;text-align:left}
-.tg .tg-sogj{font-size:15px;text-align:left}
-.tg .tg-cbs6{font-size:15px;text-align:left;vertical-align:top}
-</style>
 <table class="tg">
   <tr>
-    <th class="tg-wwp9">Output Type</th>
-    <th class="tg-wwp9">Scheduling Type</th>
-    <th class="tg-wwp9">Applies to…</th>
+    <th>Output Type</th>
+    <th>Scheduling Type</th>
+    <th>Applies to…</th>
   </tr>
   <tr>
-    <td class="tg-sogj" rowspan="2">pipelined, unbounded</td>
-    <td class="tg-sogj">all at once</td>
-    <td class="tg-sogj">Streaming jobs</td>
+    <td rowspan="2">pipelined, unbounded</td>
+    <td>all at once</td>
+    <td>Streaming jobs</td>
   </tr>
   <tr>
-    <td class="tg-sogj">next stage on first output</td>
-    <td class="tg-sogj">n/a¹</td>
+    <td>next stage on first output</td>
+    <td>n/a¹</td>
   </tr>
   <tr>
-    <td class="tg-sogj" rowspan="2">pipelined, bounded</td>
-    <td class="tg-sogj">all at once</td>
-    <td class="tg-sogj">n/a²</td>
+    <td rowspan="2">pipelined, bounded</td>
+    <td>all at once</td>
+    <td>n/a²</td>
   </tr>
   <tr>
-    <td class="tg-sogj">next stage on first output</td>
-    <td class="tg-sogj">Batch jobs</td>
+    <td>next stage on first output</td>
+    <td>Batch jobs</td>
   </tr>
   <tr>
-    <td class="tg-cbs6">blocking</td>
-    <td class="tg-cbs6">next stage on complete output</td>
-    <td class="tg-cbs6">Batch jobs</td>
+    <td>blocking</td>
+    <td>next stage on complete output</td>
+    <td>Batch jobs</td>
   </tr>
 </table>
 </center>
@@ -275,7 +299,7 @@ Additionally, for subtasks with more than one input, 
scheduling start in two way
 
 <p><br /></p>
 
-<h1 id="physical-transport">Physical Transport</h1>
+<h2 id="physical-transport">Physical Transport</h2>
 
 <p>In order to understand the physical data connections, please recall that, 
in Flink, different tasks may share the same slot via <a 
href="https://ci.apache.org/projects/flink/flink-docs-release-1.8/dev/stream/operators/#task-chaining-and-resource-groups";>slot
 sharing groups</a>. TaskManagers may also provide more than one slot to allow 
multiple subtasks of the same task to be scheduled onto the same 
TaskManager.</p>
 
@@ -283,37 +307,29 @@ Additionally, for subtasks with more than one input, 
scheduling start in two way
 <br /></p>
 
 <center>
-<style type="text/css">
-.tg  {border-collapse:collapse;border-spacing:10;}
-.tg td{font-family:Arial, sans-serif;font-size:15px;padding:10px 
80px;border-style:solid;border-width:1px;overflow:hidden;word-break:normal;border-color:black;}
-.tg th{font-family:Arial, 
sans-serif;font-size:15px;font-weight:normal;padding:10px 
80px;border-style:solid;border-width:1px;overflow:hidden;word-break:normal;border-color:black;}
-.tg 
.tg-266k{background-color:#9b9b9b;border-color:inherit;text-align:left;vertical-align:center}
-.tg .tg-c3ow{border-color:inherit;text-align:center;vertical-align:center}
-.tg .tg-0pky{border-color:inherit;text-align:left;vertical-align:center}
-</style>
 <table class="tg">
   <tr>
-    <th class="tg-266k"></th>
-    <th class="tg-266k">B.1</th>
-    <th class="tg-266k">B.2</th>
-    <th class="tg-266k">B.3</th>
-    <th class="tg-266k">B.4</th>
+    <th></th>
+    <th class="tg-wide">B.1</th>
+    <th class="tg-wide">B.2</th>
+    <th class="tg-wide">B.3</th>
+    <th class="tg-wide">B.4</th>
   </tr>
   <tr>
-    <td class="tg-0pky">A.1</td>
-    <td class="tg-c3ow" colspan="2" rowspan="2">local</td>
-    <td class="tg-c3ow" colspan="2" rowspan="2">remote</td>
+    <th class="tg-wide">A.1</th>
+    <td class="tg-center" colspan="2" rowspan="2">local</td>
+    <td class="tg-center" colspan="2" rowspan="2">remote</td>
   </tr>
   <tr>
-    <td class="tg-0pky">A.2</td>
+    <th class="tg-wide">A.2</th>
   </tr>
   <tr>
-    <td class="tg-0pky">A.3</td>
-    <td class="tg-c3ow" colspan="2" rowspan="2">remote</td>
-    <td class="tg-c3ow" colspan="2" rowspan="2">local</td>
+    <th class="tg-wide">A.3</th>
+    <td class="tg-center" colspan="2" rowspan="2">remote</td>
+    <td class="tg-center" colspan="2" rowspan="2">local</td>
   </tr>
   <tr>
-    <td class="tg-0pky">A.4</td>
+    <th class="tg-wide">A.4</th>
   </tr>
 </table>
 </center>
@@ -335,7 +351,7 @@ Additionally, for subtasks with more than one input, 
scheduling start in two way
 
 <p>The total number of buffers on a single TaskManager usually does not need 
configuration. See the <a 
href="https://ci.apache.org/projects/flink/flink-docs-release-1.8/ops/config.html#configuring-the-network-buffers";>Configuring
 the Network Buffers</a> documentation for details on how to do so if 
needed.</p>
 
-<h2 id="inflicting-backpressure-1">Inflicting Backpressure (1)</h2>
+<h3 id="inflicting-backpressure-1">Inflicting Backpressure (1)</h3>
 
 <p>Whenever a subtask’s sending buffer pool is exhausted — buffers reside in 
either a result subpartition’s buffer queue or inside the lower, Netty-backed 
network stack — the producer is blocked, cannot continue, and experiences 
backpressure. The receiver works in a similar fashion: any incoming Netty 
buffer in the lower network stack needs to be made available to Flink via a 
network buffer. If there is no network buffer available in the appropriate 
subtask’s buffer pool, Flink will stop [...]
 
@@ -350,7 +366,7 @@ Additionally, for subtasks with more than one input, 
scheduling start in two way
 
 <p><br /></p>
 
-<h1 id="credit-based-flow-control">Credit-based Flow Control</h1>
+<h2 id="credit-based-flow-control">Credit-based Flow Control</h2>
 
 <p>Credit-based flow control makes sure that whatever is “on the wire” will 
have capacity at the receiver to handle. It is based on the availability of 
network buffers as a natural extension of the mechanisms Flink had before. 
Instead of only having a shared local buffer pool, each remote input channel 
now has its own set of <strong>exclusive buffers</strong>. Conversely, buffers 
in the local buffer pool are called <strong>floating buffers</strong> as they 
will float around and are avail [...]
 
@@ -367,11 +383,11 @@ Additionally, for subtasks with more than one input, 
scheduling start in two way
 
 <p><sup>3</sup>If there are not enough buffers available, each buffer pool 
will get the same share of the globally available ones (± 1).</p>
 
-<h2 id="inflicting-backpressure-2">Inflicting Backpressure (2)</h2>
+<h3 id="inflicting-backpressure-2">Inflicting Backpressure (2)</h3>
 
 <p>As opposed to the receiver’s backpressure mechanisms without flow control, 
credits provide a more direct control: If a receiver cannot keep up, its 
available credits will eventually hit 0 and stop the sender from forwarding 
buffers to the lower network stack. There is backpressure on this logical 
channel only and there is no need to block reading from a multiplexed TCP 
channel. Other receivers are therefore not affected in processing available 
buffers.</p>
 
-<h2 id="what-do-we-gain-where-is-the-catch">What do we Gain? Where is the 
Catch?</h2>
+<h3 id="what-do-we-gain-where-is-the-catch">What do we Gain? Where is the 
Catch?</h3>
 
 <p><img align="right" 
src="/img/blog/2019-06-05-network-stack/flink-network-stack5.png" width="300" 
height="200" alt="Physical-transport-credit-flow-checkpoints-Flink's Network 
Stack" /></p>
 
@@ -384,38 +400,40 @@ Additionally, for subtasks with more than one input, 
scheduling start in two way
 <p><br /></p>
 
 <center>
-<style type="text/css">
-.tg  {border-collapse:collapse;border-spacing:0;}
-.tg td{font-family:Arial, sans-serif;font-size:14px;padding:10px 
30px;border-style:solid;border-width:1px;overflow:hidden;word-break:normal;border-color:black;}
-.tg th{font-family:Arial, 
sans-serif;font-size:14px;font-weight:normal;padding:10px 
30px;border-style:solid;border-width:1px;overflow:hidden;word-break:normal;border-color:black;}
-.tg .tg-0vnf{font-size:15px;text-align:center}
-.tg .tg-rc1r{font-size:15px;background-color:#9b9b9b;text-align:left}
-.tg .tg-sogj{font-size:15px;text-align:left}
-</style>
 <table class="tg">
   <tr>
-    <th class="tg-rc1r">Advantages</th>
-    <th class="tg-rc1r">Disadvantages</th>
+    <th>Advantages</th>
+    <th>Disadvantages</th>
   </tr>
   <tr>
-    <td class="tg-sogj">• better resource utilisation with data skew in 
multiplexed connections <br /><br />• improved checkpoint alignment<br /><br 
/>• reduced memory use (less data in lower network layers)</td>
-    <td class="tg-sogj">• additional credit-announce messages<br /><br />• 
additional backlog-announce messages (piggy-backed with buffer messages, almost 
no overhead)<br /><br />• potential round-trip latency</td>
+    <td class="tg-top">
+    • better resource utilisation with data skew in multiplexed connections 
<br /><br />
+    • improved checkpoint alignment<br /><br />
+    • reduced memory use (less data in lower network layers)</td>
+    <td class="tg-top">
+    • additional credit-announce messages<br /><br />
+    • additional backlog-announce messages (piggy-backed with buffer messages, 
almost no overhead)<br /><br />
+    • potential round-trip latency</td>
   </tr>
   <tr>
-    <td class="tg-0vnf" colspan="2">• backpressure appears earlier</td>
+    <td class="tg-center" colspan="2">• backpressure appears earlier</td>
   </tr>
 </table>
 </center>
 <p><br /></p>
 
-<blockquote>
-  <p><em>NOTE:</em> If you need to turn off credit-based flow control, you can 
add this to your <code>flink-conf.yaml</code>: 
<code>taskmanager.network.credit-model: false</code>. 
-This parameter, however, is deprecated and will eventually be removed along 
with the non-credit-based flow control code.</p>
-</blockquote>
+<div class="alert alert-info">
+  <p><span class="label label-info" style="display: inline-block"><span 
class="glyphicon glyphicon-info-sign" aria-hidden="true"></span> Note</span>
+If you need to turn off credit-based flow control, you can add this to your 
<code>flink-conf.yaml</code>:</p>
+
+  <p><code>taskmanager.network.credit-model: false</code></p>
+
+  <p>This parameter, however, is deprecated and will eventually be removed 
along with the non-credit-based flow control code.</p>
+</div>
 
 <p><br /></p>
 
-<h1 id="writing-records-into-network-buffers-and-reading-them-again">Writing 
Records into Network Buffers and Reading them again</h1>
+<h2 id="writing-records-into-network-buffers-and-reading-them-again">Writing 
Records into Network Buffers and Reading them again</h2>
 
 <p>The following picture extends the slightly more high-level view from above 
with further details of the network stack and its surrounding components, from 
the collection of a record in your sending operator to the receiving operator 
getting it:
 <br /></p>
@@ -430,7 +448,7 @@ This parameter, however, is deprecated and will eventually 
be removed along with
 <p>On the receiver’s side, the lower network stack (netty) is writing received 
buffers into the appropriate input channels. The (stream) tasks’s thread 
eventually reads from these queues and tries to deserialise the accumulated 
bytes into Java objects with the help of the <a 
href="https://ci.apache.org/projects/flink/flink-docs-release-1.8/api/java/org/apache/flink/runtime/io/network/api/reader/RecordReader.html";>RecordReader</a>
 and going through the <a href="https://ci.apache.org/proje [...]
 <br /></p>
 
-<h2 id="flushing-buffers-to-netty">Flushing Buffers to Netty</h2>
+<h3 id="flushing-buffers-to-netty">Flushing Buffers to Netty</h3>
 
 <p>In the picture above, the credit-based flow control mechanics actually sit 
inside the “Netty Server” (and “Netty Client”) components and the buffer the 
RecordWriter is writing to is always added to the result subpartition in an 
empty state and then gradually filled with (serialised) records. But when does 
Netty actually get the buffer? Obviously, it cannot take bytes whenever they 
become available since that would not only add substantial costs due to 
cross-thread communication and sy [...]
 
@@ -443,7 +461,7 @@ This parameter, however, is deprecated and will eventually 
be removed along with
 <br /></li>
 </ul>
 
-<h3 id="flush-after-buffer-full">Flush after Buffer Full</h3>
+<h4 id="flush-after-buffer-full">Flush after Buffer Full</h4>
 
 <p>The RecordWriter works with a local serialisation buffer for the current 
record and will gradually write these bytes to one or more network buffers 
sitting at the appropriate result subpartition queue. Although a RecordWriter 
can work on multiple subpartitions, each subpartition has only one RecordWriter 
writing data to it. The Netty server, on the other hand, is reading from 
multiple result subpartitions and multiplexing the appropriate ones into a 
single channel as described above.  [...]
 <br /></p>
@@ -456,7 +474,7 @@ This parameter, however, is deprecated and will eventually 
be removed along with
 <p><sup>4</sup>We can assume it already got the notification if there are more 
finished buffers in the queue.
 <br /></p>
 
-<h3 id="flush-after-buffer-timeout">Flush after Buffer Timeout</h3>
+<h4 id="flush-after-buffer-timeout">Flush after Buffer Timeout</h4>
 
 <p>In order to support low-latency use cases, we cannot only rely on buffers 
being full in order to send data downstream. There may be cases where a certain 
communication channel does not have too many records flowing through and 
unnecessarily increase the latency of the few records you actually have. 
Therefore, a periodic process will flush whatever data is available down the 
stack: the output flusher. The periodic interval can be configured via <a 
href="https://ci.apache.org/projects/f [...]
 <br /></p>
@@ -469,12 +487,12 @@ This parameter, however, is deprecated and will 
eventually be removed along with
 <p><sup>5</sup>Strictly speaking, the output flusher does not give any 
guarantees - it only sends a notification to Netty which can pick it up at will 
/ capacity. This also means that the output flusher has no effect if the 
channel is backpressured.
 <br /></p>
 
-<h3 id="flush-after-special-event">Flush after special event</h3>
+<h4 id="flush-after-special-event">Flush after special event</h4>
 
 <p>Some special events also trigger immediate flushes if being sent through 
the RecordWriter. The most important ones are checkpoint barriers or 
end-of-partition events which obviously should go quickly and not wait for the 
output flusher to kick in.
 <br /></p>
 
-<h3 id="further-remarks">Further remarks</h3>
+<h4 id="further-remarks">Further remarks</h4>
 
 <p>In contrast to Flink &lt; 1.5, please note that (a) network buffers are now 
placed in the subpartition queues directly and (b) we are not closing the 
buffer on each flush. This gives us a few advantages:</p>
 
@@ -487,13 +505,13 @@ This parameter, however, is deprecated and will 
eventually be removed along with
 <p>However, you may notice an increased CPU use and TCP packet rate during low 
load scenarios. This is because, with the changes, Flink will use any 
<em>available</em> CPU cycles to try to maintain the desired latency. Once the 
load increases, this will self-adjust by buffers filling up more. High load 
scenarios are not affected and even get a better throughput because of the 
reduced synchronisation overhead.
 <br /></p>
 
-<h2 id="buffer-builder--buffer-consumer">Buffer Builder &amp; Buffer 
Consumer</h2>
+<h3 id="buffer-builder--buffer-consumer">Buffer Builder &amp; Buffer 
Consumer</h3>
 
 <p>If you want to dig deeper into how the producer-consumer mechanics are 
implemented in Flink, please take a closer look at the <a 
href="https://ci.apache.org/projects/flink/flink-docs-release-1.8/api/java/org/apache/flink/runtime/io/network/buffer/BufferBuilder.html";>BufferBuilder</a>
 and <a 
href="https://ci.apache.org/projects/flink/flink-docs-release-1.8/api/java/org/apache/flink/runtime/io/network/buffer/BufferConsumer.html";>BufferConsumer</a>
 classes which have been introduced in F [...]
 
 <p><br /></p>
 
-<h1 id="latency-vs-throughput">Latency vs. Throughput</h1>
+<h2 id="latency-vs-throughput">Latency vs. Throughput</h2>
 
 <p>Network buffers were introduced to get higher resource utilisation and 
higher throughput at the cost of having some records wait in buffers a little 
longer. Although an upper limit to this wait time can be given via the buffer 
timeout, you may be curious to find out more about the trade-off between these 
two dimensions: latency and throughput, as, obviously, you cannot get both. The 
following plot shows various values for the buffer timeout starting at 0 (flush 
with every record) to 1 [...]
 <br /></p>
@@ -507,7 +525,7 @@ This parameter, however, is deprecated and will eventually 
be removed along with
 
 <p><br /></p>
 
-<h1 id="conclusion">Conclusion</h1>
+<h2 id="conclusion">Conclusion</h2>
 
 <p>Now you know about result partitions, the different network connections and 
scheduling types for both batch and streaming. You also know about credit-based 
flow control and how the network stack works internally, in order to reason 
about network-related tuning parameters and about certain job behaviours. 
Future blog posts in this series will build upon this knowledge and go into 
more operational details including relevant metrics to look at, further network 
stack tuning, and common an [...]
 
diff --git a/content/blog/feed.xml b/content/blog/feed.xml
index d4d033b..ebfe803 100644
--- a/content/blog/feed.xml
+++ b/content/blog/feed.xml
@@ -359,11 +359,43 @@ The website implements a streaming application that 
detects a pattern on the str
 
 <item>
 <title>A Deep-Dive into Flink&#39;s Network Stack</title>
-<description>&lt;p&gt;Flink’s network stack is one of the core components that 
make up the &lt;code&gt;flink-runtime&lt;/code&gt; module and sit at the heart 
of every Flink job. It connects individual work units (subtasks) from all 
TaskManagers. This is where your streamed-in data flows through and it is 
therefore crucial to the performance of your Flink job for both the throughput 
as well as latency you observe. In contrast to the coordination channels 
between TaskManagers and JobManage [...]
+<description>&lt;style type=&quot;text/css&quot;&gt;
+.tg  {border-collapse:collapse;border-spacing:0;}
+.tg td{padding:10px 
20px;border-style:solid;border-width:1px;overflow:hidden;word-break:normal;}
+.tg th{padding:10px 
20px;border-style:solid;border-width:1px;overflow:hidden;word-break:normal;background-color:#eff0f1;}
+.tg .tg-wide{padding:10px 30px;}
+.tg .tg-top{vertical-align:top}
+.tg .tg-center{text-align:center;vertical-align:center}
+&lt;/style&gt;
+
+&lt;p&gt;Flink’s network stack is one of the core components that make up the 
&lt;code&gt;flink-runtime&lt;/code&gt; module and sit at the heart of every 
Flink job. It connects individual work units (subtasks) from all TaskManagers. 
This is where your streamed-in data flows through and it is therefore crucial 
to the performance of your Flink job for both the throughput as well as latency 
you observe. In contrast to the coordination channels between TaskManagers and 
JobManagers which are  [...]
 
 &lt;p&gt;This blog post is the first in a series of posts about the network 
stack. In the sections below, we will first have a high-level look at what 
abstractions are exposed to the stream operators and then go into detail on the 
physical implementation and various optimisations Flink did. We will briefly 
present the result of these optimisations and Flink’s trade-off between 
throughput and latency. Future blog posts in this series will elaborate more on 
monitoring and metrics, tuning p [...]
 
-&lt;h1 id=&quot;logical-view&quot;&gt;Logical View&lt;/h1&gt;
+&lt;div class=&quot;page-toc&quot;&gt;
+&lt;ul id=&quot;markdown-toc&quot;&gt;
+  &lt;li&gt;&lt;a href=&quot;#logical-view&quot; 
id=&quot;markdown-toc-logical-view&quot;&gt;Logical View&lt;/a&gt;&lt;/li&gt;
+  &lt;li&gt;&lt;a href=&quot;#physical-transport&quot; 
id=&quot;markdown-toc-physical-transport&quot;&gt;Physical Transport&lt;/a&gt;  
  &lt;ul&gt;
+      &lt;li&gt;&lt;a href=&quot;#inflicting-backpressure-1&quot; 
id=&quot;markdown-toc-inflicting-backpressure-1&quot;&gt;Inflicting 
Backpressure (1)&lt;/a&gt;&lt;/li&gt;
+    &lt;/ul&gt;
+  &lt;/li&gt;
+  &lt;li&gt;&lt;a href=&quot;#credit-based-flow-control&quot; 
id=&quot;markdown-toc-credit-based-flow-control&quot;&gt;Credit-based Flow 
Control&lt;/a&gt;    &lt;ul&gt;
+      &lt;li&gt;&lt;a href=&quot;#inflicting-backpressure-2&quot; 
id=&quot;markdown-toc-inflicting-backpressure-2&quot;&gt;Inflicting 
Backpressure (2)&lt;/a&gt;&lt;/li&gt;
+      &lt;li&gt;&lt;a href=&quot;#what-do-we-gain-where-is-the-catch&quot; 
id=&quot;markdown-toc-what-do-we-gain-where-is-the-catch&quot;&gt;What do we 
Gain? Where is the Catch?&lt;/a&gt;&lt;/li&gt;
+    &lt;/ul&gt;
+  &lt;/li&gt;
+  &lt;li&gt;&lt;a 
href=&quot;#writing-records-into-network-buffers-and-reading-them-again&quot; 
id=&quot;markdown-toc-writing-records-into-network-buffers-and-reading-them-again&quot;&gt;Writing
 Records into Network Buffers and Reading them again&lt;/a&gt;    &lt;ul&gt;
+      &lt;li&gt;&lt;a href=&quot;#flushing-buffers-to-netty&quot; 
id=&quot;markdown-toc-flushing-buffers-to-netty&quot;&gt;Flushing Buffers to 
Netty&lt;/a&gt;&lt;/li&gt;
+      &lt;li&gt;&lt;a href=&quot;#buffer-builder--buffer-consumer&quot; 
id=&quot;markdown-toc-buffer-builder--buffer-consumer&quot;&gt;Buffer Builder 
&amp;amp; Buffer Consumer&lt;/a&gt;&lt;/li&gt;
+    &lt;/ul&gt;
+  &lt;/li&gt;
+  &lt;li&gt;&lt;a href=&quot;#latency-vs-throughput&quot; 
id=&quot;markdown-toc-latency-vs-throughput&quot;&gt;Latency vs. 
Throughput&lt;/a&gt;&lt;/li&gt;
+  &lt;li&gt;&lt;a href=&quot;#conclusion&quot; 
id=&quot;markdown-toc-conclusion&quot;&gt;Conclusion&lt;/a&gt;&lt;/li&gt;
+&lt;/ul&gt;
+
+&lt;/div&gt;
+
+&lt;h2 id=&quot;logical-view&quot;&gt;Logical View&lt;/h2&gt;
 
 &lt;p&gt;Flink’s network stack provides the following logical view to the 
subtasks when communicating with each other, for example during a network 
shuffle as required by a &lt;code&gt;keyBy()&lt;/code&gt;.&lt;/p&gt;
 
@@ -412,42 +444,34 @@ The website implements a streaming application that 
detects a pattern on the str
 &lt;p&gt;The following table summarises the valid combinations:
 &lt;br /&gt;&lt;/p&gt;
 &lt;center&gt;
-&lt;style type=&quot;text/css&quot;&gt;
-.tg  {border-collapse:collapse;border-spacing:0;}
-.tg td{font-family:Arial, sans-serif;font-size:14px;padding:10px 
30px;border-style:solid;border-width:1px;overflow:hidden;word-break:normal;border-color:black;}
-.tg th{font-family:Arial, 
sans-serif;font-size:14px;font-weight:normal;padding:10px 
30px;border-style:solid;border-width:1px;overflow:hidden;word-break:normal;border-color:black;}
-.tg 
.tg-wwp9{font-size:15px;background-color:#9b9b9b;border-color:#343434;text-align:left}
-.tg .tg-sogj{font-size:15px;text-align:left}
-.tg .tg-cbs6{font-size:15px;text-align:left;vertical-align:top}
-&lt;/style&gt;
 &lt;table class=&quot;tg&quot;&gt;
   &lt;tr&gt;
-    &lt;th class=&quot;tg-wwp9&quot;&gt;Output Type&lt;/th&gt;
-    &lt;th class=&quot;tg-wwp9&quot;&gt;Scheduling Type&lt;/th&gt;
-    &lt;th class=&quot;tg-wwp9&quot;&gt;Applies to…&lt;/th&gt;
+    &lt;th&gt;Output Type&lt;/th&gt;
+    &lt;th&gt;Scheduling Type&lt;/th&gt;
+    &lt;th&gt;Applies to…&lt;/th&gt;
   &lt;/tr&gt;
   &lt;tr&gt;
-    &lt;td class=&quot;tg-sogj&quot; rowspan=&quot;2&quot;&gt;pipelined, 
unbounded&lt;/td&gt;
-    &lt;td class=&quot;tg-sogj&quot;&gt;all at once&lt;/td&gt;
-    &lt;td class=&quot;tg-sogj&quot;&gt;Streaming jobs&lt;/td&gt;
+    &lt;td rowspan=&quot;2&quot;&gt;pipelined, unbounded&lt;/td&gt;
+    &lt;td&gt;all at once&lt;/td&gt;
+    &lt;td&gt;Streaming jobs&lt;/td&gt;
   &lt;/tr&gt;
   &lt;tr&gt;
-    &lt;td class=&quot;tg-sogj&quot;&gt;next stage on first output&lt;/td&gt;
-    &lt;td class=&quot;tg-sogj&quot;&gt;n/a¹&lt;/td&gt;
+    &lt;td&gt;next stage on first output&lt;/td&gt;
+    &lt;td&gt;n/a¹&lt;/td&gt;
   &lt;/tr&gt;
   &lt;tr&gt;
-    &lt;td class=&quot;tg-sogj&quot; rowspan=&quot;2&quot;&gt;pipelined, 
bounded&lt;/td&gt;
-    &lt;td class=&quot;tg-sogj&quot;&gt;all at once&lt;/td&gt;
-    &lt;td class=&quot;tg-sogj&quot;&gt;n/a²&lt;/td&gt;
+    &lt;td rowspan=&quot;2&quot;&gt;pipelined, bounded&lt;/td&gt;
+    &lt;td&gt;all at once&lt;/td&gt;
+    &lt;td&gt;n/a²&lt;/td&gt;
   &lt;/tr&gt;
   &lt;tr&gt;
-    &lt;td class=&quot;tg-sogj&quot;&gt;next stage on first output&lt;/td&gt;
-    &lt;td class=&quot;tg-sogj&quot;&gt;Batch jobs&lt;/td&gt;
+    &lt;td&gt;next stage on first output&lt;/td&gt;
+    &lt;td&gt;Batch jobs&lt;/td&gt;
   &lt;/tr&gt;
   &lt;tr&gt;
-    &lt;td class=&quot;tg-cbs6&quot;&gt;blocking&lt;/td&gt;
-    &lt;td class=&quot;tg-cbs6&quot;&gt;next stage on complete 
output&lt;/td&gt;
-    &lt;td class=&quot;tg-cbs6&quot;&gt;Batch jobs&lt;/td&gt;
+    &lt;td&gt;blocking&lt;/td&gt;
+    &lt;td&gt;next stage on complete output&lt;/td&gt;
+    &lt;td&gt;Batch jobs&lt;/td&gt;
   &lt;/tr&gt;
 &lt;/table&gt;
 &lt;/center&gt;
@@ -461,7 +485,7 @@ Additionally, for subtasks with more than one input, 
scheduling start in two way
 
 &lt;p&gt;&lt;br /&gt;&lt;/p&gt;
 
-&lt;h1 id=&quot;physical-transport&quot;&gt;Physical Transport&lt;/h1&gt;
+&lt;h2 id=&quot;physical-transport&quot;&gt;Physical Transport&lt;/h2&gt;
 
 &lt;p&gt;In order to understand the physical data connections, please recall 
that, in Flink, different tasks may share the same slot via &lt;a 
href=&quot;https://ci.apache.org/projects/flink/flink-docs-release-1.8/dev/stream/operators/#task-chaining-and-resource-groups&quot;&gt;slot
 sharing groups&lt;/a&gt;. TaskManagers may also provide more than one slot to 
allow multiple subtasks of the same task to be scheduled onto the same 
TaskManager.&lt;/p&gt;
 
@@ -469,37 +493,29 @@ Additionally, for subtasks with more than one input, 
scheduling start in two way
 &lt;br /&gt;&lt;/p&gt;
 
 &lt;center&gt;
-&lt;style type=&quot;text/css&quot;&gt;
-.tg  {border-collapse:collapse;border-spacing:10;}
-.tg td{font-family:Arial, sans-serif;font-size:15px;padding:10px 
80px;border-style:solid;border-width:1px;overflow:hidden;word-break:normal;border-color:black;}
-.tg th{font-family:Arial, 
sans-serif;font-size:15px;font-weight:normal;padding:10px 
80px;border-style:solid;border-width:1px;overflow:hidden;word-break:normal;border-color:black;}
-.tg 
.tg-266k{background-color:#9b9b9b;border-color:inherit;text-align:left;vertical-align:center}
-.tg .tg-c3ow{border-color:inherit;text-align:center;vertical-align:center}
-.tg .tg-0pky{border-color:inherit;text-align:left;vertical-align:center}
-&lt;/style&gt;
 &lt;table class=&quot;tg&quot;&gt;
   &lt;tr&gt;
-    &lt;th class=&quot;tg-266k&quot;&gt;&lt;/th&gt;
-    &lt;th class=&quot;tg-266k&quot;&gt;B.1&lt;/th&gt;
-    &lt;th class=&quot;tg-266k&quot;&gt;B.2&lt;/th&gt;
-    &lt;th class=&quot;tg-266k&quot;&gt;B.3&lt;/th&gt;
-    &lt;th class=&quot;tg-266k&quot;&gt;B.4&lt;/th&gt;
+    &lt;th&gt;&lt;/th&gt;
+    &lt;th class=&quot;tg-wide&quot;&gt;B.1&lt;/th&gt;
+    &lt;th class=&quot;tg-wide&quot;&gt;B.2&lt;/th&gt;
+    &lt;th class=&quot;tg-wide&quot;&gt;B.3&lt;/th&gt;
+    &lt;th class=&quot;tg-wide&quot;&gt;B.4&lt;/th&gt;
   &lt;/tr&gt;
   &lt;tr&gt;
-    &lt;td class=&quot;tg-0pky&quot;&gt;A.1&lt;/td&gt;
-    &lt;td class=&quot;tg-c3ow&quot; colspan=&quot;2&quot; 
rowspan=&quot;2&quot;&gt;local&lt;/td&gt;
-    &lt;td class=&quot;tg-c3ow&quot; colspan=&quot;2&quot; 
rowspan=&quot;2&quot;&gt;remote&lt;/td&gt;
+    &lt;th class=&quot;tg-wide&quot;&gt;A.1&lt;/th&gt;
+    &lt;td class=&quot;tg-center&quot; colspan=&quot;2&quot; 
rowspan=&quot;2&quot;&gt;local&lt;/td&gt;
+    &lt;td class=&quot;tg-center&quot; colspan=&quot;2&quot; 
rowspan=&quot;2&quot;&gt;remote&lt;/td&gt;
   &lt;/tr&gt;
   &lt;tr&gt;
-    &lt;td class=&quot;tg-0pky&quot;&gt;A.2&lt;/td&gt;
+    &lt;th class=&quot;tg-wide&quot;&gt;A.2&lt;/th&gt;
   &lt;/tr&gt;
   &lt;tr&gt;
-    &lt;td class=&quot;tg-0pky&quot;&gt;A.3&lt;/td&gt;
-    &lt;td class=&quot;tg-c3ow&quot; colspan=&quot;2&quot; 
rowspan=&quot;2&quot;&gt;remote&lt;/td&gt;
-    &lt;td class=&quot;tg-c3ow&quot; colspan=&quot;2&quot; 
rowspan=&quot;2&quot;&gt;local&lt;/td&gt;
+    &lt;th class=&quot;tg-wide&quot;&gt;A.3&lt;/th&gt;
+    &lt;td class=&quot;tg-center&quot; colspan=&quot;2&quot; 
rowspan=&quot;2&quot;&gt;remote&lt;/td&gt;
+    &lt;td class=&quot;tg-center&quot; colspan=&quot;2&quot; 
rowspan=&quot;2&quot;&gt;local&lt;/td&gt;
   &lt;/tr&gt;
   &lt;tr&gt;
-    &lt;td class=&quot;tg-0pky&quot;&gt;A.4&lt;/td&gt;
+    &lt;th class=&quot;tg-wide&quot;&gt;A.4&lt;/th&gt;
   &lt;/tr&gt;
 &lt;/table&gt;
 &lt;/center&gt;
@@ -521,7 +537,7 @@ Additionally, for subtasks with more than one input, 
scheduling start in two way
 
 &lt;p&gt;The total number of buffers on a single TaskManager usually does not 
need configuration. See the &lt;a 
href=&quot;https://ci.apache.org/projects/flink/flink-docs-release-1.8/ops/config.html#configuring-the-network-buffers&quot;&gt;Configuring
 the Network Buffers&lt;/a&gt; documentation for details on how to do so if 
needed.&lt;/p&gt;
 
-&lt;h2 id=&quot;inflicting-backpressure-1&quot;&gt;Inflicting Backpressure 
(1)&lt;/h2&gt;
+&lt;h3 id=&quot;inflicting-backpressure-1&quot;&gt;Inflicting Backpressure 
(1)&lt;/h3&gt;
 
 &lt;p&gt;Whenever a subtask’s sending buffer pool is exhausted — buffers 
reside in either a result subpartition’s buffer queue or inside the lower, 
Netty-backed network stack — the producer is blocked, cannot continue, and 
experiences backpressure. The receiver works in a similar fashion: any incoming 
Netty buffer in the lower network stack needs to be made available to Flink via 
a network buffer. If there is no network buffer available in the appropriate 
subtask’s buffer pool, Flink wil [...]
 
@@ -536,7 +552,7 @@ Additionally, for subtasks with more than one input, 
scheduling start in two way
 
 &lt;p&gt;&lt;br /&gt;&lt;/p&gt;
 
-&lt;h1 id=&quot;credit-based-flow-control&quot;&gt;Credit-based Flow 
Control&lt;/h1&gt;
+&lt;h2 id=&quot;credit-based-flow-control&quot;&gt;Credit-based Flow 
Control&lt;/h2&gt;
 
 &lt;p&gt;Credit-based flow control makes sure that whatever is “on the wire” 
will have capacity at the receiver to handle. It is based on the availability 
of network buffers as a natural extension of the mechanisms Flink had before. 
Instead of only having a shared local buffer pool, each remote input channel 
now has its own set of &lt;strong&gt;exclusive buffers&lt;/strong&gt;. 
Conversely, buffers in the local buffer pool are called &lt;strong&gt;floating 
buffers&lt;/strong&gt; as they w [...]
 
@@ -553,11 +569,11 @@ Additionally, for subtasks with more than one input, 
scheduling start in two way
 
 &lt;p&gt;&lt;sup&gt;3&lt;/sup&gt;If there are not enough buffers available, 
each buffer pool will get the same share of the globally available ones (± 
1).&lt;/p&gt;
 
-&lt;h2 id=&quot;inflicting-backpressure-2&quot;&gt;Inflicting Backpressure 
(2)&lt;/h2&gt;
+&lt;h3 id=&quot;inflicting-backpressure-2&quot;&gt;Inflicting Backpressure 
(2)&lt;/h3&gt;
 
 &lt;p&gt;As opposed to the receiver’s backpressure mechanisms without flow 
control, credits provide a more direct control: If a receiver cannot keep up, 
its available credits will eventually hit 0 and stop the sender from forwarding 
buffers to the lower network stack. There is backpressure on this logical 
channel only and there is no need to block reading from a multiplexed TCP 
channel. Other receivers are therefore not affected in processing available 
buffers.&lt;/p&gt;
 
-&lt;h2 id=&quot;what-do-we-gain-where-is-the-catch&quot;&gt;What do we Gain? 
Where is the Catch?&lt;/h2&gt;
+&lt;h3 id=&quot;what-do-we-gain-where-is-the-catch&quot;&gt;What do we Gain? 
Where is the Catch?&lt;/h3&gt;
 
 &lt;p&gt;&lt;img align=&quot;right&quot; 
src=&quot;/img/blog/2019-06-05-network-stack/flink-network-stack5.png&quot; 
width=&quot;300&quot; height=&quot;200&quot; 
alt=&quot;Physical-transport-credit-flow-checkpoints-Flink&#39;s Network 
Stack&quot; /&gt;&lt;/p&gt;
 
@@ -570,38 +586,40 @@ Additionally, for subtasks with more than one input, 
scheduling start in two way
 &lt;p&gt;&lt;br /&gt;&lt;/p&gt;
 
 &lt;center&gt;
-&lt;style type=&quot;text/css&quot;&gt;
-.tg  {border-collapse:collapse;border-spacing:0;}
-.tg td{font-family:Arial, sans-serif;font-size:14px;padding:10px 
30px;border-style:solid;border-width:1px;overflow:hidden;word-break:normal;border-color:black;}
-.tg th{font-family:Arial, 
sans-serif;font-size:14px;font-weight:normal;padding:10px 
30px;border-style:solid;border-width:1px;overflow:hidden;word-break:normal;border-color:black;}
-.tg .tg-0vnf{font-size:15px;text-align:center}
-.tg .tg-rc1r{font-size:15px;background-color:#9b9b9b;text-align:left}
-.tg .tg-sogj{font-size:15px;text-align:left}
-&lt;/style&gt;
 &lt;table class=&quot;tg&quot;&gt;
   &lt;tr&gt;
-    &lt;th class=&quot;tg-rc1r&quot;&gt;Advantages&lt;/th&gt;
-    &lt;th class=&quot;tg-rc1r&quot;&gt;Disadvantages&lt;/th&gt;
+    &lt;th&gt;Advantages&lt;/th&gt;
+    &lt;th&gt;Disadvantages&lt;/th&gt;
   &lt;/tr&gt;
   &lt;tr&gt;
-    &lt;td class=&quot;tg-sogj&quot;&gt;• better resource utilisation with 
data skew in multiplexed connections &lt;br /&gt;&lt;br /&gt;• improved 
checkpoint alignment&lt;br /&gt;&lt;br /&gt;• reduced memory use (less data in 
lower network layers)&lt;/td&gt;
-    &lt;td class=&quot;tg-sogj&quot;&gt;• additional credit-announce 
messages&lt;br /&gt;&lt;br /&gt;• additional backlog-announce messages 
(piggy-backed with buffer messages, almost no overhead)&lt;br /&gt;&lt;br 
/&gt;• potential round-trip latency&lt;/td&gt;
+    &lt;td class=&quot;tg-top&quot;&gt;
+    • better resource utilisation with data skew in multiplexed connections 
&lt;br /&gt;&lt;br /&gt;
+    • improved checkpoint alignment&lt;br /&gt;&lt;br /&gt;
+    • reduced memory use (less data in lower network layers)&lt;/td&gt;
+    &lt;td class=&quot;tg-top&quot;&gt;
+    • additional credit-announce messages&lt;br /&gt;&lt;br /&gt;
+    • additional backlog-announce messages (piggy-backed with buffer messages, 
almost no overhead)&lt;br /&gt;&lt;br /&gt;
+    • potential round-trip latency&lt;/td&gt;
   &lt;/tr&gt;
   &lt;tr&gt;
-    &lt;td class=&quot;tg-0vnf&quot; colspan=&quot;2&quot;&gt;• backpressure 
appears earlier&lt;/td&gt;
+    &lt;td class=&quot;tg-center&quot; colspan=&quot;2&quot;&gt;• backpressure 
appears earlier&lt;/td&gt;
   &lt;/tr&gt;
 &lt;/table&gt;
 &lt;/center&gt;
 &lt;p&gt;&lt;br /&gt;&lt;/p&gt;
 
-&lt;blockquote&gt;
-  &lt;p&gt;&lt;em&gt;NOTE:&lt;/em&gt; If you need to turn off credit-based 
flow control, you can add this to your 
&lt;code&gt;flink-conf.yaml&lt;/code&gt;: 
&lt;code&gt;taskmanager.network.credit-model: false&lt;/code&gt;. 
-This parameter, however, is deprecated and will eventually be removed along 
with the non-credit-based flow control code.&lt;/p&gt;
-&lt;/blockquote&gt;
+&lt;div class=&quot;alert alert-info&quot;&gt;
+  &lt;p&gt;&lt;span class=&quot;label label-info&quot; style=&quot;display: 
inline-block&quot;&gt;&lt;span class=&quot;glyphicon glyphicon-info-sign&quot; 
aria-hidden=&quot;true&quot;&gt;&lt;/span&gt; Note&lt;/span&gt;
+If you need to turn off credit-based flow control, you can add this to your 
&lt;code&gt;flink-conf.yaml&lt;/code&gt;:&lt;/p&gt;
+
+  &lt;p&gt;&lt;code&gt;taskmanager.network.credit-model: 
false&lt;/code&gt;&lt;/p&gt;
+
+  &lt;p&gt;This parameter, however, is deprecated and will eventually be 
removed along with the non-credit-based flow control code.&lt;/p&gt;
+&lt;/div&gt;
 
 &lt;p&gt;&lt;br /&gt;&lt;/p&gt;
 
-&lt;h1 
id=&quot;writing-records-into-network-buffers-and-reading-them-again&quot;&gt;Writing
 Records into Network Buffers and Reading them again&lt;/h1&gt;
+&lt;h2 
id=&quot;writing-records-into-network-buffers-and-reading-them-again&quot;&gt;Writing
 Records into Network Buffers and Reading them again&lt;/h2&gt;
 
 &lt;p&gt;The following picture extends the slightly more high-level view from 
above with further details of the network stack and its surrounding components, 
from the collection of a record in your sending operator to the receiving 
operator getting it:
 &lt;br /&gt;&lt;/p&gt;
@@ -616,7 +634,7 @@ This parameter, however, is deprecated and will eventually 
be removed along with
 &lt;p&gt;On the receiver’s side, the lower network stack (netty) is writing 
received buffers into the appropriate input channels. The (stream) tasks’s 
thread eventually reads from these queues and tries to deserialise the 
accumulated bytes into Java objects with the help of the &lt;a 
href=&quot;https://ci.apache.org/projects/flink/flink-docs-release-1.8/api/java/org/apache/flink/runtime/io/network/api/reader/RecordReader.html&quot;&gt;RecordReader&lt;/a&gt;
 and going through the &lt;a hr [...]
 &lt;br /&gt;&lt;/p&gt;
 
-&lt;h2 id=&quot;flushing-buffers-to-netty&quot;&gt;Flushing Buffers to 
Netty&lt;/h2&gt;
+&lt;h3 id=&quot;flushing-buffers-to-netty&quot;&gt;Flushing Buffers to 
Netty&lt;/h3&gt;
 
 &lt;p&gt;In the picture above, the credit-based flow control mechanics 
actually sit inside the “Netty Server” (and “Netty Client”) components and the 
buffer the RecordWriter is writing to is always added to the result 
subpartition in an empty state and then gradually filled with (serialised) 
records. But when does Netty actually get the buffer? Obviously, it cannot take 
bytes whenever they become available since that would not only add substantial 
costs due to cross-thread communication  [...]
 
@@ -629,7 +647,7 @@ This parameter, however, is deprecated and will eventually 
be removed along with
 &lt;br /&gt;&lt;/li&gt;
 &lt;/ul&gt;
 
-&lt;h3 id=&quot;flush-after-buffer-full&quot;&gt;Flush after Buffer 
Full&lt;/h3&gt;
+&lt;h4 id=&quot;flush-after-buffer-full&quot;&gt;Flush after Buffer 
Full&lt;/h4&gt;
 
 &lt;p&gt;The RecordWriter works with a local serialisation buffer for the 
current record and will gradually write these bytes to one or more network 
buffers sitting at the appropriate result subpartition queue. Although a 
RecordWriter can work on multiple subpartitions, each subpartition has only one 
RecordWriter writing data to it. The Netty server, on the other hand, is 
reading from multiple result subpartitions and multiplexing the appropriate 
ones into a single channel as described a [...]
 &lt;br /&gt;&lt;/p&gt;
@@ -642,7 +660,7 @@ This parameter, however, is deprecated and will eventually 
be removed along with
 &lt;p&gt;&lt;sup&gt;4&lt;/sup&gt;We can assume it already got the notification 
if there are more finished buffers in the queue.
 &lt;br /&gt;&lt;/p&gt;
 
-&lt;h3 id=&quot;flush-after-buffer-timeout&quot;&gt;Flush after Buffer 
Timeout&lt;/h3&gt;
+&lt;h4 id=&quot;flush-after-buffer-timeout&quot;&gt;Flush after Buffer 
Timeout&lt;/h4&gt;
 
 &lt;p&gt;In order to support low-latency use cases, we cannot only rely on 
buffers being full in order to send data downstream. There may be cases where a 
certain communication channel does not have too many records flowing through 
and unnecessarily increase the latency of the few records you actually have. 
Therefore, a periodic process will flush whatever data is available down the 
stack: the output flusher. The periodic interval can be configured via &lt;a 
href=&quot;https://ci.apache. [...]
 &lt;br /&gt;&lt;/p&gt;
@@ -655,12 +673,12 @@ This parameter, however, is deprecated and will 
eventually be removed along with
 &lt;p&gt;&lt;sup&gt;5&lt;/sup&gt;Strictly speaking, the output flusher does 
not give any guarantees - it only sends a notification to Netty which can pick 
it up at will / capacity. This also means that the output flusher has no effect 
if the channel is backpressured.
 &lt;br /&gt;&lt;/p&gt;
 
-&lt;h3 id=&quot;flush-after-special-event&quot;&gt;Flush after special 
event&lt;/h3&gt;
+&lt;h4 id=&quot;flush-after-special-event&quot;&gt;Flush after special 
event&lt;/h4&gt;
 
 &lt;p&gt;Some special events also trigger immediate flushes if being sent 
through the RecordWriter. The most important ones are checkpoint barriers or 
end-of-partition events which obviously should go quickly and not wait for the 
output flusher to kick in.
 &lt;br /&gt;&lt;/p&gt;
 
-&lt;h3 id=&quot;further-remarks&quot;&gt;Further remarks&lt;/h3&gt;
+&lt;h4 id=&quot;further-remarks&quot;&gt;Further remarks&lt;/h4&gt;
 
 &lt;p&gt;In contrast to Flink &amp;lt; 1.5, please note that (a) network 
buffers are now placed in the subpartition queues directly and (b) we are not 
closing the buffer on each flush. This gives us a few advantages:&lt;/p&gt;
 
@@ -673,13 +691,13 @@ This parameter, however, is deprecated and will 
eventually be removed along with
 &lt;p&gt;However, you may notice an increased CPU use and TCP packet rate 
during low load scenarios. This is because, with the changes, Flink will use 
any &lt;em&gt;available&lt;/em&gt; CPU cycles to try to maintain the desired 
latency. Once the load increases, this will self-adjust by buffers filling up 
more. High load scenarios are not affected and even get a better throughput 
because of the reduced synchronisation overhead.
 &lt;br /&gt;&lt;/p&gt;
 
-&lt;h2 id=&quot;buffer-builder--buffer-consumer&quot;&gt;Buffer Builder 
&amp;amp; Buffer Consumer&lt;/h2&gt;
+&lt;h3 id=&quot;buffer-builder--buffer-consumer&quot;&gt;Buffer Builder 
&amp;amp; Buffer Consumer&lt;/h3&gt;
 
 &lt;p&gt;If you want to dig deeper into how the producer-consumer mechanics 
are implemented in Flink, please take a closer look at the &lt;a 
href=&quot;https://ci.apache.org/projects/flink/flink-docs-release-1.8/api/java/org/apache/flink/runtime/io/network/buffer/BufferBuilder.html&quot;&gt;BufferBuilder&lt;/a&gt;
 and &lt;a 
href=&quot;https://ci.apache.org/projects/flink/flink-docs-release-1.8/api/java/org/apache/flink/runtime/io/network/buffer/BufferConsumer.html&quot;&gt;BufferConsumer
 [...]
 
 &lt;p&gt;&lt;br /&gt;&lt;/p&gt;
 
-&lt;h1 id=&quot;latency-vs-throughput&quot;&gt;Latency vs. 
Throughput&lt;/h1&gt;
+&lt;h2 id=&quot;latency-vs-throughput&quot;&gt;Latency vs. 
Throughput&lt;/h2&gt;
 
 &lt;p&gt;Network buffers were introduced to get higher resource utilisation 
and higher throughput at the cost of having some records wait in buffers a 
little longer. Although an upper limit to this wait time can be given via the 
buffer timeout, you may be curious to find out more about the trade-off between 
these two dimensions: latency and throughput, as, obviously, you cannot get 
both. The following plot shows various values for the buffer timeout starting 
at 0 (flush with every record [...]
 &lt;br /&gt;&lt;/p&gt;
@@ -693,7 +711,7 @@ This parameter, however, is deprecated and will eventually 
be removed along with
 
 &lt;p&gt;&lt;br /&gt;&lt;/p&gt;
 
-&lt;h1 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h1&gt;
+&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
 
 &lt;p&gt;Now you know about result partitions, the different network 
connections and scheduling types for both batch and streaming. You also know 
about credit-based flow control and how the network stack works internally, in 
order to reason about network-related tuning parameters and about certain job 
behaviours. Future blog posts in this series will build upon this knowledge and 
go into more operational details including relevant metrics to look at, further 
network stack tuning, and com [...]
 

Reply via email to