The Cache: Technology Expert's Forum
 
*
Welcome, Guest. Please login or register. September 21, 2019, 02:01:35 AM

Login with username, password and session length


Pages: [1]
  Print  
Author Topic: [EXPERT QUESTION] Maximum Sessions on Mysql+PHP+Apache project on a dedie  (Read 4778 times)
basura
Rookie
**
Offline Offline

Posts: 13


View Profile
« on: January 28, 2008, 09:32:16 AM »



Hi there /guru/programmer's i return today with an exciting question....

As system administrator and newbie PHP developer:
I have some php code that can allow a lot of users connected at same time (800 users), its a basic CMS with auth on mysql database,
its done some optimizations on the code, for example using eaccelerator, mysql_max_connections... on a dedicated server with 1Gb RAM -only-
and other dedicated server behind serving images.

Its not round robin enabled, so when the maximum users get connected i can afford more at same time his sessions...
I have peaks of users asking for images.

I have 2 solutions, one are buying more expensive servers (+100$ each one with 100mbps SLA) and the others are asking for same same problem on expert's to try to get an easy solution.

Do you have some problem like mine?

I would be in contact with high-heavy-traffic SEO's to see how are resolving this issue.

It would be nice how to optimize PHP code, or routines, and try to avoid this on the future...

^_^  Thanks in advance SlimeL0RD

Logged

No links in signatures please
perkiset
Olde World Hacker
Administrator
Lifer
*****
Offline Offline

Posts: 10096



View Profile
« Reply #1 on: January 28, 2008, 01:02:05 PM »

How'z eAccellerator treating you? I chose APC over it for performance reasons.

Are you doing your own caching? I have a CMS for my users that allows them to manage large websites on their own. If the page has not changed it is held in RAM for easy return. Pseudocode looks something like (bear in mind this is APC based, eA would be slightly different):

Code:
<?php

if ($pageBuff apc_fetch($_SERVER['REQUEST_URI']))
{
echo $pageBuff;
exit;
}

// process page completely...

apc_store($_SERVER['REQUEST_URI'], $theCompletedPageString);

// end of php...

?>


This little bit essentially avoids almost my entire PHP routine for pages that don't need to be reconstructed and also avoids the fast, but more kludgy-in-this-situation use of squid. In most cases this has increased throughput by a factor of 10, no lie. Downside: RAM. Big site? you'll need to be careful about your usage. You could consider ram-zipping the file if you wanted to, but you'd need to see how heavy that is under load. Another option is, if your site is header/footer/content or theme/content based (all of mine are) is to store the header/footer in one cached item and the body-content in another. This would reduce the memory footprint of your pages considerably, particularaly since the outer HTML (header/footer or theme) is essentially redundant.

You could even avoid the memory concatenation of this process with this:

Code:
<?php

if ($content apc_fetch($_SERVER['REQUEST_URI']))
{
$header apc_fetch('myHeader');
$footer apc_fetch('myFooter');
echo $header$content$footer;
exit;
}

?>


The thing you're really looking for is high throughput, because 800 concurrent users in an Erlang matrix is an awful lot of page pulls. (Erlang math essentially can be used to describe chaotic or clumpy usage of a resource - we used it to calculate load against our callcenters) - think about it this way: if you can halve the time it takes to produce halve of your pages, you can return 150% of the pages you currently are with the same resources. With a 10-to-1 ratio the benefit is 1000% increase in performance and everything will feel generaly snappier in general because of the way the resource is used. Of course YMMV, but this is how I go at it and get very good results.

/p

<edit>
I forgot to mention, that as of APC 3.0.13, you can supply an array for apc_fetch, so you could get multiple items at once ie., apc_fetch(array('header', 'footer')) which would return an array with both items instead of two distinct pulls.
</edit>
« Last Edit: January 28, 2008, 01:07:56 PM by perkiset » Logged

It is now believed, that after having lived in one compound with 3 wives and never leaving the house for 5 years, Bin Laden called the U.S. Navy Seals himself.
chide
Rookie
**
Offline Offline

Posts: 20


View Profile WWW
« Reply #2 on: February 03, 2008, 08:56:23 PM »

Perk - purely out of curiosity, how many page loads do you see a day over all your networks?
Logged
thedarkness
Lifer
*****
Offline Offline

Posts: 585



View Profile
« Reply #3 on: February 03, 2008, 09:34:52 PM »

<edit>
I forgot to mention, that as of APC 3.0.13, you can supply an array for apc_fetch, so you could get multiple items at once ie., apc_fetch(array('header', 'footer')) which would return an array with both items instead of two distinct pulls.
</edit>

I think it's worth noting perk that this was restricted to one dimensional arrays last time I checked so if you need to store a multi serialize it first.

This looked to be an interesting approach on the last modified/ttl front but I haven't tested it yet;

http://php.net/manual/en/function.apc-store.php#70896

Cheer,
td
Logged

"I want to be the guy my dog thinks I am."
 - Unknown
perkiset
Olde World Hacker
Administrator
Lifer
*****
Offline Offline

Posts: 10096



View Profile
« Reply #4 on: February 03, 2008, 10:24:09 PM »

I think it's worth noting perk that this was restricted to one dimensional arrays last time I checked so if you need to store a multi serialize it first.
Lost me on that one TD - the requesting array must be one dimensional or course - because it wouldn't make sense to use an array of names you want to request in a multi dimensional format... but you can store multi dimensionals in APC no problem... the only thing I know of that doesn't store right is references and system handles (file handles and such) - unless I'm way off base here... am I missing something?
Logged

It is now believed, that after having lived in one compound with 3 wives and never leaving the house for 5 years, Bin Laden called the U.S. Navy Seals himself.
thedarkness
Lifer
*****
Offline Offline

Posts: 585



View Profile
« Reply #5 on: February 04, 2008, 03:20:08 PM »

I got my info. from the last two posts here perk;

http://au.php.net/manual/en/function.apc-store.php#70822

Is this not right?

Confused,
td
Logged

"I want to be the guy my dog thinks I am."
 - Unknown
perkiset
Olde World Hacker
Administrator
Lifer
*****
Offline Offline

Posts: 10096



View Profile
« Reply #6 on: February 04, 2008, 03:43:56 PM »

Well first off, that post is from Oct '06 LOL...

But this code returns a multi-dim array, as would be expected:

Code:
<?php

$outer 
= array();
$inner1 = array(1,2,3,4);
$inner2 = array(2,3,4,5);
$inner3 = array(4,5,6,7);


$outer['inner1'] = $inner1;
$outer['inner2'] = $inner2;
$outer['inner3'] = $inner3;

apc_store('outerArray'$outer);

echo 
"Stored...<br><br>";

$arr apc_fetch('outerArray');
echo 
"<pre>"print_r($arrtrue), "</pre>";


?>


Logged

It is now believed, that after having lived in one compound with 3 wives and never leaving the house for 5 years, Bin Laden called the U.S. Navy Seals himself.
jammaster82
Lifer
*****
Offline Offline

Posts: 666


Thats craigs list for ya


View Profile
« Reply #7 on: February 06, 2008, 03:02:22 AM »

(lemonheads)

Its a shame about 'array'.


well i tried 9 puns before this,
they didnt work, and this one
did kinda so i guess:

One pun, in ten did. (intended..)

 ROFLMAO
Logged

The watched pot, never boils... But if you walk away from it , the soup burns.  What gives?
perkiset
Olde World Hacker
Administrator
Lifer
*****
Offline Offline

Posts: 10096



View Profile
« Reply #8 on: February 06, 2008, 11:30:05 AM »

D'oh!
Logged

It is now believed, that after having lived in one compound with 3 wives and never leaving the house for 5 years, Bin Laden called the U.S. Navy Seals himself.
thedarkness
Lifer
*****
Offline Offline

Posts: 585



View Profile
« Reply #9 on: February 07, 2008, 06:12:11 PM »

Well first off, that post is from Oct '06 LOL...


 D'oh!
Logged

"I want to be the guy my dog thinks I am."
 - Unknown
basura
Rookie
**
Offline Offline

Posts: 13


View Profile
« Reply #10 on: February 14, 2008, 04:56:08 AM »

[Just tunning]

Here is an interesting document:

Im happy and burned out  my dedies!!!! ^_^  You must try.

Tunning:
[MYSQL] (/etc/my.cnf)
[LINUX] kernel /etc/sysctl.conf     --> restart after changes on /sbin/sysctl -p
[APACHE] inside /etc/httpd/conf/httpd.conf), KeepAlive, Timeout, MaxClients, MaxKeepAliveRequests, KeepAliveTimeout...





[MYSQL]
MySQL w 1Gb RAM:


fine tuning of MySQL 4.1.9 and here is what my.cnf file looks like for a 2GHz machine with 1GB of memory.

[mysqld]
socket=/path/to/mysql.sock
datadir=/var/lib/mysql
skip-locking
skip-innodb
# MySQL 4.x has query caching available.
# Enable it for vast improvement and it may be all you need to tweak.
query_cache_type=1
query_cache_limit=1M
query_cache_size=32M
# max_connections=500
# Reduced to 200 as memory will not be enough for 500 connections.
# memory=key_buffer+(sort_buffer_size+read_buffer_size)*max_connections
# which is now: 64 + (1 + 1) * 200 = 464 MB
# max_connections = approx. MaxClients setting in httpd.conf file
# Default set to 100.
#max_connections=200
#interactive_timeout=180
interactive_timeout=100
#wait_timeout=180
#wait_timeout=100
# Reduced wait_timeout to prevent idle clients holding connections.
#wait_timeout=30
wait_timeout=15
connect_timeout=10
# max_connect_errors is set to 10 by default
#max_connect_errors=10
#table_cache=256
#table_cache=1024
# Checked opened tables and adjusted accordingly after running for a while.
table_cache=512
#tmp_table_size=32M by default
#thread_cache=128
# Reduced it to 32 to prevent memory hogging. Also, see notes below.
thread_cache=32
# key_buffer=258M
# Reduced it by checking current size of *.MYI files, see notes below.
key_buffer=128M
# Commented out the buffer sizes and keeping the default.
# sort_buffer_size=2M by default.
#sort_buffer_size=1M
# read_buffer_size=128K by default.
#read_buffer_size=1M
# read_rnd_buffer_size=256K by default.
#read_rnd_buffer_size=1M
# myisam_sort_buffer_size=8M by default.
#myisam_sort_buffer_size=64M
# thread_concurrency = 2 * (no. of CPU)
thread_concurrency=2
# log slow queries is a must. Many queries that take more than 2 seconds.
# If so, then your tables need enhancement.
log_slow_queries=/var/log/mysqld.slow.log
long_query_time=2

[mysql.server]
user=mysql
basedir=/var/lib

[safe_mysqld]
err-log=/var/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid
open_files_limit=8192

[mysqldump]
quick
max_allowed_packet=16M

[mysql]
no-auto-rehash
# Remove the next comment character if you are not familiar with SQL
#safe-updates

[isamchk]
key_buffer=64M
sort_buffer=64M
read_buffer=16M
write_buffer=16M

[myisamchk]
key_buffer=64M
sort_buffer=64M
read_buffer=16M
write_buffer=16M

[mysqlhotcopy]
interactive-timeout

[client]
socket=/path/to/mysql.sock

Below are notes on some of the important variables, I took down while tuning the config file.

   1. query_cache_size:
          * MySQL 4 provides one feature that can prove very handy - a query cache. In a situation where the database has to repeatedly run the same queries on the same data set, returning the same results each time, MySQL can cache the result set, avoiding the overhead of running through the data over and over and is extremely helpful on busy servers.
   2. key_buffer_size:
          * The value of key_buffer_size is the size of the buffer used with indexes. The larger the buffer, the faster the SQL command will finish and a result will be returned. The rule-of-thumb is to set the key_buffer_size to at least a quarter, but no more than half, of the total amount of memory on the server. Ideally, it will be large enough to contain all the indexes (the total size of all .MYI files on the server).
          * A simple way to check the actual performance of the buffer is to examine four additional variables: key_read_requests, key_reads, key_write_requests, and key_writes.
          * If you divide the value of key_read by the value of key_reads_requests, the result should be less than 0.01. Also, if you divide the value of key_write by the value of key_writes_requests, the result should be less than 1.
   3. table_cache:
          * The default is 64. Each time MySQL accesses a table, it places it in the cache. If the system accesses many tables, it is faster to have these in the cache. MySQL, being multi-threaded, may be running many queries on the table at one time, and each of these will open a table. Examine the value of open_tables at peak times. If you find it stays at the same value as your table_cache value, and then the number of opened_tables starts rapidly increasing, you should increase the table_cache if you have enough memory.
   4. sort_buffer:
          * The sort_buffer is very useful for speeding up myisamchk operations (which is why it is set much higher for that purpose in the default configuration files), but it can also be useful everyday when performing large numbers of sorts.
   5. read_rnd_buffer_size:
          * The read_rnd_buffer_size is used after a sort, when reading rows in sorted order. If you use many queries with ORDER BY, upping this can improve performance. Remember that, unlike key_buffer_size and table_cache, this buffer is allocated for each thread. This variable was renamed from record_rnd_buffer in MySQL 4.0.3. It defaults to the same size as the read_buffer_size. A rule-of-thumb is to allocate 1KB for each 1MB of memory on the server, for example 1MB on a machine with 1GB memory.
   6. thread_cache:
          * If you have a busy server that's getting a lot of quick connections, set your thread cache high enough that the Threads_created value in SHOW STATUS stops increasing. This should take some of the load off of the CPU.
   7. tmp_table_size:
          * "Created_tmp_disk_tables" are the number of implicit temporary tables on disk created while executing statements and "created_tmp_tables" are memory-based. Obviously it is bad if you have to go to disk instead of memory all the time.

-->

[mysqld]

connect_timeout=15

interactive_timeout=100

join_buffer_size=1M

key_buffer=256M

max_allowed_packet=16M

max_connections=500

max_connect_errors=10

myisam_sort_buffer_size=64M

read_buffer_size=2M

read_rnd_buffer_size=2M

sort_buffer_size=2M

table_cache=1024

thread_cache_size=100

thread_concurrency=4

wait_timeout=300

query_cache_size=128M

query_cache_limit=1M

query_cache_type=1

skip-innodb


For people with a single CPU be sure to set thread_concurrency to 2 (4 is for Dual CPUs). People with 1GB of RAM, you might want to consider lowering the key_buffer to 64M and the myisam_sort_buffer_size to 32M. This really just depends on how much free memory your system has during peak traffic hours. If you increase these too much and your system runs out of physical RAM and starts swapping to disk, your system is going to eat it hard.

For more information about Mysqld variables, please read the following articles as they explain all the settings in-depth and how to fine-tune them: Article 1 and Article 2 and Article 3
http://www.databasejournal.com/features/mysql/article.php/1402311
http://www.databasejournal.com/features/mysql/article.php/3367871
http://www.databasejournal.com/features/mysql/article.php/3110171





With Dual 2.0GHz Xeon with 2GB of RAM running RedHat Enterprise:

[Linux]

/etc/sysctl.conf

tcp_window_scaling, sack, fack, etc, turned off, but I leave them on

/etc/sysctl.conf
CODE
# Kernel sysctl configuration file for Red Hat Enterprise Linux

# Controls IP packet forwarding
net.ipv4.ip_forward = 0

# Controls source route verification
net.ipv4.conf.default.rp_filter = 1
net.ipv4.conf.all.rp_filter = 1

# Disables IP source routing
net.ipv4.conf.default.accept_source_route = 0
net.ipv4.conf.all.accept_source_route = 0

# Controls the System Request debugging functionality of the kernel
kernel.sysrq = 0

# Controls whether core dumps will append the PID to the core filename.

# Useful for debugging multi-threaded applications.
kernel.core_uses_pid = 1

# Increase maximum amount of memory allocated to shm
# Only uncomment if needed!
# kernel.shmmax = 67108864

# Disable ICMP Redirect Acceptance
net.ipv4.conf.default.accept_redirects = 0
net.ipv4.conf.all.accept_redirects = 0

# Enable Log Spoofed Packets, Source Routed Packets, Redirect Packets
net.ipv4.conf.default.log_martians = 1
net.ipv4.conf.all.log_martians = 1

# Decrease the time default value for tcp_fin_timeout connection
net.ipv4.tcp_fin_timeout = 25

# Decrease the time default value for tcp_keepalive_time connection
net.ipv4.tcp_keepalive_time = 1200

# Turn on the tcp_window_scaling
net.ipv4.tcp_window_scaling = 1

# Turn on the tcp_sack
net.ipv4.tcp_sack = 1

# tcp_fack should be on because of sack
net.ipv4.tcp_fack = 1

# Turn on the tcp_timestamps
net.ipv4.tcp_timestamps = 1

# Enable TCP SYN Cookie Protection
net.ipv4.tcp_syncookies = 1

# Enable ignoring broadcasts request
net.ipv4.icmp_echo_ignore_broadcasts = 1

# Enable bad error message Protection
net.ipv4.icmp_ignore_bogus_error_responses = 1

# Make more local ports available
# net.ipv4.ip_local_port_range = 1024 65000

# Set TCP Re-Ordering value in kernel to '5'
net.ipv4.tcp_reordering = 5

# Lower syn retry rates
net.ipv4.tcp_synack_retries = 2
net.ipv4.tcp_syn_retries = 3

# Set Max SYN Backlog to '2048'
net.ipv4.tcp_max_syn_backlog = 2048

# Various Settings
net.core.netdev_max_backlog = 1024

# Increase the maximum number of skb-heads to be cached
net.core.hot_list_length = 256

# Increase the tcp-time-wait buckets pool size
net.ipv4.tcp_max_tw_buckets = 360000

# This will increase the amount of memory available for socket input/output queues
net.core.rmem_default = 65535
net.core.rmem_max = 8388608
net.ipv4.tcp_rmem = 4096 87380 8388608
net.core.wmem_default = 65535
net.core.wmem_max = 8388608
net.ipv4.tcp_wmem = 4096 65535 8388608
net.ipv4.tcp_mem = 8388608 8388608 8388608
net.core.optmem_max = 40960




=== >After you make the changes to the file, you can make them effective immediately by typing in /sbin/sysctl -p

Also, you will need to issue /sbin/sysctl -w net.ipv4.route.flush=1 to flush the routing table to make some of these changes happen instantly.


[...]
Logged

No links in signatures please
basura
Rookie
**
Offline Offline

Posts: 13


View Profile
« Reply #11 on: February 14, 2008, 05:05:26 AM »

[Apache]


httpd.conf:

Timeout 60
KeepAlive On
MaxKeepAliveRequests 1000
KeepAliveTimeout 10

Setting KeepAliveTimeout low you won't have all those lingering connections.

Increasing MaxClients to 256 consumes memory and its not really necessary. every apache process consumes memory, if it gets out of memory it would use HD disk...lowering performance..

remove and Dynamic Shared Object (DSO) modules that you do not use

set the AllowOverride option to None, prevents check .htaccess file in every directory.

A security tip is to Mask your Apache version by using the following settings:
ServerSignature Off
ServerTokens ProductOnly

Its recommended to Hide your PHP info by setting expose_php = Off in your /etc/php.ini file.




Cache Tunning:

Using eAccelerator as its said before on this post. Wink For php files to help reduce overhead and increase performance.





[Linux]


- net.ipv4.tcp_fin_timeout = 1800
- net.ipv4.tcp_keepalive_time = 1800

The above noted rules would create an undesired situation allowing attackers to easily D/DoS a system and overflow the network table with absurd amount of connections before they even begin to timeout.

I would recommend the following sysctl networking paramters:

# Decrease time between keepalives
net.ipv4.tcp_keepalive_time = 1200

# Decrease the time default value for tcp_fin_timeout connection
net.ipv4.tcp_fin_timeout = 25

# Allow more SYN backlog
net.ipv4.tcp_max_syn_backlog = 1048

# Lower syn retry rates
net.ipv4.tcp_synack_retries = 2
net.ipv4.tcp_syn_retries = 3


As with regards to rpfilter, source route, icmp, martians and similar you do not need to add the context for every interface -- simply add it for default and all so it will auto adapt to all interfaces on the system.

Beyond that nice set of sysctl rules; minus the later performance related sysctl rules which one would be advised to express caution when setting up.


Security MODS:

Mod_security and Mod_dosevasive  compiled and activated.



[Mysql tip]

MaxClients = RAM available for web server / MAX child's process size



.


Wink Keep on this thread if its interested in tunning or giving more performance on compiling PHP with some modules.

(I'm system adimnistrator...and i guess all uses Linux distros, im into Solaris too...)


Regards, aka SlimeLORD
Logged

No links in signatures please
perkiset
Olde World Hacker
Administrator
Lifer
*****
Offline Offline

Posts: 10096



View Profile
« Reply #12 on: February 14, 2008, 06:49:10 PM »

Great stuff both of you... gonna go over that with a fine toothed comb and see where my stuff can benefit.

Thanks!
Logged

It is now believed, that after having lived in one compound with 3 wives and never leaving the house for 5 years, Bin Laden called the U.S. Navy Seals himself.
Pages: [1]
  Print  
 
Jump to:  

Perkiset's Place Home   Best of The Cache   phpMyIDE: MySQL Stored Procedures, Functions & Triggers
Politics @ Perkiset's   Pinkhat's Perspective   
cache
mart
coder
programmers
ajax
php
javascript
Powered by MySQL Powered by PHP Powered by SMF 1.1.2 | SMF © 2006-2007, Simple Machines LLC
Seo4Smf v0.2 © Webmaster's Talks


Valid XHTML 1.0! Valid CSS!