繁体   English   中英

Apache和Python线程奇怪的结果

[英]Apache and Python threading strange results

我正在编写一些代码,用于查询SteamAPI以获取服务器上的数据,然后编译更大的列表并输出JSON数据。

它通过以下方式实现:

  • 请求所有服务器列表Ip(ip,port)
  • 然后向ip / port发送请求
  • 改变结果,
  • 将其附加到主列表
  • 使用json.dumps()格式化最终列表

它是用python 2.7.6编写的

#!/usr/bin/env python
# -*- coding: utf-8 -*-

# gets all the miscreated servers

import Queue
import json
import unicodedata
from threading import Thread

import pyfscache
import valve.source.a2s
import valve.source.master_server

cache_it = pyfscache.FSCache('./cache/', days=0, hours=4, minutes=30)

# The main queue object
q = Queue.LifoQueue()
# this is the list we append to
final_servers_list = []


def print_headers():
    print "Content-type: application/json\n"
    print ""


def get_master_server_list():
    msq = valve.source.master_server.MasterServerQuerier()
    servers = msq.find(appid="299740")
    return servers


def normalize(data):
    if type(data) is unicode:
        return unicodedata.normalize('NFKD', data).encode('ascii', 'ignore')
    else:
        return data


def get_single_server_data():
    while not q.empty():  # check that the queue isn't empty
        try:
            server_address = q.get()
            _server = valve.source.a2s.ServerQuerier(server_address)
            info = _server.get_info()

            try:
                server_time = info['server_tags'].split(';')[0][-5:]
            except:
                server_time = '00:00'
            try:
                players = info['server_tags'].split(';')[1]
            except:
                players = '0'
            try:
                whitelisted = info['server_tags'].split(';')[2]
            except:
                whitelisted = '0'

            final_servers_list.append({'name': normalize(info['server_name']),
                                       'mapName': normalize(info['map']),
                                       'ip': normalize(server_address[0]),
                                       'port': normalize(server_address[1]),
                                       'time': normalize(server_time),
                                       'players': normalize(players),
                                       'whiteListed': normalize(whitelisted),
                                       'maxPlayers': normalize(info['max_players']),
                                       'version': normalize(info['version'])})
            q.task_done()
        except:
            q.task_done()


@cache_it
def get_server_list():
    master_server_list = get_master_server_list()
    for server in master_server_list:
        q.put(server)
    for i in range(200):
        t1 = Thread(target=get_single_server_data)  # target is the above function
        t1.start()  # start the thread
    q.join()
    return final_servers_list


if __name__ == '__main__':
    print_headers()
    print json.dumps(get_server_list())

现在这个代码在运行scotchbox vagrant灯堆的本地机器上工作正常python是服务器/ dev机器上的相同版本。

我得到了我在机器上的预期,我得到了大约500台服务器,并且所有数据完全符合我的预期。

但是当我在运行apache2的web服务器上运行它时,它会向我发回一个列表,该列表在10,000范围内,其中许多结果在列表中有10-20次。 即使我尝试过滤结果,也就像某些数据略有不同(因为它可能是一秒钟或第二次请求?服务器标签已更改?)

我认为这与使用python的线程和apache有关,并且由于某种原因它没有某种类型的Lock文件,但我不能为我的生活弄清楚这一点。 我以为我做了一个就解决了

source /etc/apache2/envvars

然后运行ssh终端的脚本

并且它开始工作但是下次缓存过期并且代码运行时它给了我相同的结果。

任何建议都会非常感激,因为我在这里碰到了一堵墙。

当我运行apache2 -V时作为旁注

它吐出一个错误:

[Wed Feb 01 05:35:59.192112 2017] [core:warn] [pid 30832] AH00111: Config variable ${APACHE_LOCK_DIR} is not defined
[Wed Feb 01 05:35:59.192531 2017] [core:warn] [pid 30832] AH00111: Config variable ${APACHE_PID_FILE} is not defined
[Wed Feb 01 05:35:59.193300 2017] [core:warn] [pid 30832] AH00111: Config variable ${APACHE_LOG_DIR} is not defined
[Wed Feb 01 05:35:59.214298 2017] [core:warn] [pid 30832] AH00111: Config variable ${APACHE_RUN_DIR} is not defined
[Wed Feb 01 05:35:59.215112 2017] [core:warn] [pid 30832] AH00111: Config variable ${APACHE_LOG_DIR} is not defined
[Wed Feb 01 05:35:59.215499 2017] [core:warn] [pid 30832] AH00111: Config variable ${APACHE_LOG_DIR} is not defined
[Wed Feb 01 05:35:59.215708 2017] [core:warn] [pid 30832] AH00111: Config variable ${APACHE_LOG_DIR} is not defined
[Wed Feb 01 05:35:59.216057 2017] [core:warn] [pid 30832] AH00111: Config variable ${APACHE_LOG_DIR} is not defined
[Wed Feb 01 05:35:59.216272 2017] [core:warn] [pid 30832] AH00111: Config variable ${APACHE_LOG_DIR} is not defined
[Wed Feb 01 05:35:59.216595 2017] [core:warn] [pid 30832] AH00111: Config variable ${APACHE_LOG_DIR} is not defined
[Wed Feb 01 05:35:59.217080 2017] [core:warn] [pid 30832] AH00111: Config variable ${APACHE_LOG_DIR} is not defined
[Wed Feb 01 05:35:59.217475 2017] [core:warn] [pid 30832] AH00111: Config variable ${APACHE_LOG_DIR} is not defined
[Wed Feb 01 05:35:59.217812 2017] [core:warn] [pid 30832] AH00111: Config variable ${APACHE_LOG_DIR} is not defined
[Wed Feb 01 05:35:59.218115 2017] [core:warn] [pid 30832] AH00111: Config variable ${APACHE_LOG_DIR} is not defined
[Wed Feb 01 05:35:59.218369 2017] [core:warn] [pid 30832] AH00111: Config variable ${APACHE_LOG_DIR} is not defined
[Wed Feb 01 05:35:59.218657 2017] [core:warn] [pid 30832] AH00111: Config variable ${APACHE_LOG_DIR} is not defined
[Wed Feb 01 05:35:59.218885 2017] [core:warn] [pid 30832] AH00111: Config variable ${APACHE_LOG_DIR} is not defined
[Wed Feb 01 05:35:59.219117 2017] [core:warn] [pid 30832] AH00111: Config variable ${APACHE_LOG_DIR} is not defined
[Wed Feb 01 05:35:59.219348 2017] [core:warn] [pid 30832] AH00111: Config variable ${APACHE_LOG_DIR} is not defined
[Wed Feb 01 05:35:59.219631 2017] [core:warn] [pid 30832] AH00111: Config variable ${APACHE_LOG_DIR} is not defined
[Wed Feb 01 05:35:59.219845 2017] [core:warn] [pid 30832] AH00111: Config variable ${APACHE_LOG_DIR} is not defined
AH00526: Syntax error on line 75 of /etc/apache2/apache2.conf:
Invalid Mutex directory in argument file:${APACHE_LOCK_DIR}

它在开发和生产机器上都这样做,所以我不认为这是一个重大交易。

最后是网站的apache配置。

<VirtualHost *:80>
        ServerName "servers.miscreatedgame.com"
        ServerAdmin "csprance@entradainteractive.com"
        DocumentRoot "/var/www/servers.com/_build"

        # serverpanel appollo
        <Directory "/var/www/servers.com/_build">
                AddHandler cgi-script .py
                Options +ExecCGI
        </Directory>



        ErrorLog ${APACHE_LOG_DIR}/servers-error.log
        CustomLog ${APACHE_LOG_DIR}/servers-access.log combined

</VirtualHost>

正如@SergGr所说,这绝对好像是多个请求之间的线程竞争条件。 我建议尝试让你的代码可以重入。 我会把实际创建Threads的代码放在一个单独的进程中构建整个服务器列表,然后将该进程返回给使用ipc处理用户请求的进程。

在什么环境下脚本实际上在服务器上运行? 它是一个独立的脚本还是作为Web服务器(Apache)的一部分运行? 在后一种情况下,您是否碰巧对同一数据有多个并发(HTTP)请求? 您的q = Queue.LifoQueue()似乎是一个全局共享变量,任何处理请求都可以访问,因此所有并发请求将填充相同的“队列”( q )。 这可能是它随机发生的原因:只有在存在对此数据的并发请求时才会发生这种情况。 如果是这种情况,解决它的明显方法是将q局部变量设置为get_server_list并使用Thread构造函数的 args参数将其显式传递给get_single_server_data ,这实际上是一件好事。 关于用于输出的final_servers_list显然也是如此。

更新

经过一番思考后,是什么清理了final_servers_list 假设您只运行此HTTP请求10次(按顺序,不同时)。 为什么你不希望在最后一个响应中报告10次服务器列表?

但正确的解决方案仍然是相同的:不要使用全局变量。 只需清除列表,它就更可靠,面向未来。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM