惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

B
Blog RSS Feed
T
The Blog of Author Tim Ferriss
P
Proofpoint News Feed
T
Threat Research - Cisco Blogs
T
The Exploit Database - CXSecurity.com
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
Application and Cybersecurity Blog
Application and Cybersecurity Blog
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
C
Cybersecurity and Infrastructure Security Agency CISA
D
Darknet – Hacking Tools, Hacker News & Cyber Security
Martin Fowler
Martin Fowler
GbyAI
GbyAI
P
Palo Alto Networks Blog
N
Netflix TechBlog - Medium
C
Cisco Blogs
Microsoft Security Blog
Microsoft Security Blog
G
Google Developers Blog
A
About on SuperTechFans
PCI Perspectives
PCI Perspectives
Scott Helme
Scott Helme
TaoSecurity Blog
TaoSecurity Blog
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
K
Kaspersky official blog
W
WeLiveSecurity
Y
Y Combinator Blog
Hacker News - Newest:
Hacker News - Newest: "LLM"
aimingoo的专栏
aimingoo的专栏
F
Fortinet All Blogs
有赞技术团队
有赞技术团队
人人都是产品经理
人人都是产品经理
月光博客
月光博客
N
News | PayPal Newsroom
Microsoft Azure Blog
Microsoft Azure Blog
G
GRAHAM CLULEY
爱范儿
爱范儿
The GitHub Blog
The GitHub Blog
MongoDB | Blog
MongoDB | Blog
V
V2EX
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Know Your Adversary
Know Your Adversary
博客园 - Franky
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
F
Full Disclosure
V
Vulnerabilities – Threatpost
V
Visual Studio Blog
Forbes - Security
Forbes - Security
Attack and Defense Labs
Attack and Defense Labs
MyScale Blog
MyScale Blog
Hacker News: Ask HN
Hacker News: Ask HN
T
Tor Project blog

Ivan on Containers, Kubernetes, and Server-Side

A grounded take on agentic coding for production environments Server-Side Playgrounds Reimagined: Build, Boot, and Network Your Own Virtual Labs [not a] Kubernetes 101 - Pods, Deployments, and Services As an Attempt To Automate Age-Old Infra Patterns JavaScript or TypeScript? How To Benefit From the Dichotomy On Software Design... and Good Writing Building a Firecracker-Powered Course Platform To Learn Docker and Kubernetes How To Publish a Port of a Running Container What Actually Happens When You Publish a Container Port A Visual Guide to SSH Tunnels: Local and Remote Port Forwarding Debugging Containers Like a Pro Docker: How To Debug Distroless And Slim Containers How To Extract Container Image Filesystem Using Docker | iximiuz Labs In Pursuit of Better Container Images: Alpine, Distroless, Apko, Chisel, DockerSlim, oh my! How To Start Programming In Go: Advice For Fellow DevOps Engineers Kubernetes Ephemeral Containers and kubectl debug Command How To Develop Kubernetes CLIs Like a Pro Docker Container Commands Explained: Understand, Don't Memorize | iximiuz Labs Learning Docker with Docker - Toying With DinD For Fun And Profit How To Extend Kubernetes API - Kubernetes vs. Django The Influence of Plumbing on Programming How To Call Kubernetes API from Go - Types and Common Machinery How To Call Kubernetes API using Simple HTTP Client Kubernetes API Basics - Resources, Kinds, and Objects OpenFaaS - Run Containerized Functions On Your Own Terms Learning Containers From The Bottom Up Docker Containers vs. Kubernetes Pods - Taking a Deeper Look | iximiuz Labs Learn-by-Doing Platforms for Dev, DevOps, and SRE Folks How HTTP Keep-Alive can cause TCP race condition How to Work with Container Images Using ctr | iximiuz Labs Multiple Containers, Same Port, no Reverse Proxy... Exploring Go net/http Package - On How Not To Set Socket Options Disposable Local Development Environments with Vagrant, Docker, and Arkade DevOps, SRE, and Platform Engineering My Choice of Programming Languages Prometheus Is Not a TSDB How to learn PromQL with Prometheus Playground Prometheus Cheat Sheet - Basics (Metrics, Labels, Time Series, Scraping) Rust - Writing Parsers With nom Parser Combinator Framework pq - parse and query log files as time series Prometheus Cheat Sheet - Moving Average, Max, Min, etc (Aggregation Over Time) Prometheus Cheat Sheet - How to Join Multiple Metrics (Vector Matching) The Need For Slimmer Containers Understanding Rust Privacy and Visibility Model Bridge vs. Switch: Takeaways from a Real Data Center Tour | iximiuz Labs From LAN to VXLAN: Networking Basics for Non-Network Engineers | iximiuz Labs KiND - How I Wasted a Day Loading Local Docker Images Go, HTTP handlers, panic, and deadlocks Exploring Kubernetes Operator Pattern Making Sense Out Of Cloud Native Buzz Service Discovery in Kubernetes: Combining the Best of Two Worlds API Developers Never REST How Container Networking Works: Building a Bridge Network From Scratch | iximiuz Labs Traefik: canary deployments with weighted load balancing Service Proxy, Pod, Sidecar, oh my! You Need Containers To Build Images You Don't Need an Image To Run a Container Not Every Container Has an Operating System Inside Working with container images in Go Master Go While Learning Containers Implementing Container Runtime Shim: Interactive Containers How to use Flask with gevent (uWSGI and Gunicorn editions) My 10 Years of Programming Experience Implementing Container Runtime Shim: First Code Implementing Container Runtime Shim: runc Kubernetes Repository On Flame Dealing with process termination in Linux (with Rust examples) conman - [the] Container Manager: Inception Journey From Containerization To Orchestration And Beyond Linux PTY - How docker attach and docker exec Commands Work Inside Illustrated introduction to Linux iptables From Docker Container to Bootable Linux Disk Image Пишем свой веб-сервер на Python: протокол HTTP 9001 способ создать веб-сервер на Python Explaining async/await in 200 lines of code Explaining event loop in 100 lines of code Save the day with gevent Пишем свой веб-сервер на Python: процессы, потоки и асинхронный I/O Truly optional scalar types in protobuf3 (with Go examples) Node.js Readable streams distilled How to on starting processes (mostly in Linux) Дайджест интересных ссылок – Июль 2016 Пишем свой веб-сервер на Python: сокеты Наследование в JavaScript Мастерить!
Node.js Writable streams distilled
Ivan Velichko · 2019-04-07 · via Ivan on Containers, Kubernetes, and Server-Side

Table of contents

  • Foreword
  • Producer–consumer problem
  • Writable stream solution
  • Stream pipes
  • Conclusion

Foreword

Writable streams are an abstraction for a destination to which data is written... And this time it's a concise abstraction! Compared to vague readable streams (multiple operation modes behind single abstraction) writable streams implement only one mode and hence expose only one essential method write(chunk). Nevertheless, the idea of writable streams is not trivial and it's due to one nice feature it provides - backpressure. Let's try to wrap our mind around writable stream abstraction.

Producer–Consumer problem visualization.

Level up your server-side game — join 20,000 engineers getting insightful learning materials straight to their inbox.

Producer–consumer problem

Imagine we have two bound processes. The first process produces data (eg. reads data from a network or generates prime numbers, etc.) and the second process consumes it (eg. dumps data to a file). If we take a look at some moving time window over such pipeline we might observe 4 different situations:

  • Producing is slower than consuming.
  • Producing is as fast as consuming.
  • Producing is faster than consuming.
  • A mix of the options from above.

To organize the pipeline we need a buffer in between such processes. I.e. a spot in memory the data would be written to by the producer and later on would be read from by the consumer. If the producer is no faster than the consumer, we would need to prevent consumer's attempts to read from the empty buffer, i.e. pause the consumer once the buffer is empty. If the consumer is no faster than the producer we would need to prevent buffer overflow, i.e. pause the producer every time the buffer is full. The described situation is a classical producer-consumer problem.

The model below tries to visualize all the major cases.

[see sources on github]

Writable stream solution

It turns out that Node.js writable streams are just such consumers with built-in buffers. I.e. a writable stream is a process consuming data from its FIFO queue. Writable streams also provide mechanisms to notify the producing counterpart about both - the buffer overflow and the buffer got some spare space situations.

Right after the creation, the writable stream is idling. Once the first chunk is added to its queue, the writing process is resumed and the internal abstract _write(chunk, encoding, callback) method is called. Once the implementation of the _write() method calls the provided callback indicating that the chunk is consumed, the writing process repeats its consumption loop. However, if the buffer is empty the process starts idling again.

The size of the buffer is specified by the highWaterMark option. When the client code (i.e. the producing part) writes a chunk to the writable stream, method write(chunk) returns a hint about the state of the internal buffer. When after the writing some free space still remains, the returning value must be true indicating the client is free to write one more time. However, if the buffer is full after the current write() invocation, the returning value must be false indicating the need for backpressure. For better or worse, the returning value of the write() method is advisory. If the producer doesn't (or can't) respect it, the writable stream will continue buffering chunks, but this might lead to memory overconsumption.

If the producer got false from write(chunk) it experiences backpressure, i.e it should pause itself. However, we need a way to resume it as soon as there is free space in the consumer's buffer. For this purpose, the writable stream emits 'drain' event every time it pulls data from the overflowing internal buffer (see the visualization above). The producer should resume writing to the writable stream after receiving 'drain' event.

Stream pipes

While it's possible to use writable streams on them own, the most powerful way is to use them in conjunction with readable streams. Pipe-ing of a readable stream to a writable stream is basically a way to gracefully hide all the integration details (and some error handling) behind a single method call. When one pipes a readable stream to a writable:

  • The writable subscribes to 'data' event leading the readable to start emitting data.
  • The readable binds its resume() method (not completely true) to the 'drain' event.
  • When on 'data' the readable receives false from write(chunk) method it pauses itself.
  • As soon as there is a free space in the buffer, the writable emits 'drain' leading to resuming of the readable.

Conclusion

We can see that during piping a readable stream operates in the flowing mode. As we already know it means that no internal buffering on the readable side is happening. Hence, the writable stream is doing all the heavy lifting in the implementation of the producer-consumer pipeline.

Level up your server-side game — join 20,000 engineers getting insightful learning materials straight to their inbox: