zoukankan      html  css  js  c++  java
  • 解析 PHP 中 session 的实现原理以及大网站应用应该注意的问题

    一 PHP SESSION原理

    session 是在服务器端保持用户会话数据的一种方法,而 cookie 是在客户端保持用户数据。HTTP 协议是一种无状态协议,服务器响应完之后就失去了与浏览器的联系。那么,服务器是如何记住众多用户的会话数据呢?

    首先要将客户端和服务器端建立一对一联系,每个客户端都得有一个唯一标识,这样服务器才能识别出来。建立唯一标识的方法有两种:cookie 或者通过 GET 方式指定。默认配置的 PHP 使用 session 的时候会建立一个名叫 "PHPSESSID" 的 cookie(可以通过 php.ini 修改 session.name 值指定),如果客户端禁用 cookie ,也可以指定通过 GET 方式把 session id 传到服务器(修改 php.ini 中 session.use_trans_sid 等参数)。

    查看服务器端 /tmp 目录(在不修改 PHP 配置的情况下)会发现很多类似 sess_0fb45ob06s3ictc5qp98frvjl6 这样的文件,这个其实就是 session id "0fb45ob06s3ictc5qp98frvjl6" 对应的数据。真相就在这里,客户端将 session id 传递到服务器,服务器根据 session id 找到对应的文件,读取的时候对文件内容进行反序列化得到 session 的值,而保存的时候先序列化再写入。

    事实就是这样,所以如果服务器不支持 session 或者你想自定义 session,通过 PHP 的 uniqid 生成永不重复的 session id,然后找个地方存储 session 的内容即可。

    二 使用 SESSION 之前为什么必须先执行 session_start()?

    了解 session 的原理之后,所谓的 session 其实就是客户端一个 session id 对应服务器端一个 session file。新建 session 之前执行 session_start() 是告诉服务器要接收一个cookie 以及准备好 session 文件,要不然 session 内容怎么存;读取 session 之前执行 session_start() 是告诉服务器,赶紧根据 session id 把 session 文件反序列化。

    只有一个 session 函数可以在 session_start() 之前执行,session_name():读取或指定 session 名称(比如默认的就是 "PHPSESSID"),这个当然要在 session_start 之前执行。

    三 SESSION影响系统性能

    session 在大访问量网站上确实影响系统性能,影响性能的原因之一由文件系统设计造成,在同一个目录下超过10000个文件时,文件的定位将非常耗时,PHP支持 session 目录hash,可以通过修改 php.ini 中 session.save_path = “2;/path/to/session/dir”,那么 session 将存储在两级子目录中,每个目录有16个子目录[0~f],不过 PHP session 不支持创建目录,需要事先把那么些目录创建好。

    还有一个问题就是小文件的效率问题,一般 session 数据都不会太大(1~2K),如果有大量这样1~2K 的文件在磁盘上,IO 效率肯定会很差。

    其实还有很多中存储 session 的方式,可以通过 php -i|grep "Registered save handlers" 查看,比如 Registered save handlers => files user sqlite eaccelerator 可以通过文件、用户、sqlite、eaccelerator来存,如果服务器装了 memcached,还有 mmcache 的选项。当然还有很多,比如 MySQL、PostgreSQL 等等,都是不错的选择。

    四 SESSION的同步

    前端可能有很多台服务器,用户在A服务器上登录了,种下了 session 信息,然后访问网站的某些页面可能会跳到 B 服务器上去了,如果这个时候 B 服务器上没有 session 信息又没有做特殊处理,可能就会出问题了。

    session 同步有很多种,如果你是存储在 memcached 或者 MySQL 中,那就很容易了,指定到同样的位置即可,如果是文件形式的,你可以用 NFS 统一存储。

    还有一种方式是通过加密的 cookie 来实现,用户在A服务器上登录成功,在用户的浏览器上种上一个加密的 cookie,当用户访问B服务器时,检查有无 session,如果有当然没问题,如果没有,就去检验 cookie 是否有效,cookie 有效的话就在 B 服务器上重建 session。这种方法其实很有用,如果网站有很多个子频道,服务器也不在一个机房,session 没办法同步又想做统一登录那就太有用了。

    当然还有一种方法就是在负载均衡那一层保持会话,把访问者绑定在某个服务器上,那么所有访问都在那个服务器上就不需要 session 同步了。

  • 相关阅读:
    阿里DatatX mysql8往 Elasticsearch 7 插入时间数据 时区引发的问题
    通俗易懂 k8s (3):kubernetes 服务的注册与发现
    ReplicaSet 和 ReplicationController 的区别
    使用Go module导入本地包
    k8s之statefulset控制器
    终于成功部署 Kubernetes HPA 基于 QPS 进行自动伸缩
    Atitit drmmr outline org stat vb u33.docx Atitit drmmr outline org stat v0 taf.docx Atitit drmmr out
    Atitit all diary index va u33 #alldiary.docx Atitit alldiaryindex v1 t717 目录 1. Fix 1 2. Diary deta
    Atitit path query 路径查询语言 数据检索语言 目录 1.1. List map >> spel 1 1.2. Html数据 》》Css选择符 1 1.3. Json 》map》
    Atitit prgrmlan topic--express lan QL query lan表达式语言 目录 1. 通用表达语言(CEL) 1 1.1. 8.2 功能概述 1 1.2. Ongl
  • 原文地址:https://www.cnblogs.com/afee666/p/6888990.html
Copyright © 2011-2022 走看看