Adding manpower to a late software project makes it later
Filed under: ruby on rails — Tags: , , — Michael Glauche @ 19:47

Missing libraries

zlib.dll not found

After downloading the latest win32-releases of ruby i was greeted with two error messages, SSLEAY32.dll not found and zlib.dll not found. The SSL library is kinda optional (gem, etc basicly work without it), but zlib not.

For this, the zlib library is needed, luckily there’s a native win32 port of it. So, download the latest win32 dll from zlib.net,
extract the zlib1.dll, rename it to zlib.dll and place it into the ruby bin directory.

SSLEAY32.dll not found

For SSLEAY32.dll the safest way i’ve found seems to use the version from the win32 postgresql client, which can be found here.

Just copy SSLEAY32.dll and libeay32.dll from the postgresql/bin directory into the ruby bin (or actually any other directory which is in your path)

readline.dll not found

Now you think everything is working, and start irb for the first time. Dang. readline.dll is missing. Readline win32 binaries can be found at http://gnuwin32.sourceforge.net/packages/readline.htm. Download the latest win32 build and copy the readline5.dll from the bin directory to your ruby bin directory again. Don’t forget to rename it to readline.dll.
Now everything should be working smoothly.

Filed under: ruby on rails,thin — Tags: , , , , , — Michael Glauche @ 00:10

Nothing spirtual here, but the cool monitoring framework god together with thin. You’ve probably read a lot of benchmarks about thin, but whats the fastest webserver when you can’t ensure they are up and running ? Right here is where god comes into play. God is (beside the silly name) a nice process monitoring framework with a ruby configuration script. You can easily start/stop/monitor daemon processes and put advanced flags on them, like CPU or memory usage.

The default god startup file looks quite neat if you only run one site, and is easily converted to work together with thin, as thin and mongrel share the same parameters. Now i don’t have the luxury of only supporting one site but rather quite a buch of (mostly small and inactive) sites which share quite a lot of critera. Creating this kind of config file for each of them seems quite exessive and against the rails DRY principle.

Now, with a recent thin version (I did try 0.6.3) you can have the configuration for each site in a seperate YAML file, there’s even a small god startup script included in the examples directory.

Now first, lets take a look at the thin yaml config of a test ruby installation, in this case test.yml in /etc/thin :

servers: 3
user: www-data
group: www-data
chdir: /var/www/rails
pid: tmp/pids/test
port: 8000
address: 0.0.0.0
log: log/thin.log

Most is pretty self explainig, the pid and logfile is relative to the startdir, and the uid/gid is set to www-data (the default on ubuntu machines)
Unfortunately the thin.god startup file in thin 0.6.3 seems to have a small bug when it comes to allocating ports (or i’m doing something wrong, but the config file works flawlessly with just thin), so here’s a fixed version of the thin.god file:

# == God config file
# http://god.rubyforge.org/
# Author: Gump
#
# fixed thin ports <michael@glauche.de>
#
# Config file for god that configures watches for each instance of a thin server for
# each thin configuration file found in /etc/thin.

require 'yaml'

config_path = "/etc/thin"

Dir[config_path + "/*.yml"].each do |file|
  config = YAML.load_file(file)
  num_servers = config["servers"] ||= 1
  for i in 0...num_servers
    God.watch do |w|
      w.group = "thin-" + File.basename(file, ".yml")
      port = config["port"] + i

      w.name = w.group + "-#{port}"

      w.interval = 30.seconds

      w.uid = config["user"]
      w.gid = config["group"]

      w.start = "thin start -C #{file} -o #{port}"
      w.start_grace = 10.seconds

      w.stop = "thin stop -C #{file} -o #{port}"
      w.stop_grace = 10.seconds

      w.restart = "thin restart -C #{file} -o #{port}"

      pid_path = config["chdir"] + "/" + config["pid"]
      ext = File.extname(pid_path)

      w.pid_file = pid_path.gsub(/#{ext}$/, ".#{port}#{ext}")

      w.behavior(:clean_pid_file)

      w.start_if do |start|
        start.condition(:process_running) do |c|
          c.interval = 5.seconds
          c.running = false
        end
      end
      w.restart_if do |restart|
        restart.condition(:memory_usage) do |c|
          c.above = 150.megabytes
          c.times = [3,5] # 3 out of 5 intervals
        end

        restart.condition(:cpu_usage) do |c|
          c.above = 50.percent
          c.times = 5
        end
      end

      w.lifecycle do |on|
        on.condition(:flapping) do |c|
          c.to_state = [:start, :restart]
          c.times = 5
          c.within = 5.minutes
          c.transition = :unmonitored
          c.retry_in = 10.minutes
          c.retry_times = 5
          c.retry_within = 2.hours
        end
      end
    end
  end
end

Note, there was a bug with older god installations and ubuntu installations, but they worked flawlessly for me with the 0.7.0 god release. (there were some problems with the 0.5.0 release and ubuntu, so check if you have an up to date god version)

It will look in /etc/thin for all .yml files and will start and supervise them accordlingly. To start up the monitoring use

 # god -c thin.god

After its up and running you can check the status of your servers with:

 # god status

That command should give the following output:

thin-test-8000: up
thin-test-8001: up
thin-test-8002: up

Filed under: nginx,ruby on rails — Tags: , , , , , — Michael Glauche @ 20:48

I wondered about how many parallel thin you need to get the optimal throughput. I often saw values from 3 to 10 servers in different configuration examples around the net. Time to get some real numbers.

To get a meaningful benchmark i took an old dual 1,3 GHz P3-s system with the latest ubuntu. I did install rails 2.0.2 and a testing project with it, then created a very simple controller, that just passes a “hello world” string to the view. Also, no database connections should be made.

The server is started with

rake thin:cluster:start RAILS_ENV=production SIZE=5 PORT=8000

You’ll need the latest thin 0.5.2 for it, as 0.5.1 has some serious bug that prevents it from running daemonized. The command above will start 5 thin instances, listening on ports 8000-8004. To actually benchmark the number of thin instances used, i did modify the upstream entries in nginx:

# only one server used in this example
upstream thin {
   server 127.0.0.1:8000;
   #server 127.0.0.1:8001;
   #server 127.0.0.1:8002;
   #server 127.0.0.1:8003;
   #server 127.0.0.1:8004;
}

The results are not really supprising and show that the nginx + thin combo scales well even up to 100 concurrent users. All Tests were done with

ab -n 10000 -c 20 http://localhost/foo/

where the “foo” controller was the minimal one returning the “hello world” page.

The results can be seen in this graph:

Nginx & thin Benchmark

As you can see, the best results for this dual cpu machine was indeed running two instances of thin. What is interesting to see that thin+nginx scale quite well over many concurent requests.

Of course this is an idealized test with minimal load times for each pagecall. In the next version i’ll put in a random delay before the template is rendered to simulate real wold loading times and slow operations (users up/downloading large files, etc ..)

Filed under: extjs,ruby on rails — Tags: , , , , — Michael Glauche @ 20:46

creating a simple logon window

First, we need a simple view for our index defined in part 1

index.rhtml in views/login

<script type="text/javascript"
   src="/javascripts/login.js"></script>    

<p>Here comes the Content which
will be used after the user logged on.</p>

This is just some dummy content that will be “blocked” by a modal extjs window. There can be any HTML content inside it, which will be disabled, but would be visible via the html source code, so aditional client checks are neccessary if it should work as a secure formular.

Now the interesting stuff is of course the login.js itself:

var loginForm = new Ext.form.FormPanel({
    baseCls: 'x-plain',
    labelWidth: 75,
    url:'/login/doLoginTest',
    defaultType: 'textfield',
    items: [{
        fieldLabel: 'Username',
        name: 'name',
        anchor:'90%'  // anchor width by percentage
    },{
    fieldLabel: 'Password',
    name: 'subject',
    anchor: '90%'  // anchor width by percentage
}],
buttons: [{
    text: 'Login',
    handler: function() {
        loginForm.getForm().submit(
            {
                method: 'GET',
                waitMsg:'Submitting...',

                reset : false,
                success : function() {
                    loginWindow.close();

                },
                failure: function(form, action){Ext.Msg.alert('Error',action.result.text)}
            });
        }
    }]

});

var loginWindow = new Ext.Window({
    title: 'Login',
    width: 300,
    height:140,
    closable:false,
    minWidth: 300,
    minHeight: 140,
    layout: 'fit',
    plain:true,
    modal:true,
    bodyStyle:'padding:5px;',
    items: loginForm
});
Ext.onReady(function(){
    loginWindow.show(this);
});

Now lets get through this step by step:
The first function that is called is Ext.onReady, which is the startup function that is called by the extjs toolkit after the page has finnished loading and the toolkit did initialize. The function shows up the loginWindow, which was declared earlier by the line “var loginWindow = new Ext.Window({“. Parameters are always passed as a Javascript Object {param1,param2,param3}, which might look a bit confusing at first, but is very practical to set different parameters. The real interesting parmeter in loginWindow is the “items: loginForm” line, it does define what will end up inside the window, here its a FormPanel. The rest are basicly only stlye information to make it look like a window.

Now, the “loginForm” Object contains the real interesting stuff. You’ll probably recognize the style stuff from the loginWindow object, along with the “items:” line. But here we are not referencing another Object, but just inline the things we need as a Javascript Object again, but this time as an array of Objects, noted with the “items:[{object1},{object2]” line. The “buttons:” line behaves the same, but uses button Objects with onClick handlers instead.

handler: function() {
        loginForm.getForm().submit(
            {
                method: 'GET',
                waitMsg:'Submitting...',

                reset : false,
                success : function() {
                    loginWindow.close();

                },
                failure: function(form, action){Ext.Msg.alert('Error',action.result.text)}
            });
        }

This javasctipt parts creates an Ajax submit form for the “Login” button. Extjs does take care of all houskeeping and wait messages, etc, you just need to tell what to display. The “success” and “failure” functions are user defined and send back from the controller in form of an json hash. Now the controller looks like this:

   def doLoginTest
      headers["Content-Type"] = "text/plain; charset=utf-8" 

      puts params[:name]
      if (params[:name] == "mg")
         data = { :success => 'true'}
      else
         data = { :failure => 'true', :text => "Username or Password wrong !"}
      end
      render :text => data.to_json, :layout => false
   end

As you can see, its a very secure mechanisim thats basicly foolproof and impossible to guess :) But all joking aside, you can see the result is gathered into a ruby hash or array, which is later then converted to json. For this to work you need either rails 2.0 (which is recommened because it makes life a lot easier with activerecord and json), or you need the json gem and put a

require 'json/objects'

on the top of the controller. Using this mechanic you can transfer all kinds of data from your rails controller to the extjs frontend. In fact all communication between extjs and rails is basicly json, but this will be covered more in part 3, where we’ll have a more in deep look into getting some activerecord data into extjs

Older Posts »

16 queries. 0.506 seconds. Powered by WordPress

Home