无法从 Python 连接到 Azure Linux VM 上的 Redis 实例 运行

Unable to connect to Redis instance running on Azure Linux VM from Python

我在 Azure 上创建了一个 Ubuntu 虚拟机。在其入站网络过滤器中,我添加了端口 22(用于 SSHing)和 6379(用于 Redis ).在此之后,我 SSH 从我的 bash shell 进入一个实例,从源代码下载、构建和安装 Redis。生成的 redis.conf 文件位于 /tmp/redis-stable,因此我对其进行了编辑以注释掉 bind 127.0.0.1 规则。

然后我从/tmp/redis-stable目录启动redis-server redis.conf,启动正常,然后我SSH进入另一个虚拟机实例,启动redis-cli 并设置一些键。取回它们,工作正常。

现在 Python 我正在 运行 执行此命令:

r = redis.Redis(host='same_which_I_use_for_SSHing', port=6379, password='pwd')

它立即连接(看起来很奇怪)。但是当我尝试像 r.get("foo") 这样的简单命令时,我得到了这个错误:

>>> r.get("foo")
Traceback (most recent call last):
  File "/lib/python3.5/site-packages/redis/connection.py", line 484, in connect
    sock = self._connect()
  File "/lib/python3.5/site-packages/redis/connection.py", line 511, in _connect
    socket.SOCK_STREAM):
  File "/usr/local/Cellar/python3/3.5.1/Frameworks/Python.framework/Versions/3.5/lib/python3.5/socket.py", line 732, in getaddrinfo
    for res in _socket.getaddrinfo(host, port, family, type, proto, flags):
socket.gaierror: [Errno 8] nodename nor servname provided, or not known

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/lib/python3.5/site-packages/redis/client.py", line 667, in execute_command
    connection.send_command(*args)
  File "/lib/python3.5/site-packages/redis/connection.py", line 610, in send_command
    self.send_packed_command(self.pack_command(*args))
  File "/lib/python3.5/site-packages/redis/connection.py", line 585, in send_packed_command
    self.connect()
  File "/lib/python3.5/site-packages/redis/connection.py", line 489, in connect
    raise ConnectionError(self._error_message(e))
redis.exceptions.ConnectionError: Error 8 connecting to username@ip_address. nodename nor servname provided, or not known.

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/lib/python3.5/site-packages/redis/connection.py", line 484, in connect
    sock = self._connect()
  File "/lib/python3.5/site-packages/redis/connection.py", line 511, in _connect
    socket.SOCK_STREAM):
  File "/usr/local/Cellar/python3/3.5.1/Frameworks/Python.framework/Versions/3.5/lib/python3.5/socket.py", line 732, in getaddrinfo
    for res in _socket.getaddrinfo(host, port, family, type, proto, flags):
socket.gaierror: [Errno 8] nodename nor servname provided, or not known

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/lib/python3.5/site-packages/redis/client.py", line 976, in get
    return self.execute_command('GET', name)
  File "/lib/python3.5/site-packages/redis/client.py", line 673, in execute_command
    connection.send_command(*args)
  File "/lib/python3.5/site-packages/redis/connection.py", line 610, in send_command
    self.send_packed_command(self.pack_command(*args))
  File "/lib/python3.5/site-packages/redis/connection.py", line 585, in send_packed_command
    self.connect()
  File "/lib/python3.5/site-packages/redis/connection.py", line 489, in connect
    raise ConnectionError(self._error_message(e))
redis.exceptions.ConnectionError: Error 8 connecting to username@ip_address. nodename nor servname provided, or not known.

知道如何解决这个问题吗?仅供参考,错误消息中的 username@ip_address 与我分别从 bash 用于 SSH 和从 Python 连接到 Redis 相同:

ssh username@ip_address
r = redis.Redis(host='username@ip_address', port=6379, password='pwd')

我还尝试在注释掉 bind 127.0.0.1 行后在 redis.conf 文件中添加 bind 0.0.0.0。同样的结果。

更新:我尝试在配置文件中将保护模式设置为 no,然后在 VM 中设置 运行ning sudo ufw allow 6379。还是一样的结果。但是现在当我 运行 redis-server redis.conf 时我得到了一个奇怪的错误。我没有得到显示为图形的典型 redis 多维数据集相反,我得到了这个:

在此之后,如果我输入 redis-cli 并发出像 set foo boo 这样的简单命令,我会收到此错误消息:

127.0.0.1:6379> set foo 1
(error) MISCONF Redis is configured to save RDB snapshots, but it is currently not able to persist on disk. Commands that may modify the data set are disabled, because this instance is configured to report errors during writes if RDB snapshotting fails (stop-writes-on-bgsave-error option). Please check the Redis logs for details about the RDB error.

此后甚至关机失败。我必须 运行 grep 找到 redis-server 的进程并手动杀死它,然后 redis-server 命令需要 运行 正常启动它。但当然,我仍然无法从远程连接 Mac.

我尝试在 Azure 上创建一个 Ubuntu VM,从源代码构建和配置 redis 服务器,并在 Azure 门户上为我的 VM NSG 添加端口规则,然后我通过相同的方式连接了 redis 服务器python redis 包代码成功。

下面是我的步骤。

  1. 在 Azure 门户上创建 Ubuntu 18.04 VM。
  2. 通过 SSH 连接 Ubuntu VM 以安装构建包(包括 build-essentialgccmake),下载并解压缩 tar.gz来自 redis.io 的 redis 源代码文件,并使用 make & make test.
  3. 构建和测试 redis 服务器
  4. 通过 vim 配置 redis.conf,将 bind 配置从 127.0.0.1 更改为 0.0.0.0
  5. 为我在 Azure 门户上的 VM 的选项卡 Settings -> Networking 中显示的 Network Interface 添加带有 TCP 的 6379 端口的新端口规则,如下图所示。

注意:在我的Networking选项卡中有两个NSG,第二个与我的Network Interface相关,可以通过互联网访问。 5. 在我的本地机器上通过 pip install redis 安装 redis。 6. 打开终端输入 python 尝试连接托管在我的 Azure Ubuntu VM 上的 redis 服务器并成功获取 foo 键的值。

>>> import redis
>>> r = redis.Redis(host='xxx.xx.xx.xxx')
>>> r.get('foo')
b'bar'

我在测试中发现了两个关键问题。

  1. 对于redis.conf,绑定主机必须是0.0.0.0。如果不是,redis 服务器将运行处于保护模式以拒绝查询。
  2. 对于 NSG 端口规则,请确保在附加到当前网络接口的 NSG 中添加的新端口规则,而不是默认子网。
  3. python包redis是惰性评估,只有在第一个命令请求发生时才连接redis服务器。

希望对您有所帮助。