python elasticsearch 8.x通过代理发起请求方法

由于python elasticsearch v8 engine的源码包中并未开放对于请求添加proxies的支持,导致在某些环境下无法连通外网的es服务。目前网上暂无相关的修改内容,我这边提供下自己修改的动态运行时替换elasticsearch包的源码方法demo

import gzip
import ssl
import time
import requests
from elastic_transport._node._http_requests import RequestsHttpNode
from typing import Any, Optional, Union
from elastic_transport._compat import warn_stacklevel
from elastic_transport._exceptions import ConnectionError, ConnectionTimeout, SecurityWarning, TlsError
from elastic_transport._models import ApiResponseMeta, HttpHeaders, NodeConfig
from elastic_transport.client_utils import DEFAULT, DefaultType, client_meta_version
from elastic_transport._node._base import (
    BUILTIN_EXCEPTIONS,
    RERAISE_EXCEPTIONS,
    BaseNode,
    NodeApiResponse,
    ssl_context_from_node_config,
)


def custom_perform_request(
        self,
        method: str,
        target: str,
        body: Optional[bytes] = None,
        headers: Optional[HttpHeaders] = None,
        request_timeout: Union[DefaultType, Optional[float]] = DEFAULT,
    ) -> NodeApiResponse:
        url = self.base_url + target
        headers = HttpHeaders(headers or ())

        request_headers = self._headers.copy()
        if headers:
            request_headers.update(headers)

        body_to_send: Optional[bytes]
        if body:
            if self._http_compress:
                body_to_send = gzip.compress(body)
                request_headers["content-encoding"] = "gzip"
            else:
                body_to_send = body
        else:
            body_to_send = None

        start = time.time()
        proxies_dict = {
            "http": "http://xx.xx.xx.xx:xx",
            "http": "http://xx.xx.xx.xx:xx",
        }
        request = requests.Request(
            method=method, headers=request_headers, url=url, data=body_to_send
        )
        prepared_request = self.session.prepare_request(request)
        send_kwargs = {
            "timeout": (
                request_timeout
                if request_timeout is not DEFAULT
                else self.config.request_timeout
            )
        }
        send_kwargs.update(
            self.session.merge_environment_settings(  # type: ignore[arg-type]
                prepared_request.url, {}, None, None, None
            )
        )
        send_kwargs.pop('proxies')
        try:
            response = self.session.send(prepared_request, proxies=proxies_dict,  **send_kwargs)  # type: ignore[arg-type]
            data = response.content
            duration = time.time() - start
            response_headers = HttpHeaders(response.headers)

        except RERAISE_EXCEPTIONS:
            raise
        except Exception as e:
            err: Exception
            if isinstance(e, requests.Timeout):
                err = ConnectionTimeout(
                    "Connection timed out during request", errors=(e,)
                )
            elif isinstance(e, (ssl.SSLError, requests.exceptions.SSLError)):
                err = TlsError(str(e), errors=(e,))
            elif isinstance(e, BUILTIN_EXCEPTIONS):
                raise
            else:
                err = ConnectionError(str(e), errors=(e,))
            self._log_request(
                method=method,
                target=target,
                headers=request_headers,
                body=body,
                exception=err,
            )
            raise err from None

        meta = ApiResponseMeta(
            node=self.config,
            duration=duration,
            http_version="1.1",
            status=response.status_code,
            headers=response_headers,
        )
        self._log_request(
            method=method,
            target=target,
            headers=request_headers,
            body=body,
            meta=meta,
            response=data,
        )
        return NodeApiResponse(
            meta,
            data,
        )


RequestsHttpNode.perform_request = custom_perform_request


from elasticsearch import Elasticsearch


es = Elasticsearch(hosts=["http://xx.xx.xxx.xxx:9200"], basic_auth=("elastic", "xxxxxxxxxxxx"), node_class=RequestsHttpNode)
query = {"query": {"match_all": {}}}
response = es.search(index="xxxxxx_prod", body= query)
print(response)

### 使用 Python 操作 Elasticsearch #### 创建连接实例 为了操作 Elasticsearch 数据库,在 Python 中首先要建立与数据库的连接。这通过 `elasticsearch` 库实现,其中包含了用于管理集群、索引以及文档的各种方法。 ```python from elasticsearch import Elasticsearch es = Elasticsearch(['http://localhost:9200']) # 建立本地连接[^1] ``` 此代码片段展示了如何初始化一个指向运行于 localhost 上,默认端口为 9200 的 Elasticsearch 实例的对象。 #### 执行批量插入 (Bulk Insert) 对于大量数据的操作,推荐采用 bulk API 来提高效率: ```python actions = [ { "_index": "test-index", "_source": {"any": f"Data {i}", "timestamp": datetime.now()}, } for i in range(100) ] helpers.bulk(es, actions) # 利用 helpers.bulk 函数执行批量插入操作 ``` 这段脚本构建了一系列要被存入名为 test-index 的索引里的记录,并一次性提交给 Elasticsearch 处理。 #### 查询数据 查询可以利用 RESTful 风格请求来完成,这里给出的是基于 match 查询的例子,用来查找描述中含有特定关键词的数据条目: ```json GET /conference/event/_search { "query": { "match": { "description": "use Elasticsearch" } } } ``` 上述 JSON 请求体定义了一个简单的全文检索命令,旨在定位那些其 description 字段提及了 “use Elasticsearch”的事件记录[^2]。 在 Python 中发送这样的查询可通过如下方式达成: ```python response = es.search( index="conference", body={ "query": { "match": { "description": "use Elasticsearch" } } } ) print(response['hits']['total']) for hit in response['hits']['hits']: print(hit["_source"]) ``` 以上代码实现了向 conference 索引发起搜索请求并打印匹配项总数及其具体内容的功能。 #### 日志处理集成案例 当涉及到日志记录时,可借助第三方模块如 CMRESHandler 将应用程序的日志直接写入到 Elasticsearch 中去,同时还可以附加自定义字段以便更好地分类或过滤日志信息。 ```python import logging from cmreslogging.handlers import CMRESHandler handler = CMRESHandler( hosts=[{"host": "localhost", "port": 9200}], auth_type=CMRESHandler.AuthType.NO_AUTH, es_index_name="app_logs-%Y.%m.%d", es_additional_fields={"environment": "production"} ) logger = logging.getLogger("my_logger") logger.addHandler(handler) logger.setLevel(logging.INFO) logger.info("This is a log message.") ``` 该例子说明了怎样设置一个 logger 并将其输出定向至带有时间戳标记的不同索引里;同时也指定了额外的信息作为每一条日志的一部分保存下来[^5]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

RayCheungCode

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值