使用 Flask ping 远程 PC,导致服务器阻塞

Pinging a remote PC with Flask, causing server to block

我有一个内部网站,它需要有文件共享链接,这些链接是指向 table 行代表的电脑上共享位置的直接链接。

访问链接时,我想首先以最快的方式测试远程电脑是否可用。我认为这将是一个 ping,但由于某种原因,超时不适用于 -w(是 windows)

这不允许花费时间,出于某种原因,它会导致 Web 服务器阻塞 ping,即使我正在使用 Tornado 异步提供 Flask 路由。

最好让服务器不断更新前端,有active/deactive个链接,允许用户只能访问pc在线的链接,限制否则他们。甚至可能维护数据库中的值。

欢迎任何建议,我以前从未真正使用过文件共享。

后端是 Python 3.4,Flask 和 Tornado。

Ajax调用

function is_drive_online2(sender){
    hostname = sender.parentNode.parentNode.id;
   $.get('Media/test',{
        drive: hostname
        },
        function(returnedData){
            console.log(returnedData[hostname]);
            if(returnedData[hostname] == 0){
                open("file://"+hostname+"/MMUsers");
            }else{
                alert("Server Offline");
            }
        }
   );
}

响应(Flask 路线)

@app.route('/Media/test', methods=['GET', 'POST'])
def ping_response():
    before = datetime.datetime.now()
    my_dict = dict()
    drive = request.args.get('drive')
    print(drive)
    response = os.system("ping -n 1 -w 1 " + drive)
    my_dict[drive] = response
    after = datetime.datetime.now()
    print(after-before)
    return json.dumps(my_dict), 200, {'Content-Type': 'application/json'}

ping 调用需要 18 秒才能解决,即使使用 -w 1(或 1000)也是如此

我只需要支持 Internet Explorer 11。这是否合理?像这样的东西是否有硬件限制服务器是否应该有一个长线程,其唯一任务是不断更新 active/deactivate 链接?我不确定最好的方法。

感谢阅读。

编辑 1:

正在尝试将 ping_response 应用为本机 Tornado 异步响应。结果一样

class PingHandler(RequestHandler):
    @asynchronous
    def get(self):
        dr = self.get_argument('drive')
        print(dr)
        b = datetime.datetime.now()
        myreturn = {self.get_argument('drive'):
                    os.system("ping -n 1 -w 1 " + self.get_argument('drive'))}
        a = datetime.datetime.now()
        print(a-b)
        self.write(myreturn)

wsgi = WSGIContainer(app)
application = Application([(r"/Media/test", PingHandler),
                           (r".*", FallbackHandler, dict(fallback=wsgi))])


application.listen(8080)
IOLoop.instance().start()

编辑 2:尝试使用芹菜。还在阻塞。

def make_celery(app):
    celery = Celery(app.name, broker=app.config['CELERY_BROKER_URL'])
    celery.conf.update(app.config)
    TaskBase = celery.Task

    class ContextTask(TaskBase):
        abstract = True

        def __call__(self, *args, **kwargs):
            with app.app_context():
                return TaskBase.__call__(self, *args, **kwargs)
    celery.Task = ContextTask
    return celery

celery = make_celery(app)


@celery.task
def ping(drive):
    """
    Background Task to test is computer is online
    :param drive: The drive name to test
    :return: Non Zero status code for Offline boxes.
    """

    response = os.system("ping -n 1 -w 1 " + drive)
    return json.dumps({drive: response}), 200, {'Content-Type': 'application/json'}


@app.route('/Media/test', methods=['GET', 'POST'])
def ping_response():
    before = datetime.datetime.now()
    my_dict = dict()
    drive = request.args.get('drive')
    print(drive)
    this_drive = temp_session.query(Drive).filter(Drive.name == drive).first()
    address = this_drive.computer.ip_address if this_drive.computer.ip_address else this_drive.name
    response = ping.apply_async(args=[address])

    return response

Tornado 没有异步地为您的 Flask 应用提供服务(这是不可能的:asynchronousness is a property of the interface and ping_response is a synchronous function). Tornado's WSGIContainer is a poor fit for what you're trying to do (see the warning 在它的文档中)

您应该将 Flask 与 gunicorn 或 uwsgi 等多线程服务器一起使用,或者使用原生 Tornado 异步 RequestHandlers