Fast CGI

(click to open)

Quick Page Table of Contents


FastCGI Service

This is a collection of mutiple FastCGI tips, including what to collect if you are working with service on a problem. Most of the FastCGI tips offered here for PHP will also work for other PASE FastCGI OS languages compiled/loaded on your IBM i machine (ie, Ruby, perl, etc.).

PHP Zend Server tunning

Following these simple suggestions, you can optimize your PHP on IBM i environment.

  • Allocate IBM i resource correctly
A full power processor fits many production environments,
while partials like 0.25 - 0.75 usually not.
  • Make sure you have a valid Zend license - Valid licenses enable optimizing some internal options.
Click on Administration tab
Check Update License section
  • Use dynamic FastCGI - Optimized method of accessing the Web
DynamicServer type="application/x-httpd-php" MinProcesses=5 MaxProcesses=100 ... 
(See FastCGI Dynamic PTFS below)
  • Turn off all Zend Server code tracing, monitor, debug features great tools when developing code, but adds overhead.
Click on Server Setup tab
Click on Components tab
  • Turn off checking for changed PHP include files (production only) - Use this when you code is in a state of flux, otherwise, turn it off.


These PTFs may fix your issue, start here.

PASE loader fix (possible PHP crash)
PTF MF52700 (v5r4m5)
PTF MF52710 (v6r1m0)
PTF MF52838 (v6r1m1)
PTF MF53041 (v5r4m0)

FastCGI socket fix (fix hangs and slow downs):
v5r4m0 PTF MF51560
v5r4m5 PTF MF51562
v6r1m0 PTF MF51559
v6r1m1 PTF MF51561
v7r1m0 PTF MF51572

FastCGI socket auth (fastcgi.conf "switch profile" setting -- less common):
Release	57**DG1 PTF       57**SS1 PASE PTF
i 5.4   SI41577, SI41688  SI41324
i 6.1   SI41253, SI41704  SI41326
i 7.1   SI41367, SI41706  SI41325

FastCGI enable Dynamic FastCGI setting (performance):
V5R4: SI43218  V5R4: SI43221
V6R1: SI43243  V6R1: SI43224
V7R1: SI43244  V7R1: SI43222

Example dynamic FastCGI for Zend Server (PHP):
; Dynamic PHP servers for default user (all one line)
DynamicServer type="application/x-httpd-php" MinProcesses=5 MaxProcesses=100 CommandLine="/usr/local/ZendSvr/bin/php-cgi.bin" SetEnv="LIBPATH=/usr/local/ZendSvr/lib" SetEnv="PHPRC=/usr/local/ZendSvr/etc/" SetEnv="PHP_FCGI_CHILDREN=1" SetEnv="PHP_FCGI_MAX_REQUESTS=0" ConnectionTimeout="60" RequestTimeout="60" SetEnv="INSTALLATION_UID=20110323113634153552" SetEnv="LDR_CNTRL=MAXDATA=0x40000000"
; Where to place socket files
IpcDir /www/zendsvr/logs
;Minimum and Maximum of dynamic servers
MinDynamicServers 5
MaxDynamicServers 100

PHP DB2 performance?

0) Allow commit
   ; change allow commit
   ; 0 = default (crtlib); 1=allow commit

1) Use db2_pconnect() - persistent connections
   change script 
     -- change to --
   Remember with persistent connections ...
   ... you must commit transactions to avoid undesired rollbacks.
     Use db2_free_result($stmt) when doing SELECTs (reads),
     to sudo close cursors, thereby allowing commands 
     for operator functions like CLRPFM to work.
     (QSQSRVR jobs remain active during sudo close,
      but operator actions like CLRPFM will 
      drop SHRRD locks)

2) Override PHP script and force db2_pconnect()
   ; change all connections to persistent connections (performance improvement)
   ; 0 = default ; 1 = db2_connect(x,x,x)->db2_pconnect(x,x,x)

3) If you MUST use full open/close connections (not recommended), 
   a) forget about user profiles and call DB2 in-line php-cgi jobs
   ; change all connection to in-process php-cgi (entire site must co-operate)
   ; 0 = default ; 1 = db2_(p)connect(x,x,x)->db2_(p)connect(null,null,null)

   b) Do not put full open/close in a loop
       for() { db2_connect(); ... do stuff ...; db2_close(); }
       for () {
         ... do stuff ...

Other Apache performance?

Often times you can find easy major performance improvements to your site by using fast caching built into IBM i Apache for selected non-PHP files. There is a whole section of documentation covering how to do this in the FRCA link below.

Self help FastCGI bad CCSID looping or PHP DB2 junk returning??

Likely you have a bad fastcgi configuration.

Which Apache file is FastCGI???
I. Apache:  /www/zendsvr/conf/httpd.conf <-- this file (ILE side)
DefaultFsCCSID 37
  It is a very good idea to set these, so DB2 works with PHP (and other PASE things).
  Mandatory setting if you are trying to run on a QCCSID 65535 machine
  as shipped default from IBM (dspsysval qccsid).
  At times these settings alone may not be sufficient for PHP,
  and you will need the following PASE specific FastCGI setting.  

II. FastCGI: /www/zendsvr/conf/fastcgi.conf <-- THIS file (PASE side)

1) Bad fastcgi.conf CCSID setting for PASE side FastCGI.
  DynamicServer type= ... CCSID=37 
  --or (37 is bad, so is 65535) --
  StaticServer type= ... CCSID=37
  Try a PASE CCSID 819 typical or 1208 (DBCS).
    Setting EBCDIC CCSID will cause unknown issues like FastCGI looping
    because PASE side of FastCGI will have no idea what you are doing,
    so check the PASE locales carefully before setting (above link).

2) Bad fastcgi.conf LANG setting (ie. English not installed on the machine.)
  DynamicServer type= ... LANG=en_US 
  --or (only bad if secondary language not installed) --
  StaticServer type= ... LANG=en_US
  Try default LANG=C, which works nearly anywhere (UNIX default).
    PASE locales are included with separately installed language groups, 
    not in BASE IBM i OS. FastCGI will likely loop attempting to recover 
    until you install any missing language, so make sure your secondary
    languages is actually installed on the machine before starting.

Self help CCSID 65535 command line PHP Db2 jun??

when using call qp2term, ssh myi, etc., i had to change parent shell job(s) ccsid to 37 before running command line php/pear worked with ibm_db2 SQL/XMLSERVICE (php-cli, pear, etc.).

Example: Jobs I had to chgjob (37) ...
QPADEV0004   ADC         BCI      .0  PGM-bsh
QPADEV0004   ADC         BCI      .0  PGM-tcsh
QPADEV0004   ADC         BCI      .0  PGM-sh
... all shells from call qp2term or ssh connections to 65535 machine.

Then php command line db2 tests work ...
call qp2term -- after pops up use another screen to chgjob (37) to  PGM-sh
export PATH=/usr/local/zendsvr/bin:$PATH
export LIBPATH=/usr/local/zendsvr/lib
php-cli mytest.php
-- or --
php mytest.php

Self help FastCGI/PHP looper (100% CPU) or waiter (0% CPU)??

Assuming configuration already good (above), here is a simple suggestion to help you detect an issue if you can not already see the problem area using the Zend monitor tooling (very good tooling).

Take a quick wrkactjob look at active PHP job(s) stacks and see where you are, and very often the API name you see in the stack will be exactly the PHP API you are calling in your PHP script.

  • script acting slow — wrkactjob see what you are calling …
  • script eating CPU — wrkactjob see what you are calling …

This will only work if the problem is occurring while you view the stack dumps with wrkactjob …

  wrkactjob (5=Work with)
  5      ZENDSVR      QTMHHTTP    BCI     4.3   TIMA

  11. Display call stack, if active
  P    php-cgi.bin                      0000008C  __start
  P    php-cgi.bin                      000008F4  main
  P    php-cgi.bin                      000001A4  fcgi_accept_request
  P    unix                             00000008  <syscall32>:naccept
  *Note: Example stack above is completely normal (fastcgi waiting for work) 

… but it works a high percentage of times and is very useful if Zend Tools are off (probability theory rules).

FastCGI data for service?

Stacks will only work if the problem is occurring while you take the stack dumps.

1) Collect Apache configuration
   Example (two files): 
     Apache:  /www/zendsvr/conf/httpd.conf
     FastCGI: /www/zendsvr/conf/fastcgi.conf
2) Stacks live FastCGI analysis (similar to wrkactjob above)
   1. Start a service tool
   2. Dump to printer (or view)
   2. Licensed Internal Code (LIC) data
   14. Advanced analysis
       Option  Command                                                             
       1      processinfo                     
       Command . . . . :   PROCESSINFO
       Options . . . . .   -names zend  
3) PASE VLOGs (historical information not live data)
   1. Start a service tool
   5. Licensed Internal Code log  
      0100xxxx  i5/OS PASE               4700  0012 - PASE coredump
      0100xxxx  i5/OS PASE               4700  0100 - PASE panic                             

FastCGI ServerUserID and UserID and .html as .php (html with embedded php)

As of this date, Apache ServerUserID and UserID settings do not work correctly on IBM i for FastCGI, so you are left with default QTMHHTTP for your php-cgi children accessing any.php files. IBM understands this issue.

QTMHHTTP — Glass half full, glass half empty … RPG CGI people will be use to “switch profile” to default QTMHHTP1, which works well because these is no such thing as RPG embedded in html documents. However, qtmhhttp default for both .php and .html can be VERY HANDY as many times you WILL HAVE php embedded in your html documents (below).

> pwd 

> cat today.html 
<body class="page_bg">
Hello, today is <?php echo date('l, F jS, Y'); ?>.

Note for those not familiar with embedded php in html using FastCGI, you will need a .htaccess file with RewriteRule ^([^/]*)\.html$ $1.php in the directory attempting force PHP to process .html files as .php (see below).

> pwd

> ls -al
total 80
drwxrwx---    2 qtmhhttp 0              8192 Jun 26 17:52 .
drwxrwxrwx    9 qtmhhttp 0              8192 Jun 26 16:52 ..
-rwxrwx---    1 qtmhhttp 0                53 Jun 26 17:51 .htaccess
-rwxrwx---    1 qtmhhttp 0               111 Jun 26 16:55 today.html
-rwxrwx---    1 qtmhhttp 0                54 Jun 26 16:59 another.php

> cat .htaccess 
AddType application/x-httpd-php .html
AddHandler fastcgi-script .html

For html as php serving you must remove httpd.conf AddCharset UTF-8 ('text/html; charset=utf-8', which has no handler set on fastcgi) 
#AddCharset UTF-8 .htm .html .xml


Tony “Ranger” Cairns - IBM i PHP / PASE