Thin The Fast Ruby Web Server

[ruby]
원문 : http://www.infoq.com/news/2008/02/thin- ··· ebserver

Today Mongrel is the defacto Ruby webserver of choice (watch Zed Shaw's, creator of Mongrel, presentation from QCon London 2007) . But a new experimental solution is now available under the name of Thin. Thin glues together three Ruby web libraries:
  • The Mongrel parser (using Ragel) the root of Mongrel speed and security.
  • Event Machine, a simple event-processing Ruby library that makes it possible to write scalable network I/O process.
  • Rack, a minimal interface between web servers supporting Ruby and Ruby frameworks.
Marc-André Cournoyer made a presentation of Thin at latest Montreal on Rails showing the benefits of Thin.

The performance improvements can be significant with increases up to 25% for requests/s and around 15% less memory used,  although the speed is dwarfed by the time spent in Rails.
Since 0.6.1 version in January Thin supports listening to UNIX sockets as well as to TCP/IP sockets, making it even faster.





Images by Marc-André Cournoyer

Thin already supports most Ruby Web Frameworks Rails, Merb, Camping, Sinatra, Ramaze, Vintage, Swiftiply.
Thin is a 3 months old project and it is worth a try before a production release is out.
2008/04/14 10:44 2008/04/14 10:44
TAG. ,

Uninitialized Constant GemRunner Error When Using Ruby Gem

[ruby]
원문 : http://www.theirishpenguin.com/2007/12/ ··· y-gem%2F

Here’s the problem…

me@host:~$ sudo gem update
/usr/bin/gem:23: uninitialized constant Gem::GemRunner (NameError)

… which had us on the ropes more than on the rails for a while. Unusually googl’ing on this error provided no solutions.

What led to the situation was that we used the source install of rubygems on Ubuntu Gutsy (7.10) instead of using the rubygems in Ubuntu’s repository but then changed our mind and apt-getted the Ubuntu repository version. Surprise! Surprise! These 2 versions were conflicting a bit; leading to the above error. The workaround is pretty simple, just go to your /usr/local/lib section and delete the site_ruby directory (as this is the remnant of the rubygems source install and thus cause of the problem). This removes all the gems (that were downloaded by the original rubygems which we no longer want) off our system. Perhaps you want to simply move this directory first in case something goes wrong and you need to revert (eg. sudo mv /usr/local/lib/site_ruby /usr_local/lib/site_ruby_old).

Note: In case your not aware, /usr/local/* is the set of directories under which programs that you compile yourself get installed to by default. Generally the directories will start out pretty empty on a freshly installed Linux distro and then as you (if ever!) compile and install programs from source (eg. using ./configure && make && make install) then they end up under this directory. Also not that programs installed using apt-get (or via rpms on non-Debian systems) don’t get put here - they usually end up under the /usr/ directory itself (this varies a bit from distro to distro but what we’ve just outlined holds true for Ubuntu anyway).

Now, once your finished you should find that gem works. Do a ‘gem list’ and see if the above error is gone. If this doesn’t work you may need to ’sudo apt-get install rubygems’. Next up, we need to rebuild that gem directory that we deleted (site_ruby) with the apt-gotten rubygems (if apt-gotten is a real word!). To do this run

sudo gem update
sudo gem update –system

You will notice that the result of these commands means that /usr/local/lib/site_ruby is back and populated. This is where ruby likes to put it’s gem extensions. Finally reinstall rails with

sudo gem install rails

Hope this solution works for you! We’re still getting to grips with this rails stuff so if you find any glaring errors in this post please comment below to let us know.


2008/04/13 09:43 2008/04/13 09:43

Implementing ActiveRecord in Java

[리소스]
원문 : http://peterbacklund.blogspot.com/2007/ ··· ava.html

The ActiveRecord (AR) design pattern is very popular right now, forming the base of web application frameworks such as Ruby on Rails and the Groovy-based Grails. Martin Fowler defines the pattern as follows:

An object that wraps a row in a database table or view, encapsulates the database access, and adds domain logic on that data.

AR is very closely related to the concept of an Object-Relational Mapper (ORM), and is an alternative to the Data Access Object (DAO) and Repository patterns. In the latter two patterns, persistent data operations are separated from the domain object into one or more dedicated interfaces.

AR is very attractive if you want to build a more powerful domain model, as opposed to using it as a simple data container. It ties the most obvious domain logic into the domain object (namely CRUD), and opens up possibilities to write higher-level properties and operations on your domain objects.

It can also aid in normalizing the three-tier architecture, by which I mean avoiding the all too common situation where you have a request mapped to an object in the MVC layer, which calls the service layer, which initiates a transaction and calls the DAO layer, which calls the ORM, which stores the object in the database. It might be even worse - you may need to convert the bound request data from a form bean to a Data Transfer Object, both of which could be separate from the domain object. Normalizing this operation would mean binding request data to a domain object, which then stores itself.

So, building an ActiveRecord base class in Java means that at least the following methods must be implemented:

public class ActiveRecord<T> {
public static <T> T load(Long id) { .. }
public void store() { .. }
public void delete() { .. }
public static <T> List<T> findAll() { .. }
}

Derived classes will add all sorts of operations, notably a number of specialized finders with similar signatures to findAll().

In order to be able to access non-domain services we need a way to access external services, preferably through Dependency Injection. It's also mandatory that we are able to isolate the domain object for test purposes, and to be able to mock or stub dependencies, all of which is enabled by using DI.

It's also natural to use a full-fledged ORM - Java now has a standard API for that (JPA), and there are a number of different implementations available: Hibernate, TopLink, OpenJPA etc. There's also JDO, iBatis and of course you could also use plain JDBC if you really have to.

I've been using (surprise, surprise!) Hibernate as ORM tool, and Spring for DI and transaction demarcation, all of which are using annotations and build-time weaving using AspectJ and AJDT. Dependency injection of service beans into domain objects is taken care of by the @Configurable annotation, and transaction demarcation by the the @Transactional annotation, so those problems are very cleanly solved.

However
: static methods, such as loaders and finders, don't seem to be woven by transactional advice, at least not when using compile-time weaving. I need to investigate this further, but I believe it might be caused by the fact that a "this" joinpoint is being used here. Workarounds include writing transactional advice manually, using TransactionTemplate for example, or following the mixed AR/Repository pattern suggested below. The best solution would be to have an aspect that's able to read transaction attributes from annotations even in a static context.

The first roadblock is how to gain access to the ORM in a static context, the loader and finder methods. We need a reference to the unit-of-work (session) provider - the SessionFactory in this case - in order to create or obtain the current session for performing data operations. Since we don't have an instance of AR or a derived class, we can't access any injected SF reference.

I've thought long and hard about this, and tried a number of different approaches, but the way I see it, you basically have to give up either static loaders/finders or give up dependency injection. Any way you look at it, you will need some sort of static handle to the SF - you might make the SF member of the AR class static, or you could use some variation of SessionFactoryUtil, or maybe use some sort of lightweight holder object that's instantiated, injected and finally discarded as part of the static operation. The problem with static references, and the ServiceLocator pattern, is that you can't isolate objects completely - there can be only one implementation per class loader at a time, and all instances of a class with a static reference must share the same implementation. This makes testing harder and less robust, compared to a pure DI environment: you must make sure to "reset" the service locator reference after each test, even in case of failures, so you'll end up with a number of try - finally blocks everywhere, and you can't run tests in parallell since you can't guarantee what implementation the factory will return. (Crazy) Bob Lee talks a little about that in this Guice presentation.

So, as far as I can tell, you will need to give up DI, or at least mix DI and ServiceLocator in your application, if you want "pure" ActiveRecord. I'll be very interested if anyone can show a way to use AR and DI together, though :-). For now, I prefer a mix between AR and Repository, but more about that in a little while. If you decide to go for pure AR by using a static SF reference, your next problem will be how to tell the ORM which class to load, without adding redundant data in derived classes, such as overriding load() or keeping a static class member pointing to its own class.

When performing a load, you will need to know what class, or sometimes what table, to load the data from, in addition to the supplied identifier property. Optimally, the implementation of load() exists in the top class ActiveRecord only, and should return a correctly typed object. In short, we want to use the API like this:

Customer c = Customer.load(1);
Item item = Item.load(125);

where Customer and Item both inherit ActiveRecord.

Typing is taken care of by generics, as you can see a few paragraphs earlier. But since it's a static method, there's no "this" to ask for the current class, so finding the current class to feed to Session.load(id, clazz) is harder. There is no API access point in Java, and I've fiddled with various reflection hacks against sun.reflect.Reflections for example, to peek at the call stack, but to no avail. I did however find a way by using the "call" joinpoint in AspectJ and the following construct:

/*
* Keep the traditional load() signature as access point.
*/
public static <T> T load(Long id) {
throw new RuntimeException("This body should never be reached, weaving has not been performed");
}

/*
* This method performs an actual load.
*/
protected static <T> T doLoad(Long id, Class clazz) {
return (T) getSession().load(id, clazz);
}

/*
* This inner class aspect intercepts the call to load, and inspects the join point
* to determine what class the static call was made on, and reroutes the call to
* doLoad() with the correct class parameter.
*/
@Aspect
protected static class ClassIdentifier {

@Before("call (* load(Long)) && args(id)")
public T interceptLoad(ProceedingJoinPoint pjp, Long id) {
Class clazz = pjp.getSignature().getDeclaringType();
return ActiveRecord.doLoad(id, clazz);
}

}

So, if you are prepared to give up reliable replacement of the ORM interface reference, ActiveRecord is within reach. In fact, you might find that you rarely or never mock or stub something like the SessionFactory, but instead simply use a dedicated data source for testing which is loaded with test data. That's perfectly reasonable imo, if you work directly against the ORM API, but it gets a bit more complicated if you keep your own DAO layer around, tested separately from the domain object, and inject that into your domain objects instead.

If you want to go for pure DI, I would argue that it's reasonable to split CRUD operations between the domain objects and a shared "read only"-repository. Operations that work on an actual instance, such as user.store() or item.delete() (non-static by nature), are placed in the domain objects. But operations that result in one or more instances are retrieved according to various criteria, loaders and finders, are placed on a separate service. Those are the same methods that would be static in ActiveRecord.

This approach is DI-compliant, because each domain object instance has its own non-static reference to the ORM, and the Repository service also is injected with an ORM reference. The repository can be regarded as a third party, where you go to retrieve instances of domain objects. By clever use of generics, the amount of code can be kept low, and a single @Transactional annotation at class level on the implementation marks every method for execution in a read-only transaction.

interface Repository {
// Typing on the methods instead of the interface
// allows us to share this interface across the domain model
<T> T load(Long id, Class clazz);
<T> List<T> findAll(Class clazz);

// Various specific finders are added as they are needed.
Customer findByUsername(String username);
List<Item> findDeliveredItems();

// Some kind of generic query-object method might be added too
}

This distinction between instance-tied domain logic versus third-party is then extrapolated throughout the application.
2008/04/07 09:15 2008/04/07 09:15

RubyConf 2007 Presentations Now Online

[ruby]
주소 : http://rubyconf2007.confreaks.com/

Conference Schedule

Presenter(s) Title Time
Marcel Molina, Jr. What Makes Code Beautiful? 9:30am Nov 2
Jim Weirich Advanced Ruby Class Design 10:30am Nov 2
Nathaniel Talbott Why Camping Matters Rm 1, 1pm Nov 2
Shunichi Shinohara
Kiwamu Kato
Introduction to AP4R Rm 1, 2pm Nov 2
Nathan Sobo Treetop: Syntactic Analysis with Ruby Rm 1, 3pm Nov 2
Paul Brannan Avoiding Pitfalls in C Extensions Rm 1, 4pm Nov 2
Ben Bleything Controlling Electronics with Ruby Rm 2, 1pm Nov 2
Andrea O. K. Wright High Art on Top of Low-Level APIs: Building Games with Ruby Rm 2, 2pm Nov 2
Ryan Davis Hurting Code for Fun and Profit Rm 2, 3pm Nov 2
Eric Ivancich Ropes: An Alternative to Ruby's Strings Rm 2, 4pm Nov 2
Yukihiro "Matz" Matsumoto Town Meeting with Ruby Creator 7pm Nov 2
John Lam State of IronRuby 9am Nov 3
Thomas Enebo
Charles Nutter
JRuby: Ruby for the JVM 10am Nov 3
Evan Phoenix Rubinius 11am Nov 3
Ed Borasky Profiling and Tuning Ruby 1.8 Rm 1, 1pm Nov 3
Phil Hagelberg Tightening the Feedback Loop Rm 1, 2pm Nov 3
Eric Hodel Maximizing Productivity Rm 1, 3pm Nov 3
Francis Hwang Conversations vs. Laws Rm 1, 4pm Nov 3
Luke Kanies Essential Incompleteness in Program Modeling Rm 2, 1pm Nov 3
Bruce Williams
Rich Kilmer
Deployable Ruby Runtimes Rm 2, 2pm Nov 3
Michael Neumann Efficient Ruby to Javascript Compilation and Applications Rm 2, 3pm Nov 3
Laurent Sansonetti Mac OS X Loves Ruby Rm 2, 4pm Nov 3
Yukihiro "Matz" Matsumoto Keynote Address: Does Language Matter? 7pm Nov 3
Dr. Nic Williams Use Ruby to Generate More Ruby - RubiGen 9am Nov 4
David Chelimsky
Dave Astels
Behaviour Driven Development with RSpec 10am Nov 4
Jay Phillips Next-Gen VoIP Development with Adhearsion 11am Nov 4
William Bereza Enhancing Embedded Development with Ruby Rm 1, 1pm Nov 4
Kyle Maxwell JRuby in the Wild Rm 1, 2pm Nov 4
Ben Scofield Cleanliness Is Next to Domain Specificity Rm 1, 3pm Nov 4
Justin Gehtland Ruby and Identity: OpenID, CAS and Information Card Rm 2, 1pm Nov 4
Erik Hatcher solr-ruby: The Best Open Source Search Engine + Ruby Rm 2, 2pm Nov 4
Aaron Bedra Sploitin' with Ruby (Point, Click, Root) Rm 2, 3pm Nov 4

Ruby Central's Google Summer of Code Participants Rm 3, 1pm Nov 4
Andreas Erik Johan Launila Gecode/R
Jeremy McAnally DCov
Helder dos Santos Ribeiro A Recorder for FireWatir
Nick Sutterer Apotomo

Presenters retain full rights to the content of their presentations, and have released them under the Creative Commons Attribution-ShareAlike license, unless otherwise noted.

2007/12/26 09:03 2007/12/26 09:03

Interview: Peter Cooper on Rails, Entrepreneurship, and Developing on Linux 0

[ruby]
주소 : http://approachingnormal.com/2007/12/19 ··· neurship

Note: This is the first in a series of interviews I will be doing over the coming months.

Thanks for agreeing to do this interview. Can you tell us a little bit about yourself?

I’m Peter Cooper, a Ruby developer and author from the wild, barren north of England. I’m probably best known in the Ruby community for being the author of Beginning Ruby, published by Apress, as well as the editor of Ruby Inside, the most popular Ruby related weblog.

Your website lists you as a serial entrepreneur. Do you consider yourself a developer who happens to be an entrepreneur, or is it the other way around?

It tends to vary year by year! I’ll go through periods where I’ll happen to be developing more for other people, and others when I focus on my own projects. Having made a successful exit with two businesses in 2007, however, I’ve been leaning towards doing more for myself. I’m likely to drop the “enterpreneur” stick soon though, as it tends to be that I merely follow my nose and the business side of it just falls into place by itself. I’m more of a curious bumbler by nature.

When did you first discover Ruby on Rails?

Rails first came onto my radar in October 2004. It was reasonably primitive then but will still appealing. As such a nascent technology based on a relatively unheard-of language, I was more interested in poaching the ideas for my favorite language of the time, Perl, and began developing my own equivalent. I developed a whole application on my framework, but it was shaky and I decided to give Rails a try, while promising not to get too bothered about learning Ruby itself.

My first Rails application was for a client and I developed a whole photography site for them in perhaps a quarter of the time it would have taken me with Perl. At that point I was hooked, and I also began to venture into the Ruby on Rails IRC channel on irc.freenode.net which, at the time, was great fun. What was it about Rails that appealed to you?

The biggest selling points were the abstraction and the speed / ease of development. I pride simplicity and economy above all, so developing Web applications in Rails was an eye opener compared to the clumsiness of Perl (I mean, take a look at mod_perl sometime!).

What does your development toolset look like? (editor, browser, etc)

Up till now, my development environment has been under OS X. I’ve stuck with MySQL for a database engine throughout, merely because I know it so well by now. Firefox was my browser of choice on OS X until Leopard, but now I mostly use Safari as it’s come on in leaps and bounds. I use Textmate as my primary editor, although I don’t know how to use any of the macro / snippet features.. it’s really just a text editor with syntax coloring and a file list down the side for me. I like to keep things really simple with little to remember.

At the deployment end of the chain, I use Linux, nearly always Red Hat Enterprise or CentOS.

You recently announced (on Twitter) that you were switching to Linux for development work, while using OS X for everything else. Can you explain what led to that switch?

As with most Ruby and Rails developers, my applications all end up deployed on Linux machines. While open source technologies make it easy to jump between different flavors of UNIX, something about OS X’s “everything for everyone” approach irks me when it comes to doing development work. It’d be like taking my city car on the track or putting a race car on the streets.. you can do it, but it feels better to have separate cars for different situations. While I don’t find Linux particularly useful for graphics work and general day to day use, it feels like a more natural operating system for developing on at the command line level. With the minimalist dwm window manager, you can even get all of the GUI control at keyboard level, meaning you can focus on work rather than moving pretty windows about.

I’m also attracted by the ability to run a single X11 server in my house, then be able to access the same development environment from different machines around the house without needing to sync up. OS X can be used as an X client quite easily, so I can be developing in the same environment anywhere and on any machine. I’m still in the process of setting all of this up though and working out the pros and cons for day to day use.

Do you have any must-have libraries or tools for Ruby?

I don’t tend to have many libraries or tools installed. I’m a big fan of the command line clients for things like MySQL, Subversion, and Git, and I don’t run my IRB with any elaborations. The only gems I tend to install are Rails, Mongrel, Daemons, Hpricot, and RMagick, although installing OS X Leopard has updated this somewhat. Mongrel and Daemons are my “favorite” gems. Mongrel because it makes building super-fast HTTP daemons so easy, and Daemons because it means I can forget all of the dull process involved in daemonizing and controlling applications and services I build.

You recently stated (also on Twitter, I believe) that JRuby was going to be a big growth area in the next few years. Can you explain why you feel that way?

There’s no escaping the fact that big businesses move slowly. Their technology departments can be frighteningly conservative and there’s often only one “approved” way to do things. This is especially true of deployment. Even medium sized companies freak out when you talk about installing Linux and putting your own Ruby / Rails stack on top. They need everything documented, centralized, and consistent. As such, the Java platform has become a real bedrock for servers and application deployment in the enterprise, and JRuby gives us the opportunity to target all of those established enterprise ecosystems by making Rails applications easy to deploy on JBoss, Tomcat, and other Java application servers.

JRuby is definitely the key to getting Ruby and Rails applications deployed inside most major companies whose ecosystems have no time for alternatives just yet. JRuby is definitely the direction you should be heading for these sorts of deployments, and I think this area is going to become significant to most profit-driven Rails developers very soon.

You wrote a book on Ruby (which I recently reviewed). What books on Ruby/Rails do you recommend, aside from your own of course :)

My book is for people who either have a reasonable understanding of programming, even if they’re not that good at it, or people who have experience with languages other than Ruby and want to move across. For people with absolutely zero programming experience I’d recommend Chris Pine’s Learn to Program. For already experienced Ruby developers who want to become real hotshots and delve into the deeper mechanics of the language, I’d recommend Hal Fulton’s The Ruby Way. Both of these books cover totally different ground than Beginning Ruby and even complement it, depending on your skill level.

Most programmers have a list of programming languages they want to learn. What is the next programming language you are hoping to learn?

I’m an opportunist developer who tries to use the right tool for the job in order to quickly capitalize on some untapped market or niche. As such, I don’t tend to learn languages for fun, at least not to a deep level. I’ve taken a look at languages like Erlang, Haskell, Io, and even written a little Lisp, but don’t see any immediate reasons to learn these languages to a professional level. It’s certainly worth understanding their paradigms and styles, however, to take something useful back to your more productive environments. Lisp has certainly given me a big appreciation for a lot of oblique programming techniques.

You’ve sold two of your sites this past year. Were those opportunistic sales, or was this something you had planned to do all along?

Opportunistic sales. In the first case, with Code Snippets, I was approached by a friend who was interested in buying the site, but after checking with my network of contacts it turned out Rick Ross of DZone was also interested and the site made a great fit with DZone, the “Digg for developers” as I call it.

Now that you’ve sold these sites, what’s next for you?

Ay, there’s the rub! Most of the projects I’ve had success with have been tools or services that I’ve desperately wanted to use myself, so I’ve had a lot of motivation to see them through. When you don’t have any nagging wants, however, you have to really dig deep to come up with the ideas. I’m currently in a bit of a low gear, with it being the end of the year, as well as having sold two businesses this year, but I hope to get back on the saddle really soon and release some more projects next year. For the meantime, however, I’m keeping Ruby Inside updated as best I can and keeping my nose to the ground!

2007/12/24 13:28 2007/12/24 13:28
TAG.

Ruby Experts: Why They Are In Love With Ruby/Rails

[ruby]
주소 : http://www.odinjobs.com/blogs/careers/e ··· y_are_in

Ruby experts tell us why they are in love with Ruby/Rails. Recently, I attended a Ruby users group in Atlanta and I was very surprised to see over 50 people attending the usergroup on  a weekday evening, and nearly all of them have been active members of the usergroup for at least over a year. I could tell that they loved Ruby/Rails unlike anything I have seen in the the C++/Java community (languages I work with). The expert panel below will tell us why they are "in love" with Ruby/Rails.

Ruby Panel Experts


Satish Talim: Has over 29 years of IT experience and is a Ruby Mentor on rubyforge.org. Maintains rubylearning.com, a thorough collection of Ruby Study Notes for those who are new to the Ruby programming language and in search of a solid introduction to Ruby's concepts and constructs.

Peter Cooper: The author of of Beginning Ruby, he is a serial entrepreneur based in the north of England. He maintains Ruby Inside  to not only flex his creative muscles but also to provide the Ruby community with a human-edited digest of interesting Ruby news, tricks, and tips.

Alex Wayne: He has been Using Rails since before 1.0. He is the Author of FlexImage Rails plugin. Greatly enjoy pizza, beer and other yummy things. He is the Asst. Organizer of the North Bay Area Ruby Users Group.His Ruby site.

Alex Leverington: Developer of popular GPL'd IT support tool named SimpleTicket.

Abhay Kumar: He is a data junkie and software engineer, is an active member of the Ruby development community - has presented at Rails related events, has published a Ruby Gem and works professionally with Ruby. His Blog.

Adam Williams: 3 years of experience with Ruby and 6 years of experience with Java. He made the jump from Java to full time Rails and couldn't be happier.
His openSource work includes RDT, Open Sails, Radiant CMS, OFXRB , EaSSL.

Alex Kane: Alex Kane is a Software Developer who comes from a financial background and is currently consulting in New York and Tokyo. He now uses Rails to become more productive.  His Website.

Adam Keys: A software developer from Dallas, TX, he’s been working on a book about Web Services and Ruby that he hopes to finish before the galaxy collapses on itself. He also writes on his weblog, The Real Adam on topics ranging from captioned cats to Ruby and microformats.

Q: If you were to start afresh, would you learn Ruby again?


Satish Talim:  Definitely a *Yes* - for Ruby's simplicity, it's terse syntax, it's endless flexibility, the feeling that we can do whatever we want, whenever we need. For inexperienced programmers there's the plus side that the learning curve is very smooth. You can master the basics in a few days and grow alongside the language. In fact, Ruby can be a good entry-level language to learn and I am trying to convince the local educational authorities in Pune, India to make this a reality.

Peter Cooper:  Yes. I started by becoming interested in Rails first and then learnt Ruby by osmosis, but looking back it makes much more sense to learn Ruby first and Rails afterwards. Ruby is very powerful in its own right, not just as the supporting language for a Web framework.

Alex Wayne: Absolutely.

Alex Leverington: Absolutely.

Abhay Kumar: Yes.

Adam Williams: Absolutely. Though I will say I am thankful for my experiences with other languages.

Alex Kane: Absolutely.  I made the switch from Java to ruby about a year ago and haven't looked back (much).  Java is a great language but it's really verbose.  One Ruby is easier to implement is that there's simply less typing. I had lunch with Yukihiro Matsumoto (aka Matz; the guy who created Ruby) in Tokyo and he's a really sharp guy.  It's his vision that's made Ruby so easy to work with.

Adam Keys: Definitely!  Even beyond the opportunities knowing Ruby has afforded me, Ruby and the people involved with it have changed the way I develop software in a profoundly positive way.  I could have learned  about metaprogramming, DSLs, aesthetic and scaling elsewhere, but I don't think I would have learned it as quickly or as well as I've been able to as part of the Ruby community.
 

Q: What do you think is the most important feature of the Ruby language?

Satish Talim: Wow, that's a very, very hard question to answer. However, what I think I love best about Ruby is described by Yukihiro Matsumoto (Matz) "Ruby's a language that makes me productive while being fun to use." Specifically, blocks are important in Ruby. I'm always surprised by how much I can do with a method that takes a block.

Peter Cooper: The freedom that Ruby provides is very important. It's a very consistent language with a well established syntax at the base level, but if you need to you can dive in and change significant parts of how Ruby works on the fly. This power, combined with how easily you can begin building simple programs, makes it a great all-rounder language.

Alex Wayne: It's dynamism.  Being able to add/remove methods, reflect on the state of objects, and use meta programming tricks is what makes ruby so powerful and fun.

Alex Leverington: Ruby has a very consistent OO methodology, syntax, and uses messaging (similar to smalltalk). This combined with the 'natural english' syntax makes code very easy to read while still being flexible enough to create complex programs.

Abhay Kumar:It is designed, from the beginning, to be object oriented and is purely so
(no wrapper classes like Java), it's dynamic, it has a great regular
expression engine (and will become even better very soon), it's intuitive
and legible (a non Ruby linguist can actually ready through source and at
least partially understand what's going on), and it has a lot of syntactic
sugar

Adam Williams: Blocks.

Alex Kane: That's a difficult question to answer.  I love the fact that Ruby code is usually easy to read. It also has many of the Object Oriented features of Java but it's a dynamic language which makes it more flexible sometimes. If I had to pick the most important standard library it would be Enumerable. Take a look at it, it's really powerful but at the same time easy to use. Check out the syntax for writing a loop, it's really easy:

[1,2,3,4,5].each {|i| puts "Number #{i}"}

Adam Keys: At a language level, Ruby would not be Ruby without blocks.  The way they change how you program is worth any price of admission on their own.  Zooming out, I again have to note that the people around Ruby are fantastic.

Q: What Ruby forums would you recommend?


Satish Talim: Obviously the *ruby-talk forum* . It's the most active forum and you would find most of the top Ruby experts helping each other and all the newbies out there. This forum is the fastest and easiest way to learn and share knowledge. The other is my own *RubyLearning forum*  for Ruby newbies. I am actively involved here, helping all the newbies with their Ruby-related problems, questions. It has a vibrant community.

Peter Cooper: Unfortunately Rubyists don't tend to congregate on forums very much. The most popular forum for discussions is the ruby-talk mailing list  although there's also RailsForum.com which is very popular for Rails and Ruby developers alike.

Alex Wayne: Ruby Forum

Alex Leverington: None, #ruby on freenode is best

Abhay Kumar: I wouldn't unless you count ruby-forum (which is really just the ruby-talk email list)

Adam Williams: None in particular. I tend to look for solutions when I approach unfamiliar problems, and stay connected to great folks who will tell me when something interesting is going on.

Alex Kane: I like Ruby Forum .  It houses a number of ruby forums with gateways to Google groups as well.

Adam Keys: If you have the means, I think the best thing to do is to show up to a Ruby or Rails conference, whether its local or national.  Establish a relationship with as many people as you can and maintain it.  Without a doubt this is the best resource for getting beyond what the books can tell you.



Q: What books would you recommend to a newbie?


Satish Talim:


Peter Cooper: If the newbie knows literally nothing about computation, algorithms or what programming even means, I'd recommend Chris Pine's "Learn to Program." It covers programming from the very first steps and uses Ruby to do it. If the newbie knows they want to use Ruby, understands at least what programming is, and perhaps has another language under his / her belt, I'd recommend my own book, "Beginning Ruby" published by Apress. I wrote the book to fill this giant hole in the market, as existing Ruby books tend to assume you know what object orientation is and so forth. In its 650 pages, Beginning Ruby takes you through everything you'd need to know about the language to feel confident to make your own way. If the newbie is really an extremely seasoned programmer who's already familiar with object orientation (possibly a Java or Python programmer) then The Ruby Way or the "Pickaxe" books are the best bet.

Alex Wayne: Pickaxe, then Agile Web Development with Rails 2nd Edition

Alex Leverington
: Latest edition of Pickaxe

Abhay Kumar: The Ruby Way (Hal Fulton); Pragmatic Ruby (Dave Thomas)

Adam Williams: Programming Ruby 2nd Edition.

Alex Kane: I got started with "Ruby for Rails" by David A. Black.  It covers Ruby pretty well while digging in to Rails.

Adam Keys: If your background is programming, the Pickaxe is the way to go.  I don't have any other books solely on the Ruby language, but I don't think you can go wrong there.If your background isn't in programming, go for The Poignant Guide.  If you're a programmer, it might aggravate you.




Q: Name a programming language that you would like to learn? (if you had the time & resources, of course)


Satish Talim: Lua - a powerful, fast, light-weight, embeddable scripting language.

Peter Cooper: PHP, surprisingly. I find it extremely inconsistent and the syntax poor, but there's no denying how useful PHP is nowadays and how easy it is to throw together very small Web facing apps with it.

Alex Wayne: C++, Objective C

Alex Leverington
: Lua

Abhay Kumar: Erlang (learning/using it now)

Adam Williams
: Erlang. We are seeing the dawn of the concurrent world

Alex Kane:
I'd like to learn Erlang.  It seems to have really cool process management, but I haven't had time to really get in to it yet.

Adam Keys: I would like to use Erlang on a real problem.  I'd also like to get a better understanding of Haskell and OCaml.  I can recognize them from a distance, but I don't yet _get it_ when it comes to those two languages.


I would like to thank the panel for sharing their thoughts with us. I am sure the answers will help everyone from a newbie with no programming experience to anyone who is looking to learn Ruby to extend their skills and, maybe, even the experienced Ruby hand can gain an insight or two.

You need to watch, Adam Keys's USS Ruby, a one act. Its Hilarious.

2007/12/24 13:26 2007/12/24 13:26
TAG. ,

Use or Force an Index with Rails

[ruby]

원문 : http://tech.rufy.com/2006/07/use-or-for ··· ils.html

I just found an ActiveRecord hint that is very useful and very undocumented. If you are working with a table who's indexes are sufficiently complex, MySQL will inevitably guess the wrong index at times. To counteract that in SQL, you write:

SELECT * FROM alphas USE INDEX (some_index) WHERE betas = gamas;
Rails does not have a corresponding :use_index for find methods. However, it does have an un-documented :from option.
Alpha.find(:all, :from => "alphas USE INDEX (some_index)", :conditions => "betas = gamas")
Keep this in the back of your mind if you are going to be working with complex database tables any time soon.
2007/07/23 19:52 2007/07/23 19:52

Apache Best Practice Deployment

[ruby]

주소 : http://mongrel.rubyforge.org/docs/apache.html

The preferred setup (for now) is to put Mongrel behind an Apache 2.2.3 server running mod_proxy_balancer. Apache is a proven web server, runs half the Internet, and is a pain to configure. These instructions should get you started, but refer to the Apache folks for anything more complex or weird.

When you’re just starting out, don’t bother with doing anything but running just Mongrel. Mongrel is slower than Apache, but not so slow that small installations will notice it. The worst thing you can do is try to learn Apache install when you’re also trying to learn Ruby on Rails and Mongrel too. Start small, then when you need, build up to the big stuff.

A simple single mongrel configuration

Start up a single mongrel instance on port 8000:


  $ mongrel_rails start -d -p 8000 \
   -e production -P /full/path/to/log/mongrel-1.pid

Now, we’ll tell Apache to simply proxy all requests to the mongrel server running on port 8000. Simply add the following to your httpd.conf or in a vhost.conf file:


  <VirtualHost *:80>
    ServerName myapp.com
    ServerAlias www.myapp.com

    ProxyPass / http://www.myapp.com:8000/
    ProxyPassReverse / http://www.myapp.com:8000
    ProxyPreserveHost on
  </VirtualHost>

That’s it, in a nutshell. Several things to note in this configuration:

1) This configuration forwards all traffic to mongrel. This means mongrel will serve images, javascript, files, and everything else. It’s quite fast at this, but Apache can do it better.

Here are some basic proxypass rules you can add to tell the ProxyPass not to forward on requests to certain documents/requests:


ProxyPass /images ! 
ProxyPass /stylesheets ! 
#continue with other static files that should be served by apache

Alias /images /path/to/public/images
Alias /stylesheets /path/to/public/stylesheets 
#continue with aliases for static content

For a more detailed set of rules for forwarding on all dynamic content to mongrel, see the more detailed configuration below for more details.

2) In this configuration, it is entirely possible that two users (web requests) could hit your application at the exact same time, and one would have to wait literally milliseconds until the first request is finished before having a turn at the mongrel instance. Unless you’ve got some really long HTTP processes, the nature of the HTTP protocol is pretty good at waiting in line. Only you can determine (through metrics) how long and how many users will come at your application at the exact same time.

Sufficient to say, if you’re ready to start scaling with multiple mongrel instances, read on.

Using multiple mongrel instances with mod_proxy_balancer

First, let’s start up a few mongrel instances (*nix-style):


$ mongrel_rails start -d -p 8001 \
   -e production -P log/mongrel-1.pid
$ mongrel_rails start -d -p 8002 \
   -e production -P log/mongrel-2.pid
$ mongrel_rails start -d -p 8003 \
   -e production -P log/mongrel-3.pid
$ mongrel_rails start -d -p 8004 \
   -e production -P log/mongrel-4.pid

You can also use mongrel_cluster by Bradley Taylor for managing several mongrel instances with a configuration file (and sysv init scripts for *nix servers).

We’re going to be requiring the use of mod_proxy_balancer, a new feature in Apache 2.1/2.2 and above to proxy requests to our mongrel instances. This software based HTTP load balancer will distribute requests evenly (applying a weighting and selection algorithm) to our mongrel instance(s). It even comes with a swell load-balancing manager page for monitoring incoming requests. For more information, see: Apache’s mod_proxy_balancer Documentation.

Obtaining Apache 2(.1+)

I won’t go into too many details, as windows and the various linux distributions all have several methods for obtaining apache2, but you will need the use of the following modules:

  • mod_proxy, mod_proxy-html, and mod_proxy_balancer
  • mod_rewrite
  • mod_deflate
  • mod_headers
  • (optional) mod_cache and one of mod_memcache or mod_filecache
  • (optional) mod_ssl

If you’re compiling from source, this configuration should do the trick:


#./configure --enable-deflate --enable-proxy --enable-proxy-html \ 
--enable-proxy-balancer --enable-rewrite --enable-cache  \ 
--enable-mem-cache --enable-ssl --enable-headers

Configuring Apache2

A good practice is the separation of apache configuration files. Recommended by several other good guides, we’ll be storing information for our application in several different files. Put these files somewhere that apache2 knows about. Apache is quite good about scanning for all .conf files in certain directories.

myapp.common

Apache lets you include common configuration items into another configuration so you can cut down on repetition. What we’re going to do is make a file that has all the common junk that every Mongrel application needs to work at all, then we’ll just include this in little .conf files for any application we deploy.

Notice that this file doesn’t end in .conf since it’s not a real configuration file, but you can name it however you wish.

Important Update: typo fixed in IE deflate rules


  ServerName myapp.com
  DocumentRoot /var/www/myapp.com/current/public

  <Directory "/var/www/myapp.com/current/public">
    Options FollowSymLinks
    AllowOverride None
    Order allow,deny
    Allow from all
  </Directory>

  RewriteEngine On

  # Uncomment for rewrite debugging
  #RewriteLog logs/myapp_rewrite_log
  #RewriteLogLevel 9 

  # Check for maintenance file and redirect all requests
  #  ( this is for use with Capistrano's disable_web task )
  RewriteCond %{DOCUMENT_ROOT}/system/maintenance.html -f
  RewriteCond %{SCRIPT_FILENAME} !maintenance.html
  RewriteRule ^.*$ /system/maintenance.html [L]

  # Rewrite index to check for static
  RewriteRule ^/$ /index.html [QSA] 

  # Rewrite to check for Rails cached page
  RewriteRule ^([^.]+)$ $1.html [QSA]

  # Redirect all non-static requests to cluster
  RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_FILENAME} !-f
  RewriteRule ^/(.*)$ balancer://mongrel_cluster%{REQUEST_URI} [P,QSA,L]

  # Deflate
  AddOutputFilterByType DEFLATE text/html text/plain text/css
  # ... text/xml application/xml application/xhtml+xml text/javascript 
  BrowserMatch ^Mozilla/4 gzip-only-text/html
  BrowserMatch ^Mozilla/4.0[678] no-gzip
  BrowserMatch \bMSIE !no-gzip !gzip-only-text/html

  # Uncomment for deflate debugging
  #DeflateFilterNote Input input_info
  #DeflateFilterNote Output output_info
  #DeflateFilterNote Ratio ratio_info
  #LogFormat '"%r" %{output_info}n/%{input_info}n (%{ratio_info}n%%)' deflate
  #CustomLog logs/myapp_deflate_log deflate

myapp.conf

We then take the above commmon file and include it in our configuration file for this application deployment.

If you’re using virtual hosting (a pretty good idea, even when you’re the only one on the server), your sample configuration can be this simple:


  <VirtualHost *:80>
    Include /etc/httpd/conf.d/myapp.common

    ErrorLog logs/myapp_errors_log
    CustomLog logs/myapp_log combined
  </VirtualHost>

myapp.proxy_cluster.conf

This is the meat of our configuration, and goes hand in hand with our mongrel (or mongrel_cluster) configuration. This configuration tells the apache2 mod_proxy_balancer to proxy requests to 3 mongrel instances running on ports 8000, 8001, and 8002.


  <Proxy balancer://mongrel_cluster>
    BalancerMember http://127.0.0.1:8000
    BalancerMember http://127.0.0.1:8001
    BalancerMember http://127.0.0.1:8002
  </Proxy>

If you had an seperate application server, you could balance to it easily by replacing the 127.0.0.1 with the ip or hostname of your application server, but be sure to make them listen on an external interface (rather than 127.0.0.1).

When you add an additional mongrel to your mongrel_cluster, you can simply add an additional BalancerMember to this file, restart apache (or reload) and you’re all set.

(optional) myapp.proxy_frontend.conf

This optional file will setup the balancer-manager—a simple front-end for viewing how your requests are being handled. This balancer in the configuration below will only work from the localhost, so no one else (or possibly you) can view it unless you alter the “Deny” and “Allow” lines.


Listen 8080
<VirtualHost *:8080>
  <Location />
    SetHandler balancer-manager
    Deny from all
    Allow from localhost
  </Location>
</VirtualHost>

SSL Requirements

In order for mongrel to know that this request has a forwarded protocol of https, we’ll need to add a special header (hence the addition of mod_header, included in most apache2 builds).


  Include /etc/httpd/conf.d/myapp.common

  # This is required to convince Rails (via mod_proxy_balancer) that we're
  # actually using HTTPS.
  RequestHeader set X_FORWARDED_PROTO 'https'

You need this mostly so that redirects go back to https and so you can spot when people are coming through SSL or not.

Automation, Automation, Automation

There are several great tools that automate the setup of Apache for use with mongrel and mongrel_cluster. The RailsMachine gem can automate an entire setup of a Rails application. Also, Slingshot Hosting has a sample set of Capistrano recipes that automatically setup Apache2 and mongrel through the rake remote:setup task. Be sure to check out both for some ideas.

Running Multiple Rails Apps with Mongrel

The newest version of Mongrel supports multiple Rails applications through the use of the—prefix command. The Apache magic for proxying a single application is here assuming your prefix is app1:


ProxyPass /app1 http://127.0.0.1:3000/app1
ProxyPassReverse /app1 http://127.0.0.1:3000/app1

You need to have the proxy pass the new directory name.

Thanks to Joey Geiger and others of the mongrel list for these instructions.

Success Stories

Martins on the mongrel-list has submitted this simple apache configuration. It serves up static content with apache, and forwards dynamic content on to mongrel using ProxyPass. Thanks Martins:


<VirtualHost *>
       ServerName myapp.tld
       ServerAlias www.myapp.tld

       DocumentRoot /var/www/sites/myapp/current/public

       <Directory "/var/www/sites/myapp/current/public">
               Options FollowSymLinks
               AllowOverride None
               Order allow,deny
               Allow from all
       </Directory>

       RewriteEngine On

       # Check for maintenance file. Let apache load it if it exists
       RewriteCond %{DOCUMENT_ROOT}/system/maintenance.html -f
       RewriteRule . /system/maintenance.html [L]

       # Let apache serve static files
       RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -f
       RewriteRule (.*) $1 [L]

       # Don't do forward proxying
       ProxyRequests Off

       # Enable reverse proxying
       <Proxy *>

               Order deny,allow
               Allow from all
       </Proxy>

       # Pass other requests to mongrel instance
       ProxyPass / http://127.0.0.1:8200/
       ProxyPassReverse / http://127.0.0.1:8200/

</VirtualHost>

Phillip Hallstrom has submitted this apache configuration, which includes support for having static directories handled by Apache, php support, and hiding svn directories.



<VirtualHost *:80>

  ServerName myserver.com
  DocumentRoot /path/to/my/app/public

  <Directory "/path/to/my/app/public">
    Options FollowSymLinks
    AllowOverride None
    Order allow,deny
    Allow from all
  </Directory>

  <Proxy balancer://mongrel_cluster>
    BalancerMember http://127.0.0.1:8805
  </Proxy>

  RewriteEngine On

  RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_FILENAME} -d
  RewriteRule ^(.+[^/])$ $1/ [R]

  RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_FILENAME} \.php
  RewriteRule ^(.*)$ $1 [QSA,L]

  RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_FILENAME} !-f
  RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_FILENAME}/index.html -f
  RewriteRule ^(.*)$ $1/index.html [QSA,L]

  RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_FILENAME} !-f
  RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_FILENAME}/index.php -f
  RewriteRule ^(.*)$ $1/index.php [QSA,L]

  RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_FILENAME} -d
  RewriteRule ^(.*)[^/]$ $1/ [QSA,L]

  RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_FILENAME} !-f
  RewriteRule ^/(.*)$ balancer://mongrel_cluster%{REQUEST_URI} [P,QSA,L]

  AddOutputFilterByType DEFLATE text/html
  AddOutputFilterByType DEFLATE application/x-javascript
  AddOutputFilterByType DEFLATE text/css
  AddOutputFilterByType DEFLATE text/plain
  AddOutputFilterByType DEFLATE text/xml
  AddOutputFilterByType DEFLATE application/xml
  AddOutputFilterByType DEFLATE application/xhtml+xml

  BrowserMatch ^Mozilla/4 gzip-only-text/html
  BrowserMatch ^Mozilla/4.0[678] no-gzip
  BrowserMatch bMSIE !no-gzip !gzip-only-text/html

  php_value include_path /path/to/my/app/php:/usr/local/lib/php:.
  php_value auto_prepend_file /path/to/my/app/php/auto_prepend.php

  # this not only blocks access to .svn directories, but makes it appear
  # as though they aren't even there, not just that they are forbidden
  <DirectoryMatch "^/.*/\.svn/">
    ErrorDocument 403 /404.html
    Order allow,deny
    Deny from all
    Satisfy All
  </DirectoryMatch>

</VirtualHost>

Jens Kraemer reports this differing proxy setup that uses the P option in Rewrite rules so as not to use the ProxyPass directive:


  # Don't do forward proxying
   ProxyRequests Off

   # Enable reverse proxying
   <Proxy *>
     Order deny,allow
     Allow from all
   </Proxy>

   RewriteEngine On

   # Check for maintenance file. Let apache load it if it exists
   RewriteCond %{DOCUMENT_ROOT}/system/maintenance.html -f
   RewriteRule . /system/maintenance.html [L]

   # Rewrite index to check for static
   RewriteRule ^/$ /index.html [QSA]

   # Let apache serve static files (send everything via mod_proxy that
   # is *no* static file (!-f)
   RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} !-f
   RewriteRule .* http://127.0.0.1:8200%{REQUEST_URI} [L,P,QSA]

the P option to the last rule replaces the ProxyPass and ProxyPassReverse directives.

SVN Security

If you use svn to issue checkouts instead of exports, you’ll need to hide those pesky .svn directories. This works:


# this not only blocks access to .svn directories, but makes it appear
  # as though they aren't even there, not just that they are forbidden
  <DirectoryMatch "^/.*/\.svn/">

    ErrorDocument 403 /404.html
    Order allow,deny
    Deny from all
    Satisfy All
  </DirectoryMatch>

</VirtualHost>

Reading REMOTE_USER from mongrel through proxy

Jon Reads reports successfully reading the REMOTE_USER variable:

After many hours trying to solve the same problem I found this post: Forcing a proxied host to generate REMOTE_USER

and can confirm that the following works for me when put in the Proxy directive on Apache 2:


   RewriteEngine On
   RewriteCond %{LA-U:REMOTE_USER} (.+)
   RewriteRule . - [E=RU:%1]
   RequestHeader add X-Forwarded-User %{RU}e

References and Other Guides

[1] Time For A Grown-Up Server: Rails, Mongrel, Apache, Capistrano and You

[2] Bradley Taylor’s Fluxura and RailsMachine

[3] Slingshot Hosting Automated Capistrano Recipe

Thanks to many users on the mongrel list for making it easy for me to compile all these tips and tricks as they come across the list.

2007/07/08 07:28 2007/07/08 07:28

이벤트 기반 몽그렐의 성능

[ruby]

주소 : http://myruby.net/articles/2007/07/04/% ··· 58a%25a5

루비는 자체적인 스레딩 시스템(green thread)을 가지고 있다. 그런데 이 그린 스레드가 빈약한 기능과 성능, 멀티 코어에 대응되지 못하는 등 여러 문제를 가지고 있어서 많은 이슈를 만들고 있다. 그린 스레드를 루비의 장점으로 보는 시각도 있지만, 루비 2.0에서는 그린 스레드가 빠진다, 계속 남는다 등등 아직도 말이 많은 상태다.

레일스에서 널리 사용되는 애플리케이션 서버인 몽그렐도 그린 스레드를 이용해 동시 요청을 처리한다. 하지만 지난 RailsConf에서 루비의 Mutual Lock의 성능이 좋지 않고, 되려 스레드간의 문맥 전환에서 상태 정보를 복사하느라 오버헤드가 많다는 주장이 있었다. 그래서 멀티 스레드 몽그렐을 이벤트 기반의 싱글 스레드로 다시 작성하면 성능면에서 얻는 이득이 있다는 것이다.  메모리 사용량, IO 스루풋도 나아진다고 한다.

Swifitply에 포함된 evented_mongrel.rb가 바로 몽그렐을 이벤트 기반 싱글 스레드로 바꿔주는 Hotfix이다. 여기에는 EventMachine이라는 네이티브 라이브러리가 사용되었다. 이 fix를  적용하려면 gem으로 EventMachine과 Swiftiply를 모두 설치하고 몽그렐을 시작할 때 환경변수 EVENT를 1로 설정해주기만 하면 된다. Swiftiply가 mongrel_rails를 재정의하는데, 환경변수에 따라 몽그렐이 동작하는 모드를 바꿔준다.

  1. gem install eventmachine
  2. gem install swiftiply
  3.  
  4. env EVENT=1 mongrel_rails start -e production -d

실제 애플리케이션이 동작하는데 영향을 주는 부분을 바꾸는 것이 없기 때문에 이벤트 기반 몽그렐을 사용한다고 해서 기존 애플리케이션이 동작하지 않는다거나 하는 일은 일어나지 않을 것 같다. 그런데 정말 빠를까? 빠르다면 얼마나 빠를까? 스프링노트에 적용하기 전에 간단한 벤치마크 테스트를 해보았다. 결론부터 이야기하자면, 정말 더 빠르다.

벤치마크

테스트를 수행한 장비는 사양은 이렇다.

  • CPU: AMD64 2CPU
  • MEMORY 8G
  • 운영체제: RHEL4

벤치마크에 사용한 소프트웨는 몽그렐 1.0.1, Swiftiply 0.5.1, EventMachine 0.7.2이고, 레일스의 버전은 EdgeRails 리비전 7161이다. 그리고 테스트를 위해 간단하게 Hello World를 출력하는 애플리케이션을 작성했다.

  1. class TestsController < ApplicationController
      def show
        render :text => ‘Hello, Rails’
      end
    end

위 애플리케이션을 스레드 모드와 이벤트 모드로 각각 구동하고 동시 요청 수를 1에서 1000까지 늘리면서 테스트를 해보았다.

결과

아파치 벤치마크 툴(ab)로 검사한 결과는 다음과 같다.

결과 중 초당 처리한 요청 수만을 표로 정리하면 아래와 같다.

data.png

동시 요청 수에 상관없이 항상 이벤트 기반 몽그렐이 더 나은 성능을 보여줌을 알 수 있다. 특히 주목할만한 점은 동시 요청이 늘어난 즉, 더 가혹한 상황에서 이벤트 기반 몽그렐이 실력을 발휘한다는 사실이다. 기존 몽그렐은 동시 요청이 늘어남에 따라 계속 성능이 떨어지는 모습을 보이지만, 이벤트 기반 몽그렐은 더 나은 성능을 보이기도 하고, 전체적으로 비슷한 수준을 유지함을 알 수 있다.

evented_mongrel.png

그래프로 그려보니 그 차이가 더 명확하다.

사실 스프링노트에서는 2주째 이벤트 기반 몽그렐을 사용하고 있다.  그간 이벤트 기반 몽그렐때문에 문제가 발생한 적은 한 차례도 없다. 안정적으로 서비스하는데 문제가 없다는 이야기다. 레일스 서비스를 고려한다면, 꼭 이벤트 기반 몽그렐로 바꿔서 성능 테스트를 한번 해보기를 권한다. 공짜로 얻을 수 있는 성능 향상이니까.

다음에는 Swiftiply 프록시를 테스해볼 생각이다.  아직 몇 가지 버그가 있는 듯 보여 본격적인 사용은 미루고 있지만, 이는 성능보다는 ‘안정성’에 도움이 될 수 있는 방법이니만큼 꼭 테스트해봐야겠다.

2007/07/05 10:21 2007/07/05 10:21
TAG. , ,

5 Minute Beta Authentication in Rails

[ruby]

주소 : http://www.igvita.com/blog/2007/06/21/5 ··· rails%2F

Releasing your application in stages is often a very good idea, it allows you to build a core user base, and more importantly, it gives you time to winnow out the bugs before the full public launch. If you’re inventive, you could even turn this process into a marketing coup by playing with scarcity (think gmail), but that’s an area we won’t get into here. Instead, we’ll actually build a ‘limited beta’ subsystem in Rails.

Leveraging acts_as_authenticated

Instead of starting from scratch we’ll use acts_as_authenticated as our starting point. If you haven’t already, I encourage you to check it out, it’s an excellent set of generators which will get you up and running in no time. Not to mention, the wiki itself is worth its weight in gold.

After getting through the basic setup of acts_as_authenticated we can move on to the next step. In order to have a true limited beta, we will put a login_required filter around our entire application with an exception of a few account management actions:

> beta_application.rb

class ApplicationController < ActionController::Base
    session :session_key => '_app_session_id'      

    include AuthenticatedSystem # generated by acts_as_authenticated    
    before_filter :login_required, :except => [:welcome, :beta, :activate]       

    # custom handler, will redirect to a 'welcome' splash page,    
    # which does not require authentication.     

    def access_denied      
        respond_to do |accepts|        
            accepts.html do          
                store_location          
                flash[:warning] = "Beta login required."          
                redirect_to :controller => 'main', :action => 'welcome'        
            end          
                accepts.xml do           
                    headers["Status"]           = "Unauthorized"           
                    headers["WWW-Authenticate"] = %(Basic realm="Web Password")           
                    render :text => "Could't authenticate you", :status => '401 Unauthorized'         
            end       
        end       
        false    
    end  
end

By introducing the filter in application.rb, our Rails application will force the user to validate their login credentials prior to execution of any action - hence, outsiders can’t get in. Additionally, we also provided a custom access_denied method which will send our user to a nice splash page if the credentials are lacking.

Of course, now that we have locked everyone out, we need to let a few users in! And here is where all the magic happens: if you only want to grant full access to a select number of users, then you only have to guard the sign-up process. If a user is registered, then they must have had the right secret key, and we don’t have to worry about anything else anymore. Alternatively, if you want to allow access to a subset of features, things get trickier ? you might need another filter to check for access permissions on a more refined (action) level. However, we’ll keep things simple and implement the former case.

Allowing beta sign-ups

Since we only care about guarding the sign-up process, we will require a special beta key as part of the registration process. By providing an extra text field in our form, we pipe the key into Rails and validate it in our sign-up procedure:

> account_controller.rb

def signup    
    # Verify beta key    
    beta_verify = Digest::MD5.hexdigest("Secret application salt"+params[:user][:email])    
    return redirect_to(:controller => 'main', :action => 'beta', :key => params[:key]) unless params[:key] == beta_verify       

    # default acts_as_authenticated code follows ...  
end

Here’s the trick, take the users email address, add a secret ‘salt‘ value, crank the results through a one-way cryptographic function (like MD5) and out comes a unique key which you can give to the user. Once the user fills in the form, we have enough data to recreate the key and validate it on the fly, and if everything is OK, then we process the sign-up!

Generating custom beta keys

Finally we can write a small command line ruby script to generate a custom key for a user. In this example, we’ll use the email address and a custom salt value:

> beta_key.rb

require 'rubygems'  
require 'digest/md5'