PHP 接入 OneZore

在现代应用开发中,数据的安全性至关重要。OneZore 是一个强大的服务,但为了确保数据传输的安全性,我们通常需要使用加密通道。本文将介绍如何通过 Stunnel 建立加密通道,并使用 PHP 安全地连接 OneZore。
什么是 Stunnel?
Stunnel 是一个开源的多平台代理工具,用于在不支持加密的客户端和服务端之间提供 SSL/TLS 加密。它通过将未加密的流量封装在加密通道中,确保数据在传输过程中的安全性。
为什么使用 Stunnel?
- 加密通信:确保数据在传输过程中不被窃听或篡改。
- 兼容性:支持多种协议,适用于不同系统或应用之间的安全通信。
- 灵活性:可以在不修改现有应用代码的情况下实现加密通信。
实现步骤
1. 安装 Stunnel
首先,我们需要在服务器上安装 Stunnel。
在 Linux 上安装 Stunnel
sudo apt-get update
sudo apt-get install stunnel4
在 Windows 上安装 Stunnel
从 Stunnel 官网 下载并安装。
2. 配置 Stunnel
编辑 Stunnel 的配置文件(通常位于 /etc/stunnel/stunnel.conf 或 stunnel.conf),添加以下内容:
[onezore]
client = yes
accept = 127.0.0.1:8080
connect = onezore-server-address:port
accept:Stunnel 监听的本地地址和端口。connect:OneZore 服务端的地址和端口。
3. 启动 Stunnel
在 Linux 上启动 Stunnel
sudo service stunnel4 start
在 Windows 上启动 Stunnel
通过服务管理器启动 Stunnel。
4. 使用 PHP 连接 Stunnel
在 PHP 中,我们可以通过连接到 Stunnel 监听的本地地址和端口来建立加密通信。
<?php
// 连接到 Stunnel 监听的本地端口
$host = "127.0.0.1";
$port = 8080;
// 创建 socket 连接
$socket = fsockopen($host, $port, $errno, $errstr, 30);
if (!$socket) {
echo "连接失败: $errstr ($errno)";
} else {
// 发送请求
$request = "GET /endpoint HTTP/1.1\r\nHost: onezore-server\r\nConnection: Close\r\n\r\n";
fwrite($socket, $request);
// 读取响应
$response = "";
while (!feof($socket)) {
$response .= fgets($socket, 128);
}
fclose($socket);
echo "响应: " . $response;
}
5. 验证连接
运行 PHP 脚本,如果一切正常,你应该能够看到 OneZore 服务端的响应。通过 Stunnel,所有的通信都已经过加密,确保了数据的安全性。
总结
通过 Stunnel,我们可以轻松地在 PHP 应用中实现与 OneZore 的安全通信。这种方法不仅简单易行,而且无需修改现有代码,非常适合需要快速实现加密通信的场景。
通过端口和进程ID定位进程运行地址
在实际的系统管理和故障排查中,我们经常需要根据端口或进程ID(PID)来定位进程的运行地址。本文将详细介绍如何通过端口找到进程ID,再通过进程ID找到进程的运行地址。
场景描述
假设我们有一条Redis命令日志:
1739755907.286905 [0 172.31.0.12:47294] "ZADD" "test_hash" "2" "1"
从日志中我们可以看到,Redis客户端连接的IP地址是172.0.0.1,端口是47294。我们的目标是通过这个端口找到进程ID,再通过进程ID找到进程的运行地址。
步骤详解
1. 登录到目标服务器
首先,我们需要登录到IP地址为172.0.0.1的服务器。可以使用SSH命令登录:
ssh user@172.0.0.1
2. 通过端口找到进程ID
登录到服务器后,我们可以使用lsof命令来查找哪个进程正在使用端口47294:
lsof -i :47294
输出可能类似于:
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
redis-ser 14202 redis 6u IPv4 123456 0t0 TCP *:47294 (LISTEN)
从输出中我们可以看到,进程ID(PID)是14202,进程名称是redis-server。
3. 通过进程ID找到进程的运行地址
接下来,我们可以使用ps命令来查看该进程的详细信息,包括命令行参数:
ps -p 14202 -o args=
输出可能类似于:
/usr/bin/redis-server *:6379
4. 查找进程的工作目录
为了找到进程的运行地址,我们可以使用pwdx命令来查看进程的工作目录:
pwdx 14202
输出可能类似于:
14202: /var/lib/redis
5. 使用/proc文件系统进一步确认
我们还可以通过/proc文件系统来查看进程的当前工作目录:
ls -l /proc/14202/cwd
输出可能类似于:
lrwxrwxrwx 1 redis redis 0 Oct 1 12:34 /proc/14202/cwd -> /var/lib/redis
通过以上步骤,我们成功地通过端口47294找到了进程ID14202,并通过进程ID找到了进程的运行地址/var/lib/redis。这一过程在系统管理和故障排查中非常有用,尤其是在需要定位特定服务的运行环境时。
关键命令总结
通过端口查找进程ID:
lsof -i :47294
通过进程ID查看命令行参数:
ps -p 14202 -o args=
通过进程ID查找工作目录:
pwdx 14202
通过/proc文件系统确认工作目录:
ls -l /proc/14202/cwd
SSE 协议详解:使用场景与 Swoole 实现
1. 什么是 SSE?
SSE(Server-Sent Events)是一种允许服务器向客户端推送实时更新的技术。与 WebSocket 不同,SSE 是单向的,即服务器可以向客户端发送数据,但客户端不能向服务器发送数据。SSE 基于 HTTP 协议,使用简单的文本格式进行数据传输。

2. SSE 与 WebSocket 的区别
2.1 通信方式
- SSE: 单向通信,服务器向客户端推送数据。
- WebSocket: 双向通信,服务器和客户端可以互相发送数据。
2.2 协议
- SSE: 基于 HTTP 协议,使用简单的文本格式。
- WebSocket: 基于独立的 WebSocket 协议,支持二进制和文本数据。
2.3 连接管理
- SSE: 客户端通过 HTTP 请求建立连接,服务器保持连接并推送数据。
- WebSocket: 客户端和服务器通过 WebSocket 握手建立连接,之后可以双向通信。
2.4 适用场景
- SSE: 适用于服务器向客户端推送实时更新的场景,如股票行情、新闻推送等。
- WebSocket: 适用于需要双向通信的场景,如聊天应用、在线游戏等。
图解 SSE 和 WebSocket 的区别
+-------------------+ +-------------------+
| | | |
| Client | | Client |
| | | |
+--------+----------+ +--------+----------+
| |
| HTTP Request | WebSocket Handshake
| |
v v
+--------+----------+ +--------+----------+
| | | |
| Server | | Server |
| | | |
+-------------------+ +-------------------+
| |
| SSE (Server Push) | WebSocket (Bi-directional)
| |
v v
+--------+----------+ +--------+----------+
| | | |
| Client | | Client |
| | | |
+-------------------+ +-------------------+
3. SSE 协议格式
SSE 数据格式非常简单,每条消息由若干行文本组成,每行以换行符 \n 结尾。消息可以包含以下字段:
data: 消息的内容,可以有多行。event: 事件类型,可选。id: 消息的唯一标识符,可选。retry: 客户端重连的时间间隔,单位为毫秒,可选。
图解 SSE 协议格式
event: message\n
id: 123\n
retry: 5000\n
data: {\n
data: "message": "Hello, World!"\n
data: }\n
\n
4. SSE 的使用场景
SSE 适用于以下场景:
- 实时通知: 如新闻推送、系统通知等。
- 实时数据更新: 如股票行情、天气预报等。
- 日志监控: 实时查看服务器日志。
- 进度更新: 如文件上传进度、任务处理进度等。
5. Swoole 实现 SSE 示例
5.1 服务端代码
<?php
use Swoole\Http\Request;
use Swoole\Http\Response;
use Swoole\Http\Server;
$server = new Server("0.0.0.0", 9501);
$server->on("request", function (Request $request, Response $response) {
// 设置响应头
$response->header("Content-Type", "text/event-stream");
$response->header("Cache-Control", "no-cache");
$response->header("Connection", "keep-alive");
// 发送初始数据
$response->write("event: connect\n");
$response->write("data: " . json_encode(["message" => "Connected"]) . "\n\n");
// 模拟实时数据推送
$i = 0;
while (true) {
$i++;
$response->write("data: " . json_encode(["message" => "Message $i"]) . "\n\n");
sleep(1);
}
});
$server->start();
5.2 客户端代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>SSE Client</title>
</head>
<body>
<div id="messages"></div>
<script>
const eventSource = new EventSource("http://127.0.0.1:9501");
eventSource.onmessage = function(event) {
const data = JSON.parse(event.data);
document.getElementById("messages").innerHTML += `<p>${data.message}</p>`;
};
eventSource.onerror = function(event) {
console.error("EventSource failed:", event);
};
</script>
</body>
</html>
6. 总结
SSE 是一种简单且高效的服务器推送技术,适用于需要服务器向客户端实时推送数据的场景。与 WebSocket 相比,SSE 更加轻量级且易于实现。通过 Swoole,我们可以轻松实现 SSE 服务端,并结合前端技术实现实时数据推送功能。
[踩坑] Mysql 主从延迟排故过程分析
昨天帮朋友 看一个问题, 服务器间接主从延迟问题, 延迟时间不固定, 偶现1到2小时随机出现, 每次延迟最高30秒,维持1分钟左右.
主库CPU长期50% 负载不严重, 从库了解到更是没流量没负载.


常见出现主从延迟的场景如下:
- 主从配置不同, 从库配置查同步慢
- 从库负载过高, 导致延迟
- 大事务操作,
insert select 最为经典, 还有 就是 for update / delete / update 语句中的 where 使用区间索引.
了解到 可以排除前两样 1 和 2, 排除法定位 查询是否存在慢日志.
使用谷歌的GCP云服务, 内部提供了个查询工具, 通过平均执行时间倒序 找出问题的

1) 逐一SQL排查 发现 发现 存在 insert select 语句 是个大问题
2) 又发现两个 delete 语句 where 条件是 id <= $id and type=1 and status=1, id 是主键 type不是1就是2 虽然 type status 存在索引,但这个delete 语句 用到的还是 主键索引! 索引导致区间锁的问题.
解决方案:
修改 1) 2) 的SQL语句, 改为
1. 查询出需要删除的表 500条
2. 事务开启
3. 批量插入500条到新表
4. 使用 主键ID, delete from where id in () 批量删除500条
5. 事务提交