当前位置: 首页 > news >正文

山东威海网站开发采集数据做网站

山东威海网站开发,采集数据做网站,幼儿教育网站源码,用记事本做电影介绍的网站为何 Hyperf 能够在两个端口上监听 WebSocket 连接#xff1f; 源码角度来看#xff0c;在配置了多个 Servers 时#xff0c;实际上#xff0c;只启动了一个 Server 注#xff1a;我之前接触的代码都是启动一个服务绑定一个端口#xff0c;之前也看过 swoole 扩展的文档… 为何 Hyperf 能够在两个端口上监听 WebSocket 连接 源码角度来看在配置了多个 Servers 时实际上只启动了一个 Server 注我之前接触的代码都是启动一个服务绑定一个端口之前也看过 swoole 扩展的文档但是没留意服务和监听端口也是分离的这启发了我一种思维代码凡是能继续拆分的就继续拆分这样代码就会有更多的灵活每个功能都能进行扩展将服务和端口进行拆分之后就可以在一个 Server 绑定多个 Port每个 Port 又能有独立的事件。 /*** param Port[] $servers* return Port[]*/ protected function sortServers(array $servers): array {$sortServers [];foreach ($servers as $server) {switch ($server-getType()) {case ServerInterface::SERVER_HTTP:$this-enableHttpServer true;if (! $this-enableWebsocketServer) {array_unshift($sortServers, $server);} else {$sortServers[] $server;}break;case ServerInterface::SERVER_WEBSOCKET:$this-enableWebsocketServer true;array_unshift($sortServers, $server);break;default:$sortServers[] $server;break;}}return $sortServers; } 从源码看排在第一个的服务配置会被创建服务之后都是增加监听 protected function initServers(ServerConfig $config) {$servers $this-sortServers($config-getServers());foreach ($servers as $server) {$name $server-getName();$type $server-getType();$host $server-getHost();$port $server-getPort();$sockType $server-getSockType();$callbacks $server-getCallbacks();if (! $this-server instanceof SwooleServer) {$this-server $this-makeServer($type, $host, $port, $config-getMode(), $sockType);$callbacks array_replace($this-defaultCallbacks(), $config-getCallbacks(), $callbacks);$this-registerSwooleEvents($this-server, $callbacks, $name);$this-server-set(array_replace($config-getSettings(), $server-getSettings()));ServerManager::add($name, [$type, current($this-server-ports)]);if (class_exists(BeforeMainServerStart::class)) {// Trigger BeforeMainServerStart event, this event only trigger once before main server start.$this-eventDispatcher-dispatch(new BeforeMainServerStart($this-server, $config-toArray()));}} else {/** var bool|\Swoole\Server\Port $slaveServer */$slaveServer $this-server-addlistener($host, $port, $sockType);if (! $slaveServer) {throw new \RuntimeException(Failed to listen server port [{$host}:{$port}]);}$server-getSettings() $slaveServer-set(array_replace($config-getSettings(), $server-getSettings()));$this-registerSwooleEvents($slaveServer, $callbacks, $name);ServerManager::add($name, [$type, $slaveServer]);}// Trigger beforeStart event.if (isset($callbacks[Event::ON_BEFORE_START])) {[$class, $method] $callbacks[Event::ON_BEFORE_START];if ($this-container-has($class)) {$this-container-get($class)-{$method}();}}if (class_exists(BeforeServerStart::class)) {// Trigger BeforeServerStart event.$this-eventDispatcher-dispatch(new BeforeServerStart($name));}} } 从makeServer函数来看如果服务中有SERVER_WEBSOCKET则这个会被作为主服务启动,new SwooleWebSocketServer protected function makeServer(int $type, string $host, int $port, int $mode, int $sockType): SwooleServer {switch ($type) {case ServerInterface::SERVER_HTTP:return new SwooleHttpServer($host, $port, $mode, $sockType);case ServerInterface::SERVER_WEBSOCKET:return new SwooleWebSocketServer($host, $port, $mode, $sockType);case ServerInterface::SERVER_BASE:return new SwooleServer($host, $port, $mode, $sockType);}throw new RuntimeException(Server type is invalid.); } $this-registerSwooleEvents($this-server, $callbacks, $name); 这句代码会将 Websocket 的各种事件都注册进去于是主服务器拥有 websocket 的各种事件而后 http 服务器挂载 9501 端口上绑定了 onrequest 事件但是如果有 websocket 连接9501 端口上时默认该服务器是自动开启 websocket 自动升级的又因为监听 9501 端口绑定的主服务器是 WebSocketServer因此WebSocketServer 默认的 onmessageonopen事件就会被拿来用。 推测如果开启 9503 WebSocket服务器那么理论上用 WebSocket连接 9501 端口应该就是连接的 9503 的回调事件。如果不想让 http 监听端口自动开启 websocket 协议则将open_websocket_protocolfalse ?php return [ // 这里省略了该文件的其它配置 servers [[name http,type Server::SERVER_HTTP,host 0.0.0.0,port 9501,sock_type SWOOLE_SOCK_TCP,callbacks [Event::ON_REQUEST [Hyperf\HttpServer\Server::class,onRequest],],settings [open_websocket_protocol false,]],]];关于很多SWOOLE中出现的常量来看这些东西在执行脚本时会被自动设置好通过实际代码运行发现 define(SWOOLE_HTTP2_ERROR_COMPRESSION_ERROR, 9); define(SWOOLE_HTTP2_ERROR_CONNECT_ERROR, 10); define(SWOOLE_HTTP2_ERROR_ENHANCE_YOUR_CALM, 11); define(SWOOLE_HTTP2_ERROR_INADEQUATE_SECURITY, 12); define(SWOOLE_BASE, 1); define(SWOOLE_PROCESS, 2); define(SWOOLE_IPC_UNSOCK, 1); define(SWOOLE_IPC_MSGQUEUE, 2); define(SWOOLE_IPC_PREEMPTIVE, 3); 以下随便设置的一个test.php中输出SWOOLE_BASE,都能输出1我之前都以为这些常量是运行时设置的呢看来这种理解是错误的。 ?php echo SWOOLE_BASE.\n; echo hello\n;// 输出 1 hello Hyperf-skeleton 给的默认配置就是进程模式这个竟然没有发现这样就比较明确了使用的都是PROCESS模式那么在websocket连接时所有的连接都是由Manager来控制 SWOOLE_PRECESS 和 SWOOLE_BASE 两种模式 Server 的两种运行模式介绍 在 Swoole\Server 构造函数的第三个参数可以填 2 个常量值 -- SWOOLE_BASE或 SWOOLE_PROCESS下面将分别介绍这两个模式的区别以及优缺点 SWOOLE_PROCESS SWOOLE_PROCESS 模式的 Server 所有客户端的 TCP 连接都是和主进程建立的内部实现比较复杂用了大量的进程间通信、进程管理机制。适合业务逻辑非常复杂的场景。Swoole 提供了完善的进程管理、内存保护机制。 在业务逻辑非常复杂的情况下也可以长期稳定运行。 Swoole 在 Reactor线程中提供了 Buffer 的功能可以应对大量慢速连接和逐字节的恶意客户端。 进程模式的优点 连接与数据请求发送是分离的不会因为某些连接数据量大某些连接数据量小导致 Worker 进程不均衡 Worker 进程发生致命错误时连接并不会被切断 可实现单连接并发仅保持少量 TCP 连接请求可以并发地在多个 Worker 进程中处理 进程模式的缺点 存在 2 次 IPC 的开销master 进程与 worker 进程需要使用 unixSocket进行通信 SWOOLE_PROCESS 不支持 PHP ZTS在这种情况下只能使用 SWOOLE_BASE 或者设置 single_thread为 true SWOOLE_BASE SWOOLE_BASE 这种模式就是传统的异步非阻塞 Server。与 Nginx 和 Node.js 等程序是完全一致的。 worker_num参数对于 BASE 模式仍然有效会启动多个 Worker 进程。 当有 TCP 连接请求进来的时候所有的 Worker 进程去争抢这一个连接并最终会有一个 worker 进程成功直接和客户端建立 TCP 连接之后这个连接的所有数据收发直接和这个 worker 通讯不经过主进程的 Reactor 线程转发。 BASE 模式下没有 Master 进程的角色只有 Manager进程的角色。 每个 Worker 进程同时承担了 SWOOLE_PROCESS模式下 Reactor线程和 Worker 进程两部分职责。 BASE 模式下 Manager 进程是可选的当设置了 worker_num1并且没有使用 Task 和 MaxRequest 特性时底层将直接创建一个单独的 Worker 进程不创建 Manager 进程 BASE 模式的优点 BASE 模式没有 IPC 开销性能更好 BASE 模式代码更简单不容易出错 BASE 模式的缺点 TCP 连接是在 Worker 进程中维持的所以当某个 Worker 进程挂掉时此 Worker 内的所有连接都将被关闭 少量 TCP 长连接无法利用到所有 Worker 进程 TCP 连接与 Worker 是绑定的长连接应用中某些连接的数据量大这些连接所在的 Worker 进程负载会非常高。但某些连接数据量小所以在 Worker 进程的负载会非常低不同的 Worker 进程无法实现均衡。 如果回调函数中有阻塞操作会导致 Server 退化为同步模式此时容易导致 TCP 的 backlog队列塞满问题。 BASE 模式的适用场景 如果客户端连接之间不需要交互可以使用 BASE 模式。如 Memcache、HTTP 服务器等。 BASE 模式的限制 在 BASE 模式下Server 方法除了 send和 close以外其他的方法都不支持跨进程执行。 Reactor 线程和 Worker 进程 Reactor 线程 Reactor 线程是在 Master 进程中创建的线程 负责维护客户端 TCP 连接、处理网络 IO、处理协议、收发数据 不执行任何 PHP 代码 将 TCP 客户端发来的数据缓冲、拼接、拆分成完整的一个请求数据包 Worker 进程 接受由 Reactor 线程投递的请求数据包并执行 PHP 回调函数处理数据 生成响应数据并发给 Reactor 线程由 Reactor 线程发送给 TCP 客户端 可以是异步非阻塞模式也可以是同步阻塞模式 Worker 以多进程的方式运行 他们之间的关系可以理解为 Reactor 就是 nginxWorker 就是 PHP-FPM。Reactor 线程异步并行地处理网络请求然后再转发给 Worker 进程中去处理。Reactor 和 Worker 间通过 unixSocket进行通信。 在 PHP-FPM 的应用中经常会将一个任务异步投递到 Redis 等队列中并在后台启动一些 PHP 进程异步地处理这些任务。Swoole 提供的 TaskWorker 是一套更完整的方案将任务的投递、队列、PHP 任务处理进程管理合为一体。通过底层提供的 API 可以非常简单地实现异步任务的处理。另外 TaskWorker 还可以在任务执行完成后再返回一个结果反馈到 Worker。 Swoole 的 Reactor、Worker、TaskWorker 之间可以紧密的结合起来提供更高级的使用方式。 一个更通俗的比喻假设 Server 就是一个工厂那 Reactor 就是销售接受客户订单。而 Worker 就是工人当销售接到订单后Worker 去工作生产出客户要的东西。而 TaskWorker 可以理解为行政人员可以帮助 Worker 干些杂事让 Worker 专心工作。 结论 SWOOLE_PROCESS 模式下Websocket 的连接对象都是由 Server 来控制创建一个 Reactor 后将该连接交付给 Reactor 来管理Reactor 会将请求分配给 Worker 处理Worker 处理完后再把消息发给ServerServer 将消息压入队列等具体的 Reactor 发送出去 hyperf 中有一处进程间通信目前还不清楚这里为何要向其他进程求助以及其他进程监听到消息后会不会多发 开发者说如果是 SWOOLE_PROCESS模式下不会触发让其他 Worker 发送的机制只有 SWOOLE_BASE 模式下每个链接交给每个 Worker 单独处理时才需要在多个 Worker 协作处理因为每个 Worker 争抢到的连接都是隔离的所以不会出现发送多个的情况 上面 2 给了一种分布式 websocket 构建方式采用这种多进程的方式就能让多台服务器协作提供长连接服务保证千级万级用户的接入量 下面这段代码是来自onPipeMessage 监听器的意味着其他 worker 收到后判断是在自己进程上的连接就执行
http://www.dnsts.com.cn/news/141470.html

相关文章:

  • 深圳网站建设服务哪便宜网站开发制作公司简介
  • 做详情页生成代码的网站二手书市场网站建设项目规划表
  • php网站建设面试好用的网站管理系统
  • 建站公司兴田德润好不好怎么做网站的访问量
  • 满山红网站建设公司网站开发背景鼠标跟随
  • 深圳网站建设信科公司便宜网站优化的代码
  • 吉林省城市建设学校网站百度网站怎样做
  • 制作网站的平台有趣的网页设计
  • 建一个手机网站需要多少钱做个公司网站大概多少钱
  • 保险网站wordpress如何去掉amp
  • 教育智慧城市型网站开发建设工业网站
  • 网站字体大小合适太原关键词优化报价
  • 网站建设评比网站开发微信端
  • 免费的个人主页空间百度搜索引擎优化
  • 网站的备用金怎么做凭证wordpress的关键字哪里设置
  • 单位网站改版做婚恋交友类网站
  • 苏州做网站的公司有哪些荥阳网站开发
  • 企业网站设计与规划论文360建筑网一级消防
  • 济南seo网站优化微信加人推码35一单
  • 深圳南山工厂网站建设费用企业融资渠道有哪些
  • 云主机开网站教程营销方案100例
  • 小说网站开发源码wordpress uk
  • 安徽省城乡建设厅网站wordpress可以管理现有网啊
  • 做网站一屏是多大wordpress html5 win8
  • 成都食品网站开发有个性的个人网站
  • 泰安有口碑的企业建站公司华宁网站建设
  • 网站建设houxiaoer大连网络公司排名
  • 大连网站排名推广最新科技新闻消息
  • 用网站做数据库吗为网站做安全认证服务
  • 《网站开发实践》 实训报告什么网站必须要flash