SlideShare verwendet Cookies, um die Funktionalität und Leistungsfähigkeit der Webseite zu verbessern und Ihnen relevante Werbung bereitzustellen. Wenn Sie diese Webseite weiter besuchen, erklären Sie sich mit der Verwendung von Cookies auf dieser Seite einverstanden. Lesen Sie bitte unsere Nutzervereinbarung und die Datenschutzrichtlinie.
SlideShare verwendet Cookies, um die Funktionalität und Leistungsfähigkeit der Webseite zu verbessern und Ihnen relevante Werbung bereitzustellen. Wenn Sie diese Webseite weiter besuchen, erklären Sie sich mit der Verwendung von Cookies auf dieser Seite einverstanden. Lesen Sie bitte unsere unsere Datenschutzrichtlinie und die Nutzervereinbarung.
node.js and Containers: Dispatches from the Frontier
node.js and Containers:
Dispatches from the Frontier
Application architecture, circa 2000
• The late 1990s saw the rise of three-tier architectures consisting
of presentation, application logic and data tiers
• Many names for roughly the same notion: “Service-oriented
architecture”, “Model/View/Controller”, etc.
• The AJAX+REST revolution of the mid-2000s gave rise to true
web applications in which application logic could live on the edge
• Led to some broader architectural questioning...
• Why should HTTP be restricted to the web?
• Why should REST be restricted to web apps?
• Instead of having one monolithic architecture, why not have a
series of (smaller) services that merely did one thing well?
• In case this sounds vaguely familiar...
The Unix Philosophy
• The Unix philosophy, as articulated by Doug McIlroy:
• Write programs that do one thing and do it well
• Write programs to work together
• Write programs that handle text streams, because that is a
• The single most important revolution in software systems thinking
• Applying it to HTTP-based services...
• Microservices do one thing, and strive to do it well
• Replace a small number of monoliths with many services that
have well-documented, small HTTP-based APIs
• Larger systems can be composed of these smaller services
• While the trend it describes is real, the term “microservices” isn’t
without its controversy...
• node.js is a perfect ﬁt for microservices:
• Light memory footprint
• Purely asynchronous
• Expresses Unix programming model with respect to the
operating system (processes, pipes, ﬁles, sockets, etc.)
• Module approach encourages libraries over frameworks
• node.js is itself an expression of the Unix philosophy
• Microservices are tautologically small
• One physical machine per service is clearly uneconomical…
• ...but deploying many orthogonal services on a single machine is
a well-known operational nightmare (e.g. conﬂicting
dependencies, shared fault domain)
• The key is to virtualize — but at what layer of the stack?
• Virtualization has ramiﬁcations with respect to performance and
density — which is to say, economics
• The historical answer to virtualization — since the 1960s — has
been to virtualize the hardware:
• A virtual machine is presented upon which each tenant runs an
operating system that they choose (and must manage)
• There are as many operating systems on a machine as tenants!
• Can run entire legacy stacks unmodiﬁed...
• ...but operating systems are heavy and don’t play well with others
with respect to resources like DRAM, CPU, I/O devices, etc.
• With microservices, overhead dominates!
• Virtualizing at the application platform layer addresses the
tenancy challenges of hardware virtualization, and presents a
much more nimble (& developer friendly!) abstraction...
• ...but at the cost of dictating abstraction to the developer
• This is the “Google App Engine” problem: developers are in a
straightjacket where toy programs are easy — but sophisticated
applications are impossible
• Virtualizing at the application platform layer poses many other
challenges with respect to security, containment, etc.
• Virtualizing at the operating system hits a sweet spot:
• A single operating system (i.e. a single kernel) allows for efﬁcient use of
hardware resources, maximizing tenancy and performance
• Disjoint instances are securely compartmentalized by the operating system
• Gives tenants what appears to be a virtual machine (albeit a very fast one)
on which to run higher-level software: PaaS ease with IaaS generality
• Also: boots like a bandit!
• Model was pioneered by FreeBSD jails and taken to their logical
extreme by Solaris zones — and then aped by Linux containers
OS-level virtualization at Joyent
• Joyent runs OS containers in the cloud via SmartOS — and we
have run containers in multi-tenant production since ~2006
• Adding support for hardware-based virtualization circa 2011
strengthened our resolve with respect to OS-based virtualization
• This is especially true for microservices: as services get small,
overhead and latency become increasingly important — and OS
containers become a bigger and bigger win
• Our belief in containers for microservices comes from our own
experience in developing cloud management software...
SmartDataCenter as microservices microcosm
• SmartDataCenter is our cloud orchestration system
• Reﬂects its times: born in ~2006 as a Rails app; by late 2011,
consisted of some node.js microservices + a Ruby monstrosity
• In 2012/2013, we rewrote SmartDataCenter to be entirely node.js-
based, microservices-based and container-based
• Open sourced in November 2014: https://github.com/joyent/sdc
• Learned many things along the way — some more surprising than
Microservices: State management
• While decentralization is an important tenet of microservices, be
careful about applying this to canonical state
• State should be offered through its own microservice that can be
rigorously developed, tightly controlled, closely managed, etc.
• To this end, we developed Moray, a node.js-based key/value
store backed by replicated Postgres
• Moray’s Postgres replication is managed (and automated) with
Manatee, a node.js + ZooKeeper-based system
• Essentially all of our services are backed by Moray + Manatee
Microservices: Deployment + conﬁg
• With their larger numbers, microservices will exacerbate any
deployment, conﬁguration or image management pain
• To alleviate this, we developed our own services API (SAPI) —
but the results were still dissatisfying...
• A little-known PaaS called dotCloud saw the same problem and
developed a container-based solution for image management...
• Docker allows developers to encode deployment procedures via
an image that can in turn be deployed as a container
• Docker will do to apt what apt did to tar
Microservices: CAP omnipresence
• Some malcontent towards microservices may stem from the
breathlessness of some of its proponents, especially with respect
to resilience and reliability
• Microservices make your system more distributed — and
therefore more vulnerable to its CAP tradeoffs
• More monolithic systems are able to hide from CAP — or are
deliberately C+A systems
• It’s not just CAP: performance pathologies can be much more
difﬁcult to understand in a distributed system
Microservices: System topology
• Our system is historically an AMQP/HTTP hybrid
• The principles of AMQP are very attractive…
• ...but in practice, implementation and operational issues have
made message brokers a single point of failure
• We still use AMQP for some kinds of broadcast trafﬁc, but we try
to go point-to-point and HTTP as quickly as we can
Microservices: Service discovery
• Moving from monolithic to microservices means moving from
tightly coupled to a loosely federated system — and necessitates
• We developed Binder, a node.js-based DNS + ZooKeeper system
• While Binder has been sufﬁcient for our needs, service discovery
remains broadly a thorny problem — especially around rollbacks,
service maintenance, etc.
Microservices: Interface primacy
• Microservices have many more interfaces — so interface-based
pathologies will naturally become more acute
• ...and JSON-based systems can exhibit interface-based pathologies
not seen in more rigid systems
• We use JSON Schema (v3) to add rigor without sacriﬁcing agility
• We implement HTTP routes with Restify, a node.js module that
includes support for interface versioning (+ DTrace support!)
• Postel’s Law (“...an implementation should be conservative in its
sending behavior, and liberal in its receiving behavior”) remains
helpful, but apply with moderation!
Microservices: Pathological behavior
• Systems will misbehave — and distributed systems have much
more surface area; hope is not a strategy!
• We have invested heavily in node.js-based infrastructure to allow
us to quickly diagnose aberrant behavior in production:
• Bunyan is a logging facility for node.js (+ DTrace support!)
• SmartOS DTrace support for node.js proﬁling
• See @dapsays’ “Industrial-grade node.js” talk!
• OS containers have made our microservices approach possible
• They have proven essential for every aspect of our system: speed
of deployment, robustness, latency, debuggability, etc.
• Historically, our approach has been limited to SmartOS...
• While SmartOS is Unix, it’s not Linux — and we understand that
many (most?) have an established Linux binary footprint...
• We have implemented support for LX-branded zones in SmartOS
that allow for Linux binaries (and distributions!) to run out-of-the
box in a secure OS container
Microservices, containers and node.js
• Microservices represent a real and important trend in systems
• We have found node.js to be the perfect ﬁt for implementing these
systems — especially given its production debugging support
• Containers have been an essential ingredient for our own
deployment of microservices-based architectures
• LX-branded zones will allow our microservices approach to be
applicable to a much broader audience!
• @mcavage, @pfmooney, @dapsays, @yunongx, @tumederanges for
• @dapsays and @tjfontaine for bringing humanity debugging support for
node.js in production
• @trentmick for Bunyan (https://github.com/trentm/node-bunyan)
• @trevero, @notmatt for Binder (https://github.com/joyent/binder)
• @joshwilsdon for much of SDC — and for being right about AMQP
• Jerry Jelinek, @pfmooney, @jmclulow and @jperkin for their work on