Old topic: revisit the session that was difficult

Time:2019-11-9

Original address: https://t.ti-node.com/thread/

This is basically an old topic. Almost all PHPer will be asked questions about session in the first interview. If there is no accident, it is usually the following three axes:

  1. What is PHP session
  2. Where and when does PHP session exist
  3. What’s the difference between session and cookie in PHP

These three questions can be called the three basic questions about PHP session. If you don’t master them well, it will directly lead to the interview hanging up, which is very sad.

Briefly review the above three questions:

  1. The translation of session into Chinese is mostly conversation. We know that the HTTP protocol is a stateless protocol, which means “you don’t know which calf initiated this HTTP request at all” or “you never know whether the HTTP request is the last husky or the last fat guy”. So to solve this problem, PHP introduces session to mark “to” Who initiated this HTTP request. In PHP, PHP will generate a random session ID for each different user. Each user has a different session ID. In every interaction with the server, the user is identified by the session ID. It is very easy for PHP to generate session. Just call the session_start() function directly, as shown in the following figure is the generated session file:

Old topic: revisit the session that was difficult
Where sess is the file prefix, followed by “njjf8l3lh**FF6 “is your session ID. But now the content of the session file is empty. If we use the following code, we can generate the content of the session file:

<?php
//Open session
session_start();
$_SESSION['hello'] = 'world';

Refresh the web page, and then check the original session file again, which will contain the following contents:
Old topic: revisit the session that was difficult
That is to say, what you save to the global variable $session is essentially PHP, which stores it to the server as text. The server reads the corresponding session file according to your session ID and then reads out the content, and you will get your $\.

  1. By default, the session of PHP is stored in the system disk in the form of file. In PHP 7.0.28 running in Ubuntu 16.04 system, the session is stored in the / var / lib / PHP / sessions folder. You can check and confirm it through the session.save_path in the php.ini configuration file. The expiration time of PHP is determined by the PHP configuration item session.gc ﹣ maxlifetime. The unit of the value is seconds, and the default value is 1440. That is to say, when the specific last modification time of the session file exceeds 1440 seconds, the session file is expired.It is worth noting that the expired session file does not mean that it will be deleted immediately by the garbage collection mechanism, or it may remain for some time.So, when will it be deleted? This depends on the two configuration items of session.gc-probability and session.gc-advisor. The ratio of these two options (session. GC ﹣ probability / session. GC ﹣ divisor) is the probability of triggering the garbage collection mechanism. For example, (1 / 100) can be simply and roughly understood as “once every 100 requests are generated, the PHP garbage collection mechanism will be triggered to delete expired session files”. So you remember: if you want an exact expired session file in PHP At least, the default session configuration is absolutely impossible. In other words, it’s not all because PHP doesn’t start a separate thread or process to scan garbage, so we can only use this “probability” to solve this problem, not impossibleOld topic: revisit the session that was difficultOld topic: revisit the session that was difficultOld topic: revisit the session that was difficult
  2. At the beginning of the article, in order to find out whether it’s husky or fat, we have to introduce additional tag data. In fact, the first cookie and the second session are all generated to solve this problem. Their enmity lies in:

    • Cookies exist on the client side, while sessions exist on the server side, so sessions are relatively safer
    • The server can read session and cookies, but the client (that is, the browser) can only read cookies
    • By default, session is inseparable from cookies. In the final analysis, the “safe session usage” must rely on cookies to eat. Because session ID is saved by a cookie, the client browser will carry the cookie every time it sends a request. The default name of the cookie is phpsessid, and the value is session ID.
    • If you can’t use cookies, then session is not really unavailable. When cookies are disabled, sessions can be delivered by using URL through configuration, that is, query string is directly exposed in the URL, which is very insecure and frightening. This method is not recommended seriously, and even should be directly disabled!
    • The cookie size is slightly Limited (it is said to consider using localstorage instead?) , session is relatively loose

About these, I don’t need to elaborate any more. I suggest you cooperate with php.ini file to study the above three problems.

If we really only review these three questions, isn’t it true that we should “open content 1-5 with the title as fierce as a tiger”? As I said, I’m a serious blog site. It’s a real PHP culture site with some connotations. I can’t just talk about some primary content. It’s a topic that we should try to put some high-end things into the site anyway.

Old topic: revisit the session that was difficult

Just mentioned, session is saved in a folder of the server in the form of a text file by default. People who are interested in it should know that “too many files in a directory will reduce the reading efficiency”. Therefore, when using some PC software, you can see that these software will disperse the data needed by TA to different subdirectories. PHP session files can do the same. Generally speaking, they are relatively simple and crude. We need to focus on the following two PHP configuration items:

  • One is session.save_handler. The default value of this product is “files”, that is, files
  • One is session.save_path. The default value of this product is a directory path, such as / var / lib / PHP / session. Now we change this value to something like session.save_path = “n; / path”, where n is a positive integer. The meaning of this value is to divide the directory into several levels, such as session.save_path = “2; / var / lib / PHP / sessions”, restart Apache or FPM process manager, and execute the following code:
<?php
echo "let rock session";
session_start();

Refresh the web page as shown in the following figure:
Old topic: revisit the session that was difficult
Compared with the error causes, you can see that “/ var / lib / PHP / sessions / N / J /” does not exist. Switch to this directory, as shown in the following figure:
Old topic: revisit the session that was difficult
As expected, it is empty, that is to say, there is no subdirectory / N / J. it seems that it has been created manually. However, you really can’t create it by hand, because where do you know the name of the folder? Go back to the configuration file and find the following words near the session.save path configuration item:

; NOTE 1: PHP will not create this directory structure automatically.
;         You can use the script in the ext/session dir for that purpose.
; NOTE 2: See the section on garbage collection below if you choose to
;         use subdirectories for session storage

English is rather poor. It may be translated as follows:

; note 1: PHP will not help you create these folders at all. Download the PHP source package yourself and go to the session directory of the EXT directory to find the script to create
; note 2: if you want to use subdirectories to store sessions, remember to look at garbage collection. If you don't look, there will be a pit. (I'll tell you directly here, that is to say, you need to make your own subdirectory to store sessions. Then my garbage collection mechanism, which can be triggered only by faith and probability, will not be triggered at all. You can figure out your own way to handle your expired sessions. I don't care.)

So, we download a PHP source package. It’s better to extract the PHP source package that is the same as your running environment version. The command line is cut to the EXT / session directory, as shown in the following figure:
Old topic: revisit the session that was difficult
Do you see the mod_files.sh? This is the script under Linux. Mod_files.bat is for windows. Add execution permission to Chmod + X mod_files.sh, and then check the following usage:
Old topic: revisit the session that was difficult
In order to help the nearsighted readers, please translate the usage:

. / mod_files.sh 'session file root' directory depth hash function bit size
My PHP development environment is:
./mod_files.sh /var/lib/php/sessions/ 2 5
The first item is the root directory where you store the session, the second item is the N, and the third item is the session.hash'bits'per'character configuration item

Then execute as shown in the following figure:
Old topic: revisit the session that was difficult
At this time, go to / var / lib / PHP / sessions to check and see if there is a directory. Then, refresh the web page again, and you may still encounter errors that were supposed to be very smooth, as follows:

session_start(): open(/var/lib/php/sessions/n/j/sess_njjf8l3lhfrpq8nrlnl1d9qff6, O_RDWR) failed: Permission denied (13)

Vaguely recognizing the letters permission denied seems to be a permission problem. Is it because the current Apache process user or FPM process user does not have permission to write data to these directories? Change the owner of these directories to WWW data, and try again. It’s really good!

There are always diaobin who think this can solve a big problem, but it’s tragic that it’s not. At present, this solution can solve the problem of too many session files to some extent, but there are still two problems not solved:

  1. It’s still file storage. If the amount of access is too large, the read io of session file from the hard disk may become the bottleneck of the program. Of course, SSD speed will be much better
  2. If the website is deployed to two servers respectively, the session cannot be shared and fails. What do you mean? In order to ensure high availability, the website program is on server a and server B respectively, and then uses a nginx to balance the load at the front. A certain HTTP request of passerby a may be assigned to either a or B. The session file generated by passerby a on a will be saved on the hard disk of server a, but not on server B. if the user’s request is hit on B, unfortunately, the session is lost, some data will be lost, and passerby a will scold customer service. In other words, server a and server B need to share the same set of sessions!

In this way, we introduce a problem, that is, how to solve the problem of session sharing in Distributed Web deployment!

I don’t want to sell it. It’s not interesting. The first thing I think about is redis. It’s OK to provide a C redis server for a and B. in this way, I can solve the problem “more quickly, better economy” at one stroke! As expected, the introduction of redis can successfully solve three problems:

  • Memory level read and write speed, Shua Shua!
  • Session is easy to share, even if the business server continues to expand horizontally to server D in the future
  • The expiration of the session can finally be accurate to seconds. If you say no, you will not have to rely on faith and probability

To save a session to redis, you need to modify the following two PHP configurations: first, set session.save_handler = redis, and then set session.save_path = “tcp://127.0.0.1:6379”. Then restart Apache or FPM to refresh the webpage. If there is no error reported on the webpage, the session data has been sent to redis in theory. Connect redis to view the key, as shown below:
Old topic: revisit the session that was difficult

From the top to the bottom, I executed five redis commands, respectively

  1. View all keys to get the session file name assigned to me by PHP
  2. Get the remaining time of this key. After expiration, redis the key is invalid
  3. Looking at the data type of the key, you can see that it is a string type
  4. Get the value of string directly
  5. After a period of time, I refreshed the webpage again, and then used TTL to see the remaining time of the key again, which was extended to 1440 seconds again

In addition to redis (I won’t give an example for Memcache, which is similar to redis), another solution is to realize it through NFS sharing. The general principle is to get a server that can read and write to all PHP service servers through intranet sharing. You know that disks can be mounted in a folder under Linux, so NFS can be mounted in a directory of each PHP service server , and then follow the above article to modify the response configuration. I haven’t tried this, and I’m too lazy to try it on my own, so I’ll just throw a connection for you. It’s an article on Lao Ye’s blog, “I MySQL | Lao Ye teahouse, PHP realizes NFS sharing of multi server session sharing”.

After installation, if there is any problem, leave a message and correct it quickly!

Recommended Today

Explain idea git branch backoff specified historical version

scene When I submitted this modification to the local and remote branches, I found that there were still some changes missing in this submission, or this modification was totally wrong, but I also pushed it to the remote repository. How to go back? problem How can the content that has been submitted to the repository […]