HTTP Web服务器只是停止响应

时间:2020-08-05 17:26:39

标签: python python-3.x

我之前写过multi threaded web server,有时它会停止处理请求,并在高峰时间终止。

我也已经在基于Python Websocket的服务器中实现了基于opencv的相同处理,

对于非常老的浏览器,我还需要使用Web服务器进行基于POST的处理。我从多线程转换为单线程,但这也停止了不同的时间,并且没有打印任何日志等。

我检查了syslog,但没有发现线索。没有找到解决方案已经过去了一个多星期。我怀疑与Digital Ocean VPS或网络有关。

我有这段代码,无法弄清楚为什么它应该停止响应:

from http.server import HTTPServer, BaseHTTPRequestHandler
import threading
import cgi
import tempfile
import resource
import base64
from common import *
from datetime import datetime

print( datetime.now());

gg_hashmap = getHash()

USE_HTTPS = True

def dump(obj):
  for attr in dir(obj):
    print("obj.%s = %r" % (attr, getattr(obj, attr)))

class PostHandler(BaseHTTPRequestHandler):
        def handle(self):
            try:
                BaseHTTPRequestHandler.handle(self)
            except :
                pass

        def do_POST(self):
            try:
          
                print("new req="+str( datetime.now()),flush=True);

                form = cgi.FieldStorage(
                    fp=self.rfile,
                    headers=self.headers,
                    environ={'REQUEST_METHOD': 'POST',
                             'CONTENT_TYPE': self.headers['Content-Type'],
                             })

                
                self.send_response(200)
                self.send_header("Content-type", "text/html")
                self.send_header("Access-Control-Allow-Origin", "*")
                
                self.end_headers()


              

                for field in form.keys():
                    field_item = form[field]
                    if field_item.filename:
                        
                        file_data = field_item.file.read()
                        file_len = len(file_data)
                        del file_data
                        self.wfile.write('\tUploaded %s as "%s" (%d bytes)\n' % \
                                         (field, field_item.filename, file_len))
                    else:
                        pass
                        

                if ('base64' in form and 'license' in form):
                    print("license=",form['license'].value);

                    global gg_hashmap

                    file_content = form['base64'].value
                    try:
                        
                        f, temp_file_path = tempfile.mkstemp(prefix='sand', suffix='jpg')
                        os.close(f)
                        with open(temp_file_path, 'wb') as w:
                            w.write(base64.b64decode (file_content))

                        input_hashes = get_input_img(temp_file_path)

                        all_letters = ""
                        if input_hashes != None:

                            for inp_hash in input_hashes:

                                lowest = 1000
                                lowest_letter = ''
                                for letter, arr in gg_hashmap.items():

                                    for hashval in arr:

                                        if int(inp_hash - hashval) < lowest:

                                            lowest = int(inp_hash - hashval)
                                            lowest_letter = letter
                                
                                all_letters += lowest_letter

                        self.wfile.write(bytes(all_letters, "utf8"))

                    except Exception as e:
                        print("exception3 caught")
                        print(e)
                        print(str(e))
                return
            except Exception as e:
                print("Caught unknown exception",e)
             

        def do_GET(self):
            
            self.send_response(200)
            self.end_headers()
            message =  threading.currentThread().getName()
            self.wfile.write(bytes(message,'utf-8'))
            self.wfile.write('\n')
            return


            form = cgi.FieldStorage(
                fp=self.rfile,
                headers=self.headers,
                environ={'REQUEST_METHOD': 'POST',
                         'CONTENT_TYPE': self.headers['Content-Type'],
                         })

           
            self.send_response(200)
            self.end_headers()
        
            for field in form.keys():
                field_item = form[field]
                if field_item.filename:
                    
                    file_data = field_item.file.read()
                    file_len = len(file_data)
                    del file_data
                    self.wfile.write('\tUploaded %s as "%s" (%d bytes)\n' % \
                                     (field, field_item.filename, file_len))
                else:
                    pass
                   

            return



def run():
   # resource.setrlimit(resource.RLIMIT_STACK, (2**29,-1))
   # threading.stack_size(24*1048576)
    server = HTTPServer(('0.0.0.0', 443), PostHandler)
    if USE_HTTPS:
        import ssl
        server.socket = ssl.wrap_socket(server.socket, keyfile='./ssl/key.pem', certfile='./ssl/public.pem'
                , ca_certs="./ssl/cap1_transactionfailed_com.ca-bundle" , server_side=True)

    server.serve_forever()


if __name__ == '__main__':
    run()

2 个答案:

答案 0 :(得分:0)

我认为没有多少人会想通读所有157行复杂的HTTP请求处理代码(其中一些甚至没有发布,from common import *)来尝试解释为什么它可能会在某些情况下停止给定时间。

这可能不是您想听到的答案,但是HTTPServer确实不是任何人在Python生产中使用的答案。

您应该考虑使用其中一种(我在撰写本文时的建议)重写代码

    <{3}}上的
  • FastAPI(或其底层Starlette框架)(Uvicorn允许您在同一过程中完成websocket的工作),或者
  • Uvicorn在Gunicorn或uWSGI上

例如,这是对Starlette代码的大致估计。 (因为它是干编码的,所以可能会出现错误,并且肯定不是完全异步的,但这在这里无关紧要。)

import tempfile
import base64
from starlette.applications import Starlette
from starlette.requests import Request
from starlette.responses import PlainTextResponse

app = Starlette()


def get_all_letters(input_hashes):
    all_letters = ""
    if input_hashes:
        for inp_hash in input_hashes:
            lowest = 1000
            lowest_letter = ""
            for letter, arr in gg_hashmap.items():
                for hashval in arr:
                    if int(inp_hash - hashval) < lowest:
                        lowest = int(inp_hash - hashval)
                        lowest_letter = letter
            all_letters += lowest_letter
    return all_letters


@app.route("/", methods=["GET", "POST"])
async def handle(request: Request):
    if request.method == "GET":
        return PlainTextResponse("Hello!")
    form = await request.form()

    if not ("base64" in form and "license" in form):
        return PlainTextResponse("Missing data!", status_code=400)
    with tempfile.NamedTemporaryFile(prefix="sand", suffix="jpg") as f:
        content = await form["base64"].read()
        f.write(base64.b64decode(content))
        f.flush()
        input_hashes = get_input_img(f)
    if not input_hashes:
        return PlainTextResponse("No input hashes!", status_code=400)
    all_letters = get_all_letters(input_hashes)
    return PlainTextResponse(all_letters)

然后,您可以使用Uvicorn(它将为您处理所有HTTPS内容)运行此程序。

答案 1 :(得分:0)

使用mkstemp,必须删除临时文件。您可能用完了磁盘空间,或者用尽了temp目录中的文件。如AKX所述,尽管您应该研究使用更强大的http服务器。如果不是文件问题,那么使用非生产型HTTP服务器时还会出现很多其他问题。

相关问题