Build a serious WordPress server for high traffic website with nginx
Deploy multiple nginx instance on 1 server for load balance
When building WordPress for high traffic website, we maintain and restart the web server frequently for better SEO and better user experience; but we don’t want to interrupt user’s visiting.
When we get familiar with SEO, the link/site structure may change and need to update nginx configuration which need restart of nginx. When nginx new version released for fixing a dangerous security issue, we need upgrade nginx.
So we need at least 2 nginx instance for load balance, and another nginx as proxy server. Let’s build the 3 nginx instance on a single server with the same nginx installation(or use 2 nginx installation if need upgrading nginx ). Two of the instance serves WordPress with the same WordPress installation and the same database.
The architecture and network composition:
The following steps describes how to do in on Debian.
1. Deploy single wordpress server on nginx
Make sure your system is up-to-date. Reference the following links to install php pre-requirements:
cd /opt wget http://nginx.org/download/nginx-1.0.9.tar.gz tar -zxvf nginx-1.0.9.tar.gz cd /opt/nginx-1.0.9/ ./configure --prefix=/opt/nginx --user=nginx --group=nginx --with-http_ssl_module --with-ipv6 make make install
Create init script to manage nginx:
wget -O init-deb.sh http://library.linode.com/assets/682-init-deb.sh mv init-deb.sh /etc/init.d/nginx chmod +x /etc/init.d/nginx /usr/sbin/update-rc.d -f nginx defaults /etc/init.d/nginx start
2. Duplicate nginx configurations
cd /opt/nginx (change directory to where nginx is installed)
cp conf/nginx.conf conf/nginx.81.conf
cp conf/nginx.conf conf/nginx.82.conf
mv conf/nginx.conf conf/nginx.backup.conf
And then change the listen port 80 to 81,82 respectively in nginx.81.conf and nginx.82.conf; also don’t forget to comment out the pid line and change the pid file for each instance so that each instance can be stopped normally:
pid logs/nginx.81.pid; ### in file nginx.81.conf
pid logs/nginx.82.pid; ### in file nginx.82.conf
3. Configure and deploy the proxy nginx server
vi conf/nginx.conf,
copy the following content to listen on port 80 which is balanced by two nginx instance at port 81 and 82.
#deploy multiple nginx instance for load balance on 1 server
upstream main {
server 106.187.45.82:81;
server 106.187.45.82:82;
}
server {
listen 106.187.45.82:80
location / {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://main;
}
}
4. Stop your old server and start the new instance with load balance support
sbin/nginx -s stop, or kill -QUI pid
Then you can start the new instance by:
cd /opt/nginx sbin/nginx -c conf/nginx.81.conf sbin/nginx -c conf/nginx.82.conf sbin/nginx -c conf/nginx.conf
In case you want to stop the instance, you can run one/all of these commands:
sbin/nginx -s stop -c conf/nginx.81.conf sbin/nginx -s stop -c conf/nginx.82.conf sbin/nginx -s stop -c conf/nginx.conf
Of course, you can stop the instance by executing this command too: kill -QUIT pid-of-the-nginx
5. Debug and maintenance one of the nginx instance
When you debugging on one of the nginx node, if you visit http://106.187.45.82:81, WordPress will redirect your url to the default WordPress site URL automatically(for example http://www.beyondlinux.com/ ), and then you don’t know which instance you are visiting.
But why wordpress has automatic url redirects? You can typically visit the home page of a WordPress web site by several different URLs:
http://www.beyondlinux.com:81/
The problem with allowing all of these URLs to access a single page is that it can potentially hurt your website’s overall search engine optimization (SEO). It means search engines could index duplicate copies. So WordPress fixes this problem by employing automatic redirects known as Canonical URL Redirection, which only enables one url per page.
When debugging and testing new functions, you don’t want to enable the redirection. You can add the following code to functions.php file. remove_filter('template_redirect','redirect_canonical');
If you don’t like editing the file, you could install the plugin: “Permalink Fix & Disable Canonical Redirects Pack“, and activate it, then redirection would be disabled.
After debugging and testing of your WordPress finished, you should deactivate the plugin to enable the Redirection for a better SEO site.
6. Redirect request to next server if error or timeout.
When in load balance mode, nginx will redirect/resend request to another server by default when server error or timeout; for more error processing, we can leverage the directive of proxy_next_upstream and fastcgi_next_upstream.
syntax: proxy_next_upstream [error|timeout|invalid_header|http_500|http_502|http_503|http_504|http_404|off]; default: proxy_next_upstream error timeout;
context: http, server, location
The directive determines in what cases the request will be transmitted to the next server, here’s an example config:
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504 http_404;
fastcgi_next_upstream error timeout invalid_header http_500 http_503 http_404;
Why Load Balance not work in Hessian C# client calling to hessian service?
Filed under: design, java, troubleshooting
When I was migrating our application from C# to Java, our Java service moved ahead of the client application. The client application is in C#. And we export service through Hessian service. So we call java hessian service through C# hessian client.
But we met a big problem on load balance after the new application deployed. The load is never balanced on the C# hessian client’s request. The service is invoked through F5.
After digging into the code of C# hessian, I found the cause: C# Hessian Client uses HttpWebRequest with default properties to call java hessian service, while the default HttpWebRequest’s KeepAlive property is true. That means after the C# client connected to a load balance server, it will keep on calling the same back-end service and the request from this client will not routed to other back-end service.
So the solution is to change the default KeepAlive property in file CHessianMethodCaller.cs
HttpWebRequest req = webRequest as HttpWebRequest;
req.KeepAlive = false; // newly added line to assure load balance work
Noticeable Hacker news I read(2011/09-2011/11)
Filed under: tech watch
Programming:
Signs that you’re a bad programmer
How you should go about learning NoSQL
What’s new in Cassandra 1.0: Performance | DataStax
Spark Cluster Computing Framework
Interview with Dennis Ritchie, Bjarne Stroustrup, James Gosling
Lucene Eurocon 2011: Presentation slides are now available
What are the most learner-friendly resources for learning about algorithms? – Quora
What questions are Java Software Engineers seeing the most of on technical interviews? – Quora
Don’t Call Yourself A Programmer, And Other Career Advice | Kalzumeus Software
Building a Node.js Events App Using RabbitMQ, Websockets, and Django – James Burkhart
Productivity Tools:
Unofficial Google Advanced Search
Ask HN: What programming blogs do you read daily?
Startup Lessons Learned:
‘Try demo’ or ‘Buy now’: A/B testing finds which button increased clickthroughs by 47%
The Case for the Single Founder StartupIf I Launched a Startup
5 Things a Good Product Manager Should Think About
A Few Lessons I Learned After Having Failed
What if the Secret to Success Is Failure? – NYTimes.com
10 Habits of Effective Startup Mentors « Lean Startup Machine
Suffered by wordpress permanent links in nginx
Filed under: linux, server
I installed wordpress several month ago by default. The page links were in default format like /blog/p?101. After some posts written I realized that these format is not friendly to search engine. So I decided to change the permalinks format in wordpress. It is a suffered experience.
After I changed the permalinks to custom structure, such as “/%year%/%monthnum%/%day%/%postname%/”, then some pages, and the category, tags links, pages could not be visited correctly.
And I tried install the WP plugin “advanced permalinks”. The plugin’s feature sounds very promising, it can reserve your old pages’ permalinks in an different structure. But after activated, some of my links (like category, tags) broken too.
Then I added configurations in nginx.conf, with lots of location definitions …. :
77 location /blog/2011 { ### for nginx redirection, 2011/06
78 try_files $uri $uri/ /blog/index.php?q=$uri&$args;
79 }
80 location /blog/category { ### for nginx redirection, 2011/06
81 try_files $uri $uri/ /blog/index.php?q=$uri&$args;
82 }
83 location /blog/feed{ ### for nginx redirection, 2011/06
84 try_files $uri $uri/ /blog/index.php?q=$uri&$args;
85 }
86 location /blog/comments{ ### for nginx redirection, 2011/06
87 try_files $uri $uri/ /blog/index.php?q=$uri&$args;
88 }
89 location /blog/sample-page{ ### for nginx redirection, 2011/06, About me
90 try_files $uri $uri/ /blog/index.php?q=$uri&$args;
91 }
95 location /blog/index.php{ ### for nginx redirection, 2011/06
96 try_files $uri $uri/ /blog/index.php?q=$uri&$args;
…. Each time a new kind of url(which has the same prefix) I added a location config, it is difficult and boring to maintenance the file.
Even more worse, when I installed a new wordpress plugin, the configuration page is in a new url, it couldn’t be accessed.
Oh my god, finally, I changed the nginx.conf like this (leave a catch-all entry in the end), then pages are shown without any colors and styles except black and white…
77 location /blog/2011 { ### for nginx redirection, 2011/06
78 try_files $uri $uri/ /blog/index.php?q=$uri&$args;
79 }
80 location /blog/category { ### for nginx redirection, 2011/06
81 try_files $uri $uri/ /blog/index.php?q=$uri&$args;
82 }
83 location /blog/feed{ ### for nginx redirection, 2011/06
84 try_files $uri $uri/ /blog/index.php?q=$uri&$args;
85 }
...
92 location /blog/index.php/category{ ### for nginx redirection, 2011/06
93 try_files $uri $uri/ /blog/index.php/?q=$uri&$args;
94 }
95 location /blog/index.php{ ### for nginx redirection, 2011/06
96 try_files $uri $uri/ /blog/index.php?q=$uri&$args;
97 }
98 location /blog/{ ### for nginx redirection, 2011/06
99 try_files $uri $uri/ /blog/index.php?q=$uri&$args;
100 }
Setup your cloud server in 3 minutes with Xen 4.1 on Ubuntu 11.10
Ubuntu support xen officially since 11.10. It is really easy to install the packages. Although some issues should be fixed manually, it is a painless experience. Here’s the steps to setup your cloud server in 3 minutes with Xen 4.1 on Ubuntu 11.10.
1. Install xen hypervisor and utilities
sudo apt-get install xen-hypervisor-4.1-amd64 xen-utils-4.1 xenwatch xen-tools xen-utils-common xenstore-utils
sudo apt-get install virtinst virt-viewer virt-manager
2. Restart os, choose the xen kernel, verify xen installation
# xm info
# brctl show
3. Config your xend
$ sudo vim /etc/xen/xend-config.sxp
comment out (xend-unix-server yes) at the file, that means make sure the following line exists or been added :
(xend-unix-server yes)
#vi ~/.bashrc , add the following line:
export VIRSH_DEFAULT_CONNECT_URI="xen:///"
4. Restart, choose the xen kernel, and verify libvirt
# virsh version
Compiled against library: libvir 0.8.3
Using library: libvir 0.8.3
Using API: Xen 3.0.1
Running hypervisor: Xen 4.0.0
Conguratulations, all packages installed successfully.
5. Run virtual machine manager to manage your vms.
# virt-manager
Then you will see the screen virtual machine manager screen:
Create virtual machine in virt-manager,
error occur when finish creation, and show something like:
if ret is None:raise libvirtError(‘virDomainCreateLinux() failed’, conn=self)
….
/usr/lib64/xen/bin/qemu-dm: ….
that means qemu-dm could not be found, try to fix it:
#mkdir /usr/lib64/xen -p
#cp /usr/lib/xen-4.1/* -r /usr/lib64/xen/
then continue to finish creation of the virtual machine, still error occured, and show something like:
libvirtError: POST operation failed: xend_post: error from xen daemon: (xend.err …
or something like this:
libvirtError: POST操作失败: xend_post:来自 xen 守护进程的错误:<Fault 3: ”>
check the error log, it will give you some clues:
# less /var/log/xen/xend.log
the log shows error occured and logged at /var/log/xen/qemu-dm-demo.log, check it:
# less /var/log/xen/qemu-dm-demo.log
it says /usr/share/qemu/keymaps/en-us could not be found, the keymaps really does not exist in my disk.
and find it at /usr/share by :
#ls /usr/share/qemu (and press Tab, it shows qemu-linaro exist)
so just copy it to fix:
#cp -r /usr/share/qemu-linaro/ /usr/share/qemu
then continue to finish the vm creation. Wow, it works!














