User Tools

Site Tools


Translations of this page:



faq

FAQ

How to send traffic

Standard approach: Send traffic directly to your domain root:

http://mycj.com/

The script extracts the trader's domain from the HTTP referrer.

Alternative: Specify the trader explicitly in the URL:

http://yourdomain.com/?id=trader.com

where `trader.com` is the trader's domain.

Skimming 101

The setting “101” is a special value meaning “use the default skimming percentage.” You can't actually skim more than 100%. For example, if your default is 60% and you set a rule to 101, that rule will use 60% skimming. Any other value (0–100) overrides the default with a custom value.

Skimming params

You can add parameters to skimming values using the format `skim#options`, where options are `var=value&var2=value2`, etc. Currently this applies mainly to Tube switch rules, but may be useful elsewhere.

When `tube_embeded_switch_rules` is enabled, the first click normally goes to your sponsor. However, you may want to keep certain traffic (like direct search engine visitors or visitors from external links) on your site. To disable the sponsor redirect for specific cases, use:

100#tube_embed_switch_rules=off

This sets 100% to content and disables the sponsor redirect.

To apply the setting only to the first click:

100#tube_embed_switch_rules=off,100

The rule applies only to the first click; subsequent clicks use normal settings.

Skim Priority by Entity

By default, skimming priority is: 1. URL parameter (highest priority) 2. Trader's personal settings 3. Default skimming from CJSettings (lowest priority)

You can change this priority order in the settings by dragging parameters up and down.

Skimming list

You can set different skimming values for each click in sequence. For example, `100,60` means the first click gets 100% skimming and the second (and all subsequent) clicks get 60%. The last value repeats indefinitely. To alternate, list the pattern as needed: `100,60,100,60,100,60,100,60`, etc.

You can also specify traders or rules in the list. For example:

100,trader.com,60,sell,50

The 1st click is skimmed at 100%, the 2nd goes to trader.com, the 3rd is skimmed at 60%, the 4th goes to sales, and the 5th+ are skimmed at 50%.

You can also add parameters:

100#skip_sell=true,50

Here, `#skip_sell=true` disables sales traffic on the first click even if sales rules are configured. Subsequent clicks use 50% skimming.

URL variables

You can use environment variables in trader URLs, sales URLs, and redirects. The available variables are `$_GET` and `$_SERVER`. For example, when selling traffic to `http://broker.com/`, you can track the source:

http://broker.com/?from={SERVER_HTTP_HOST}

This passes your domain name. Useful when copying settings to multiple domains.

You can also pass page parameters:

out.php?url=http://gallery.com/?from={GET_slug}

Here, `{GET_slug}` pulls the `slug` parameter from the current page URL.

Example with rewrites: - Visible URL: `http://domain/gallery/cool_gallery.html` - Real URL: `http://domain/scj/cgi/out.php?url=content&slug=cool_gallery` - Available GET parameters: `url` and `slug`

To pass the slug to your sales broker:

http://broker.com/?broker_parameter_for_slug={GET_slug}

When clicked, `{GET_slug}` becomes `cool_gallery`, resulting in:

http://broker.com/?broker_parameter_for_slug=cool_gallery

Real Skimming

Real Skimming shows the actual ratio of content clicks to trade clicks. It can differ from your set skimming in either direction.

Example 1: If your top traders are set to 100% skim (all to traders) and your default is 50%, the real skimming might be 40% because top traders are getting extra traffic.

Example 2: If your homepage categories force 100% content clicks, your real skimming will be higher than 50%.

Last Clicks

This metric shows the percentage of users who stopped clicking after leaving your site for a trader. It's a measure of how well that trader retains visitors for return visits.

First Click

To ensure the first click always goes to content, set skimming to `100,50` — the first click gets 100% content, and all subsequent clicks get 50%.

MySQL Settings

Database credentials are stored in `scj/includes/config.php`.

Traffic Adding

Testing traffic quality: If you buy traffic from a source (like TrafficHolder), add a test trader (e.g., `podliv.com`) and mark it inactive. Send traffic to `/?id=podliv.com` to monitor its quality.

Many buyers test sources with trial-and-error, buying small amounts from different sources repeatedly.

Automate the process: 1. Buy traffic without specifying an ID; just send to `http://your_domain.com/` 2. Enable Settings > Processed Data > “Add Notrade as Inactive Traders” 3. The script automatically creates traders for each new referrer source 4. Track productivity from each source 5. Once you identify the best sources, buy more traffic from them exclusively

I forgot my admin password, how do I recover it?

You cannot recover the password, but you can reset it.

Option 1: Standard (HTTP Basic) Authorization

Use this if you did NOT click “Switch to multiaccess” in Settings > Password:

1. Rename `/scj/admin/.htaccess` to `/scj/admin/htaccess`
2. Access the admin panel (no password required now)
3. Change your password
4. Rename `/scj/admin/htaccess` back to `/scj/admin/.htaccess`

For nginx (which doesn't read .htaccess):

  1. Either regenerate `.htpasswd` from a domain where you know the password
  2. Or temporarily disable authentication in your nginx config, set a new password, then re-enable it (ask your admin if unsure)

Option 2: Multi-access Authorization

Use this if you clicked “Switch to multiaccess” in Settings > Password:

1. Create a file `/scj/admin/reset.php` with this content:
<?php
require('../includes/prepare.php');
db_query("update admins set password = MD5('admin') where login = 'admin' ");
echo 'Done';
2. Open `/scj/admin/reset.php` in your browser
3. Delete the `reset.php` file

Troubleshooting:

If you switched to multi-access and renamed .htaccess but still can't access the admin panel:

Problem 1: Directory protected by nginx or other server-level auth - Test by accessing `/scj/admin/test.php` — if it asks for a password, the directory is protected - Solution: Ask your admin to temporarily disable directory-level authentication

Problem 2: Server uses php_fpm - Create `/scj/admin/123.php`:

<?
   if (isset($_SERVER['PHP_AUTH_USER'])) {
      print_r($_SERVER);
   } else {
      header('WWW-Authenticate: Basic realm="SmartCJ Admin area."');
      header('HTTP/1.0 401 Unauthorized');
      echo 'Access Restricted';
      exit;
   }
?>

- Open it in your browser. If it still asks for a password after entering credentials, you have a php_fpm issue. - Solution: See http://smartcj.com/wiki/doku.php?id=ru:password#php-fpm_castcgi_multiaccess_problem

Alternative: Disable multi-authorization

Create `/scj/admin/reset.php`:

<?php
require('../includes/prepare.php');
db_query("update settings set value = '' where name = 'scj_admin_auth' ");
echo 'Done';
?>

Open it in your browser, then delete the file.

I changed my IP, but access in admin is limited by IP

To reset IP restrictions:

1. Create `/scj/admin/reset.php`:
<?php
require('../includes/prepare.php');
db_query("UPDATE settings SET value = '' WHERE name = 'admin_limit_ip' ");
echo 'Done';
?>
2. Open `/scj/admin/reset.php` in your browser
3. Delete the `reset.php` file

How to create an inactive trader that only receives forced hits

Add a trader with these settings:

  1. Active: Yes
  2. Ratio: 0
  3. Eligible for Exout hits: No

How to import traders from other scripts?

Go to Maintenance > Import Traders. The script supports importing from most popular scripts. If yours isn't listed, contact support to add it.

What is the Bookmarks field?

This estimates the percentage of surfers from a trader who bookmarked your site. The script tracks it by setting a cookie when a surfer arrives. If a surfer later returns with no referrer but still has the cookie, the script assumes they used a bookmark.

For galleries or internal pages:

Start with a simple link:

<a href="/somepage.html">Link Desc</a>

Add this JavaScript to the page:

<script type="text/javascript">
function scj_click(out_param, url) {
	var a = new Image;
	a.src="out.php?"+out_param+"="+url;
	return true;
}
</script>

Modify the link:

<a href="/somepage.html" onClick="return scj_click('url', this.href);">Link Desc</a>

For trader toplists:

Use the same JavaScript, but adjust the link format:

<a href="http://trader.com/" onClick="return scj_click('member', 'trader.com');">Link Desc</a>

(Replace `trader.com` with the actual trader domain.)

How to make a full database dump (mysqldump)

Access your shell (SSH) and run:

mysqldump -uLOGIN -pPASS DBNAME > dump.sql

Replace `LOGIN`, `PASS`, and `DBNAME` with your MySQL credentials.

To compress the backup:

gzip dump.sql

To restore from a backup:

mysql -uLOGIN -pPASS DBNAME < dump.sql

How to move to another server

Recommended approach:

1. Update the script to the latest version on the old server
2. Perform a fresh install on the new server
3. Restore the MySQL dump
4. Copy thumbnail files

If you prefer to copy the full installation:

1. Copy all files with permissions preserved
2. Update paths and credentials in:
   - `scj/admin/.htaccess`
   - `common.php` (all instances)
   - `includes/config.php`

Master-Slave setup:

Note that slave installations store the master database name. If you move and the master database name changes, update the slave's settings after migration to reflect the new master database credentials.

Keywords: script migration

How to rename the script folder

For new installations, choose the folder name during setup.

For existing installations, you can rename the folder, but update paths in:

  • `includes/config.php`
  • All instances of `common.php`
  • `admin/.htaccess`
  • URL rewrites:
    1. Apache: update `.htaccess`
    2. Nginx: update your nginx config file

Anticheat when selling traffic

This is a test solution for filtering bot/cheat traffic during sales by detecting JavaScript and image loading capabilities. If a surfer lacks JavaScript support, send them 100% to galleries.

Setup:

1. Create a User Var "Determine % of surfers without JS and images" that sets a `user_var` cookie via `user.php`
2. CJ Settings > Traffic Check > Cheat Hit: Set to "cookie doesn't exist" with the `user_var` name. If no cookie, the script counts it as a cheat click.
3. Sys. Traders > cheat_clicks: Set personal skimming to 100 so all cheat clicks always go to galleries
4. Traffic Sell: Configure sales only from trade clicks. Since sales come only from trade, you may get fewer trade hits and might need to reduce overall skimming.

Troubleshooting: If you receive a list of cheating IPs but can't find them, remember that the script stores data for the last 24 hours by default. Increase this in the “Keep Links, hours” setting if needed.

How to make "page rotation" only for certain traders

For example, we have pages niche_page1.html and niche_page2.html, which we would like to rotate only for certain traders. It's done like this:

  • create a file for example trader.php on the domain root
<?
$pages = array(
	'/usr/home/domain.com/niche_page1.html',
	'/usr/home/domain.com/niche_page2.html',
);

include($pages[rand(0, count($pages)-1)]);
  • write PATH (!!!) to trader.php as a personal page for the trader

What is the difference between Trade by country and Quality settings

These are 2 separate systems for managing traffic quality. Quality settings - these are discounts for certain countries. For example, clicks from country A are counted at a 50% discount, which means 2 clicks will be counted as 1. Which means less productivity, less debt, trader will receive less return.

Trade by country - this is the ability for a trader to send the same countries (in terms of quality) that he sends us.

So if both systems are enabled, the trader will conditionally return China and even less than he sent us.

Does it make sense to use both at the same time - you need to check on a specific site in practice.

Can you trade with toplists

Yes, a resetless toplist is a practical classic TGP. For reset toplists there is a convenient feature to determine the time when this toplist needs to be forced. In edit trader Other Settings - Site type you need to set Toplist and the script will check once a day the total number of hits on the toplist to determine the reset time. All detected resets are written there as well as visible in trade when you hover your mouse over the trader's domain (in the popup).

Why is there no web installer and why don't updates install from root

Web installer: Usually hacks happen from the web through scripts where input data is not checked. At the same time, they usually make a web shell - they upload a script to a directory which the web server can write to. The web server usually can write to a directory which has an owner the web server itself or write permissions (0777). If the script is installed from the web, all files and directories get the owner = web server. The downside is that if somewhere they break in, not only can they put a shell in any script directory, but they can also substitute out.php for example and take part of the traffic for themselves, and the site owner won't even suspect it. If you install the script from the shell, then files and directories get the owner = user and accordingly they can't be changed from the web.

Updates and root: an attempt to do good to the people :) If you ask any admin, they will tell you that the correct behavior is to never go to the server from root. You always go from a user, if you need root permissions you do su (sudo). Why is this bad in our specific case: if the script runs from root and cron from user - cron won't be able to change files (because owner is root). If it's installed from root and cron from root - then everything works well. But here's the problem: if they find a hole in the script, and no one is immune to that, the attacker will get a script running from root, which means they will be able to inject a rootkit - a program that will allow them to manage the entire server so that no one will notice, not only the site owner, but also often the admin.

Can crons be run not every minute

In\out don't work with the database so the load on MySQL doesn't affect the trade, and every minute the cron processes clicks for a minute and puts them in the database, recalculates traders and so on.

Crons can be run as often as you like, even once a day When cron runs it does the following:

  • calculates trader priorities (so if once a day then calculation once a day, etc)
  • creates a thumb for 1 trader per run
  • creates a toplist of traders

In general, nothing irreversible happens, you can set it as often as you like, if something doesn't work - you can write to support or just set cron more often.

How many sites will a server with such specs handle...?

A question of the sort “how many boxes will fit in a car?” - it depends 100% on the weight of the boxes, their size and the desire to optimally pack them.

For example, a site can be just 1 index page that can be cached and served at huge speed

10M galleries in the database with 3 types of sorting, 500 categories, 100k tags, search filtering, 10 custom variables etc - this is also 1 site.

Leave search on mysql - one load, don't lazy to configure sphinx - different load, and so on.

Mysql Backup

The script automatically makes a backup once a day, saves the last 3 days and deletes old ones.

The script tries to set the backup time to a random time so that if there are multiple copies on the server, they don't all backup at once. However, if the databases are large or the time randomly overlaps, scripts can back up simultaneously, which loads the server.

If you have so many scripts or such a size of databases that backups load the server, then the best option is to disable automatic backup in the script and set database backup to cron at a time when the server has the least load.

From general recommendations: 1. set backup to the time when load is the least 2. do backups in turn, so that only 1 mysqldump works at one time 3. do backup physically to another disk relative to where the databases themselves are located.

Abnormally high notrade prod

Notrade can have very high productivity, i.e. many clicks with a small number of inputs.

The question is that often notrade hits are hits made through Google translator. The situation is roughly as follows:

  • user came from trader, we remembered that conditionally IP 123.123.123.123 from trader asd.com
  • on the index (or category, it doesn't matter in general) the browser sees that the site is in English, and the user for example from India, and offers to start translating the site
  • the user agrees - from that moment all traffic starts coming from googleusercontent.com and Google's IP

As you can see at this point we get 2 problems:

  1. notrade shows unrealistic productivity
  2. there's an error in trader productivity

Theoretically, given that productivity for all traders decreases proportionally, this doesn't affect overall operation, however the display of notrade statistics suffers

To avoid this, you need to add this to the code

<meta name="google" value="notranslate">

According to Google's documentation this should help.

Feeders

How to count traffic from feeders:

1. the simplest option - create a conditional trader feeder.com and send traffic as http://domain.com/?id=feeder.com? all statistics for traffic are visible at trader feeder.com

2. Traffic comes from different sources and they change. Such traffic by default is counted in notrade. But you can auto divide it. In settings “Add Notrade as Inactive Feeder Traders” and each domain will be added as a new feeder.

There are 2 options:

- as separate trader - each will be as a separate trader, but then many traders will appear in the main screen trade and it's not very convenient - as subfeeder - here you need to send http://domain.com/?id=feeder.com (you need to create feeder.com first), then all referrers with their stats will be visible in feeder.com stats as subfeeders

If traffic comes without a referrer or referrer is changed then usually some parameter is transmitted in the URL. Then it's enough to turn this parameter into a referrer and the above methods will work.

For example, traffic comes as http://domain.com/?site_id=12345

Add to common.php

if (isset($_GET['site_id'])) {
   $_SERVER['HTTP_REFERER'] = 'http://feeder-' . $_GET['site_id'] . '.com/';
}

so the referrer in this case will be http://feeder_12345.com/ and it's easy to understand where this traffic is from. At the same time, if there are more parameters in the URL then the referrer can be formed so that it takes into account all these parameters, conditionally

$_SERVER['HTTP_REFERER'] = 'http://feeder-' . $_GET['site_id'] . '-' .  $_GET['some_other_parameter'] . '.com/';

by creating such a referrer, it's clear where the traffic came from

Recaptcha check

There's an interesting option to check traffic quality using recaptcha from Google. The essence is that Google writes what % of traffic it considers normal, not botted.

1. Go to https://developers.google.com/recaptcha, register and get Recaptcha V3 Site key Recaptcha V3 Secret key

2. enter these values in Rotation - Settings - Social

3. on any page, but 99% of the time this will be the index and category page add the code

<script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
<script src="https://www.google.com/recaptcha/api.js?render=<!--TUBE_RECAPTCHA_SITE_KEY-->"></script>

<script>
req_flag = false;
recaptcha_code = '';


if ('<!--RECAPTCHA_MAX_RATE-->') {
    if (Math.random() > '<!--RECAPTCHA_MAX_RATE-->') req_flag = true;
}


grecaptcha.ready(function() {
    grecaptcha.execute('<!--TUBE_RECAPTCHA_SITE_KEY-->', {action: 'index_page'}).then(function(token) {
       recaptcha_code = token;
    });
});


$(document).ready(function(){
	$('.gallery_link').each(function() {
		$(this).click(function(){
		    if (req_flag || recaptcha_code === '') return;
		    req_flag = true;

        	$.post('/',
	        {
                'action': 'check_recaptcha',
                'recaptcha_code': recaptcha_code,
    	    },
	        function (data) {

	        }
	        );

		});
	});


});



</script>

on links to galleries or categories add class='gallery_link' as in the example below

<thumb num=1-10>
<a class='gallery_link' href='/gallery/<!--GALLERY_SLUG-->/index.html'> <!--GALLERY_ID--> </a> <br>
</thumb>

you can of course replace gallery_link with anything, the meaning is that in JS we hang an event on these links $('.gallery_link').each(function() {

4. in the admin go to Settings - layouts - and enable the Google Recaptcha column

That's it, now you can see the percentage of good traffic in Trade - recaptcha column

PATH and URL

One of the common problems - misunderstanding (or carelessness?) of the difference between URL and Path.

URL - is something like http://domain.com/blabla/, i.e. the location of a file on the internet.

PATH - is the location of the file on disk.

Consider a simple example: on the server disk the directory with your domains is usually located approximately as /home/user/domain.com/. Suppose there is also a file 1.html there. The path to it is /home/user/domain.com/1.html The URL to the same file is http://domain.com/1.html

Periodically questions arise about relative and absolute paths. Relative path - is the path relative to the current position in the system, it can change. A path like /home/user/domain.com/1.html (here / at the beginning of the path indicates the root of the file system) - is an absolute path, it doesn't change.

This is expressed for example in the rotator, where to save thumbs there are 2 parameters: URL to data and PATH to data. You want them to be not in the scj directory (the URL to the thumbs becomes http://domain/scj/thumbs/1/2.jpg), but in /thumbs so that the path becomes http://domain/thumbs/1/2.jpg Your domain is in /home/user/domain.com/.

Script Update version 1 -> 2

The first branch of the script (1.X) is no longer being developed and in 2016 we completely switched to branch 2. If you have a version 1 script, to move to version 2 you need to

  1. install version 2 script on the same domain (but in a different folder) where version 1 is (you'll need a separate database)
  2. update version 1 to the latest available version
  3. in the shell go to scj/bin and run php scj_1to2_db_converter.php

The script will ask where version 1 is located and copy all the data from there.

Don't forget that if you have your own code in common.php then you also need to copy it.

PHP update

Due to changes in IonCube, now you need to prepare a separate file for each PHP version, i.e. what was written for PHP 5 won't work on PHP 7 and vice versa.

When you install the script it determines your PHP version and downloads files for your version. If you then change the PHP version you'll get a message that the downloaded files are for a different PHP version (the one it was installed on).

The essence of what you need to do: replace all PHP files of the script with files for the required version.

Options for how to do this:

1. simplest:

  • make a backup
  • update PHP
  • install the script from 0, it downloads files for the required version
  • restore the backup

2. for those who like to copy files

  • update PHP
  • install on 1 domain a version for the required PHP version
  • copy *.php files to other domains (except common.php and config.php)

3. if there are many domains with traffic

  • make 2 PHP versions, default - old, conditionally 5
  • install PHP 7
  • make a copy of domains, but on PHP 7, install everything as it was and switch to the new version by domain

Domain change

All data is stored in the database, so

  1. install the script on the new domain
  2. copy the backup to the new domain and restore it
  3. Settings - CJ Pages change to the actual path

That's all.

Optimize DB

The item simply runs the optimize command for the database; in most cases this makes sense for MyISAM tables; more details and officially you can read at the link https://dev.mysql.com/doc/refman/8.0/en/optimize-table.html

Truncate deletes all data from the table.

SimilarWeb Stats

The script can collect statistics for your traders from SimilarWeb. To do this, you need to get a free API key

  • register for free on similarweb
  • go to menu Account - API - Generated Keys
  • create a new key and enter it in Settings - Anticheat - Similarweb Api Key

How to hide the script

1. Put .htaccess in the scj folder

RewriteEngine On
RewriteCond %{REMOTE_ADDR} !^123\.255\.123\.255
RewriteCond %{REMOTE_ADDR} !^xxx\.xxx\.xxx\.xxx
RewriteRule ^(.*)$ - [L,R=404]

and it will give 404 to everyone except the specified IPs.

If you use nginx - this is written in its config.

It's important to write your server's IP here, otherwise Global Admin won't be able to collect statistics.

2. If your thumbs were by default in scj/thumbs then you need to either physically move them to the location you want, or make a symlink. If you know what a symlink is then you can do it without problems yourself, if you don't know what it is - it's better to move physically.

After that, the script needs to know where you moved them

- quickly: in the database in the rot_galleries table change the URL; if you don't know how to change in the database, better option 2 - slower - list thumbs - massedit - change part of the thumbs URL. As usual, it won't hurt to make a backup.

After that in Rotation → Setting → Graber Settings there are fields: URL to data and PATH to data URL, accordingly, change to /name_of_new_folder PATH - to /home/_path_to_domain/name_of_new_folder

How to change naming of parameters in URL

Let's say we have a parameter

&url=http://gallery

but we want to somehow cleverly encrypt the parameter. For this you need to:

1. in the template we have for example

&url=/gallery/<!--GALLERY_SLUG-->/index.html

this should be replaced with

&url=<?=your_super_function('/gallery/<!--GALLERY_SLUG-->/index.html');?>

2. as a result your function will somehow encrypt the specified text and we get for example

&url=sdfskldfkejhfklewhfklwerhfklwerhf

3. in common we need to decrypt for the script what you did, for example

if (isset($_GET['url'])) $_GET['url'] = your_decode_function($_GET['url']);

That's all.

Landing Pages

In the general stats and each trader's stats there is a list of URLs that traffic comes to.

Outlist and Priority

This is essentially what all traffic distribution comes down to.

Traders get priority by the calculation of Trade Formula. And also by forces (for example 1 fast force adds 10000 to priority so the trader is higher in priority).

Cron once a minute arranges traders by priority in the outlist (settings - out settings). With each click to out we send to the trader in accordance with probability in the outlist.

Conclusions that need to be understood:

1. if a trader is in the first position in outlist (and in priority) - not a fact that they will get the first click 2. if you have 10 positions in outlist, then in a specific minute the top 10 traders by priority get hits 3. if you set forces more than positions in the list, they will be given in turn, not all at once (and of course forces shouldn't be more than traffic)

Page Track

When moving around the site you can monitor which links traffic comes to, for this add &page_track=.. to the link

How to test script

It always makes sense to check that everything works as intended.

  • Enable in CJ Settings - Add debug comments, you will see additional information about each click.
  • if you need to test rules for a specific country in common.php for your IP you can add
  if ($_SERVER['REMOTE_ADDR'] == 'your IP') {
     $_SERVER['GEOIP_COUNTRY_CODE'] = 'country_code!';
  }

and this way you can test how rules work for the needed country.

Server Load

What can be turned off to reduce server load? Short answer - everything can be turned off. All that you can turn off in the admin - you can also turn back on if something is wrong.

In most cases it's easy to guess that if you turn off for example Process browsers, then you won't have browser statistics, but if you don't need it then ok.

If you want to look further than “the admin told me” and you can check basic things on the server, then it makes sense to read further.

You can compare server load to a situation where water flows into a pool through one pipe and out through another. It doesn't happen that “load is 120% but the server is holding!”. Either less water flows in than can go out and everything is fine, or the pool starts to fill up and after a while will overflow. Depending on the pool's capacity you can for some time pour more water than leaves, but to a certain limit and conditionally if you supply 150% of the pipe's throughput, the pool will overflow in a minute, and at 101% - in an hour.

What does pool overflow mean, a more realistic example:

On the server Apache runs (web server), mysql and the server serves files (static). 50% memory - static cache 20% - apache 30% - mysql

For example, mysql can handle 100 requests per minute.

If you give 110 then requests will queue up, memory will be allocated to store request data. Because of this mysql will take for example 60% of memory, and 20% will be left for cache. Because static isn't cached - server starts reading more from disk, taking up disk performance. Because of this mysql, which also works with the disk, drops in performance from 100 to 90 requests, it turns out the queue forms already with an excess of not 10%, but roughly 20% (90 is now the maximum, and we still give 110).

This increases the rate of queue growth, which further squeezes static out of memory = more disk load = mysql performance drops even more = queue grows even faster until at some point memory runs out.

That's why “everything was fine, but I just added a little bit” - doesn't lead to everything being “a little bit slower because of overload”, but overload leads to everything crashing (sharp performance degradation)

Sometimes an admin configures a server a bit more carefully and the server can drop requests when overload starts: conditionally 110 requests came in, the server just drops these 10 requests, the surfer doesn't see the site, but everyone is happy: the server isn't overloaded, the admin isn't bothered, the owner doesn't rack their brains why something is wrong, only traffic is lost.

Basically the script consists of 2 parts

  1. web part, which forms site pages getting info from the database
  2. what is executed by crontab (once a minute or less often)

Let's start with the web part.

You need to take your favorite option for viewing server load and check what mainly loads the server. In general, there are 3 parts: processor, memory and disk. There's also channel bandwidth, but we can skip that.

1. Processor: if a web server is at the top of the load (conditionally apache, nginx, php-fcgi and so on), i.e. everything that forms and shows the site page to the surfer, then most likely you have something heavy in the template.

Briefly: the template is processed in 2 steps. First, script tags are replaced with actual data, conditionally <!–ALT–> is replaced with actual text. Then the template is executed as PHP to execute your PHP code.

After step 1 the template is cached, this means that if the template has no PHP code, but only conditionally <!–ALT–> then on the next request of the same page the server will immediately get the ready HTML from the cache. This is very fast.

But often templates have includes of your PHP code. You need to remember that this code is executed on every request of every page and when writing it remember that you can cache something etc.

mysql: if mysql is at the top, then probably some query is not optimized. From what's heavy in the script: this is the most max orders <thumb order=rand because rand - is a very heavy operation for mysql (the script has easy_rand which somewhat solves the problem)

Or search: mysql searches much slower than sphinx (you need to switch to mysql fulltext or sphinx)

In general you need to go to mysql and check which queries hang at the top, maybe there's rand() or like % - then these are the cases above. If this isn't there, then contact us - we'll look closer, you need mysql root and ssh access immediately.

2. Memory and Disk - are related, which makes sense: if you need to serve the header.jpg file on every request, then you either cache it in memory and serve it without even accessing the disk, or you read from disk every time. Reading from disk is roughly 1000 times harder.

On average mysql tries to load as much of the database into memory as possible so it doesn't access the disk for data, and if there's enough memory, it will load the entire database into memory. After that, accesses to disk will only be for recording click statistics and when recalculating ctr.

Here comes the question of priority: we can load all the database and take conditionally 80% of memory and leave 20% for cache, or vice versa. What's the difference: for example we have a site with a database of 100 galleries. All don't fit in memory at once, you need to choose: load more database into memory or more static.

If traffic comes only to the main page, then it's important to load in memory html + all static of this page so we serve without accessing the disk. If it comes to all 100 galleries, then it's important to keep the database in memory so we form pages without accessing the disk.

For example, you chose to load the entire database into memory, but you have traffic coming only to a couple of pages. Because of the database, there's not enough memory to cache static = web servers (apache, nginx) constantly read from disk, and the site opens, but loads slowly.

It's clear that these parameters don't switch from the script. Here as usual there are 2 options: either you spend time figuring out your situation and optimally configure how much memory mysql can take, or you flush the problem with money, i.e. just take a server with more memory and everything fits in memory.

2. crontab

By cron (i.e. periodically) the script does several things:

  • cron.php - recalculates trader statistics (who owes how much, priorities), makes trader thumbs, backups, turns traders on and off etc.
  • rotation.php - updates thumb statistics in the database
  • gallery_grabber & gallery_checker - grabs thumbs and checks that galleries are available.

Can they be run not every minute - yes, even once a day, but it makes sense that if you run rotation.php once a day then all day the thumbs will be in the same position on the page. cron.php - trader priorities will change 1 time etc.

From all this follows the question: how many sites will such a server handle…? This question is from the category “how many boxes will fit in a car?” - it depends 100% on the weight of the boxes, their size and the desire to optimally pack them.

How cache works

How caching works on the internet

+------------------+
|  User             |
+------------------+
         |
         v
+------------------+
|     Browser      |
+------------------+
         |
         |
         v
+----------------------------------+
|        Browser cache             | if you cache the page here then the server
+----------------------------------+ and the script never know that
         |                           the user opened the URL
         v
+----------------------------------+
|        CDN                       | Same here, the request hasn't reached the server yet
+----------------------------------+
         |
         |
         v
+----------------------------------+
|     Web server                    |
|   (Apache / Nginx)               |   Web server can cache the page completely
+----------------------------------+   and the script won't know there was a request
         |        \
         |         \ request
         |          v
         |   +--------------------+
         |   |  Server cache       |
         |   | (files / Redis)     |
         |   +--------------------+
         |
         |
         v
+----------------------------------+
|     Script / Application         |  here the script knows there was a request
+----------------------------------+
         |        \
         |         \ request
         |          v
         |   +--------------------+
         |   |   Data cache        |
         |   | Redis \ memcache    |
         |   +--------------------+
         |
         v
+------------------+
|   Database       |
+------------------+

How the browser gets a page and where cache appears on the internet

When a user enters a site address in the browser, it seems that the browser “just goes to the server and gets the page”. Actually, the browser tries not to go to the server if possible.

The entire internet system is designed so that:

  • get the answer as quickly as possible
  • go as little distance as possible
  • involve as few servers as possible

For this, caches are used.

Step 1. Browser and browser cache

After entering the address, the browser first checks: “Do I already have this page?”

A browser can store:

  • ready HTML page
  • styles
  • JS scripts
  • images

If the needed data is already in the browser cache:

  • no request to the internet happens
  • the server doesn't know about the user at all
  • the page opens instantly

This is the fastest option.

Step 2. DNS - searching for the server address

If the browser still needs to go to the internet, first it needs to understand:

“Where to go?”

For this DNS is used. DNS translates the site name to an IP address

Step 3. CDN - a server closer to the user

If the browser still needs to go to the internet, first it needs to understand: After DNS, the request doesn't necessarily go directly to the main server.

Between the browser and the server there can be a CDN - a network of servers in different countries.

Example: the main server is in Europe, the user is in South America

If you always go to Europe:

  • the signal needs to go a long distance
  • the page will load slowly

CDN works like this:

  • first request goes to the main server
  • the answer is saved on the CDN server closer to the user
  • subsequent users get the page faster

CDN is convenient to use for content that doesn't change on every request

  • if CDN gives an answer from cache, the request doesn't reach the main server
  • the script doesn't know about the user

Step 4. Web server (Apache / Nginx)

If CDN couldn't give the page, the request comes to the web server. A web server is a program that takes HTTP requests.

The web server has a choice:

  • give a ready-made page (if it somehow knows what to give)
  • pass the request further to the script

If the web server has a ready answer:

  • it immediately returns the page
  • the script doesn't run
  • the script doesn't know there was a request
  • Apache can pass a request to the script 1 time and cache the answer

Important point: what is server cache. Server cache is not part of the web server and not part of the script.

This is:

  • separate storage
  • files, memory or Redis
  • roughly this is like a separate box in which anyone working on the server can put data

Once more for understanding. Server cache can be written to by:

  • web server
  • script
  • both at the same time

Step 5. Script (application)

If the request reached the script:

  • the script definitely knows there was a user
  • can record statistics
  • can decide to form the page again or give from cache

The script forms the page from data.

Important: not just the entire page can be cached, but also individual data.

Example:

  • site name is stored in the database and almost never changes
  • current date should be new every time

Then: the site name can be taken from the database 1 time and saved in the cache, and the date is formed anew each time

So not the entire page is cached, but only certain data from which the page is formed. So HTML is created on every request, requests exist, but load on the database is almost non-existent

Step 6. Database

If there's no data in any cache:

  • the script accesses the database
  • the database reads the data (here variants - if there's enough memory, MySQL keeps data in memory, if not - it reads from disk)
  • the page is completely formed anew

What you need to understand from all this

  • if the request didn't reach the script - the script simply doesn't know about it
  • page cache, Redis, memcache, server cache and a bunch of other words - this isn't important, this is just the name of the “boxes” where data is stored. What's important is only at which point and what exactly you cache
faq.txt · Last modified: 2026/04/20 13:54 by 127.0.0.1