文章851
标签121
分类10

Nginx Cache 查看命中率

在高性能 Web 服务器中,缓存是提高响应速度和减少服务器负担的重要手段。Nginx 作为流行的反向代理服务器,提供了强大的缓存功能。本文将介绍如何查看 Nginx 缓存的命中率,以帮助您优化网站性能。

1. 什么是 Nginx 缓存?

Nginx 缓存允许将静态内容和动态内容的响应结果存储在内存或磁盘中,从而减少对后端服务器的请求。缓存可以显著提高网站的性能和响应速度,尤其是在高流量情况下。

1.1 缓存命中率

缓存命中率是衡量缓存效率的重要指标,表示从缓存中成功返回的请求占总请求的比例。命中率越高,说明缓存效果越好。

2. 配置 Nginx 缓存

在查看缓存命中率之前,您需要确保已正确配置 Nginx 缓存。以下是一个简单的 Nginx 配置示例:

http {
    proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=my_cache:10m max_size=1g inactive=60m use_temp_path=off;

    server {
        listen 80;
        server_name example.com;

        location / {
            proxy_pass http://backend_server;
            proxy_cache my_cache;
            proxy_cache_valid 200 1h;
            proxy_cache_use_stale error timeout updating;
            add_header X-Cache-Status $upstream_cache_status;
        }
    }
}

在上述配置中:

  • proxy_cache_path 指定缓存存储的位置和相关参数。
  • proxy_cache 启用缓存。
  • add_header 用于返回缓存状态的响应头。

3. 查看缓存命中率

3.1 使用响应头

通过在 Nginx 配置中添加 add_header X-Cache-Status $upstream_cache_status;,您可以在 HTTP 响应中看到缓存状态。常见的状态值包括:

  • HIT:请求命中缓存。
  • MISS:请求未命中缓存。
  • BYPASS:请求被绕过,不使用缓存。
  • STALE:请求使用了过期的缓存。

您可以使用 curl 命令查看响应头:

curl -I http://example.com

输出示例:

HTTP/1.1 200 OK
Content-Type: text/html
X-Cache-Status: HIT

3.2 通过日志分析

Nginx 的访问日志中也可以记录缓存状态。您可以在 Nginx 配置文件中自定义日志格式,记录缓存状态:

log_format cache_log '$remote_addr - $remote_user [$time_local] "$request" '
                    '$status $body_bytes_sent "$http_referer" '
                    '"$http_user_agent" "$http_x_cache_status"';

access_log /var/log/nginx/access.log cache_log;

然后,您可以使用 grep 命令分析日志文件,统计命中率:

cat /var/log/nginx/access.log | grep 'HIT' | wc -l
cat /var/log/nginx/access.log | grep 'MISS' | wc -l

3.3 计算命中率

最后,您可以通过以下公式计算命中率:

命中率 = (命中次数) / (命中次数 + 未命中次数) * 100%

4. 优化缓存命中率

  • 调整缓存时间:根据内容变化频率合理设置 proxy_cache_valid 的时间。
  • 使用适当的缓存键:确保缓存键的设置能够充分利用缓存。
  • 监控流量模式:根据流量模式分析并优化缓存策略。

5. 结论

查看 Nginx 缓存命中率是优化网站性能的重要步骤。通过分析缓存状态和访问日志,您可以了解缓存的使用情况,并根据需要进行调整。这将有助于提高网站的响应速度和用户体验。

使用php生成RSA公钥私钥及进行加密/解密/签名/验证

这篇文章主要介绍使用PHP开发接口,数据实现RSA加密解密后使用,实例分析了PHP自定义RSA类实现加密与解密的技巧,非常具有实用价值,需要的朋友可以参考下。

简单介绍RSA

RSA加密算法是最常用的非对称加密算法,CFCA在证书服务中离不了它。但是有不少新手对它不太了解。下面仅作简要介绍。RSA是第一个比较完善的公开密钥算法,它既能用于加密,也能用于数字签名。RSA以它的三个发明者Ron Rivest, Adi Shamir, Leonard Adleman的名字首字母命名,这个算法经受住了多年深入的密码分析,虽然密码分析者既不能证明也不能否定RSA的安全性,但这恰恰说明该算法有一定的可信性,目前它已经成为最流行的公开密钥算法。RSA的安全基于大数分解的难度。其公钥和私钥是一对大素数(100到200位十进制数或更大)的函数。从一个公钥和密文恢复出明文的难度,等价于分解两个大素数之积(这是公认的数学难题)。

下面为具体类:Rsa.class.php

<?php

/**
 * RSA算法类
 * 签名及密文编码:base64字符串/十六进制字符串/二进制字符串流
 * 填充方式: PKCS1Padding(加解密)/NOPadding(解密)
 *
 * Notice:Only accepts a single block. Block size is equal to the RSA key size!
 * 如密钥长度为1024 bit,则加密时数据需小于128字节,加上PKCS1Padding本身的11字节信息,所以明文需小于117字节
 */
class RSA
{
    private $pubKey = null;
    private $priKey = null;

    /**
     * 构造函数
     */
    public function __construct()
    {
        // 需要开启openssl扩展
        if (!extension_loaded("openssl")) {
            $this->_error("Please open the openssl extension first.");
        }
    }

    /**
     * 读取公钥和私钥
     * @param string $public_key_file 公钥文件(验签和加密时传入)
     * @param string $private_key_file 私钥文件(签名和解密时传入)
     */
    public function init($public_key_file = '', $private_key_file = '')
    {
        if ($public_key_file) {
            $this->_getPublicKey($public_key_file);
        }

        if ($private_key_file) {
            $this->_getPrivateKey($private_key_file);
        }
    }

    /**
     * 自定义错误处理
     */
    private function _error($msg)
    {
        die('RSA Error:' . $msg); //TODO
    }

    /**
     * 检测填充类型
     * 加密只支持PKCS1_PADDING
     * 解密支持PKCS1_PADDING和NO_PADDING
     *
     * @param int 填充模式
     * @param string 加密en/解密de
     * @return bool
     */
    private function _checkPadding($padding, $type)
    {
        if ($type == 'en') {
            switch ($padding) {
                case OPENSSL_PKCS1_PADDING:
                    $ret = true;
                    break;
                default:
                    $ret = false;
            }
        } else {
            switch ($padding) {
                case OPENSSL_PKCS1_PADDING:
                case OPENSSL_NO_PADDING:
                    $ret = true;
                    break;
                default:
                    $ret = false;
            }
        }
        return $ret;
    }

    private function _encode($data, $code)
    {
        switch (strtolower($code)) {
            case 'base64':
                $data = base64_encode('' . $data);
                break;
            case 'hex':
                $data = bin2hex($data);
                break;
            case 'bin':
            default:
        }
        return $data;
    }

    private function _decode($data, $code)
    {
        switch (strtolower($code)) {
            case 'base64':
                $data = base64_decode($data);
                break;
            case 'hex':
                $data = $this->_hex2bin($data);
                break;
            case 'bin':
            default:
        }
        return $data;
    }

    private function _getPublicKey($file)
    {
        $key_content = $this->_readFile($file);
        if ($key_content) {
            $this->pubKey = openssl_get_publickey($key_content);
        }
    }

    private function _getPrivateKey($file)
    {
        $key_content = $this->_readFile($file);
        if ($key_content) {
            $this->priKey = openssl_get_privatekey($key_content);
        }
    }

    private function _readFile($file)
    {
        $ret = false;
        if (!file_exists($file)) {
            $this->_error("The file {$file} is not exists");
        } else {
            $ret = file_get_contents($file);
        }
        return $ret;
    }

    private function _hex2bin($hex = false)
    {
        $ret = $hex !== false && preg_match('/^[0-9a-fA-F]+$/i', $hex) ? pack("H*", $hex) : false;
        return $ret;
    }

    /**
     * 生成Rsa公钥和私钥
     * @param int $private_key_bits 建议:[512, 1024, 2048, 4096]
     * @return array
     */
    public function generate(int $private_key_bits = 1024)
    {
        $rsa = [
            "private_key" => "",
            "public_key" => ""
        ];

        $config = [
            "digest_alg" => "sha512",
            "private_key_bits" => $private_key_bits, #此处必须为int类型
            "private_key_type" => OPENSSL_KEYTYPE_RSA,
        ];

        //创建公钥和私钥
        $res = openssl_pkey_new($config);

        //提取私钥
        openssl_pkey_export($res, $rsa['private_key']);

        //生成公钥
        $rsa['public_key'] = openssl_pkey_get_details($res)["key"];
        /*Array
        (
            [bits] => 512
            [key] =>
            [rsa] =>
            [type] => 0
        )*/
        return $rsa;
    }

    /**
     * 生成签名
     *
     * @param string 签名材料
     * @param string 签名编码(base64/hex/bin)
     * @return bool|string 签名值
     */
    public function sign($data, $code = 'base64')
    {
        $ret = false;
        if (openssl_sign($data, $ret, $this->priKey)) {
            $ret = $this->_encode($ret, $code);
        }
        return $ret;
    }

    /**
     * 验证签名
     *
     * @param string 签名材料
     * @param string 签名值
     * @param string 签名编码(base64/hex/bin)
     * @return bool
     */
    public function verify($data, $sign, $code = 'base64')
    {
        $ret = false;
        $sign = $this->_decode($sign, $code);
        if ($sign !== false) {
            switch (openssl_verify($data, $sign, $this->pubKey)) {
                case 1:
                    $ret = true;
                    break;
                case 0:
                case -1:
                default:
                    $ret = false;
            }
        }
        return $ret;
    }

    /**
     * 加密
     *
     * @param string 明文
     * @param string 密文编码(base64/hex/bin)
     * @param int 填充方式(貌似php有bug,所以目前仅支持OPENSSL_PKCS1_PADDING)
     * @return string 密文
     */
    public function encrypt($data, $code = 'base64', $padding = OPENSSL_PKCS1_PADDING)
    {
        $ret = false;
        if (!$this->_checkPadding($padding, 'en')) $this->_error('padding error');
        if (openssl_public_encrypt($data, $result, $this->pubKey, $padding)) {
            $ret = $this->_encode($result, $code);
        }
        return $ret;
    }

    /**
     * 解密
     *
     * @param string 密文
     * @param string 密文编码(base64/hex/bin)
     * @param int 填充方式(OPENSSL_PKCS1_PADDING / OPENSSL_NO_PADDING)
     * @param bool 是否翻转明文(When passing Microsoft CryptoAPI-generated RSA cyphertext, revert the bytes in the block)
     * @return string 明文
     */
    public function decrypt($data, $code = 'base64', $padding = OPENSSL_PKCS1_PADDING, $rev = false)
    {
        $ret = false;
        $data = $this->_decode($data, $code);
        if (!$this->_checkPadding($padding, 'de')) $this->_error('padding error');
        if ($data !== false) {
            if (openssl_private_decrypt($data, $result, $this->priKey, $padding)) {
                $ret = $rev ? rtrim(strrev($result), "\0") : '' . $result;
            }
        }
        return $ret;
    }
}

RSA类的使用:use.php

<?php

if (!class_exists("RSA")) {
    require_once "Rsa.class.php";
}

$private_key_file = __DIR__ . "/cert/private_key.pem";
$public_key_file = __DIR__ . "/cert/public_key.pem";

$rsa = new RSA();

// 没有就生成一对
if (!file_exists($private_key_file) || !file_exists($public_key_file)) {
    $key = $rsa->generate();

    file_put_contents($private_key_file, $key['private_key'], LOCK_EX);
    file_put_contents($public_key_file, $key['public_key'], LOCK_EX);
} else {
    $key = [
        "private_key" => file_get_contents($private_key_file),
        "public_key" => file_get_contents($public_key_file)
    ];
}

//显示数据
echo "private_key:\n" . $key['private_key'] . "\n\r";
echo "public_key:\n" . $key['public_key'] . "\n\r";

//要加密的数据
$data = "Web site:http://blog.kilvn.com";
echo '加密的数据:' . $data, "\n-------------------------------\n";

$rsa->init($public_key_file, $private_key_file);


//加密
$encrypt = $rsa->encrypt($data);
echo "公钥加密后的数据: " . $encrypt . "\n";

//解密
$decrypt = $rsa->decrypt($encrypt);
echo "私钥解密后的数据: " . $decrypt, "\n-------------------------------\n";

//签名
$sign = $rsa->sign($data);
echo "签名的数据: " . $sign . "\n";

//验证
$verify = $rsa->verify($data, $sign);
echo "验证的数据: " . $verify . "\n", "\n-------------------------------\n";

运行结果如下:

/usr/bin/php /Volumes/Mac软件/WEB/www/use.php
private_key:
-----BEGIN PRIVATE KEY-----
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
mpPQ1kaLJ7QoBD/vT74UhxpqUgCma/Q=
-----END PRIVATE KEY-----

public_key:
-----BEGIN PUBLIC KEY-----
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAwGji+aUGELbI6sa7ifb0
W9QYCp9aMSy0zg5TXV/fDmg/9/hAqjRpTeLThLSxeTNPmzf2VZ9jvrZ7IjkYldfA
2VOe4x91DosU1Fniwf6TYuNemM3H/DK9dGuFXzI1jsiiAobyd5Jb5Ptt0HWLgKNb
jXquh8UddadHgaeKwlbtYYIypb9hhf4ocywQc2dbBBS6e7RpI/XQr+TDkhZPvUYa
4lAaDnPdbc9V75qE/WU9Q2ACiw6jtrcpL1nH5Hif4OHrAHrKLOUyUhUXdkKDFjxN
aZfXxDEUqxLkUw7PXlmww3Rcr3S5MQVP9UXqgHlvOQOYiddXYY81XKA5pXKcWIrA
xjbeUPmVW7UmCFOlYcV/j+rVNDMokQqUragMi+pqpYkzXum7UXB5zjsB8kMVx8l4
/0M5vNk4XGzFCbj4pdsLwxRFW7AVqHqRiGYEEEkl/UpHIl+T+aEZXQI/uAa0q9+R
BoqXVqMqmoYT6R5wPUOliDYchAQUxJkGVow60Y7kVrtIlqPvOG4ugLLpKRTiT+Tz
4mtmMEX+N+UmrAKABJUiGj7JD/lLPWAIKvOx+WlB47k2bTVZp5yTweezU0nOnaU5
gdoWqemWo5EC7JXO73ItLcKGQIY3qUu9tUTXUKTDO/XiDvPP04ggE9bODLfvoSBS
Ph5ANrtx0wxRMeu+VNoeqx8CAwEAAQ==
-----END PUBLIC KEY-----

加密的数据:Web site:http://blog.kilvn.com
-------------------------------
公钥加密后的数据: WJ3JtHA9h+fJyPgl4WNtmplqexi6AvBCP0yC4zFo8AsgHyIu2u5Jt/olDw8Hmjmy4++XjdJwlKC9pNwNTiuj/TvDoWAulDJSgmrTZ/Jrp78K8Puik8n3Zudtmqj9rMMKAwgaX4t8+QRA+tBs5HiRUBpDsKPL8rejqIYZwMwxf67ldbwWFUtuFb8OWvG6EeQjPoKV2mOWi7/KnNFTLc6970sWTgcVe53KeqWrNyHvHLhQda3uom8lf1eOwOrOmhtI1sQdihH36LATCzObcDDsRTJr2oW3Y2d1Sx1npVJ92AvOmOVxFcena8ppkZ+cCRWAxTbiZejdLv9dGCn227yEm5/A5b1MXSHxZcXQ56Vy56Lo735+G6V5zkupVbQJrZBAJg0iDJPi6DFzffLMlTmRlszmiGxg67lxbKQQMhpYkVgZ9PfgYmXzUPVZSXRCz7zGkrP7qqAmbA2tGxRadh1FgekDmb8lSYEbLP6w1gKv5eJTCWYAeUTYuSHsLvCzF2+rJfRz9XrYYVaYAz5ECPCSCOSldENu97Ol612FWJuLZZNFiTLfpkqTYIvgSVGnqbuIMxU+HIifC+/cHabwSpvJ7q2lGmtdcv5mmHfi2V2XpB7SRfe67sbBIeIhF0XOqFoOf1VuhsC+ZP0INV1DIQVvTmivl5+IrORhrxc1c090Eso=
私钥解密后的数据: Web site:http://blog.kilvn.com
-------------------------------
签名的数据: enU5lIt8t7R5nsWw0OK7O8n4yttwo4cR44MDCqr8l4CmobLKgsFJyNskY33EtusisWST8UQconXtRxscEWrFXZTO74xsLKVLP1ZffJZyeRB0hiygNk/h3rZgtZXzGvMDBuOHBn40f4x+DQ83eZuvNPNNjA6nbuoBvyKT7WiP3bQ9HeJQBj7hfQhHbGYnOLwXTvXUbJDhDfpX6Ux4pAz9rjV14s9eKyfmncH0gIbHQDpMd+B06cdKi8i3pX2tGzPleEw9XRIfu1fkDxZ4J9ZruTUDUU0V5jhi+YlBFDo7Hsj3wsAVPTwOIgoRVwggaFCNeXLqx2u0u4BHj0FxJ6Qk2CC8izhcSoVQCfhrS3g9rUP5jCX4JP62kPJ1tIrxx2T+xs2tbdppe7q4Wx6EuIlZvWpnc7oHmPRP2Z3wEfsn49n8wI2f0zSYq3YmyrO0yEFT5bpvLggf6eyIsnnOO/uI/QfksAzSoKuJ3Wf6v0jYZrij/Y6d0jXIkn1MQpFjk5ZA4Dajt2frAzPXViqgdO8YuMFCFD5U2V6GnSYQ8xLR1V88zm3bH/baqqQFOMV0wMaZh9UtgBT5mCRXnUtYHdSjAhfj9xygOtw61p66EKO4Ykf7yxpivOI1QNn1hzA52MPktOTJwitUQXvSUDB5mgkjCPbS05LitAGU71REQ1urk5w=
验证的数据: 1

-------------------------------

Process finished with exit code 0

相关参考:

【摘要】HTTPS 的介绍及工作原理

在互联网安全日益重要的今天,HTTPS(超文本传输安全协议)成为了保护用户数据和隐私的关键技术。本文将对 HTTPS 进行介绍,并详细阐述其工作原理。

1. 什么是 HTTPS?

HTTPS 是 HTTP(超文本传输协议)的安全版本。它通过在 HTTP 的基础上加入 SSL/TLS(安全套接层/传输层安全)协议,实现数据加密传输,确保数据在客户端和服务器之间的安全性。HTTPS 主要用于保护用户的隐私信息,如信用卡号、登录凭据和个人数据等。

1.1 主要特点

  • 加密:使用 SSL/TLS 加密数据,防止中间人攻击和数据窃听。
  • 身份验证:通过数字证书验证服务器身份,确保用户连接的是合法网站。
  • 数据完整性:确保数据在传输过程中未被篡改。

2. HTTPS 的工作原理

HTTPS 的工作原理主要分为以下几个步骤:

2.1 客户端发起请求

用户在浏览器中输入 HTTPS URL(如 https://www.example.com),浏览器向服务器发送请求,要求建立安全连接。

2.2 服务器响应

服务器收到请求后,返回其数字证书。数字证书包含了公钥和由可信任的证书颁发机构(CA)签名的信息。

2.3 验证数字证书

客户端(浏览器)对服务器的数字证书进行验证:

  • 检查证书是否有效(未过期、未被吊销)。
  • 验证证书的颁发者是否可信(是否由受信任的 CA 签发)。
  • 确认证书中所包含的域名与访问的域名一致。

2.4 建立加密连接

一旦客户端验证通过,双方将开始建立加密连接,具体过程如下:

  1. 握手过程

    • 客户端生成一个随机数(称为 Pre-Master Secret),并用服务器的公钥加密后发送给服务器。
    • 服务器使用其私钥解密,得到 Pre-Master Secret。
  2. 生成会话密钥

    • 客户端和服务器使用 Pre-Master Secret 和之前交换的随机数生成对称加密密钥(会话密钥)。
  3. 加密通信

    • 客户端和服务器使用会话密钥进行加密通信,确保数据的安全传输。

2.5 结束通信

当数据传输完成后,客户端和服务器可以通过发送“关闭连接”消息来结束安全会话。

3. HTTPS 的优势

  • 保护敏感数据:HTTPS 确保用户在网上传输的敏感信息得到保护,减少数据泄露的风险。
  • 增强 SEO 排名:搜索引擎(如 Google)对使用 HTTPS 的网站给予更高的排名。
  • 提高用户信任:用户更倾向于信任使用 HTTPS 的网站,增强品牌形象。

4. 注意事项

  • 证书管理:定期更新和管理 SSL/TLS 证书,以确保其有效性。
  • 强制 HTTPS:通过 HTTP Strict Transport Security (HSTS) 强制浏览器使用 HTTPS 连接。
  • 性能影响:虽然加密会增加 CPU 的负担,但现代硬件和优化技术使得 HTTPS 的性能影响最小化。

5. 结论

HTTPS 是现代互联网安全的重要组成部分。通过加密和身份验证,它有效地保护了用户的数据和隐私。在构建网站时,实施 HTTPS 是确保用户安全和信任的基本要求。

Mongo geoNear 使用笔记

在地理信息系统(GIS)和位置服务的应用中,MongoDB 提供了强大的地理空间查询能力。geoNear 是 MongoDB 中用于查找离一个给定点最近的文档的操作。本文将介绍 geoNear 的基本用法和示例,帮助您在项目中有效地利用这一功能。

1. 什么是 geoNear?

geoNear 是 MongoDB 的一个聚合管道操作,允许您根据地理坐标查询文档。它的主要功能包括:

  • 根据指定点的地理位置返回最近的文档。
  • 可以限制返回的结果数量和排序方式。
  • 支持计算距离和使用地理空间索引提高查询性能。

2. 准备工作

2.1 创建集合和插入数据

首先,我们需要创建一个集合并插入带有地理信息的文档。以下是一个示例代码:

use mydatabase;

db.places.insertMany([
    { name: "Place A", location: { type: "Point", coordinates: [102.0, 0.5] } },
    { name: "Place B", location: { type: "Point", coordinates: [103.0, 1.0] } },
    { name: "Place C", location: { type: "Point", coordinates: [104.0, 2.0] } }
]);

2.2 创建地理空间索引

为了使用 geoNear 查询,我们需要在 location 字段上创建一个地理空间索引:

db.places.createIndex({ location: "2dsphere" });

3. 使用 geoNear 查询

3.1 基本查询

以下是一个使用 geoNear 查询最近地点的基本示例:

db.places.aggregate([
    {
        $geoNear: {
            near: { type: "Point", coordinates: [102.5, 0.5] },
            distanceField: "dist.calculated",
            maxDistance: 10000, // 限制最大距离,单位为米
            spherical: true, // 使用球面距离计算
            query: { name: { $ne: "Place A" } } // 可选:过滤条件
        }
    }
]);

3.2 查询解析

  • near:指定查询的中心点,必须是一个 GeoJSON 格式的点。
  • distanceField:指定返回文档时,计算出的距离字段名称。
  • maxDistance:可选参数,限制返回的文档距离中心点的最大距离。
  • spherical:设置为 true,表示使用球面距离计算,适用于地球上位置的查询。
  • query:可选的过滤条件,可以根据需要添加。

3.3 查询结果

执行上述查询后,您将获得离指定点最近的地点,并且每个地点都有一个计算出的距离字段。例如:

[
    { "name": "Place A", "location": { "type": "Point", "coordinates": [102.0, 0.5] }, "dist": { "calculated": 500 } },
    { "name": "Place B", "location": { "type": "Point", "coordinates": [103.0, 1.0] }, "dist": { "calculated": 1000 } }
]

4. 实际应用场景

  • 位置服务:查找用户附近的餐馆、商店等。
  • 物流管理:根据配送中心位置查找最近的客户。
  • 社交网络:推荐附近的朋友或活动。

5. 注意事项

  • 索引:确保在地理空间字段上创建索引,以提高查询性能。
  • 数据格式:确保插入的数据符合 GeoJSON 格式,便于 geoNear 查询。
  • 距离单位:根据需要选择合适的距离单位(米或公里)。

6. 结论

MongoDB 的 geoNear 操作是一个强大的工具,可以帮助开发者轻松实现地理位置查询功能。通过合理使用地理空间索引和聚合管道,您可以在项目中高效地处理与位置相关的数据。

kafka安装及Kafka-PHP扩展的使用,kafka-php扩展

在现代分布式系统中,Apache Kafka 是一种流行的消息队列系统,用于高吞吐量的数据传输和处理。本文将介绍如何安装 Kafka,并详细讲解如何使用 kafka-php 扩展在 PHP 中与 Kafka 进行交互。

1. 什么是 Apache Kafka?

Apache Kafka 是一个开源流处理平台,能够处理实时数据流。它的主要特性包括:

  • 高吞吐量:支持每秒处理数百万条消息。
  • 可扩展性:支持水平扩展,通过增加服务器轻松扩展集群。
  • 持久性:支持消息的持久化存储,确保数据不会丢失。

2. Kafka 安装步骤

2.1 安装 Java

Kafka 是用 Java 编写的,因此需要安装 Java Runtime Environment (JRE):

sudo apt update
sudo apt install default-jre

您可以通过以下命令检查 Java 是否安装成功:

java -version

2.2 下载 Kafka

Apache Kafka 官网 下载最新版本的 Kafka。

wget https://downloads.apache.org/kafka/<version>/kafka_<scala_version>-<kafka_version>.tgz
tar -xzf kafka_<scala_version>-<kafka_version>.tgz
cd kafka_<scala_version>-<kafka_version>

2.3 启动 Zookeeper 和 Kafka

Kafka 依赖 Zookeeper 来管理分布式系统的状态。您可以通过以下命令启动 Zookeeper 和 Kafka:

# 启动 Zookeeper
bin/zookeeper-server-start.sh config/zookeeper.properties &

# 启动 Kafka
bin/kafka-server-start.sh config/server.properties &

2.4 创建主题

在 Kafka 中,消息被组织在主题中。可以使用以下命令创建一个新主题:

bin/kafka-topics.sh --create --topic test-topic --bootstrap-server localhost:9092 --partitions 1 --replication-factor 1

2.5 验证安装

您可以使用以下命令列出所有主题,验证 Kafka 是否安装成功:

bin/kafka-topics.sh --list --bootstrap-server localhost:9092

3. Kafka-PHP 扩展的使用

3.1 安装 Kafka-PHP 扩展

kafka-php 扩展是一个用于 PHP 的 Kafka 客户端库。使用 Composer 安装:

composer require nmred/kafka-php

3.2 生产者示例

以下是使用 kafka-php 扩展编写的生产者示例代码:

<?php

require 'vendor/autoload.php';

use Kafka\Producer;
use Kafka\ProducerConfig;

// 配置生产者
$producer = new Producer();
ProducerConfig::getInstance()->setMetadataBrokerList('127.0.0.1:9092');

// 发送消息
$producer->send([
    [
        'topic' => 'test-topic',
        'value' => 'Hello Kafka!',
        'key' => '',
        'partition' => 0,
    ],
]);

echo "Message sent to Kafka\n";
?>

3.3 消费者示例

以下是使用 kafka-php 扩展编写的消费者示例代码:

<?php

require 'vendor/autoload.php';

use Kafka\Consumer;
use Kafka\ConsumerConfig;

// 配置消费者
ConsumerConfig::getInstance()
    ->setMetadataBrokerList('127.0.0.1:9092')
    ->setGroupId('test-group')
    ->setTopics(['test-topic']);

$consumer = new Consumer();

// 开始消费
$consumer->start(function ($topic, $partition, $message) {
    echo "Received message: {$message['value']}\n";
});
?>

4. 运行示例

  1. 启动 Kafka 生产者:
php producer.php
  1. 启动 Kafka 消费者:
php consumer.php

消费者将接收并打印出生产者发送的消息。

5. 注意事项

  • 配置:根据实际情况调整 Kafka 的配置文件,确保网络和性能满足应用需求。
  • 错误处理:在生产环境中,添加错误处理机制以应对网络问题和消息处理失败。
  • 安全性:考虑使用 SSL 和认证机制保护 Kafka 集群。

6. 结论

通过本文的介绍,您应该能够成功安装 Kafka,并使用 kafka-php 扩展在 PHP 中与 Kafka 进行交互。Kafka 是一个强大的工具,适用于实时数据流处理和高吞吐量消息传递。

">