The easiest way to create a maintenance page for a .Net application is creating a static html page called
app_offline.htm and saving it to the root directory.
When IIS detects the existence of app_offline.htm, it will not only display the maintenance page, but also
return a “503 Service Temporarily Unavailable” error code, which is important to prevent search engine crawlers
from indexing the maintenance message as your site’s content.
A nice little trick: You could use data uri to embed images in your app_offline.htm, such as
1234567891011121314151617181920
<!DOCTYPE html><html><head><metacharset="UTF-8"><title>Maintenance</title><style type="text/css">#logo{width:216px;height:105px;background-repeat:no-repeat;background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAANgAAABpCAYAAABYtu09AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA7dpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wUmlnaHRzPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvcmlnaHRzLyIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcFJpZ2h0czpNYXJrZWQ9IkZhbHNlIiB4bXBNTTpPcmlnaW5hbERvY3VtZW50SUQ9InhtcC5kaWQ6Rjk3RjExNzQwNzIwNjgxMTgwODNFQjgzQzYyQkQ3QzEiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6ODNCNzQ0RkFDRkMxMTFFMjg5NzU4NzFDODk4Q0JENUMiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6ODNCNzQ0RjlDRkMxMTFFMjg5NzU4NzFDODk4Q0JENUMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoTWFjaW50b3NoKSI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOjc5QUQ2N0E3MTcyMDY4MTE4MDgzQzJDQzYxNjRF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);}</style></head><body><divid="logo"></div><divlang="en">Here goes the maintenance message.</div></body></html>
A web site I’m working on uses Kentico CMS version 7. Occasionally its search function would break down due to a corrupted Lucene index.
Kentico CMS’s SmartSearch is built on top of Lucene.Net. Kentico 7 comes with Lucene.Net 2.1.0.3, a very old version. One of the things I tried was to upgrade Lucene.Net.
Although the latest version is 3.0.3, I decided to go with 2.9.4.1.
nuget install Lucene.Net -Version 2.9.4.1
Then I replaced Kentico’s Lucene.Net.dll and dependency ICSharpCode.SharpZipLib.dll.
As expected, Kentico throws an error “Could not load file or assembly ‘Lucene.Net, Version=2.1.0.3, Culture=neutral, PublicKeyToken=d846ee227f01c7a1’ or one of its dependencies. The located assembly’s manifest definition does not match the assembly reference.”
Trying to work around it, I added the following to web.config:
If your IIS 7 server sits behind a load balancer or a proxy server, it will always
record the IP of the proxy or load balancer as the client IP, which makes it impossible
to determine the origin of your visitors.
Recently I discovered Gatling, a load testing framework written in Scala, and used it to test a Kentico 7 web site.
I love it so much that I’ll ditch Apache JMeter from now on.
While both have a GUI to record tests, the major difference between them is JMeter tests are saved as .jmx files (XML),
but Gatling tests are .scala scripts written in Scala-based DSL.
Another interesting option would be Ruby JMeter, but I haven’t had a chance to try it yet.
This blog from flood.io points out that Gatling outperformances JMeter with over 20,000 concurrent users.
I must admit, however, that Gatling stil has a few rough edges, at least on Windows.
For example, some of my tests couldn’t finish because a report file’s file name was too long for Windows (260 characters maximum).
As a Ubuntu user and a Ruby enthusiast who prefers simple solutions, they’re a perfect combo.
I was just about to blog on how to set them up, when I found out this guy’s post beat me by a year. :-)
It’s a great post with step by step instructions.
I have just the following to add:
To set up your SSH key authentication, you can locate you Cloud 9 SSH key by going to “Your Account”, and then “Show SSH Key” under “Account Settings” on the right hand side.
Copy that key, click the Settings icon on the top right corner of your GitHub page, and then “SSH Keys” on the left side. Click “Add SSH Key” on the right to add your Cloud 9 SSH Key.
In case you use non-ASCII characters, for example, if you’re writing in German, you may get the followoing error when you run rake generate:
YAML Exception reading 2014-06-11-learn-german.markdown: invalid byte sequence in US-ASCII
/home/ubuntu/workspace/octopress/plugins/backtick_code_block.rb:13:in `gsub': invalid byte sequence in US-ASCII (ArgumentError)
from /home/ubuntu/workspace/octopress/plugins/backtick_code_block.rb:13:in `render_code_block'
from /home/ubuntu/workspace/octopress/plugins/octopress_filters.rb:12:in `pre_filter'
from /home/ubuntu/workspace/octopress/plugins/octopress_filters.rb:28:in `pre_render'
from /home/ubuntu/workspace/octopress/plugins/post_filters.rb:112:in `block in pre_render'
from /home/ubuntu/workspace/octopress/plugins/post_filters.rb:111:in `each'
from /home/ubuntu/workspace/octopress/plugins/post_filters.rb:111:in `pre_render'
from /home/ubuntu/workspace/octopress/plugins/post_filters.rb:166:in `do_layout'
from /usr/local/rvm/gems/ruby-2.1.1@rails4/gems/jekyll-0.12.0/lib/jekyll/post.rb:195:in `render'
from /usr/local/rvm/gems/ruby-2.1.1@rails4/gems/jekyll-0.12.0/lib/jekyll/site.rb:200:in `block in render'
from /usr/local/rvm/gems/ruby-2.1.1@rails4/gems/jekyll-0.12.0/lib/jekyll/site.rb:199:in `each'
from /usr/local/rvm/gems/ruby-2.1.1@rails4/gems/jekyll-0.12.0/lib/jekyll/site.rb:199:in `render'
from /usr/local/rvm/gems/ruby-2.1.1@rails4/gems/jekyll-0.12.0/lib/jekyll/site.rb:41:in `process'
from /usr/local/rvm/gems/ruby-2.1.1@rails4/gems/jekyll-0.12.0/bin/jekyll:264:in `<top (required)>'
from /usr/local/rvm/gems/ruby-2.1.1@rails4/bin/jekyll:23:in `load'
from /usr/local/rvm/gems/ruby-2.1.1@rails4/bin/jekyll:23:in `<main>'
from /usr/local/rvm/gems/ruby-2.1.1@rails4/bin/ruby_executable_hooks:15:in `eval'
from /usr/local/rvm/gems/ruby-2.1.1@rails4/bin/ruby_executable_hooks:15:in `<main>'
The solution is run export LC_ALL=C.UTF-8 first. To save time, I would join the commands as export LC_ALL=C.UTF-8 && rake generate.
(Some posts on the web suggest expoort LC_ALL=en_US.UTF-8, but that won’t work for the current version Cloud 9 at the time of writing.
To be sure, you can run locale -a to get a list of available locales.)
And then run jruby --command bundle install to get the gems ready.
Note: The tux gem works as a console to interact with my Sinatra application. I would also love to have the shotgun gem, but unfortuantely it’s unavaible for JRuby.
The JDBC driver (sqljdbc4.jar) for SQL Server is included in the source code, but if you prefer, you can also get it from Microsoft’s web site. We’ll just save it to our application root.
SQL Server table
Our application will use one table called “users”.
require'rubygems'require"sinatra"require"sinatra/activerecord"require'sinatra/form_helpers'require'active_record'require'active_record/connection_adapters/jdbc_adapter'require'sqljdbc4.jar'config_dev={:adapter=>"jdbc",:driver=>"com.microsoft.sqlserver.jdbc.SQLServerDriver",:url=>"jdbc:sqlserver://SERVER:1433;databaseName=DB_NAME",:username=>"USER",:password=>"PASS"}# JBoss connectoin pool. Need to set up datasource in JBossconfig_jboss={:adapter=>"jdbc",:driver=>"com.microsoft.sqlserver.jdbc.SQLServerDriver",:jndi=>"DATASOURCE_NAME"}# On JBoss $servlet_context is definedconfig=defined?($servlet_context)?config_jboss:config_devActiveRecord::Base.establish_connection(config)classUser<ActiveRecord::Basevalidates:consent,acceptance:true,presence:truevalidates:firstname,presence:truevalidates:lastname,presence:truevalidates:email,presence:true,format:{with:/\A[^@]+@([^@\.]+\.)+[^@\.]+\z/}endhelpersdodefh(text)Rack::Utils.escape_html(text)endendget"/users"do@users=User.take(10)erb:"users/index"endget"/users/:id"do@user=User.find(params[:id])erb:"users/show"endput"/users/:id"do@user=User.find(params[:id])if@user.update_attributes(params[:user])redirect'/users'elseerb:"users/show"endend
Our layouts and templates sit in the views folder with the following content.
Let’s get started by installing Warbler as a gem jruby --command gem install warbler. Next, we need to configure Warbler:
Create a new folder called config under our application root
Run jruby --command warble config, which generates a configuration template called warble.rb under the config folder
Edit config/warble.rb and update these lines:
config/warble.rb
12345678
# Application directories to be included in the webapp.config.dirs=%w(views)# Additional files/directories to include, above those in config.dirsconfig.includes=FileList['app.rb','sqljdbc4.jar']# Uncomment this if you don't want to package rails gem.config.gems-=["rails"]
Now we’re ready to package our app: jruby --command warble
A war file will be created as myapp.war.
Deploy the WAR file
I tried the JBoss 6 Admin console first, but got an Out of Memory error. I worked around it by copying the WAR file to the deploy folder (in my case
/usr/jboss6/server/default/deploy/) and restarting JBoss. And voila, our application is live on JBoss at http://jboss_address/myapp .