Python requests "超过最大重试次数" 错误

1 投票
1 回答
6272 浏览
提问于 2025-04-18 00:41

我有一个虚拟服务器启动的过程需要实现,其中一个步骤是将新启动实例生成的ssh密钥添加到部署服务器的“authorized_keys”文件中。

为此,我创建了一个简单的flask应用,它会在部署服务器上监听来自新实例的get请求,这些请求包含实例的IP地址和端口号,以便将密钥添加到authorized_keys中。

下面是部署服务器上的flask应用:

from flask import Flask, render_template
import requests
import os
from time import sleep

app = Flask(__name__)


#Get the ip and port number from the newly launched port
@app.route('/<ip_addr>/<port>')
def get_ip_port(ip_addr, port):

    #rmt_response = requests.get('http://%s:%s/id_rsa.pub' % (ip_addr, port))
    rmt_response = requests.get('http://127.0.1.1:9090/id_rsa.pub', timeout=1)
    #sleep(5)
    if rmt_response.status_code == 200:
        auth_file = open("authorized_keys", "a")
        auth_file.write(rmt_response.content)
        return render_template('layout.html', ip_addr=ip_addr, port=port, \
                           srvrsp=rmt_response.content, rmt_response=rmt_response)
    else:
        return render_template('layout.html', rmt_response=rmt_response)


if __name__ == '__main__':
    app.run(debug=True)

下面是将在新服务器实例上运行的python应用:

import sys, socket
import BaseHTTPServer
from SimpleHTTPServer import SimpleHTTPRequestHandler
import requests

HandlerClass = SimpleHTTPRequestHandler
ServerClass = BaseHTTPServer.HTTPServer
Protocol = "HTTP/1.0"



local_ip = socket.gethostbyname(socket.gethostname())

if sys.argv[1:]:
    port = int(sys.argv[1])
else:
   port = 9090

#Send the ip and the port num to deployment host
r = requests.get("http://127.0.0.1:5000/%s/%s"%(local_ip,port))
#For debug only
rtext = "http://127.0.0.1:5000/%s/%s"%(local_ip,port)
server_address=(local_ip, port)

HandlerClass.protocol_version = Protocol
httpd = ServerClass(server_address, HandlerClass)

sa = httpd.socket.getsockname()
print "Serving HTTP on", sa[0], "port", sa[1], "..."
print local_ip
print r
print rtext
httpd.serve_forever()

当我运行上面的实例代码,并通过浏览器发出get请求,同时也用python的requests库发出get请求时,我得到了预期的结果,也就是id_rsa.pub文件的内容。但是,当从Flask应用发出相同的请求时,却出现了错误。

ConnectionError: HTTPConnectionPool(host='127.0.1.1', port=9090): Max retries exceeded with url: /id_rsa.pub (Caused by <class 'socket.error'>: [Errno 111] Connection refused)

我研究了这个错误,因为它与python的requests库有关,但没有找到明确的解决方案。我知道这个文件是可以访问的,因为我可以通过浏览器下载它,也可以发出请求

x = requests.get("http://127.0.1.1:9090/id_rsa.pub")

能够获取文件的内容,但不知为何在flask应用中却无法正常工作。

1 个回答

0

第二个脚本中的请求:

r = requests.get("http://127.0.0.1:5000/%s/%s"%(local_ip,port))

是在服务器开始监听之前发生的,位置在那个脚本的底部。与此同时,flask应用会立即发出一个请求:

rmt_response = requests.get('http://127.0.1.1:9090/id_rsa.pub', timeout=1)

如果服务器已经在监听,只是反应慢,那么超时参数会起作用。但因为服务器根本没有在监听,所以“连接被拒绝”的错误会立刻出现。在你的9090端口的服务器还没开始监听的时候,你的flask请求就已经抛出异常了。

要让这个工作正常,你需要在flask应用中引入一个延迟,也就是在接收到请求和发出请求之间加点时间,或者让发起请求的部分在服务器开始监听后以线程的方式运行。

撰写回答