January 4, 2014 · erlang yaws laravel concurrent world php

How to run Laravel on YAWS :

"There is no shame in being wrong, only in failing to correct our mistakes." - George Soros

Summary: In this article, I'll try to give some information about the concurrency philosophy of ERLANG. Also,I'll explain installing ERLANG, PHP (both CGI and CLI interfaces), YAWS and coding,compiling,including modules (appmode) to YAWS on an Ubuntu 12.04 based Linux distribution (elementary OS - Luna). Finally, we'll run Laravel welcome page on YAWS.

Disclaimer : The author cannot guarantee the validity of the information found here. The content of any given article may recently have been changed, vandalized or altered by someone whose opinion does not correspond with the state of knowledge or the actual product versions. The author cannot be held responsible for damages of any possible kind to you, your computer systems, your data, your working or home environment, which may be the result of direct or indirect use of the article, including documentation or software in source codes. A published article is by no means obliged to test, confirm, correct, approve the methods in an article before, after or during publishing. The article is provided at no charge. Therefore, it is completely unsupported and it is published with absolutely no warranty of any kind.

A short introduction to the technology :

What is YAWS?

Yaws Logo

YAWS (Yet Another Webserver) is a HTTP 1.0/1.1 webserver which is completely written in ERLANG. YAWS has been noted well suited for dynamic-content web applications in many cases. YAWS can work two different mode on your project / server:

What are the key advantages of YAWS that makes different than some other well-known webservers?

Performance, simplicity and high-availability.

I know the answer is a little bit unclear. Let me to the explain that.
But, before the clarification, you can look a comparison YAWS and APACHE via following link:

http://www.sics.se/~joe/apachevsyaws.html

What is ERLANG?

ERLANG Logo

ERLANG is a general-purpose functional programming language and runtime environment. ERLANG has built-in support for concurrency, distribution and fault tolerance. ERLANG is used in several large telecommunication systems from Ericsson. ERLANG is available as open source from http://www.erlang.org. *

About a year ago I met with concurrency world thanks to my dude kunthar.
If you're coming from of programming in imperative languages (such as C/C++, Java, Python, .Net, PHP, Ruby, PERL etc.) to ERLANG world, you have to forget most of things what you know about computer programming. ERLANG is a new thinking way -like many functional languages- which you have never been familiar. Also, I'll be covering the ERLANG in further articles.

For having a high-available system and stable application there are some clear requirements:

So, the answer is :

ERLANG Movie

What are the solutions of ERLANG?

"We can't solve problems by using the same kind of thinking we used when we created them." - Albert Einstein

The common question is there : If there are not neither object sharing, nor mutable state, even nor synchronized methods like locks; how communicates the processes? I'll cover a just short introduce fundamentals of ERLANG life cycle in this article. It seems a subject of an article series.

We can group the solutions of ERLANG under two main headers:

1 - Lightweight processes
2 - Copying & Message passing

Lightweight Processes:

The ERLANG Virtual Machine (ERLANG VM) runs as single OS process. ERLANG VM executes the just single operating system thread each core by default to achieve maximum efficient use of the machine.

ERLANG processes have no connection to either OS processes or OS threads. Actually, that means concurrent process are belongs to who created them : the language, not OS. The ERLANG processes are implemented entirely by the ERLANG VM. Because of all the facts, the ERLANG processes are "lightweight processes" and naturally lighter than operating system process. So even if you have over one million processes it is still only single operating system processes and single thread each core. BTW it's perfectly possible to own systems running numerous concurrent ERLANG processes, actually one good example is WhatsApp :


Copying & Message Passing :

Processes in ERLANG are extremely light-weight (significantly lighter than OS processes) and the amount of processes in typical any programs is large (in WhatsApp case more than hundred thousand processes on a single node). ERLANG’s concurrency fundamentals allow a process to spawn new processes and communicate with other processes through asynchronous message passing with copying semantics. Any kind of data value can be sent as a message and the recipient may be located on any machine on the network.

All data in messages between ERLANG processes is copied, with the exception of refc binaries on the same ERLANG node.*

When a message is sent to a process on another ERLANG node, it will first be encoded to the ERLANG External Format before being sent via an TCP/IP socket. The receiving ERLANG node decodes the message and distributes it to the right process.

Concurrency in ERLANG is achieved just by using three simple language constructs : spawn, send (!) and receive.

Message Passing

Let's explain the above figure. Actually to understanding ERLANG message passing you can think the action as some conversation between two persons . In this figure A represents you and B is your girlfriend. And you're in a very crowded place like an airport which everybody has different names. When you want to call your girlfriend you have to say her name. Because there would be many women. Let's closer look how realize that ERLANG between processes:

B!{self(),foo} = Annie! I am here, sweety.

First, we calling the name of the girl (B = Annie) with our message (foo = I am here, sweety.)

self() is returns the Pid (Process Identity) of the process executing this function. The action (calling the Annie) is also a process.

So, let's look closer to the Annie's (B) side:

recive              
    {From,Msg}->        
        Actions
end


someone is calling me (heard her name "Annie")
    {This is Stanley, He says something (I am here, sweety.)}
            I have to do or say something
...

If you aren't dating with a zombie the process will be something like that. :)

Sometimes when I read or write an ERLANG code, I feel myself in a some kind of real-life simulation. So you can think about the figures which at the below like some examples from real world.

concurrency programming in Erlang

Media source : http://www.erlang.org/course/concurrent_programming.html

concurrency actions

Media source : http://ferd.ca/an-open-letter-to-the-erlang-beginner-or-onlooker.html

Looks great huh? Yes, and I think enough for this article and a PHP/Python developer. Because if I'll continue to explain; I have to cover many things that my knowledge probably not enough yet such as supervisors, garbage collection, error handling and fault tolerance in ERLANG etc.

Why still coding PHP?

As a developer I believe that the tools, languages and development environments should be closer to the our project. For coding a portal that will not receive hundred thousand of requests, I'll prefer to use PHP because of its community and finding a group member is really easier than any others. So, we earn the money by realizing the wishes of who hires us. Look the chart at below an think about that :

Languages usage in web projects

If you ask the question to core development team of Facebook or any huge project's like facebook, probably they give an answer to you some kind of like:

Believe me, if I have enough money to fulfilling for a year all of my essentials, I will just learn ERLANG and an another functional programming language that not thinking like ERLANG when solving the problems. But, life is so expensive, like our experiences.

When we need to use YAWS?

If you face some memory problems that originating from your webserver, YAWS is a good choice in this situation. But you if you have performance problems that coming from your code, may the force be with you. First debug your code, if it doesn't work, try to :

rewrite

Installing ERLANG and YAWS on Linux

Installing ERLANG on Linux :

I suggest to you use packages which distributing by Erlang Solutions for installing ERLANG. Navigate the https://www.erlang-solutions.com/downloads/download-erlang-otp and download your system's package. You can find there always the latest version of ERLANG as packed.

Alternatively and my preferred way is adding repository to the package manager and install ERLANG via the package manager:

$ wget http://packages.erlang-solutions.com/erlang-solutions_1.0_all.deb && sudo dpkg -i erlang-solutions_1.0_all.deb

Update the repository cache and install the ERLANG package :

$ sudo apt-get update && sudo apt-get install erlang

This enough for installing ERLANG on any Ubuntu-based Linux distribution.

Installing YAWS on Linux :

First we need to get latest version of YAWS

$ wget https://github.com/klacke/yaws/archive/master.zip && unzip master.zip && cd yaws-master

Then compile & install the YAWS as root :

 # autoconf && ./configure --sysconfdir=/etc && make && make install && update-rc.d yaws defaults && /etc/init.d/yaws start

That's all. Now we need to PHP and Laravel

Installing Laravel PHP Framework on Linux :

YAWS supports the plain CGI for PHP very well. There are two common ways to run YAWS cgi script is either as regular CGI scripts or as PHP scripts through the php-cgi binary. So, we need to install both php-cgi and php-cli from repository. As you know Laravel needs to php-cli (PHP Command Line Interface) for installing or updating packages via composer.

$ sudo apt-get update && sudo apt-get upgrade

$ sudo apt-get install mysql-server mysql-client php5 php5-gd php5-mysql php5-curl php5-cli php5-cgi php5-dev php5-fpm php5-mcrypt

Let's do our webserver's document-root folder. I prefer to use /var/www folder. Because I keep the all data in another HDD partition which is mounted there. Executing the following single-line command as root is enough for creating the folder, installing Laravel and composer:

#mkdir /var/www && cd /var/www && wget http://github.com/laravel/laravel/archive/master.zip && unzip master.zip && rm -f master.zip && mv laravel-master/* . && rm -rf laravel-master/ && curl -sS https://getcomposer.org/installer | php && php composer.phar install

After all we have installed both PHP and YAWS. Well, we need to run PHP on YAWS and configure our first virtual host. As I've mentioned at the beginning of the section, YAWS supports the plain CGI. Actually, that means theoretically, that we can run any kind of CGI script on YAWS such as written in PERL, Python etc.. Hence, we do not need any extra modules such as lib-phpX and message passing module something like calling worker or itk.

Btw there is a problem, YAWS doesn't support .htaccess files. May be you thinking that url rewriting is troublesome in YAWS, but it's not so. Let's create our virtual host and then take a look at the url rewriting.

Configuring virtual hosts in YAWS :

Before start, I have to warn you about CGI FORCE_REDIRECT. Most of *nix systems compiling php-cgi without "--enable-force-cgi-redirect" by default for some security issues.

Enabling url-rewriting in php-cgi :

So, we need to enable CGI FORCE REDIRECT in our php-cgi's php.ini:

$ sudo cp /etc/php5/cgi/php.ini /etc/php5/cgi/php.ini.bckp
$ sudo nano /etc/php5/cgi/php.ini

and navigate to the "Paths and Directories" section in the file. There is a good comment about force redirect support. So, we have two alternatives here to enable the force redirect:

First of them is defining our doc-root :

doc_root = /var/www/public

Second of them is adding the following code under the section :

cgi.force_redirect = 0

It doesn't matter which alternative you choose. My preferred way is the second one without any reason. So now coming the funny part of the article.

Writing an appmod for enabling url-rewrite on YAWS :

The main issue is that most of PHP application frameworks (like Laravel, Codeigniter, Kohana, Zend etc...) and also almost all favorite PHP applications (like Joomla, Wordpress, Drupal, Prestashop, etc..) needs a . htaccess file for defining Apache's mod_rewrite rules. Because, the applications/frameworks forwards all requests over an "index.php" file for handling the URL routing and also dedicating static files (like images, JavaScript, CSS files etc..) to serving on Apache. Sometimes the method calling as SEF (SEO Friendly URLs).

In YAWS, appmods (application modules) are a cool way to let the application programmer take control over the URL path. *

YAWS coming with a clean and powerful API which calling as yaws_api and easily accessible under the shell:

$ man yaws_api

So, that means we need to code some ERLANG. Save the file with the name laravelurlrewrite.erl :

% File: laravelurlrewrite.erl

-module(laravelurlrewrite).
-author('ibrahim <at> drlinux.org').
-export([out/1]).
-include("/usr/local/lib/yaws/include/yaws_api.hrl").

out(Arg) ->
  FullPathFileName = Arg#arg.docroot ++ Arg#arg.pathinfo,
  IsStaticFile = filelib:is_regular(FullPathFileName),
  if
      IsStaticFile == true -> % The request equals to a static file
          [
              {page, Arg#arg.server_path} % Let Yaws the serve file
          ];
      true -> % Request is not equal a static file, call cgi responder
          yaws_api:call_fcgi_responder(Arg, [
              {extra_env, [
                  {"SCRIPT_FILENAME", Arg#arg.docroot ++ "/index.php"}
              ]}
          ])
  end.

Before clarification the code, we need to compile the file. First navigate to the folder where you saved the laravelurlrewrite.erl file. We have two ways to do this. First of them is using erlc, the ERLANG compiler:

$ erlc laravelurlrewrite.erl

The secondone is compiling the code inside the ERLANG shell (or in YAWS) with c(filename).:

    root@drlinux-samsung:~# erl
    Erlang R14B04 (erts-5.8.5) [source] [64-bit] [smp:4:4] [rq:4] [async-threads:0] [kernel-poll:false]

    Eshell V5.8.5  (abort with ^G)
    1> c(laravelurlrewrite.erl).

Both of two ways will create for us a beam file which is named as laravelurlrewrite.beam. The file is an Erlang Compiled Erlang Code file. Actually this is really very long to explain. But just you need to know the file can be load by ERLANG VM.

A short introduction to ERLANG compiler :

The first version of Erlang compiler was developed by Joe Armstrong in Prolog language in 1986. The current compiler is written in ERLANG itself. Today Erlang is compiled into two intermediate languages, first the Erlang source code is translated into something called Core Erlang and then later it is translated into BEAM assembler and then written to a binary file, a so called BEAM file. Between these different stages some code optimizations are done as well.*

Loading appmod and configuring the virtual host :

I prefer to keep the appmods under my application's folder together with the application files. That gives me easy manage,backup and porting my applications. But it is your choice, any directory (always accessible by the OS) suitable for keep 'em all. So, we need to create a directory and move the BEAM file into that:

# mkdir /var/www/app-erlang-mods
# cp laravelurlrewrite.erl /var/www/app-erlang-mods/

Let's explain the code in a short. The code basically listens all URL requests then fetching the file name with the path which requested. Then we call the ERLANG's file library for checking that "The requested file regular (did not created by any router class or something like that) or not?" As you can see above in my comments in the code, we serving the regular files on YAWS like before we did by Apache. The CGI scripts should interpret by it's interpreter. After interpreting, the result printing out by YAWS. It is an easy solution for the problem of mine, if you develop something better, please keep in touch with me. I would really like to learn some different methods.

Also, the time is the configuring the virtual host. We need to edit just a single file :

 $ sudo cp /etc/yaws/yaws.conf /etc/yaws/yaws.conf.bckp
 $ sudo nano /etc/yaws/yaws.conf

The file is typical *nix configuration file probably most of *nix user already familiar with it. You should edit your virtual machine like following :

# Add the path where laravelurlrewrite.beam (appmod) is located:
ebin_dir = /var/www/app-erlang-mods
# Virtualhost configuration
<server localhost>
      port = 80
      listen = 0.0.0.0
      #Add laravel's default routing path
      docroot = /var/www/public
      auth_log = true
      allowed_scripts = php yaws cgi
      #Add the path where located php-cgi
      php_handler = <cgi, "/usr/bin/php-cgi">
      appmods = <cgi-bin, laravelurlrewrite>
</server>

After, we need to reload YAWS :

# /etc/init.d/yaws restart

That's all guys, the result is at the below :

Laravel on YAWS Screenshot

Summary

During the article I've tried to explain ERLANG's basic fundamentals, YAWS web server and working with Laravel PHP Framework on YAWS. If you are a PHP developer you must take a look at Laravel. The framework will give you %30 - %40 more time in each project which you can spend anything else (may be learning ERLANG?).

Laravel 4 Book

You can order the book on Amazon safely. http://amzn.to/laravel-book

Please let me know to update the article, if you see anything that wrong.

I'm planning to cover Riak in the next article. So, until I publish the article you can read about a fresh language in the concurrent world by following the white rabbit.

  • LinkedIn
  • Tumblr
  • Reddit
  • Google+
  • Pinterest
  • Pocket
Comments powered by Disqus