参考社区的示例使用自定义进程方式写的sse服务,正常不使用nginx或者不使用ssl时可正常连接,但是加上ssl就不行,服务器上尝试相同的ssl配置用node写的sse示例能正常输出
namespace process;
use Workerman\Connection\TcpConnection;
use Workerman\Protocols\Http\Request;
use Workerman\Protocols\Http\ServerSentEvents;
use Workerman\Protocols\Http\Response;
use Webman\Channel\Client;
use Workerman\Timer;
class EventSource
{
protected $connections = [];
/**
* 函数描述
* onWorkerStart
* @author :lance
* @description:{初始化工作进程,并连接至channel服务}
*/
public function onWorkerStart()
{
// 连接到 Channel 服务(默认监听 2206 端口)
try {
Client::connect(channelIP, channelPort);
// 订阅消息频道
Client::on('sse_message', function ($data) {
$token = $data['token'] ?? false;
if ($token && $token !== '' && isset($this->connections[$token])) {
foreach ($this->connections[$token] as $connection) { // 需自行维护连接池
$connection->send(new ServerSentEvents([
'event' => 'message',
'data' => json_encode($data),
'id' => $data['mid']
]));
}
}
});
} catch (\Exception $e) {
error_log("Failed to connect to Channel service: " . $e->getMessage());
return;
}
}
/**
* 函数描述
* onMessage
* @param TcpConnection $connection
* @param Request $request
* @author :lance
* @description:{服务连接时进行消息推送}
*/
public function onMessage(TcpConnection $connection, Request $request)
{
// 如果Accept头是text/event-stream则说明是SSE请求
// if ($request->header('accept') === 'text/event-stream') {
// 首先发送一个 Content-Type: text/event-stream 头的响应
$connection->send(new Response(200, [
'Content-Type' => 'text/event-stream',
'Access-Control-Allow-Origin' => '*', // 允许的域名
'Access-Control-Allow-Methods' => 'GET, POST, OPTIONS', // 允许的请求方法
'Access-Control-Allow-Headers' => 'Content-Type, Authorization', // 允许的请求头
], '\r\n'));
// 假设请求中带有用户标识,比如 URL ?uid=123
$token = $request->get('token') ?? $connection->id;
$connection->token = $token;
$connectionId = $connection->id;
// 保存该连接到全局数组中
$this->connections[$token][$connectionId] = $connection;
//默认发送一个hello信息
$connection->send(new ServerSentEvents(['event' => 'message', 'data' => 'hello', 'id' => 1]));
// 定时向客户端推送数据
$timer_id = Timer::add(2, function () use ($connection, &$timer_id) {
// 连接关闭的时候要将定时器删除,避免定时器不断累积导致内存泄漏
if ($connection->getStatus() !== TcpConnection::STATUS_ESTABLISHED) {
Timer::del($timer_id);
return;
}
// 发送message事件,事件携带的数据为hello,消息id可以不传
$connection->send(new ServerSentEvents(['event' => 'message', 'data' => json_encode(['t'=>'hello']), 'id' => 1]));
});
return;
//}
$connection->send('ok');
}
/**
* 函数描述
* onClose
* @param TcpConnection $connection
* @author :lance
* @description:{关闭连接时,删除连接}
*/
public function onClose(TcpConnection $connection)
{
if (isset($connection->token)) {
if (isset($this->connections[$connection->token])) {
if(isset($this->connections[$connection->token][$connection->id])){
// 删除连接
unset($this->connections[$connection->token][$connection->id]);
}
}
}
}
}
Nginx配置如下
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name pdfapi.xxxx.cn;
root /mnt/sse;
ssl_certificate "/mnt/ssl/xxxx/fullchain.cer";
ssl_certificate_key "/mnt/ssl/xxxx/xxxx.cn.key";
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 10m;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
# Load configuration files for the default server block.
# include /etc/nginx/default.d/*.conf;
error_page 404 /404.html;
location = /40x.html {
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
location / {
proxy_pass http://192.168.0.18:8687/;
#proxy_pass http://127.0.0.1:3001/;
proxy_http_version 1.1;
proxy_set_header Connection '';
proxy_buffering off;
proxy_cache off;
proxy_read_timeout 86400;
}
}
无ssl时能正常输出
加上ssl时报错
同样配置下node写的测试环境可以正常访问
系统为centos6.7,php版本为7.2,
应该不是nginx配置的原因,网上的配置基本我都试过了,我昨晚又试了webman2.1的版本是可以的反向代理的,我的webman版本是1.47
找到原因了,第一次发的文件头,多了换行符“\r\n”,给大家参考