我最近在我们的测试环境中从Azure App Services Windows切换到了Linux。除了我们的套接字连接之外,一切都像以前一样工作。关于Linux应用程序服务,似乎有很多过时的信息,而且文档也乏善可陈。然而,根据这些发行说明,Azure App Service Linux上的web套接字支持。
在某些适用于 Linux 的 Azure 应用服务文档中,它指出必须禁用 perMessageDeflate
才能使 Web 套接字与 Linux 应用服务和 NodeJS 配合使用。我相信我已经在下面的HapiJS服务器代码中做到了这一点。我已经通过控制台.log(io)
验证了perMessageDeflate
的设置似乎正确设置为false。
import Server from 'socket.io';
import socketioJwt from 'socketio-jwt';
const myHapiJSPlugin = {
name: 'myPluginName',
version: '2.0.0',
register: function (server, options) {
const io = new Server(server.listener, {
perMessageDeflate: false,
transports: ['websocket'],
origins: '*:*'
});
io.use(socketioJwt.authorize({
secret: JWT_SECRET_KEY,
handshake: true
}));
io.on('connection', socket => {
console.log(io);
// more code here
};
};
};
当我使用我的网络客户端打开Chrome控制台的网络页面时,我从服务器获得了101响应代码。I console.log
连接/断开socket.io的客户端回调。我可以看到它不断地连接/断开,尽管得到了服务器的确认(101响应)。控制台中的连接状态显示为“已停止”。当回调触发时,我似乎订阅了一个特定的路由。
自从从Azure App Services Windows切换以来,我没有做过其他代码更改,尽管下面的配置是为测试socket.io文档添加perMessageDeflate
和origins
。我想在握手或身份验证过程中出现了问题。
Status Code: 101 Switching Protocols
Access-Control-Allow-Origin: *
Connection: Upgrade
Date: Tue, 01 Oct 2019 18:04:57 GMT
Sec-WebSocket-Accept: <HASH>
Server: Kestrel
Upgrade: websocket
我还在我的客户端代码中添加了perMessageDeflate
。这没有什么区别。
const client = new io(URL, {
query: 'token=' + jwt,
perMessageDeflate: false,
transports: ['websocket'],
upgrade: false
});
我还缺什么?如何在Azure App Service Linux上启用web套接字?我检查了类似Windows的配置设置。似乎没有这样的设置,因为默认情况下似乎启用了web套接字。我已经在日志中验证了web服务器没有持续重新启动导致连接/断开连接。
如果身份验证关闭,您的WebSockets还能工作吗?
我只有在启用身份验证功能时才会遇到使用Linux应用程序的WebSocket问题。
我认为这是由于EasyAuth代理的实现很差,并且它被认为是MS很难解决的问题。
通过应用服务上的门户禁用LinuxCORS和AUTH。
通过转到应用服务来禁用 CORS,在左侧菜单栏的“API”下选择“CORS”,删除其中的任何条目。通过删除所有条目,你将禁用 Azure 的应用服务的 CORS 实现。
通过转到左侧菜单栏上“设置”标题下的“身份验证/授权”来禁用身份验证。单击开关以“关闭”。
这将允许 Web 套接字在 Linux 应用服务中按预期工作。但是,您现在需要使用 Web 服务器框架配置 CORS 和 AUTH。
在收到我的 MS 支持代表的回复后,她确认启用 CORS 或 AUTH 会破坏 Linux 应用服务的套接字实现。Linux App Service CORS 和 AUTH 功能尚未由 Microsoft 实现。
为了使用Linux应用服务和利用CORS或认证功能,你根本不能,因为它没有实现。官方推荐的解决方案是切换到Windows App服务。
无论Azure留档状态如何,WebSocket都不需要使用perMessageDeflate
socket.io.我让它在没有它的情况下正常工作。要从门户为应用服务配置CORS,它与Windows相同。您可以在门户中转到您的应用服务,在API下的左侧菜单中选择CORS。删除其中的任何条目以禁用应用服务的CORS功能。我在测试期间只使用了一个条目(*
),因为在切换到Linux之前,我的Windows应用服务正确配置了CORS。
如果删除了所有条目,则应该可以使用没有CORS的Web套接字。但是,请记住,出于安全原因,您应该使用web服务器框架配置CORS。如果它是用socket.io表达的,你就必须这样做。大多数web框架都遵循类似的范例,将其指定在服务器对象上作为选项。
在 GitHub 上的此线程中有更多关于此内容的信息。
我在 Node 上遇到了类似的问题。socket.io 在 Azure CDN 托管域上的 Linux 上运行的应用服务上失败。能够通过使用自定义域和 TLS/SSL 设置将我的域链接到应用服务 URL,而不是在应用服务上设置 Azure CDN,来缓解此问题。