MongoDB Best Practices »
Created at: 20.12.2011 21:30, source: Engine Yard Blog, tagged: Technology
When the team was formed earlier in the year, our first job was to expand our stack with MongoDB. However, we felt it would be a disservice to you, our customers, if we added a NoSQL datastore into the stack without first updating the relational databases that we support. So, we decided to pause MongoDB development to update both MySQL and PostgreSQL. As of today, MySQL 5.5 has gone into Beta, PostgreSQL 9.1 Beta is coming soon, and we plan to GA both releases in Q1 2012.
As we focus more on MongoDB, we have assisted several customers with custom MongoDB environments. During this process we discovered a variety of potentially problematic settings. So, we wanted to take this opportunity to share Engine Yard’s best practices for MongoDB.
If you have a custom installation of MongoDB, please make sure to check your installation against this post. We recommend that you make changes as necessary. If you need help (until we offer Mongo in our product), our Professional Services organization can lend you a hand.
General NoSQL best practices
Many articles have been written to address the NoSQL selection process. Factors that influence your choice of database deal with your application’s needs when it comes to: read/write throughput, durability, consistency of data, latency, etc. This criteria is nicely summarized by Nathan Hurst in his “Visual Guide to NoSQL Systems”.
Selecting the right NoSQL database is beyond of the scope of this post, but please do your research. It will pay off in the end as no single solution fits all scenarios. This article assumes that your research has led you to choose MongoDB for your application. We at Engine Yard recommend that you:
Test exhaustively
Don’t assume that what worked for your RDBMS will translate
Think about the consistency and durability needs of your data.
Understand what to expect from EBS volumes
MongoDB Best Practices
Here are the guidelines we follow as we work on releasing MongoDB into our stack.
Always use replica sets
Keep current with versions
Don’t run MongoDB on 32-bit systems
Turn journaling on by default
Mind the location of your data files
Your working set should fit in memory
You have two options when your data exceeds your available RAM: increasing the size of your MongoDB instance or sharding. We recommend increasing instance size first.
Scale up if your metrics show heavy use
Be careful when sharding
Sharded installations require careful understanding of your application’s data access patterns. Please take the time to understand how MongoDB sharding works and if you really need it. Also remember that selecting a good sharding key is important as it will affect your performance.
Config servers are critical to the health of your cluster. You MUST have 3 configuration servers in a sharded production environment. NEVER delete their data, always make sure you back them up frequently, and refer to them, if you can, by name using an /etc/hosts file (this will make your cluster more resilient).
Config servers are light processes but they must also live on 64-bit instances. Don’t put all 3 config servers in the same instance! You can schedule a consultation with Engine Yard Professional Services if you are considering a sharded install.
Use Mongo MMS to graphically monitor your service
Keep up with MongoDB resources
- Documentation: http://www.mongodb.org/display/DOCS/Home
- Google Group: http://groups.google.com/group/mongodb-user
- Bugs: https://jira.mongodb.org
- Blog: http://blog.mongodb.org/
Want to hear more? Give us feedback!
more »
Zero Downtime Deploys with Migrations »
Created at: 13.12.2011 22:30, source: Engine Yard Blog, tagged: ruby Technology
I gave a talk at RubyConf that went over how we automate our development and deploy process here at Engine Yard. The part of the talk that got the most questions and spawned the most discussion was about the way we do deploy with zero downtime, even with migrations. Here is a bit more detail on the process.
A Caveat
At Engine Yard, we almost exclusively use DataMapper for our ORM. This means that we specify all of the properties for our models in the model class, there is no database introspection to generate accessors for the properties. I have not tried this technique with ActiveRecord but the concepts will be the same.
Example: Adding a column
This is the simplest example, but also the most common migration that we do.
First, before merging any part of the feature to master that needs a new column, create a migration on master that adds the column.
migration 1, :"add published_at to posts" do
up do
modify_table :posts do
add_column :published_at, Time
end
end
end
Then we simply test the migration, and ship it all the way to production. Now the column is created in the database—ready for us to use when we merge the code that requires the column.
This also allows us to always run migrations last in the deploy, after we have restarted the app servers. This means that new code is running on the app servers earlier in the deploy process.
Renaming a Column
Adding a column is pretty straightforward but there are some migrations that are much trickier to do with zero downtime.
Lets say you have a Post model, and you want to rename the body field to content.
We have a solution for this as well.
Step 1: Add the new column
Same as above, write and deploy the migration to add the new column to the database.
migration 1, :"add content to posts" do
up do
modify_table :posts do
add_column :content, Text
end
end
end
Step 2: Make the code aware of both columns
We usually do this by writing the code as if we were solely using the new column, then having a few accessors and hooks on the model to sync the data over.
class Post
def content
update_content
attribute_get(:content)
end
def content=(new_content)
self.body = new_content
attribute_set(:content, new_content)
end
before :save, :update_content
def update_content
self.content = body
end
end
Step 3: Migrate the data
Now that your code is handling the migration of data as it runs, we need to migrate all columns to the new schema.
We can either use a migration for this or just write and run a rake task to copy all data from the body column to the content column.
Once this step is complete, the content column should be canonical and remain that way due to the way the code is written.
Step 4: Remove the temporary syncing code
We can now remove all references to the body column, including the code that syncs the data between the two columns.
At this point, we are almost done. The code is all updated not to use the old column; it only remains in the database.
Step 5: Drop the column
Finally, all we need to do is write a migration to drop the column from the database and deploy it to production. The code does not reference the column, so we can deploy it at our leisure.
YMMV
This technique has worked very well for us at Engine Yard. It can be more complex, but overall it leads to less friction in the deploy process. When you know that there is no downtime needed for any step of your work, you can simply write code and ship it to production when you're ready, rather than being blocked on waiting for a maintenance window.
Adding a column to the database is by far the most common kind of migration that we do. And using this technique still makes that very simple. Over all it has not added a significant amount of overhead to getting things done, and the lack of friction is a huge win.
Doesn't always work
All this said, there are a small number of cases when you really cannot perform this technique. These are cases where the migration will take a long time and lock tables or cause heavy load on the database server. In the past year, these kinds of migrations have been the only ones that we have had to take downtime for. The most common manifestation was adding an index on a very large table. But if your database is heavily loaded, many ALTER TABLE statements may take an unacceptably long time.
more »
What Are Events, Why Might You Care, and How Can EventMachine Help? »
Created at: 08.12.2011 22:13, source: Engine Yard Blog, tagged: ruby Technology
You have likely heard of event based/driven programming, which you may also see referred to as "evented" programming. It has been around and in use for a long time, but it is seeing a growing swell of interest in recent years. Perl has had POE for years. Likewise, Python has had Twisted for quite a few years. Graphics toolkits such as GTK use event loops to respond to user interface events. Javascript has been getting a lot of attention lately because of the Node.js event driven framework. Ruby has had the EventMachine library since 2006, with other event driven programming libraries such as Rev and Coolio being released since then.
Despite this relative wealth of libraries, and growing interest in the event driven programming paradigm, this realm of software design is still shrouded in mystery and unknowns for many developers. People who are new to it tend to misunderstand it, often assuming magic that does not exist, or simply misunderstanding what "event driven" really means. Even developers with experience writing event based software using one of the previously mentioned libraries are often fuzzy on the details. They may assume that their library of choice represents the "real" world of event based programming. Or simply because their use cases only take them to a few familiar neighborhoods of evented programming, they may retain some of that newbie fog for other parts.
This series of articles is going to attempt to rectify some of those situations. The precise course of the articles will be determined as they progress, but for today, let's start at the beginning. Event Based/Driven Programming. It'a hot. All the cool kids are doing it. It's got EVENTS! Raise your hand if you truly know what that means, or why you should actually care.
Event–noun
- something that happens or is regarded as happening; an occurrence, especially one of some importance.
- the outcome, issue, or result of anything: The venture had no successful event.
- something that occurs in a certain place during a particular interval of time.
That quote was courtesy of http://dictionary.reference.com/browse/event
Applying that definition to the world of software is a pretty direct thing, as it turns out. Event based programming is nothing more than letting the flow of the program be determined by some set of events. Hardware interrupts are an example of a ubiquitous source of events. On Unix systems, signals and the signal handlers that deal with them are a type of event based programming, as well. A typical pattern for windowing systems is to operate with an event based model; the software can't know when one is going to click on a menu item, or a dialog button, so the software instead runs in a loop, waiting for some event to happen. When an event occurs, the software calls into another piece of code to handle that event.
At its simplest, that general pattern of the system being divided into a dyad consisting of one part that detects or selects events, with a second part that handles them, is what event based programming is actually about. If you have been programming for any length of time, the odds are pretty good that at least in some small ways, you have engaged in event driven programming even if you didn't realize it.
If you go back and look at any of those libraries that I mentioned at the top of the articles, you will notice a trend. Each of those libraries is an event driven programming library, but there is a fair amount of variation across them. This is because event driven is a vague label, encompassing numerous patterns and feature sets. One of the most common of these patterns is the Reactor pattern.
The Reactor pattern describes a system that handles asynchronous events, but that does so with synchronous event callbacks. There are several ruby implementations of this pattern, including the most common library for event based programming in Ruby today, EventMachine. A reactor is good at handling many concurrent streams of incoming our outgoing IO, but because the callbacks are invoked synchronously, callback handling can severely impact the concurrency, or apparent concurrency, of a reactor implementation. Nonetheless, reactors are easy to implement, and with a little care, can be used to drive high performance IO on a single threaded, single process application.
As I mentioned, EventMachine is a Reactor implementation. And it is perfectly possible to install EventMachine, look at a few documents and a few examples, and start writing your own event based software that uses it without really having a good idea of how the machine is running under the hood. But there is value in understanding what a Reactor actually is, so that you better understand what a library like EventMachine is doing for you. Ruby gives us a lot of tools that make it reasonably easy to write a very simple pure ruby reactor implementation, so let's do that. It should make this topic much clearer when you see how simple it actually is. All of the code shown below can also be found on GitHub at https://github.com/engineyard/khaines_blog_code_examples/tree/master/what_are_events. All of these pure ruby examples should work on every Ruby implementation. I have tried it on MRI 1.8.7_p352 and 1.9.3_p0, as well as JRuby 1.6.5 and Rubinius 2.0.0dev, though I did not extensively test on anything other than MRI 1.9.3, so quirks may exist.
For our pure ruby reactor, we want only a few features.
- Unlike EventMachine, which also includes substantial support for managing creations of network connections, servers, and other more sophisticated activities, our reactor is going to limit itself to only being a tool for handling events. Therefor, all that it needs is a way to attach and detach IO objects to/from the reactor. We'll use the built in ruby mechanisms for everything else.
- Ruby has the select() call available to it on all platforms, so our reactor will be designed to use it. The select() call returns readable handles, writeable handles, and errors from a set of filehandles to operate on, so those three events (
:read, :write, :error) will likewise be all that our reactor handles. - Timers are very useful, and are pretty easy to implement in a reactor, so it would be nice to have a timer implementation.
Even though it is not strictly necessary for a reactor implementation, I will start our implementation with the timer functionality. Timers are events which are time based. Their callback is triggered at some point after a given time threshold is reached. The difficulty with timers is in choosing a mechanism for storing them such that the ones which need to be triggered can be easily and efficiently detected. Time, however, is a sortable attribute, and there are some data structures that are great for storing sortable data where that sorted data order is important. There are tree based data structures which are very efficient at maintaining this sort of data. Ruby doesn't have one of those as a native data type, so for this example, I will just fake it. If I were writing a serious implementation, I would have to do more work to provide an efficient data structure for timer data. The following data structure is built on top of a hash, makes no claims to be efficient, and provides the bare minimum API for our reactor to have the tool that it needs to implement timers.
class SimpleReactor
class TimerMap < Hash
def []=(k,v)
super
@sorted_keys = keys.sort
v
end
def delete k
r = super
@sorted_keys = keys.sort
r
end
def next_time
@sorted_keys.first
end
def shift
if @sorted_keys.empty?
nil
else
first_key = @sorted_keys.shift
val = self.delete first_key
[first_key, val]
end
end
def add_timer time, *args, &block
time = case time
when Time
Time.to_i
else
Time.now + time.to_i
end
self[time] = [block, args] if block
end
def call_next_timer
_, v = self.shift
block, args = v
block.call(*args)
end
end
end
Ok. Now let's start writing a reactor! Since we started with timers, we'll just write enough to make timers work. So, first, an #initialize method, and a method to add timers.
class SimpleReactor
def initialize
@running = false
@timers = TimerMap.new
@block_buffer = []
end
def add_timer time, *args, &block
time = time.to_i if Time === time
@timers.add_timer time, *args, &block
end
There's nothing interesting with the initialization. It just sets the @running instance variable false. This will be used in an upcoming bit of code. The method to add a timer also does nothing special; it just passes everything into a method of the same name in the TimerMap. The next part that is needed is the skeleton of our reactor. Here is what it looks like:
def next_tick &block
@block_buffer << block
end
def tick
handle_pending_blocks
handle_events
handle_timers
end
def run
@running = true
yield self if block_given?
tick while @running
end
def stop
@running = false
end
def handle_pending_blocks
@block_buffer.length.times { @block_buffer.shift.call }
end
def handle_events
end
def handle_timers
now = Time.now
while !@timers.empty? && @timers.next_time < now
@timers.call_next_timer
end
end
def empty?
@timers.empty? && @block_buffer.empty?
end
end
There you have it. A reactor skeleton, albeit one that only supports timers and next_tick right now. Here's an example that uses it:
require 'simplereactor'
puts <<ETXT
This demo will add a sequence of numbers to a sum, via a timer, once a second,
for four seconds, with the fifth number immediately following the fourth.
1+2+3+4+5 == 15. Let's see if that's the answer that we get."
ETXT
n = 0
reactor = SimpleReactor.new
reactor.add_timer(1) do
puts "one"
n += 1
end
reactor.add_timer(2) do
puts "two"
reactor.add_timer(1, n + 2) do |sum|
puts "three"
reactor.add_timer(1, sum + 3) do |sum|
puts "four"
n = sum + 4
reactor.next_tick do
puts "five"
n += 5
puts "n is #{n}\nThe reactor should stop after this."
end
end
end
end
reactor.tick until reactor.empty?
There's no real magic here. The code shows that one can create timers, and can create new timers within the callback code of existing timers, leveraging Ruby's block syntax. If you run this, you will get output like this:
This demo will add a sequence of numbers to a sum, via a timer, once a second, for four seconds, with the fifth number immediately following the fourth. 1+2+3+4+5 == 15. Let's see if that's the answer that we get. one two three four five n is 15 The reactor should stop after this.
Take note of the last line in the example code -- reactor.tick until reactor.empty?. The reactor will not do anything until that line runs. That line sits in a loop, ticking our reactor repeatedly until there's nothing left for it to do. At that point, #empty? returns true, the loop terminates, and the program terminates.
The next step in this adventure is to add enough code to our reactor to do something useful with IO objects, as well. We need to be able to attach them to the reactor, detach them from the reactor, and put enough intelligence into the reactor to find events to respond to, and trigger the callbacks for those events.
First add a constant and some accessors, and change the #initialize method:
Events = [:read, :write, :error].freeze
attr_reader :ios
def self.run &block
reactor = self.new
reactor.run &block
end
def initialize
@running = false
@ios = Hash.new do |h,k|
h[k] = {
:events => [],
:callbacks => {},
:args => [] }
end
@timers = TimerMap.new
@block_buffer = []
end
This adds a hash for holding our IO objects. It has an initializer to hold an array of events that that the IO object will respond to, a hash of callbacks (potentially one per event type), and some set of args which can be passed to an invoked callback. A hash is also created to hold unhandled events, should they occur.
Next, let's add some methods to attach an IO object to the reactor, setup callbacks, and detach an IO object to the reactor.
def attach io, *args, &block
events = Events & args
args -= events
@ios[io][:events] |= events
setup_callback io, events, *args, &block
self
end
def setup_callback io, events, *args, &block
i = @ios[io]
events.each {|event| i[:callbacks][event] = block }
i[:args] = args
i
end
def detach io
@ios.delete io
end
The code takes an IO object, a set of args to pass into the callback, and a block. It adds it to the @ios hash, and sets up the callback for the given events.
Next, we need to add a few small methods to enable triggering on IO events.
def handle_events
unless @ios.empty?
pending_events.each do |io, events|
events.each do |event|
if @ios.has_key? io
if handler = @ios[io][:callbacks][event]
handler.call io, *@ios[io][:args]
end
end
end
end
end
end
The #handle_events method is straightforward. If there are any attached IO objects, iterate through the events, calling the callbacks for each. In the existing code, we should never have unhandled events, but by adding that now, one could take this library and expand it more easily into a larger pure ruby reactor that handles types of events other that just what select() uses.
def pending_events
# Trim our IO set to only include those which are not closed.
@ios.reject! {|io, v| io.closed? }
h = find_handles_with_events @ios.keys
if h
handles = Events.zip(h).inject({}) {|handles, ev| handles[ev.first] = ev.last; handles}
events = Hash.new {|h,k| h[k] = []}
Events.each do |event|
handles[event].each { |io| events[io] << event }
end
events
else
{} # No handles
end
end
def find_handles_with_events keys
select find_ios(:read), find_ios(:write), keys, 0.01
end
def find_ios(event)
@ios.select { |io, h| h[:events].include? event}.collect { |io, data| io } }
end
def empty?
@ios.empty? && @timers.empty? && @block_buffer.empty?
end
This last bit of code just adds the nitty gritty methods that figures out if there are any events that need to be handled. It removes from @ios any handles that are closed, uses select() to find IO events, and then returns a hash of IO objects and the events that have been triggered on them. String all of this code together, and it is all that you need to have a basic working Reactor pattern for event based programming, with timer support. Here's a trivial example that uses pipes, to illustrate how it works.
require 'simplereactor'
chunk = "01234567890" * 30
reactor = SimpleReactor.new
reader, writer = IO.pipe
reactor.attach writer, :write do |write_io|
bytes_written = write_io.write chunk
puts "Sent #{bytes_written} bytes: #{chunk[0..(bytes_written - 1)]}"
chunk.slice!(0,bytes_written)
if chunk.empty?
reactor.detach write_io
write_io.close
end
end
reactor.attach reader, :read do |read_io|
if read_io.eof?
puts "finished; detaching and closing."
reactor.detach read_io
read_io.close
else
puts "received: #{read_io.read 200}"
end
end
reactor.add_timer(2) do
puts "Timer called; the code should exit after this."
end
reactor.tick until reactor.empty?
All that code does is to open a pair of pipes. The reactor attaches to one end as a writer, and the other end as a reader. The callbacks are used to send data from one end of the pipe to the other, where it is received. The Reactor will run for two seconds, then after the timer runs, the reactor will be empty, and it will exit. It looks like this:
Sent 330 bytes: 012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890 received: 01234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001 received: 2345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890 finished; detaching and closing. Timer called; the code should exit after this.
Here's another example. This one takes user input through the reactor via STDIN, and at the same time runs the stupidest, simplest web server possible. That web server will return a response that includes whatever the user input. The example code is also written to leverage the #run method defined in the library instead of cranking it ourselves.
require './simplereactor'
require 'socket'
server = TCPServer.new("0.0.0.0", 9949)
buffer = ''
puts <<ETXT
Type some text and press after each line. The reactor is attached to
STDIN and also port 9949, where it listens for any connection and responds with
a basic HTTP response containing whatever has been typed to that point. These
two dramatically different IO streams are being handled simultaneously. Type
to exit, or wait one minute, and a timer will fire which causes the
reactor to stop and the program to exit.
ETXT
SimpleReactor.run do |reactor|
reactor.attach(server, :read) do |server|
conn = server.accept
conn.gets # Pull all of the incoming data, even though it is not used in this example
conn.write "HTTP/1.1 200 OK\r\nContent-Length:#{buffer.length}\r\nContent-Type:text/plain\r\nConnection:close\r\n\r\n#{buffer}"
conn.close
end
characters_received = 0
reactor.attach(STDIN, :read) do |stdin|
characters_received += 1
data = stdin.getc # Pull a character at a time, just for illustration purposes
unless data
reactor.stop
else
buffer << data
end
end
reactor.add_timer(60) do
reactor.stop
end
end
When this is executed, it attaches to STDIN, allowing one to provide input which is buffered internally. Any connection to port 9949 returns a simple HTTP response that contains the buffer that was created through STDIN. The process will run for 60 seconds, then the reactor will stop. Bearing in mind that this is a ridiculously trivial example, it does perform pretty well, too. Below is an excerpt from a test run, done using Ruby 1.9.3_preview1, on one of my older Linux machines.
Concurrency Level: 25 Time taken for tests: 1.60504 seconds Complete requests: 15000 Failed requests: 0 Write errors: 0 Total transferred: 1275000 bytes HTML transferred: 75000 bytes Requests per second: 14144.22 [#/sec] (mean) Time per request: 1.768 [ms] (mean) Time per request: 0.071 [ms] (mean, across all concurrent requests) Transfer rate: 1173.97 [Kbytes/sec] received
Of course, this is an absurdly trivial example. There may be bugs, and it doesn't really do a lot for you, but it is an event reactor, written in pure ruby, and if you went through the code and examples as you read, you should have a better feel for what a reactor truly is.
If you want to write more sophisticated event based software, you could continue using a simple hand-rolled pure ruby reactor like this one, or you might choose to use one of the other common libraries for Ruby today. There are several of them, each with their own strengths and weaknesses, though the most common is EventMachine. Just like our simple reactor, EventMachine offers timers and asynchronous handling of events, though EventMachine's versions will scale better. This article's version uses the select() call, which limits code using it to 1024 open file descriptors. On the other hand, EventMachine, if used on a platform that support epoll (Linux) or kqueue (various *BSD platforms), can readily support at least 10s of thousands. EventMachine also offers a more rich set of features for implementing event based code than this article's example reactor. As a parting example, here is the HTTP server example from above, written to use EventMachine.
require 'rubygems'
require 'eventmachine'
module ServerHandler
def initialize(buffer)
@buffer = buffer
super
end
def receive_data data
send_data "HTTP/1.1 200 OK\r\nContent-Length:#{@buffer.length}\r\nContent-Type:text/plain\r\nConnection:close\r\n\r\n#{@buffer}"
close_connection_after_writing
end
end
module KeyHandler
def initialize buffer
@counter = 0
@buffer = buffer
super
end
def receive_data data
@counter += 1
if data.chomp.empty?
EM.stop
else
@buffer << data
end
end
end
puts <<ETXT
Type some text and press after each line. The reactor is attached to
STDIN and also port 9949, where it listens for any connection and responds with
a basic HTTP response containing whatever has been typed to that point. These
two dramatically different IO streams are being handled simultaneously. Type
a blank line to exit, or wait one minute, and a timer will fire which causes the
reactor to stop and the program to exit.
ETXT
buffer = ''
EventMachine.run do
EM.start_server('0.0.0.0',9949,ServerHandler,buffer)
EM.attach(STDIN, KeyHandler, buffer)
EM.add_timer(60) do
EM.stop
end
end
And since I demonstrated the performance of the pure Ruby version, here's the performance of the EventMachine version (using EventMachine 0.12.10), running on the same system, using the same Ruby 1.9.3_preview1 installation.
Concurrency Level: 25 Time taken for tests: 0.696320 seconds Complete requests: 15000 Failed requests: 0 Write errors: 0 Total transferred: 1275425 bytes HTML transferred: 75025 bytes Requests per second: 21541.82 [#/sec] (mean) Time per request: 1.161 [ms] (mean) Time per request: 0.046 [ms] (mean, across all concurrent requests) Transfer rate: 1787.97 [Kbytes/sec] received
The code is structured differently, but as you can see, it works similarly. In our simple reactor example, if you changed data = stdin.getc to data = stdin.gets, the STDIN handling would behave similarly to the EM examples STDIN handling. However, given the experience of writing a pure ruby reactor, even if you have never used EventMachine before, I think you can now look at that piece of EventMachine code and generally understand how it works, both at the level of the ruby code itself, and with a good idea of what EventMachine is handling for you. This basic understanding of how event driven software actually works is key to writing software that uses the event paradigm effectively.
I have focused on EventMachine in this article because it is the most commonly used event reactor implementation in the Ruby world today. As I mentioned at the beginning of the article, however, there are other choices, such as Coolio. In future articles I will continue to focus on EventMachine, but I will try to include some examples from other frameworks, and also some examples focused on JRuby and Rubinius. Please let us know if there are particular topics that you would like to see discussed.
more »
Improved DB Slaves, with love from EY PDX »
Created at: 03.12.2011 02:21, source: Engine Yard Blog, tagged: Product Technology
It may be cold and rainy but our database enhancements are hot!
We’re happy to announce that Engine Yard Cloud database support just got better! We’ve made several database functionality improvements that make scaling your application easier than ever. You can now provision slave instances that are smaller or larger than your database master. Also, you have new snapshot and volume options when creating database slaves. You can provision slaves with a larger storage volume than their master, and soon you’ll be able to use an existing snapshot to speed up slave creation.
Larger DB Volumes for Database Slaves
It is now possible to provision a database slave with a larger volume size than your db master. This, again, makes it easier to upgrade to a larger db master (or specialized slave!).
There is a caveat with regard to db volume increases: the db partition needs to be re-sized after the instance boots. If your stack is up-to-date, this will happen automatically. If not, you can click ‘Upgrade’ or have support enlarge the db partition for you.
Larger Instance Sizes for Database Slaves
It is now possible to provision a database slave using a larger AWS instance size than its current master. This lets you add a beefy slave, allowing you to get one step closer to that larger database master you’ve always wanted.
There are some restrictions (it is the real world, after all). When using PostgreSQL you can't use a snapshot created on a 32-bit instance when building a 64-bit instance and, vice-versa. Don’t worry, we won’t let you accidentally make a mistake. The instance sizes you are offered are the ones that will work with your database master.
Smaller Slaves Also Possible
Save $$! You can now boot a database slave using a smaller instance size than the database master. This is particularly handy if you just want a smaller slave to back-up from, but not serve reads or be a candidate for failover.
Not all combinations work equally well, however. We don’t recommend creating a Small replica for a High Memory 4XL. Here are our recommendations for minimum sizes. Please refer to the documentation for more information.
|
Master |
Minimum Recommended Replica |
|
Small |
Small |
|
High CPU Medium |
Small |
|
Large |
Small or High CPU Medium |
|
High Memory XL |
Large |
|
XL |
Large or High Memory XL |
|
High CPU XL |
High Memory XL, Large, High CPU Medium |
|
High Memory 2XL |
High Memory XL or XL |
|
High Memory 4XL |
High Memory 2X |
PDX Update
We hope you are as excited as we are about these new features. The PDX team worked tirelessly to get this very important feature out in record time. Speaking of PDX! We just passed our three-month anniversary at the new office space on December 1st. It’s been a very busy few months, with a steady stream of visiting SF developers, designers, and guests dropping in to work from the comfort of our couches.
We’re still looking to round out the PDX office with a couple of stellar support peeps. Support Engine Yard style, aka people who are passionate about web technology, love to solve different problems, and get pleasure in helping others. We (PDX developers) are particularly looking forward to having support staff on site, to easily chat about what our customers might most want and need.
more »
Introducing Node.js and Engine Yard Labs »
Created at: 18.11.2011 00:55, source: Engine Yard Blog, tagged: Engine Yard Cloud ruby Technology
This is an exciting day for us. Engine Yard, the leading platform-as-a-service for Ruby on Rails and PHP—has learned a new trick. You can now run your Node.js apps on Engine Yard Cloud!
Node.js
Starting today, Engine Yard is enabling early access support for Node.js applications on Engine Yard Cloud. Node.js is a popular event-driven framework written in JavaScript that is ideal for low-latency, real-time applications.
Node.js has a growing, active and self-motivated community that reminds us of the time when we started with Ruby. We love that energy, and so do our customers.
Every Engine Yard Cloud customer—including Free Trial customers—will now be able to take advantage of Node.js features. This feature is being delivered to you through a new program called Engine Yard Labs.
Engine Yard Labs
Engine Yard Labs allows users to try out experimental new features and capabilities on the Engine Yard platform. Engine Yard Labs will accelerate the pace of innovation by involving you, the user, in the vetting of new ideas. By actively taking in your feedback, we will be able to rapidly decide and act on the most promising features for Engine Yard products.

The features released through Engine Yard Labs are not officially supported and may or may not become supported as a part of Engine Yard products in the future. Our goal is to innovate jointly with you, harvest the most compelling features and make them generally available as quickly as possible. We hope you enjoy the process and benefit from the results!
How to access Node.js
Go to the Early Access Docs Page, and request access to Node.js.
Node.js in a few minutes
If you’re new to the Node.js world, let us explain the minimum required pieces that you’ll need to assemble a new application.
- An application source file called “app.js”. or “server.js” A simple example using also the web framework Express looks like this:
var express = require('express'); var app = express.createServer(); var port = process.env.PORT || 3000; app.get('/', function(request, response) { response.send('Hello Engine Yard Cloud!'); }); app.listen(port);We pass through the internal port number via `process.env.PORT` for your application to listen on.
- An application and dependency descriptor called “package.json”. We use it internally to install your Node.js dependencies via the great npm packaging system. A simple application descriptor that has the web framework Express as a dependency looks like this:
{ "name": "nodeApplication", "version": "0.0.1", "dependencies": { "express": "2.5.0" } } - Store the application in a hosted git repository, just like you’re already doing with your current Engine Yard Cloud applications. Feeling a little lazy? Try a demo Node.js app we made earlier for you. With this you’re ready to deploy your first Node.js application on Engine Yard Cloud. Go to your dashboard and create a new app. This time, select Node.js in the application stack drop-down menu. Fill out the form with the information about your application, create a new environment, and deploy your app.
Perhaps now try an example that uses WebSockets.
You can read more about Node.js on Engine Yard Cloud in our documentation.
Pssst
If you're feeling more adventurous, follow this screencast and give other experimental features a try.
more »

