搜尋
首頁後端開發php教程關於php中beanstalkd訊息佇列的詳解以及類別的分享

這篇文章主要為大家分享了php-beanstalkd訊息佇列類別實例程式碼,具有一定的參考價值,有興趣的小夥伴們可以參考一下

概況:
Beanstalkd,一個高效能、輕量級的分散式記憶體佇列系統,最初設計的目的是想透過後台非同步執行耗時的任務來降低高容量Web應​​用系統的頁面存取延遲,支援過有9.5 million用戶的Facebook Causes應用。後來開源,現在有PostRank大規模部署使用,每天處理百萬級任務。 Beanstalkd是典型的類Memcached設計,協議和使用方式都是同樣的風格,所以使用過memcached的用戶會覺得Beanstalkd似曾相識。
beanstalk核心概念:
job:一個需要非同步處理的任務,需要放在一個tube中。
tube:一個有名的任務佇列,用來儲存統一型別的job
producer:job的生產者
consumer:job的消費者
簡單來說流程就一句話:
由producer 產生一個任務job ,並將job 推進到一個tube 中,
然後由consumer 從tube 中取出job 執行(當然了,這一切的操作的前提是beanstalk服務正在運行中)。

一個job有READY(時刻準備著被消費者取出), RESERVED(任務正在被一個消費者處理中), DELAYED(延遲任務,設定的延遲時間後進入ready狀態), BURIED(休眠中,需要轉移狀態後才能操作)四種狀態。當producer直接put一個job時,job就處於READY狀態,等待consumer來處理,如果選擇延遲put,job就先到DELAYED狀態,等待時間過後才遷移到READY狀態。 consumer取得了目前READY的job後,該job的狀態就遷移到RESERVED,這樣其他的consumer就不能再操作該job。當consumer完成該job後,可以選擇delete, release或bury操作;delete之後,job從系統消亡,之後不能再獲取;release操作可以重新把該job狀態遷移回READY(也可以延遲該狀態遷移操作),使其他的consumer可以繼續獲取和執行該job;有意思的是bury操作,可以把該job休眠,等到需要的時候,再將休眠的job kick回READY狀態,也可以delete BURIED狀態的job。正是有這些有趣的操作和狀態,才可以基於此做出很多意思的應用,例如要實現一個循環隊列,就可以將RESERVED狀態的job休眠掉,等沒有READY狀態的job時再將BURIED狀態的job一次性kick回READY狀態。

範例分析:微博是一個很典型的例子:
1,發一個微博
2,推送給他的粉絲(如果有100w個粉絲,這個地方會堵塞很久,用戶感受到的就是延遲)
在微博上發布一條內容要做上面兩件事情才算完整,發一條微博只需要進行一次簡單的數據庫操作,
但是推送給他的粉絲卻要操作100w次資料庫,導致用戶發一個微博要等待很長的延遲才能回傳結果發送成功。
採用隊列的方式,用戶發送一條微博立馬返回結果,發送成功,剩下的推送就放到隊列裡面異步執行,
推送並不需要特別及時,延遲過幾秒幾十秒都是可以接受的。    

本文實例為大家分享了php beanstalkd訊息佇列類別的具體程式碼,供大家參考,具體內容如下

<?php
namespace Common\Business;
/**
 * beanstalk: A minimalistic PHP beanstalk client.
 *
 * Copyright (c) 2009-2015 David Persson
 *
 * Distributed under the terms of the MIT License.
 * Redistributions of files must retain the above copyright notice.
 */
 
use RuntimeException;
 
/**
 * An interface to the beanstalk queue service. Implements the beanstalk
 * protocol spec 1.9. Where appropriate the documentation from the protocol
 * has been added to the docblocks in this class.
 *
 * @link https://github.com/kr/beanstalkd/blob/master/doc/protocol.txt
 */
class BeanStalk {
 
  /**
   * Minimum priority value which can be assigned to a job. The minimum
   * priority value is also the _highest priority_ a job can have.
   *
   * @var integer
   */
  const MIN_PRIORITY = 0;
 
  /**
   * Maximum priority value which can be assigned to a job. The maximum
   * priority value is also the _lowest priority_ a job can have.
   *
   * @var integer
   */
  const MAX_PRIORITY = 4294967295;
 
  /**
   * Holds a boolean indicating whether a connection to the server is
   * currently established or not.
   *
   * @var boolean
   */
  public $connected = false;
 
  /**
   * Holds configuration values.
   *
   * @var array
   */
  protected $_config = [];
 
  /**
   * The current connection resource handle (if any).
   *
   * @var resource
   */
  protected $_connection;
 
  /**
   * Constructor.
   *
   * @param array $config An array of configuration values:
   *    - `&#39;persistent&#39;` Whether to make the connection persistent or
   *             not, defaults to `true` as the FAQ recommends
   *             persistent connections.
   *    - `&#39;host&#39;`    The beanstalk server hostname or IP address to
   *             connect to, defaults to `127.0.0.1`.
   *    - `&#39;port&#39;`    The port of the server to connect to, defaults
   *             to `11300`.
   *    - `&#39;timeout&#39;`   Timeout in seconds when establishing the
   *             connection, defaults to `1`.
   *    - `&#39;logger&#39;`   An instance of a PSR-3 compatible logger.
   *
   * @link https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-3-logger-interface.md
   * @return void
   */
  public function __construct(array $config = []) {
    $defaults = [
      &#39;persistent&#39; => true,
      &#39;host&#39; => &#39;127.0.0.1&#39;,
      &#39;port&#39; => 11300,
      &#39;timeout&#39; => 1,
      &#39;logger&#39; => null
    ];
    $this->_config = $config + $defaults;
  }
 
  /**
   * Destructor, disconnects from the server.
   *
   * @return void
   */
  public function __destruct() {
    $this->disconnect();
  }
 
  /**
   * Initiates a socket connection to the beanstalk server. The resulting
   * stream will not have any timeout set on it. Which means it can wait
   * an unlimited amount of time until a packet becomes available. This
   * is required for doing blocking reads.
   *
   * @see \Beanstalk\Client::$_connection
   * @see \Beanstalk\Client::reserve()
   * @return boolean `true` if the connection was established, `false` otherwise.
   */
  public function connect() {
    if (isset($this->_connection)) {
      $this->disconnect();
    }
    $errNum = &#39;&#39;;
    $errStr = &#39;&#39;;
    $function = $this->_config[&#39;persistent&#39;] ? &#39;pfsockopen&#39; : &#39;fsockopen&#39;;
    $params = [$this->_config[&#39;host&#39;], $this->_config[&#39;port&#39;], &$errNum, &$errStr];
 
    if ($this->_config[&#39;timeout&#39;]) {
      $params[] = $this->_config[&#39;timeout&#39;];
    }
    $this->_connection = @call_user_func_array($function, $params);
 
    if (!empty($errNum) || !empty($errStr)) {
      $this->_error("{$errNum}: {$errStr}");
    }
 
    $this->connected = is_resource($this->_connection);
 
    if ($this->connected) {
      stream_set_timeout($this->_connection, -1);
    }
    return $this->connected;
  }
 
  /**
   * Closes the connection to the beanstalk server by first signaling
   * that we want to quit then actually closing the socket connection.
   *
   * @return boolean `true` if diconnecting was successful.
   */
  public function disconnect() {
    if (!is_resource($this->_connection)) {
      $this->connected = false;
    } else {
      $this->_write(&#39;quit&#39;);
      $this->connected = !fclose($this->_connection);
 
      if (!$this->connected) {
        $this->_connection = null;
      }
    }
    return !$this->connected;
  }
 
  /**
   * Pushes an error message to the logger, when one is configured.
   *
   * @param string $message The error message.
   * @return void
   */
  protected function _error($message) {
    if ($this->_config[&#39;logger&#39;]) {
      $this->_config[&#39;logger&#39;]->error($message);
    }
  }
 
  public function errors()
  {
    return $this->_config[&#39;logger&#39;];
  }
  /**
   * Writes a packet to the socket. Prior to writing to the socket will
   * check for availability of the connection.
   *
   * @param string $data
   * @return integer|boolean number of written bytes or `false` on error.
   */
  protected function _write($data) {
    if (!$this->connected) {
      $message = &#39;No connecting found while writing data to socket.&#39;;
      throw new RuntimeException($message);
    }
 
    $data .= "\r\n";
    return fwrite($this->_connection, $data, strlen($data));
  }
 
  /**
   * Reads a packet from the socket. Prior to reading from the socket
   * will check for availability of the connection.
   *
   * @param integer $length Number of bytes to read.
   * @return string|boolean Data or `false` on error.
   */
  protected function _read($length = null) {
    if (!$this->connected) {
      $message = &#39;No connection found while reading data from socket.&#39;;
      throw new RuntimeException($message);
    }
    if ($length) {
      if (feof($this->_connection)) {
        return false;
      }
      $data = stream_get_contents($this->_connection, $length + 2);
      $meta = stream_get_meta_data($this->_connection);
 
      if ($meta[&#39;timed_out&#39;]) {
        $message = &#39;Connection timed out while reading data from socket.&#39;;
        throw new RuntimeException($message);
      }
      $packet = rtrim($data, "\r\n");
    } else {
      $packet = stream_get_line($this->_connection, 16384, "\r\n");
    }
    return $packet;
  }
 
  /* Producer Commands */
 
  /**
   * The `put` command is for any process that wants to insert a job into the queue.
   *
   * @param integer $pri Jobs with smaller priority values will be scheduled
   *    before jobs with larger priorities. The most urgent priority is
   *    0; the least urgent priority is 4294967295.
   * @param integer $delay Seconds to wait before putting the job in the
   *    ready queue. The job will be in the "delayed" state during this time.
   * @param integer $ttr Time to run - Number of seconds to allow a worker to
   *    run this job. The minimum ttr is 1.
   * @param string $data The job body.
   * @return integer|boolean `false` on error otherwise an integer indicating
   *     the job id.
   */
  public function put($pri, $delay, $ttr, $data) {
    $this->_write(sprintf("put %d %d %d %d\r\n%s", $pri, $delay, $ttr, strlen($data), $data));
    $status = strtok($this->_read(), &#39; &#39;);
 
    switch ($status) {
      case &#39;INSERTED&#39;:
      case &#39;BURIED&#39;:
        return (integer) strtok(&#39; &#39;); // job id
      case &#39;EXPECTED_CRLF&#39;:
      case &#39;JOB_TOO_BIG&#39;:
      default:
        $this->_error($status);
        return false;
    }
  }
 
  /**
   * The `use` command is for producers. Subsequent put commands will put
   * jobs into the tube specified by this command. If no use command has
   * been issued, jobs will be put into the tube named `default`.
   *
   * @param string $tube A name at most 200 bytes. It specifies the tube to
   *    use. If the tube does not exist, it will be created.
   * @return string|boolean `false` on error otherwise the name of the tube.
   */
  public function useTube($tube) {
    $this->_write(sprintf(&#39;use %s&#39;, $tube));
    $status = strtok($this->_read(), &#39; &#39;);
 
    switch ($status) {
      case &#39;USING&#39;:
        return strtok(&#39; &#39;);
      default:
        $this->_error($status);
        return false;
    }
  }
 
  /**
   * Pause a tube delaying any new job in it being reserved for a given time.
   *
   * @param string $tube The name of the tube to pause.
   * @param integer $delay Number of seconds to wait before reserving any more
   *    jobs from the queue.
   * @return boolean `false` on error otherwise `true`.
   */
  public function pauseTube($tube, $delay) {
    $this->_write(sprintf(&#39;pause-tube %s %d&#39;, $tube, $delay));
    $status = strtok($this->_read(), &#39; &#39;);
 
    switch ($status) {
      case &#39;PAUSED&#39;:
        return true;
      case &#39;NOT_FOUND&#39;:
      default:
        $this->_error($status);
        return false;
    }
  }
 
  /* Worker Commands */
 
  /**
   * Reserve a job (with a timeout).
   *
   * @param integer $timeout If given specifies number of seconds to wait for
   *    a job. `0` returns immediately.
   * @return array|false `false` on error otherwise an array holding job id
   *     and body.
   */
  public function reserve($timeout = null) {
    if (isset($timeout)) {
      $this->_write(sprintf(&#39;reserve-with-timeout %d&#39;, $timeout));
    } else {
      $this->_write(&#39;reserve&#39;);
    }
    $status = strtok($this->_read(), &#39; &#39;);
 
    switch ($status) {
      case &#39;RESERVED&#39;:
        return [
          &#39;id&#39; => (integer) strtok(&#39; &#39;),
          &#39;body&#39; => $this->_read((integer) strtok(&#39; &#39;))
        ];
      case &#39;DEADLINE_SOON&#39;:
      case &#39;TIMED_OUT&#39;:
      default:
        $this->_error($status);
        return false;
    }
  }
 
  /**
   * Removes a job from the server entirely.
   *
   * @param integer $id The id of the job.
   * @return boolean `false` on error, `true` on success.
   */
  public function delete($id) {
    $this->_write(sprintf(&#39;delete %d&#39;, $id));
    $status = $this->_read();
 
    switch ($status) {
      case &#39;DELETED&#39;:
        return true;
      case &#39;NOT_FOUND&#39;:
      default:
        $this->_error($status);
        return false;
    }
  }
 
  /**
   * Puts a reserved job back into the ready queue.
   *
   * @param integer $id The id of the job.
   * @param integer $pri Priority to assign to the job.
   * @param integer $delay Number of seconds to wait before putting the job in the ready queue.
   * @return boolean `false` on error, `true` on success.
   */
  public function release($id, $pri, $delay) {
    $this->_write(sprintf(&#39;release %d %d %d&#39;, $id, $pri, $delay));
    $status = $this->_read();
 
    switch ($status) {
      case &#39;RELEASED&#39;:
      case &#39;BURIED&#39;:
        return true;
      case &#39;NOT_FOUND&#39;:
      default:
        $this->_error($status);
        return false;
    }
  }
 
  /**
   * Puts a job into the `buried` state Buried jobs are put into a FIFO
   * linked list and will not be touched until a client kicks them.
   *
   * @param integer $id The id of the job.
   * @param integer $pri *New* priority to assign to the job.
   * @return boolean `false` on error, `true` on success.
   */
  public function bury($id, $pri) {
    $this->_write(sprintf(&#39;bury %d %d&#39;, $id, $pri));
    $status = $this->_read();
 
    switch ($status) {
      case &#39;BURIED&#39;:
        return true;
      case &#39;NOT_FOUND&#39;:
      default:
        $this->_error($status);
        return false;
    }
  }
 
  /**
   * Allows a worker to request more time to work on a job.
   *
   * @param integer $id The id of the job.
   * @return boolean `false` on error, `true` on success.
   */
  public function touch($id) {
    $this->_write(sprintf(&#39;touch %d&#39;, $id));
    $status = $this->_read();
 
    switch ($status) {
      case &#39;TOUCHED&#39;:
        return true;
      case &#39;NOT_TOUCHED&#39;:
      default:
        $this->_error($status);
        return false;
    }
  }
 
  /**
   * Adds the named tube to the watch list for the current connection.
   *
   * @param string $tube Name of tube to watch.
   * @return integer|boolean `false` on error otherwise number of tubes in watch list.
   */
  public function watch($tube) {
    $this->_write(sprintf(&#39;watch %s&#39;, $tube));
    $status = strtok($this->_read(), &#39; &#39;);
 
    switch ($status) {
      case &#39;WATCHING&#39;:
        return (integer) strtok(&#39; &#39;);
      default:
        $this->_error($status);
        return false;
    }
  }
 
  /**
   * Remove the named tube from the watch list.
   *
   * @param string $tube Name of tube to ignore.
   * @return integer|boolean `false` on error otherwise number of tubes in watch list.
   */
  public function ignore($tube) {
    $this->_write(sprintf(&#39;ignore %s&#39;, $tube));
    $status = strtok($this->_read(), &#39; &#39;);
 
    switch ($status) {
      case &#39;WATCHING&#39;:
        return (integer) strtok(&#39; &#39;);
      case &#39;NOT_IGNORED&#39;:
      default:
        $this->_error($status);
        return false;
    }
  }
 
  /* Other Commands */
 
  /**
   * Inspect a job by its id.
   *
   * @param integer $id The id of the job.
   * @return string|boolean `false` on error otherwise the body of the job.
   */
  public function peek($id) {
    $this->_write(sprintf(&#39;peek %d&#39;, $id));
    return $this->_peekRead();
  }
 
  /**
   * Inspect the next ready job.
   *
   * @return string|boolean `false` on error otherwise the body of the job.
   */
  public function peekReady() {
    $this->_write(&#39;peek-ready&#39;);
    return $this->_peekRead();
  }
 
  /**
   * Inspect the job with the shortest delay left.
   *
   * @return string|boolean `false` on error otherwise the body of the job.
   */
  public function peekDelayed() {
    $this->_write(&#39;peek-delayed&#39;);
    return $this->_peekRead();
  }
 
  /**
   * Inspect the next job in the list of buried jobs.
   *
   * @return string|boolean `false` on error otherwise the body of the job.
   */
  public function peekBuried() {
    $this->_write(&#39;peek-buried&#39;);
    return $this->_peekRead();
  }
 
  /**
   * Handles response for all peek methods.
   *
   * @return string|boolean `false` on error otherwise the body of the job.
   */
  protected function _peekRead() {
    $status = strtok($this->_read(), &#39; &#39;);
 
    switch ($status) {
      case &#39;FOUND&#39;:
        return [
          &#39;id&#39; => (integer) strtok(&#39; &#39;),
          &#39;body&#39; => $this->_read((integer) strtok(&#39; &#39;))
        ];
      case &#39;NOT_FOUND&#39;:
      default:
        $this->_error($status);
        return false;
    }
  }
 
  /**
   * Moves jobs into the ready queue (applies to the current tube).
   *
   * If there are buried jobs those get kicked only otherwise delayed
   * jobs get kicked.
   *
   * @param integer $bound Upper bound on the number of jobs to kick.
   * @return integer|boolean False on error otherwise number of jobs kicked.
   */
  public function kick($bound) {
    $this->_write(sprintf(&#39;kick %d&#39;, $bound));
    $status = strtok($this->_read(), &#39; &#39;);
 
    switch ($status) {
      case &#39;KICKED&#39;:
        return (integer) strtok(&#39; &#39;);
      default:
        $this->_error($status);
        return false;
    }
  }
 
  /**
   * This is a variant of the kick command that operates with a single
   * job identified by its job id. If the given job id exists and is in a
   * buried or delayed state, it will be moved to the ready queue of the
   * the same tube where it currently belongs.
   *
   * @param integer $id The job id.
   * @return boolean `false` on error `true` otherwise.
   */
  public function kickJob($id) {
    $this->_write(sprintf(&#39;kick-job %d&#39;, $id));
    $status = strtok($this->_read(), &#39; &#39;);
 
    switch ($status) {
      case &#39;KICKED&#39;:
        return true;
      case &#39;NOT_FOUND&#39;:
      default:
        $this->_error($status);
        return false;
    }
  }
 
  /* Stats Commands */
 
  /**
   * Gives statistical information about the specified job if it exists.
   *
   * @param integer $id The job id.
   * @return string|boolean `false` on error otherwise a string with a yaml formatted dictionary.
   */
  public function statsJob($id) {
    $this->_write(sprintf(&#39;stats-job %d&#39;, $id));
    return $this->_statsRead();
  }
 
  /**
   * Gives statistical information about the specified tube if it exists.
   *
   * @param string $tube Name of the tube.
   * @return string|boolean `false` on error otherwise a string with a yaml formatted dictionary.
   */
  public function statsTube($tube) {
    $this->_write(sprintf(&#39;stats-tube %s&#39;, $tube));
    return $this->_statsRead();
  }
 
  /**
   * Gives statistical information about the system as a whole.
   *
   * @return string|boolean `false` on error otherwise a string with a yaml formatted dictionary.
   */
  public function stats() {
    $this->_write(&#39;stats&#39;);
    return $this->_statsRead();
  }
 
  /**
   * Returns a list of all existing tubes.
   *
   * @return string|boolean `false` on error otherwise a string with a yaml formatted list.
   */
  public function listTubes() {
    $this->_write(&#39;list-tubes&#39;);
    return $this->_statsRead();
  }
 
  /**
   * Returns the tube currently being used by the producer.
   *
   * @return string|boolean `false` on error otherwise a string with the name of the tube.
   */
  public function listTubeUsed() {
    $this->_write(&#39;list-tube-used&#39;);
    $status = strtok($this->_read(), &#39; &#39;);
 
    switch ($status) {
      case &#39;USING&#39;:
        return strtok(&#39; &#39;);
      default:
        $this->_error($status);
        return false;
    }
  }
 
  /**
   * Returns a list of tubes currently being watched by the worker.
   *
   * @return string|boolean `false` on error otherwise a string with a yaml formatted list.
   */
  public function listTubesWatched() {
    $this->_write(&#39;list-tubes-watched&#39;);
    return $this->_statsRead();
  }
 
  /**
   * Handles responses for all stat methods.
   *
   * @param boolean $decode Whether to decode data before returning it or not. Default is `true`.
   * @return array|string|boolean `false` on error otherwise statistical data.
   */
  protected function _statsRead($decode = true) {
    $status = strtok($this->_read(), &#39; &#39;);
 
    switch ($status) {
      case &#39;OK&#39;:
        $data = $this->_read((integer) strtok(&#39; &#39;));
        return $decode ? $this->_decode($data) : $data;
      default:
        $this->_error($status);
        return false;
    }
  }
 
  /**
   * Decodes YAML data. This is a super naive decoder which just works on
   * a subset of YAML which is commonly returned by beanstalk.
   *
   * @param string $data The data in YAML format, can be either a list or a dictionary.
   * @return array An (associative) array of the converted data.
   */
  protected function _decode($data) {
    $data = array_slice(explode("\n", $data), 1);
    $result = [];
 
    foreach ($data as $key => $value) {
      if ($value[0] === &#39;-&#39;) {
        $value = ltrim($value, &#39;- &#39;);
      } elseif (strpos($value, &#39;:&#39;) !== false) {
        list($key, $value) = explode(&#39;:&#39;, $value);
        $value = ltrim($value, &#39; &#39;);
      }
      if (is_numeric($value)) {
        $value = (integer) $value == $value ? (integer) $value : (float) $value;
      }
      $result[$key] = $value;
    }
    return $result;
  }
}
 
?>

以上是關於php中beanstalkd訊息佇列的詳解以及類別的分享的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
您什麼時候使用特質與PHP中的抽像類或接口?您什麼時候使用特質與PHP中的抽像類或接口?Apr 10, 2025 am 09:39 AM

在PHP中,trait適用於需要方法復用但不適合使用繼承的情況。 1)trait允許在類中復用方法,避免多重繼承複雜性。 2)使用trait時需注意方法衝突,可通過insteadof和as關鍵字解決。 3)應避免過度使用trait,保持其單一職責,以優化性能和提高代碼可維護性。

什麼是依賴性注入容器(DIC),為什麼在PHP中使用一個?什麼是依賴性注入容器(DIC),為什麼在PHP中使用一個?Apr 10, 2025 am 09:38 AM

依賴注入容器(DIC)是一種管理和提供對象依賴關係的工具,用於PHP項目中。 DIC的主要好處包括:1.解耦,使組件獨立,代碼易維護和測試;2.靈活性,易替換或修改依賴關係;3.可測試性,方便注入mock對象進行單元測試。

與常規PHP陣列相比,解釋SPL SplfixedArray及其性能特徵。與常規PHP陣列相比,解釋SPL SplfixedArray及其性能特徵。Apr 10, 2025 am 09:37 AM

SplFixedArray在PHP中是一種固定大小的數組,適用於需要高性能和低內存使用量的場景。 1)它在創建時需指定大小,避免動態調整帶來的開銷。 2)基於C語言數組,直接操作內存,訪問速度快。 3)適合大規模數據處理和內存敏感環境,但需謹慎使用,因其大小固定。

PHP如何安全地上載文件?PHP如何安全地上載文件?Apr 10, 2025 am 09:37 AM

PHP通過$\_FILES變量處理文件上傳,確保安全性的方法包括:1.檢查上傳錯誤,2.驗證文件類型和大小,3.防止文件覆蓋,4.移動文件到永久存儲位置。

什麼是無效的合併操作員(??)和無效分配運算符(?? =)?什麼是無效的合併操作員(??)和無效分配運算符(?? =)?Apr 10, 2025 am 09:33 AM

JavaScript中處理空值可以使用NullCoalescingOperator(??)和NullCoalescingAssignmentOperator(??=)。 1.??返回第一個非null或非undefined的操作數。 2.??=將變量賦值為右操作數的值,但前提是該變量為null或undefined。這些操作符簡化了代碼邏輯,提高了可讀性和性能。

什麼是內容安全策略(CSP)標頭,為什麼重要?什麼是內容安全策略(CSP)標頭,為什麼重要?Apr 09, 2025 am 12:10 AM

CSP重要因為它能防範XSS攻擊和限制資源加載,提升網站安全性。 1.CSP是HTTP響應頭的一部分,通過嚴格策略限制惡意行為。 2.基本用法是只允許從同源加載資源。 3.高級用法可設置更細粒度的策略,如允許特定域名加載腳本和样式。 4.使用Content-Security-Policy-Report-Only頭部可調試和優化CSP策略。

什麼是HTTP請求方法(獲取,發布,放置,刪除等),何時應該使用?什麼是HTTP請求方法(獲取,發布,放置,刪除等),何時應該使用?Apr 09, 2025 am 12:09 AM

HTTP請求方法包括GET、POST、PUT和DELETE,分別用於獲取、提交、更新和刪除資源。 1.GET方法用於獲取資源,適用於讀取操作。 2.POST方法用於提交數據,常用於創建新資源。 3.PUT方法用於更新資源,適用於完整更新。 4.DELETE方法用於刪除資源,適用於刪除操作。

什麼是HTTP,為什麼對Web應用程序至關重要?什麼是HTTP,為什麼對Web應用程序至關重要?Apr 09, 2025 am 12:08 AM

HTTPS是一種在HTTP基礎上增加安全層的協議,主要通過加密數據保護用戶隱私和數據安全。其工作原理包括TLS握手、證書驗證和加密通信。實現HTTPS時需注意證書管理、性能影響和混合內容問題。

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
3 週前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳圖形設置
3 週前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您聽不到任何人,如何修復音頻
3 週前By尊渡假赌尊渡假赌尊渡假赌
WWE 2K25:如何解鎖Myrise中的所有內容
3 週前By尊渡假赌尊渡假赌尊渡假赌

熱工具

Atom編輯器mac版下載

Atom編輯器mac版下載

最受歡迎的的開源編輯器

SAP NetWeaver Server Adapter for Eclipse

SAP NetWeaver Server Adapter for Eclipse

將Eclipse與SAP NetWeaver應用伺服器整合。

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

SecLists

SecLists

SecLists是最終安全測試人員的伙伴。它是一個包含各種類型清單的集合,這些清單在安全評估過程中經常使用,而且都在一個地方。 SecLists透過方便地提供安全測試人員可能需要的所有列表,幫助提高安全測試的效率和生產力。清單類型包括使用者名稱、密碼、URL、模糊測試有效載荷、敏感資料模式、Web shell等等。測試人員只需將此儲存庫拉到新的測試機上,他就可以存取所需的每種類型的清單。

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用