Django连接远程Elasticsearch遭拒绝,请求排查原因
我有一个Django项目,包含如下模型:
class ParentFoodDirectory(TimeStampedModel): uuid = models.UUIDField(default=uuid.uuid4, editable=False) name = models.CharField(max_length=1000, null=False, blank=False) active = models.BooleanField(null=False, blank=False, default=True) p_id = models.IntegerField(null=False, blank=False) class Meta: verbose_name_plural = "Parent Food Items" def __str__(self): return self.name
该模型有超过1000万条数据,查询速度极慢,因此引入Elasticsearch。在另一台实例部署ES,用Nginx对外提供服务,可通过公网IP访问。创建documents.py映射模型:
from django_elasticsearch_dsl import Document, fields from django_elasticsearch_dsl.registries import registry from .models import ParentFoodDirectory @registry.register_document class ParentFoodDirectoryDocument(Document): name = fields.TextField() active = fields.BooleanField() p_id = fields.IntegerField() class Index: name = 'parentfooddirectory' class Django: model = ParentFoodDirectory
在settings.py配置ES地址:
ELASTICSEARCH_HOST = 'http://35.141.96.246/' ELASTICSEARCH_DSL = { 'default': { 'hosts': '35.141.96.246', }, }
执行命令python manage.py search_index --rebuild时出现错误:
elasticsearch.exceptions.ConnectionError: ConnectionError(<urllib3.connection.HTTPConnection object at 0x7f49febf8d90>: Failed to establish a new connection: [Errno 111] Connection refused) caused by: NewConnectionError(<urllib3.connection.HTTPConnection object at 0x7f49febf8d90>: Failed to establish a new connection: [Errno 111] Connection refused)
已确认Elasticsearch可达且防火墙规则配置正确,请问可能是什么原因导致该问题?
端口未指定或不匹配
默认Elasticsearch监听9200端口,若Nginx反向代理使用了非默认端口(如80、443),Django配置的hosts必须加上对应端口。比如Nginx用80端口,配置应修改为:ELASTICSEARCH_DSL = { 'default': { 'hosts': '35.141.96.246:80', }, }如果是HTTPS协议,需明确协议头:
'hosts': 'https://35.141.96.246:443',Nginx反向代理配置错误
检查Nginx配置是否正确转发请求到Elasticsearch的9200端口,示例正确配置如下:location / { proxy_pass http://localhost:9200; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; }同时确保Nginx服务正常运行,无语法错误或启动失败情况。
Elasticsearch绑定地址限制
查看Elasticsearch的elasticsearch.yml配置,确认network.host未仅绑定localhost或内网IP。若ES仅允许本地访问,即使Nginx能连接,Django的请求也会被拦截。需将network.host设置为0.0.0.0(允许所有地址访问)或指定公网/内网IP,同时单节点模式下需配置discovery.type: single-node避免集群发现异常。Django配置的hosts格式不规范
django_elasticsearch_dsl支持完整URL格式配置,直接使用带协议、端口的URL更可靠:ELASTICSEARCH_DSL = { 'default': { 'hosts': 'http://35.141.96.246:80', }, }避免仅写IP导致默认端口(9200)与Nginx代理端口不匹配。
Elasticsearch安全设置拦截
若ES开启了身份验证,需在Django配置中添加认证信息:ELASTICSEARCH_DSL = { 'default': { 'hosts': 'http://username:password@35.141.96.246:80', }, }若使用HTTPS且为自签名证书,需关闭SSL验证:
ELASTICSEARCH_DSL = { 'default': { 'hosts': 'https://35.141.96.246:443', 'verify_certs': False, }, }实例间网络隐性限制
即使公网能访问ES,Django所在实例到ES实例的网络可能存在限制。可在Django实例上执行curl http://35.141.96.246:80测试,确认是否能正常返回ES响应,排查云服务商安全组出站规则、实例内部防火墙等隐性拦截问题。
内容的提问来源于stack exchange,提问作者Hemant Chaudhary

