Tip:
Highlight text to annotate it
X
Our next topic is to talk about the shared- nothing architecture
that substantially all internet systems used today and what that
means for scalability. Going back to our diagram, we started out
at the top level asking about the connection between clients and
servers. Now, we're going to go one level deeper and look inside
the server box to see what it's made up of. As we'll see,
there's three major building blocks that servers are generally
composed of these days. There is the presentation tier or front
end, that's a web server like Apache or Microsoft IIS. There is
the application server. That's where the action is, it's where
your application code usually runs. We're going to be using one
called rack which supports application written in ruby. Then,
there's a persistence layer or storage layer or tier where data
that's permanently associated with your application like your
customer data would get stored, typically like a database. In
the old days, the web really began as a way for people to
exchange static documents, graphics and so forth and early web
servers had a pretty job. All they had to do was accept an
incoming TCP request, figure out which file to serve and get
that file back into the browser but very quickly it became the
case that the more interesting sites were actually more like
running a program and having the program generate the page you
saw. If you think about it, this is the case for things like e-
commerce sites where you visit a page, you search for some
products and what happens is a program has to get run to find
all the products matching your search criteria and build the
page on the fly just for you. Originally, people authored sites
like this by saying, well, HTML is what the browser consumes but
what we'll do is we'll find a way to stick a little bit of code
here and there into the HTML and that code is what's going to
create the content on the fly. It very quickly became clear that
the code was the interesting part. The code became the tail that
wags the dog, it sort of moved out of the web server into its
own home in the application tier. Now, we're going to look at
these different pieces and how they work and what are the
implications for architecture of software as a service. If the
site is really about running a program rather than about serving
a static file, well, when you're going to run a program, even if
it's from the command line, you have to worry about things like
how do you figure out which program to run so which URI coming
into the site, how do you map a URI into the right program or
subprogram, how do you pass arguments to that program? How do
you get the program to run on the server? What happens if
there's an error? Who cleans up after the program and provides
the error messages? All of these tasks have to be handled in
SaaS apps as well except that instead of running programs from
the command line or directly through a GUI, we're running them
as a the response to a request from a web browser. Because all
of this kind of functionality has to be taken care of no matter
what language you use and no matter what framework you use,
frameworks have evolved to support all of these common
activities so that you don't have to. Really, today, it's more
like you fill in the codes that's specific to your application
and all of these other details like mapping URI's to which piece
of code and how do you pass arguments from maybe stuff that the
user typed in, how do you pass those tier code, all of those
things are now taken care of by the framework, it saves a lot of
work. Now, even within the logical architecture where we said
that there's these three different tiers, that's just the
logical diagram. Another question is how do those things map
onto physical hardware. Now, in the case of the homeworks you're
doing in this course or when you're doing your own development
of your own SaaS applications, typically you'll have a single
machine that's hosting all of the pieces. This gray box here,
you can think of as your laptop and on that same machine, you're
running your own web browser which has things. You're running
some kind of a presentation tier and we're using Webrick which
is a really simple development web server that ships with rails
by default. It can only handle one user at a time so not great
for big sites but it's fine when you're developing your own
code. In purple, we have the application tier which has an app
server, rack that provides some of the machinery around allowing
your ruby code to run as part of the rail SaaS app. We have the
rails library itself which your code can use. Then, finally, we
have the storage tier where permanent data lives. Well, in
development mode, the only permanent data is data right on your
computer that you're using really for testing. We're going to be
using SQLite which has a very good name. It's like a SQL
relational database which we'll talk about more in the next few
segments but it'd so lightweight that only a single user at a
time can use it. This is the baby version of the setup that's
fine for one person developing and testing. When you move out
into a production environment, typically you'll see something
like this where you really have multiple copies of the entire
stack. You'll see that we've replaced Webrick with thin which is
a production quality, very fast, very lean front end
presentation tier. We have many copies, so to speak, of the
application stack that includes the presentation layer and our
application code. The reason we're able to do this, remember
that we said previously, HTTP is a stateless protocol. Every
request is truly independent. Well, if it's really true that the
only thing that ties together different request from the same
user is data that would be put into this persistence tier, then
we should be able to create multiple copies of the app to serve
many more users which should be able to direct incoming traffic
to anyone of those copies because they're all independent
request and rely only on the stored data to tie together request
from different users. This is in fact, exactly what's done. Now,
the reason it's a little bit more difficult why I haven't drawn
multiple copies of the database and I'm using McSQL as a stand
in here, the database is a little more tricky because as soon as
you have multiple copies of the database, that means there might
be a multiple copies of some data items. Now, there's the
problem of whether those copies can always be kept in sync if
there's multiple databases. That is an open problem and if
you've heard about the NoSQL movement or of NoSQL databases, it
is one of the problems they try to solve and we're going to try
to shed some light on what's difficult about solving that
problem momentarily. In this course, we're going to be using
Heroku for our deployment. They have a very similar environment
but they have custom engineered what they called Dynos which are
sort of a lightweight app servers that they can run. Each app
also has databases devoted to it. It's got database caching
built in so that commonly done database queries can be easily
repeated and they have their own technology for a bank of
presentation tiers, HTTP servers so that they can scale those
out separately from the application servers but the basic idea
that were coming back too is the same. The stateless parts of
the sac like the presentation tier and the app tier can
essentially be scaled out by making many copies of them. With
cloud computing, it's so cheap to have multiple machines that is
is a very popular strategy but sooner or later, the database is
likely to become your bottleneck and scaling that out is much
more tricky which we'll come back to in a moment. What do people
do when it's time to scale out the database? If you've heard the
term sharding and replication, one thing you might say is, well,
if I have some data elements that are really not shared across
different users, for example, my personal preferences, my user
profile in a site like my Yahoo, well, one possibility is I
could actually have multiple databases and users who's user name
start with different letters might be stored in different
databases. Now, that works really well as long as you never need
to combine information from two of those databases and then
things can get pretty hairy but this is called sharding and the
idea that if you have some data that really never has to
interact with other data from different users or from different
entities in your application, you could just store that data on
different databases. Replication is another solution. This says,
well, why don't be have many copies of the database and only one
copy accepts updates because the idea that updates happen less
frequently than queries and periodically, the updates will get
propagated to the other copies. This is often called Master
Slave Replication and it's one way to do this. What kind of data
is it the case that reads occur much more frequently than
rights? Well, think about Facebook and the idea of posting on a
timeline or liking something, there's many more people who are
going to consume the results of that than people who are
updating it at any given time. Having some amount of
inconsistency actually has been an issue for Facebook that
they've done a lot of engineering to work around. It is the case
that if you do an update to your timeline, there's a bounded
amount of time during which not all of your friends will see it
right away. They'll see it at slightly different times. Now, to
their great credit, Facebook has done an enormous amount of
engineering to minimize that window so they did practice most
people never even notice it. The message here is there's no free
lunch. If you try to scale your way out of the database problem
by replicating, you're going to have the issue at some point
where different copies of the data might not all be up to date.
If you try to get out of it by sharding, you avoid that problem
but now you have the problem of data that's in different
databases. It's really hard to combine and join together.
Neither one of this is the solution to the database scaling
problem and it arises directly from the fact that in this three
tier architecture, scaling where the data is is just hard to do.
To summarize the high points of the software to service
architecture, the browsers are the clients. They ask questions,
they make request to the servers. HTTP is the protocol that the
use and they use URIs and HTTP methods like get and post to name
what they want to do. HTTP is the request reply protocol so
everything begins with a client asking a question. Service can't
really push information to you pro- actively, they have to wait
the client to ask. Even in cases where it looks like the server
is pushing information, it's really usually just the client
asking over and over again. In modern SaaS applications, when
you make a request to a server, it's not going to serve you a
static file, it's going to generate some content on the fly for
you. HTML is the medium by which that content is encoded. CSS or
cascading style sheet is how we control its visual appearance
and because HTTP was designed a stateless protocol, cookies
allow the servers to track different clients and to keep track
of the same client coming back on multiple requests. There's an
important architectural trade off that was made here. The
architectural trade off is stateless means you can actually
scale out those middle tiers by replicating the app server or
replicating the presentation tier in a way that you can't really
do with the database. In retrospect, you could argue that even
those statelessness seems to introduce the complication of
requiring cookies on the hole that was a good architectural
choice because it allows parts of the application to be scaled
much more easily. Frameworks like rails and like Django and like
others, try to collect some of the common machinery necessary to
support SaaS apps like the machinery we've been talking about
and make it conveniently available to you so that not every new
program has to reinvent the wheel. Finally, the mapping between
these logical tiers and the shared- nothing architecture,
frameworks are responsible for giving you that too. They have to
identify where different functionality goes, how the framework
supports each piece and that's what we'll explore in the next
couple of segments.