【问题标题】:Why am I getting WinError 10061 (connection refused) here?为什么我在这里收到 WinError 10061(连接被拒绝)?
【发布时间】:2021-01-30 18:39:42
【问题描述】:

我知道对此有几个问题。但我不认为这个案子已经涵盖了。

我只是编写了一些代码来安装,然后启动 W10 Elasticsearch 服务(如果它尚未启动并运行)。当我在未安装 ES 服务的情况下运行此程序时,我在 requests.get( ...) 处收到一个 ES 内部错误(它会终止脚本)。

但如果我再次运行该脚本,服务会被识别为运行良好,requests.get( ...) 返回 OK,不会引发内部 ES 错误。这表明该脚本确实同时安装和启动服务......但出于某种原因,之后立即发送 URL 请求(相同的运行/进程)会导致问题。

顺便说一句,如果我只是简单地停止服务,所以它仍然安装,但停止了,然后运行脚本,它再次出错(即在简单地启动服务之后)并发生错误。

更重要的是,我很确定昨天我开始试验时并没有发生这种情况。出于这个原因,我在我的回购中回到了最简单的实现,希望有人可以解释发生了什么以及如何(是否)可以解决它。 IE。我希望能够在同一个 Python 运行(进程)中安装、启动它,然后开始使用它。

这是一个 MRE:

import os, sys, io, requests, psutil, elasticsearch

def install_and_start_es_service():
    def get_service(name):
        service = None
        try:
            service = psutil.win_service_get(name)
            service = service.as_dict()
        except Exception as ex:
            print( f'service {name} not yet installed' )
        return service
    try:
        destination_extract_dir = 'D:/apps/ElasticSearch'
        es_bin_dir = destination_extract_dir + '/elasticsearch-7.10.2/bin'
        service = get_service('elasticsearch-service-x64')
        if service and service['status'] == 'running':
            # best case scenario
            return True
        # at this point we will need to try to either start or install the service.
        # to do either of those we need to ensure that the ES bin directory is in place
        if not os.path.isdir( es_bin_dir ):    
            print( 'ES bin dir not found' )
            return False 
        os.chdir( es_bin_dir )
        if not service:
            # can we install the service?
            print( f'before service.bat install...' )
            os.chdir( es_bin_dir )
            os.system( 'elasticsearch-service.bat install' )
            print( f'after service.bat install...' )
        service = get_service('elasticsearch-service-x64')
        if not service:
            print( 'something went wrong trying to install the ES service')
            return False    
        # can we start the service?
        print( f'before service.bat start...' )
        os.chdir( es_bin_dir )
        os.system( 'elasticsearch-service.bat start' )
        print( f'after service.bat start...' )
        service = get_service('elasticsearch-service-x64')
        if service == None or service['status'] != 'running':
            print( 'something went wrong trying to start the ES service')
            return False
    except Exception as e:
        logger.exception( 'unexpected exception thrown while trying to install and start ES service' )
        return False    
    return True
    
es_started = install_and_start_es_service()
print( f'ES started? {es_started}')
if not es_started:
    sys.exit()
r = requests.get('http://localhost:9200')
print( f'type r {type(r)}') # requests.models.Response

这是出现问题时堆栈跟踪的典型结束:

  File "D:\more software projects\python_venv\env\lib\site-packages\requests\adapters.py", line 516, in send
    raise ConnectionError(e, request=request)
requests.exceptions.ConnectionError: HTTPConnectionPool(host='localhost', port=9200): Max retries exceeded with url: / (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x0000020842FAAD30>: Failed to establish a new connection: [WinError 10061] No connection could be made because the target machine actively refused it'))

请注意,这是一个内部 ES 错误...即跟踪不是源自我的代码行。但是,我可以确定是 requests.get( ... 行导致了它。

编辑

leandrojmp 有用地建议可能需要一个非零等待期。我应该提到我已经用time.sleep( 5 ) 尝试过这个。我本以为这应该绰绰有余了……但我会沿着这些思路尝试更多的实验……

【问题讨论】:

    标签: python windows elasticsearch service


    【解决方案1】:

    您收到的错误是来自请求库的错误,因为您的 elasticsearch 实例尚未准备好。

    由于目标机器主动拒绝,无法建立连接

    这意味着您的 elasticsearch 正在运行,端口已打开,但尚未准备好响应请求,因为它仍在启动中。

    从您在 Windows 机器上启动 Elasticsearch 服务到 Elasticsearch 服务可以真正响应请求的那一刻,这可能需要几秒钟,有时甚至几分钟。

    您需要在启动服务后等待一段时间才能发出请求,或者实现一些逻辑以继续尝试,直到它可以与您的 elasticsearch 实例通信。

    如果您尝试在启动服务后立即发出请求,您的脚本可能会失败,该服务需要一些时间来启动 JVM 并启动 elasticsearch 应用程序。

    【讨论】:

    • 谢谢。我确实尝试了time.sleep( 5 ),我应该在问题中提到它:现在将编辑。当然 5 秒就足够了吗? ...虽然我会尝试更长的时间并进行相应的编辑。
    • 视情况而定,不是固定时间,有时可能需要超过 5 秒。最好的解决方案是继续尝试,直到服务开始响应。
    • 事实证明这是正确的。在我的机器上,从“elasticsearch-service.bat start”返回和不会引发内部 ES 异常(状态为 200)的 requests.get(... 之间的平均时间约为 6 秒。通常需要在requests.get(... 进行 3 次尝试(每次都需要有限的时间)。太棒了。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-04
    • 1970-01-01
    相关资源
    最近更新 更多