简体   繁体   English

大型PHP会话减慢了Web应用程序的速度

[英]Large PHP session slowing down web application

I have a web application where complex permissions determine whether or not a user has access to each of thousands of different files. 我有一个Web应用程序,其中复杂的权限确定用户是否可以访问数千个不同文件中的每一个。 A user can see all files, but there is an indicator to open files that they have access to. 用户可以查看所有文件,但有一个指示器可以打开他们有权访问的文件。 A user has access to a file if someone else in their organization has access to it, or if someone that they are in a collaboration with has shared access to that file. 如果用户中的其他人可以访问该文件,或者他们与之合作的某人拥有该文件的共享访问权限,则该用户可以访问该文件。

Right now, I have a complex PHP function that generates a large PHP session by building arrays of the files a user has access to, either in their organization or their collaborations, and merging these access arrays. 现在,我有一个复杂的PHP函数,通过构建用户可以访问的文件数组(在组织或协作中)以及合并这些访问数组来生成大型PHP会话。 When these files are displayed to the user, PHP checks this array to see if they have access, and if they do, it adds the button to open the file. 当这些文件显示给用户时,PHP会检查此数组以查看它们是否具有访问权限,如果有,则会添加按钮以打开该文件。 I am doing it this way because running the query to check for access for each individual file ended up taking way too long when displaying long file lists, and PHP's in_array() was substantially faster. 我这样做是因为运行查询以检查每个单独文件的访问权限,在显示长文件列表时最终会占用太长时间,并且PHP的in_array()速度要快得多。

The problem is... 问题是...

The php session has gotten so large that it seems to be slowing down simple website functions to a crawl, and I need to think of a new way to do this. php会话已经变得如此之大以至于它似乎正在减慢简单网站功能的速度,我需要考虑一种新方法来实现这一目标。

My question is... 我的问题是......

What would be the best way to replace PHP sessions for storing file permissions and file locations for thousands of files a user has access to, so that when lists of files are being displayed, PHP can rapidly retrieve this information, without needing to run a query for each individual file? 替换PHP会话以存储用户有权访问的数千个文件的文件权限和文件位置的最佳方法是什么,以便在显示文件列表时,PHP可以快速检索此信息,而无需运行查询对于每个单独的文件?

Hm, without knowing the full scope of the problem, I'd suggest adding a Sessions table in your database and include a FilePermissions field and a UserId field. 嗯,在不知道问题的全部范围的情况下,我建议在数据库中添加一个Sessions表,并包含一个FilePermissions字段和一个UserId字段。

This field would store a json representation of your permissions structure. 该字段将存储权限结构的json表示。 This would only require one call to the database and the majority of the processing would take place while parsing the json data server-side (which shouldn't be much overhead at all). 这只需要对数据库进行一次调用,并且大部分处理将在解析json数据服务器端时进行(根本不应该有很多开销)。

This is a standard way to reduce the size of client-side session information. 这是减少客户端会话信息大小的标准方法。 A good rule of thumb is putting anything in the Sessions table that exposes the logic of your application. 一个好的经验法则是在Sessions表中放置任何公开应用程序逻辑的东西。

Update 更新

I would only store the files that they do have access to in the json field. 我只会存储, 他们必须在JSON现场访问的文件。 Non-existence can be assumed as prohibiting them from accessing the files. 可以假设不存在禁止他们访问文件。 This would again reduce the performance footprint. 这将再次降低性能足迹。

This would only work if there isn't a complex permissions structure (like each file has permissions for read and write). 只有在没有复杂的权限结构时(例如每个文件都具有读写权限),这才有效。 If it doesn't, I'd say you're in the clear. 如果没有,我会说你很清楚。

I'm not sure there is much you can do. 我不确定你能做多少。 Perhaps memcached can help, but I haven't used it (although, from what I heard, that's what it's used for). 也许memcached可以提供帮助,但我没有使用它(尽管,从我所听到的,这就是它的用途)。

You could persist the array in a file, although, as far as I know, that's exactly what sessions do. 您可以将数组保存在文件中,但据我所知,这正是会话的作用。

You could also try using shared memory to persist user data in-memory between script launches. 您还可以尝试使用共享内存在脚本启动之间将用户数据保留在内存中。

Do you really need the entire list of user's permissions in one single array? 您是否真的需要在一个阵列中使用用户权限的完整列表? That is, do you always display thousands of files to the user? 也就是说,您是否总是向用户显示数千个文件? If so, why? 如果是这样,为什么? Would it be possible to redesign the system using AJAX to lazily fetch only a portion of files? 是否有可能使用AJAX重新设计系统来懒惰地只获取一部分文件?


UPDATE: Another idea. 更新:另一个想法。

You could also precalculate permissions of the user for each file and store that in the database. 您还可以为每个文件预先计算用户的权限,并将其存储在数据库中。 Table could be called FilesPermittedPerUser and have two-column primary key userID / fileID . 表可以称为FilesPermittedPerUser并具有两列主键userID / fileID This will create an index that is sorted first by userID , then by fileID . 这将创建一个首先按userID排序,然后按fileID排序的索引。 A two-column key would also enforce uniqueness of entries. 双列密钥也会强制条目的唯一性。

Since it would then be indexed by user, you can simply ORDER BY userID and LIMIT 10, 10 to list only files 10-20. 由于它将由用户编入索引,因此您可以简单地按ORDER BY userIDLIMIT 10, 10来仅列出文件10-20。 Fetching only parts of the list via AJAX would mean you'd never cause the terrible memory load that your scripts currently cause. 通过AJAX获取列表中的部分内容意味着您永远不会导致脚本当前导致的可怕内存负载。

It would only require that whenever permissions of the file are updated (for example, file is created, file is deleted, group permissions are changed, group membership of user is changed, group membership of file is changed...) you would have to update the table. 它只需要每当更新文件的权限时(例如,创建文件,删除文件,更改组权限,更改用户的组成员身份,更改文件的组成员身份......),您将不得不更新表格。 I suspect this should not be too difficult. 我怀疑这不应该太难。 Just make sure you do cache update in a transaction, to preserve operation atomicity. 只需确保在事务中执行缓存更新,以保持操作原子性。

You may also want to organize the filesystem in folders. 您可能还希望在文件夹中组织文件系统。 It makes very little sense to just throw tons of files at users and have to maintain them at all times. 向用户扔掉大量文件并且必须始终维护它们是没有意义的。 Try throwing 10.000 files at Explorer/Finder/Nautilus and see what happens when you open that folder. 尝试在Explorer / Finder / Nautilus上抛出10.000个文件,看看打开该文件夹时会发生什么。 Nothing nice, and they get to keep the memory around - and with PHP you don't. 什么都不好,他们可以保持记忆 - 而PHP则不然。

Final idea (although you probably don't have to go to these extremes): rewrite filesystem APIs in something that isn't PHP and can keep the permission data around. 最后的想法(虽然你可能不必去这些极端):在非PHP的东西中重写文件系统API并且可以保留权限数据。 Use PHP only to forward requests to this custom server that runs on a different. 仅使用PHP将请求转发到在其他服务器上运行的自定义服务器。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM