通过Django调用k8s client来实现webssh登录:

涉及技术

  • Kubernetes Stream:接收数据执行,提供实时返回数据流
  • Django Channels:维持长连接,接收前端数据转给Kubernetes,同时将Kubernetes返回的数据发送给前端
  • xterm.js:一个前端终端组件,用于模拟Terminal的界面显示

基本的数据流向是:用户 –> xterm.js –> django channels –> kubernetes stream,接下来看看具体的代码实现

用到的模块:

关键文件:

k8s.py:

consumer.py:

 

出现问题:

  1. 窗口自适应的问题:
  2. cat有中文字符的文件,会卡住,报错:UnicodeDecodeError: ‘utf-8’ codec can’t decode bytes in position…
    1. 原因:是k8s client python sdk的一个bug, 解决方式是修改/root/.py_env/.virtualenvs/ansible/lib/python3.9/site-packages/kubernetes/stream/ws_client.py, 修改第179行data = data.decode(“utf-8”)为:data = data.decode(“utf-8”, “replace”)
      1.  参考:
      2. https://github.com/kubernetes-client/python-base/issues/88
      3. https://github.com/kubernetes-client/python-base/commit/15474efbaf906bf557c4a38392a0b06c95ce7841
  3. 打开webterminal页面后,容器所在机器的CPU负载会飙升,改成async异步也解决不了,官方sdk有个方法:

/root/.py_env/.virtualenvs/ansible/lib/python3.9/site-packages/kubernetes/stream/ws_client.py:


      1.  

     

    1. 解决: 在方法K8SStreamThread 里加上self.stream.update(timeout=1),当有最多一个完整的输入帧时更新通道缓冲区
    2. 参考: https://github.com/kubernetes-client/python/tree/release-12.0/examples

 

 

websocket原理:

Django WebSocket (一):WebSocket 概念及原理

WebSocket

基本概念

  • WebSocket允许服务端主动向客户端推送数据
  • 在WebSocket协议中
    • 客户端浏览器和服务器只需要一次握手就可以创建持久性的连接
    • 并在浏览器和服务器之间进行双向的数据传输
  • HTTP、WebSocket
    • 都是建立在TCP连接基础之上
    • websocket协议是通过http协议来建立传输层的TCP连接
docker

请求头

  • ConnectionUpgrade:表示客户端发起的是WebSocket请求
  • Sec-WebSocket-Version:客户端所使用的的WebSocket协议版本号,服务端会确认是否支持该版本号
  • Sec-WebSocket-Key:一个Base64编码值,有浏览器随机生成,用于升级request
  • Sec-WebSocket-Extensions:客户端想要表达的协议级的扩展

响应头

  • HTTP/1.1 101 Switching Protocols:切换协议,WebSocket协议通过HTTP协议来建立运输层的TCP连接
  • ConnectionUpgrade:表示服务端返回的是WebSocket响应

连接过程

目的:用户能够实时接受信息

JavaScript轮询

  • 客户端发送GET,请求,服务器返回页面数据
  • 客户端不停地发送请求,询问服务器是否有数据返回,服务器一直响应请求
  • 这种方式,服务器会浪费很多资源
docker

WebSocket连接

  • 1 .客户端通过HTTP协议发送GET请求,携带ConnectionUpgrade,指定要将HTTP协议升级成WebSocket协议
  • 2 .服务器给客户端返回HTTP/1.1 101 Switching Protocols,表示协议切换成功
  • 3 .服务端与客户端进行通信
docker

优缺点及应用场景

  • 优点:
    • 支持双向通信,实时性更强
    • 数据格式比较轻量,性能开销小,通信高效
    • 支持扩展。用户可以扩展协议或者实现自定义的自协议(比如支持自定义压缩算法)
  • 缺点
    • 少部分浏览器不支持,浏览器支持的程度和方式有区别
    • 长连接对后端处理业务的代码稳定性要求更高,后端推送功能相对复杂
    • 成熟的HTTP生态下有大量的组件可以使用,WebSocket较少
  • 应用场景
    • 及时聊天通信,网站消息通知
    • 在线协同编辑,如腾讯文档
    • 多玩家在线游戏,视屏弹幕、股票基金实时报价

Django 使用 WebSocket

Django WebSocket (二):Channels 概念及原理

Django Channels

Channels是一个为Django提供异步扩展的库,通常主要用来提供WebSocket支持和后台任务。

查看浏览器对WebSocket的支持

网络架构

  • Protocol Type Router:协议类型解析器,对不同类型的协议进行解析
    docker

处理请求

Django 请求

  • Django是一个同步框架:接收到请求之后,必须处理完这个请求,返回了之后,浏览器才能显示加载完毕
  • 业务场景:Django处理一个时间很长的请求
    • 面临的问题
      • 客户端浏览器会一直等待
      • Nginx会超时(TimeOut),关闭连接
    • 可以考虑的方案
      • 使用celery,将比较耗时的任务传递给celery,进行异步处理;Django正常返回
      • 问题:celery执行是否成功/执行成功之后的结果,都无法再通过Django主动发送给前端
        docker

Django Channels

  • interface server:接口服务器,负责对协议进行解析,将不同协议分发到不同的Channel
  • Channel Leyer:频道层,可以是一个FIFO(先进先出,first in;first out)队列,通常使用Redis
  • consumer:消费者,接受和处理消息
    docker

Channels中文件和配置的含义

  • 配置步骤
    • INSTALLED_APPS中注册Channels应用

在settings.py的配置文件中,添加CHANNEL_LAYERS缓存

 

  • asgi.py:介于网络协议服务和Python应用之间的标准接口,能够处理多重通用类型协议,包括HTTP、HTTP2和WebSocket
  • channel_layers:在settings.py中配置,类似于一个通道,发送者(producer)在一段发送消息,消费者(consumer)在另一端监听
  • routungs.py:相当于Django中的urls.py
  • consumers.py:相当于Django中的views.py
    • views.py: 用来开发符合WSGI规范的应用
    • consumers.py: 用来开发符合ASGI接口规范的Python应用

WSGI 和 ASGI

  • WSGI:
    • 为Python语言定义的Web服务器和Web应用程序或框架之前的一种简单而通用的接口
    • uWSGI:一个Web服务器, 可安装的软件,提供服务的
    • WSGI:一套标准,(HTTP,HTTPS)
  • ASGI:
    • 异步服务网关接口,一个介于网络协议器和Python之间的标准接口
    • 能够处理多种通用的协议类型,包括HTTP、HTTPS和WebSocket
  • 部署:
    • HTTP、HTTP2:Nginx/Apache + WSGI(uWSGI) + Django/Flask/Python3
    • HTTP、HTTP2、WebSocket:Nginx/Apache + ASGI)(Daphne)+ Django/Flask/Python3
  • 区别
    • WSGI:基于HTTP协议模式的,不支持WebSocket
    • ASGI:就是为了支持Python常用的WSGI所不支持的新的协议标准
    • 即:ASGI是WSGI的扩展,而且能通过asyncio异步运行

Consumer的使用

  • event loop:事件循环
  • event handler:事件处理
  • sync:同步
  • async:异步

scope:在ASGI接口规范中定义了,相当于WSGI中的request

 

ORM 同步到异步

什么时候用sync什么时候用async 异步的代码里面不要写入同步的逻辑,否则起不到真正意义上的异步并发

 

socp

在ASGI接口规范中定义了,相当于WSGI中的request

 

Generic Consumer同步与异步通信

docker

 

Channels的路由Routing开发

  • ProtocolTypeRouter:协议类型解析
  • self.scope[‘type’]获取协议类型
  • self.scope[‘url_route’][‘kwargs’][‘username’]获取url中关键字参数

channels routing是scope级别的,一个连接只能由一个consumer接收和处理

 

  • OriginValidator、AllowedHostsOriginValidator可以防止通过WebSocket进行CSRF攻击

OriginValidator需要手动添加允许访问的源站,如:

 

Django WebSocket (三):Channels + WebSocket 实现在线聊天

安装:pipenv install channels-redis

后端开发

注册应用

 

ASGI配置

asgi.py

配置asgi的时候,需要结合当前文件的目录结构,==> wsgi.py同级目录

 

setting配置

在settings.py中添加

 

Consumer配置

Channels的原理中说了:consumer.py相当于Django中的view.py 用来处理请求

 

Routing配置

  • 这里就相当于Django中的urls.py
  • 主要用来匹配不同的请求

 

前端代码

WebSocket基本使用

 

使用

 

参考: https://zhengxingtao.com/article/125/

更多知识:

https://segmentfault.com/a/1190000023402628

https://www.neerajbyte.com/post/how-to-implement-websocket-in-django-using-channels-and-stream-websocket-data

 

https://segmentfault.com/a/1190000023402628

Categories: 未分类

0 Comments

Leave a Reply

Avatar placeholder

Your email address will not be published. Required fields are marked *