美文网首页Python工作生活
项目经验 | 后端与判题端的socket通信和调度

项目经验 | 后端与判题端的socket通信和调度

作者: 格致匠心 | 来源:发表于2019-06-30 10:54 被阅读7次

本项目的后端是用Django开发的,而我主要做的是判题端的通信调度,判题端是用Python手撸的,并且采用socket进行通信。

总体流程图

遇到的问题:

  • 多个socket进行通信的架构
    之前没有遇到过创建多个socket来通信的结构,这里记录下代码。
    判题端用socketserver创建服务器,后端用socket创建多个客户端连接多个判题端。
class Clients:
    def __init__(self):
        self.judgers = Judger.objects.all()
        self.clients = {}
        for judger in self.judgers:
            self.clients[judger.ip] = socket.socket(
                socket.AF_INET, socket.SOCK_STREAM)
            try:
                self.clients[judger.ip].connect((judger.ip, JUDGER_PORT))
                logger.info('clients add %s' % (judger.ip))
            except:
                del self.clients[judger.ip]
        if not self.clients:
            raise ConnectionError('[client] 当前没有判题机在线')
  • 外部文件import Django内部文件的model问题

外部文件import django内部文件的model会出现引用失败的情况,需要加上如下代码

pathname = os.path.dirname(os.path.abspath(__file__))
sys.path.insert(0, pathname)
sys.path.insert(0, os.path.abspath(os.path.join(pathname, '..')))
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "OnlineJudge.settings")
django.setup()
  • Django ORM断连问题

这个搞得我头大,之前用过隔一个小时发一个wakeup包的方法,现在看到一个原生的方法还不错,在执行orm出错的语句前加上它就能无视6小时诅咒了。

db.close_old_connections()
  • 大文件传输问题

TCP传递大文件会遇到问题,这里的方法是,把需要传递的包切成1024等分的包数组,然后传包数提醒判题服务器,再把每个小包传过去,这里传递每个包后可以收下判题服务器的返回'ok',防止粘包。

body_list = [body[i:i+1024] for i in range(0, len(body), 1024)]
body_list_lenght = str(len(body_list)).encode('utf-8')
def send_data(self, client, body_list, body_list_lenght):
    client.send(body_list_lenght)
    logger.info('send body_list_lenght: %d ' %len(body_list) )
    for item in body_list:
        client.send(item)
        res = str(client.recv(10)) # 防止粘包
        logger.debug('send: %d | %s' % (len(item),res) )
    res = str(client.recv(10))
    logger.info('send body: %s'%res)
  • 判题端的结构

第一次写不用框架的python独立应用哈,还是前端菜鸟写的,结构有点奇葩轻喷
数据库初始化封装成 model.py
对model的操作封装成 model_api.py
对接客户端的服务端封装成 server.py
分配任务处理数据开辟线程的封装成 controller.py
判题端实际上是从原来后端里分离出来的,所以依然有 judge.pyJudger.py
docker的单例化文件 docker_client.py
文件夹有 log存放日志, question存放输入输出样例、 code存放临时代码

  • 多线程判题

开辟线程前必须要注意对数据库的活动容器记录必须在主线程,不然的话绝对出神奇的错误,然后用threading.Thread().start()启动线程,并且配合信号量sem = Semaphore(),在使用的时候python有语法糖,只需要 with sem: 就行啦

相关文章

  • 项目经验 | 后端与判题端的socket通信和调度

    本项目的后端是用Django开发的,而我主要做的是判题端的通信调度,判题端是用Python手撸的,并且采用sock...

  • Web socket与服务器-12.22

    Web socket 1.HTTP 与 socket的区别相同:都是客户端与服务端进行通信的协议不同: HTTP:...

  • 知识点

    关于Socket通信:客户端通过new Socket()方法创建通信的Socket对象服务器端通过new Serv...

  • day017 笔记 08-07

    socket套接字 通过socket实现服务器端 通过socket实现客户端 多次通信(服务器端) 多次通信(客户...

  • Java学习5-socket通信(2)

    基于TCP协议的socket通信 目标:了解概念,通信模型,实现socket的步骤,服务端和客户端应该做些什么 什...

  • day 17

    part 1 网络通信 socket套接字:指的就是通过代码来创建实现通信的两个端(服务器和客户端)socket一...

  • Python网络基础之socket

    一、socket socket编程(套接字):通过代码来创建实现通信的两个端(服务器和客户端)socket一般可以...

  • 5.0.3.Socket

    Socket(网络套接字)是网络编程提供的一种机制,通信的两端都要有socket,网络通信就是socket通信数据...

  • ThinkPHP和Workerman整合实现Socket通信De

    因为最近有个项目涉及到Socket通信,于是自己尝试了一下搭建一个服务端WebSocket通信的项目,写个笔记,能...

  • ThinkPHP和Workerman整合实现Socket通信De

    因为最近有个项目涉及到Socket通信,于是自己尝试了一下搭建一个服务端WebSocket通信的项目,写个笔记,能...

网友评论

    本文标题:项目经验 | 后端与判题端的socket通信和调度

    本文链接:https://www.haomeiwen.com/subject/oevvcctx.html