我想听听你对一个项目的看法。无论是现在还是将来,我开始自己的方式,慢慢地提出许多差距和问题,都会产生大问题。
该系统将具有通知系统、好友系统、消息系统(专用),以及一般的此类系统。所有这些都是我设置的:jQuery、PHP、mysqli往返,避免冗长。我正在理解标题所说的。
如果所有这些都做一个简单的PHP代码,并为3-4个在线用户发布和获取方法,那将是令人惊叹的!问题是,当我有几个用户时,我能做些什么来更好地利用服务器的资源?所以我开始寻找更多,发现像这个插座。io
我只想有人告诉我,谁知道什么是最好的选择。想想更新通知系统现在是如何工作的。jQuery带有post,每3-5秒重复一次,但这绝不是正确的。
如果您的目标是建立一个高度可扩展的通知服务,那么可能不是
这不是一个严格的否定,因为除了速度还有其他因素需要考虑,但当谈到速度时,请继续阅读
WebSockets确实为用户提供了一个持续开放的双向连接,从本质上讲,这种连接非常快速。此外,客户端不需要请求新的信息;在任何一方认为合适的时候发送。
然而,就生成内容的成本而言,连接本身所节省的时间可以忽略不计。您进行了多少次数据库调用来检查新通知?您生成了多少结构化数据来让客户端知道如何更改通知图标?您从磁盘或通过网络读取数据的次数?
当使用任何WebSocket服务器时,这些相同的成本都不会消失;它只是让一种缓解技术变得更加明显:将用户的通知状态保存在内存中,并在通知更改时进行更新,以防止代价高昂的磁盘、数据库和服务器本地网络访问。
已知的经验证的技术,可以降低服务快速变化的网络内容的时间成本:
反向代理(清漆缓存)
位于端口80上,充当一个非常瘦的web服务器。如果请求的内容不在代理的RAM缓存中,它会将请求发送到"真正的"web服务器。这对于提供很少更改的内容(如图像和脚本)特别有用,并且对于大多数保持不变但有一些无法缓存的小元素的内容,它具有边缘包含。。。例如,在电子商务网站上,产品的描述、图像等可能都被缓存,但显示用户购物车内容的HTML不能,因此是边缘包含的理想候选者。
这将大大降低系统负载,因为使用磁盘IO的请求将少得多,而磁盘IO是一种比内存IO更有限的资源
内存键值存储(Memcached)
就创建一个可扩展的通知系统而言,这可能会给你带来最大的回报。
还有其他内存中的键值存储系统,但这一个系统在PHP中内置了支持,不仅一次,而且两次!(在PHP核心开发的伟大传统中,他们决定考虑弃用损坏的版本,而不是修复损坏的实现,而没有实际将该系统标记为弃用,并发出适当的警告等,这将使人们停止使用损坏的系统。mysql_v.mysqli_,我看着你…)(使用memcached版本,而不是memcache。)
无论如何,这很简单:当您频繁调用数据库、文件系统或网络时,将结果存储在Memcached中。当您通过网络更新记录、文件或推送数据,并且该数据用于存储在Memcached中的结果时,请更新Memcached。
然后,当您需要数据时,请先检查Memcached。如果它不存在,则进行漫长而昂贵的磁盘、数据库或网络访问。
请记住,Memcached不是一个持久的数据存储。。。也就是说,如果重新启动服务器,Memcached会完全清空。您仍然需要一个持久的数据存储,所以仍然可以使用您的数据库、文件和网络。此外,Memcached被专门设计为易失性存储器,只快速提供访问次数最多、更新次数最多的数据。如果数据变旧,可以将其擦除,为新数据腾出空间。毕竟,RAM很快,但它远不如磁盘空间便宜,所以这是一个很好的折衷方案。
此外,没有关键值存储系统是关系数据库。建立关系数据库是有原因的。您不想围绕键值存储编写自己的ACID保证包装器。您不希望在键值存储中强制执行引用完整性。键值存储的一个奇特名称是"无SQL"数据库。请记住:您可能会从Cassandra等获得横向可扩展性,也可能从Memcached等获得惊人的速度,但您无法获得SQL以及RDBMS经过几十年的发展。
最后:
不要混用语言
如果在实现了反向代理和内存缓存之后,您仍然想实现WebSocket服务器,那么您将获得更多的权力。请记住您选择的服务器的含义。
如果您想将Socket.io与Node.js一起使用,请用Javascript编写整个应用程序。否则,请选择与系统其他部分使用相同语言编写的WebSocket服务器。
1语言解决方案示例:
<?php // ~/projects/MySocialNetwork/core/users/myuser.php
class MyUser {
public function getNotificationCount() {
// Note: Don't got to the DB first, if we can help it.
if ($notifications = $memcachedWrapper->getNotificationCount($this->userId) !== null) // 0 is false-ish. Explicitly check for no result.
return $notifications;
$userModel = new MyUserModel($this->userId);
return $userModel->getNotificationCount();
}
}
...
<?php // ~/projects/WebSocketServerForMySocialNetwork/eventhandlers.php
function websocketTickCallback() {
foreach ($connectedUsers as $user) {
if ($user->getHasChangedNotifications()) {
$notificationCount = $user->getNotificationCount();
$contents = json_encode(array('Notification Count' => $notificationCount));
$message = new WebsocketResponse($user, $contents);
$message->send();
$user->resetHasChangedNotifications();
}
}
}
如果我们使用socket.io,我们将不得不编写两次MyUser类,一次是用PHP编写,一次用Javascript编写。谁敢打赌这两种语言中的类将以相同的方式实现相同的逻辑?如果两个开发人员正在处理类的不同实现,该怎么办?如果在PHP代码中应用了错误修复程序,但没有人记得Javascript,该怎么办?