首页 > 解决方案 > 从本地另一个烧瓶应用程序调用烧瓶应用程序

问题描述

我有两个 Flask 应用程序(A 和 B)。应用程序 A 在本地端口 5000 上运行,并向运行在端口 5002 上的应用程序 B 发出 post 请求,如下所示:

headers = {
    'accept': 'application/type',
    'Content-Type': 'application/json'
}

data = '{"test_string": "test input string", "flatten": true}'

response = requests.post('http://localhost:5002/endpoint', headers=headers, data=data)

回复是:

Max retries exceeded with url: /endpoint/ Failed to establish a new connection: [Errno 111] Connection refused

我打开终端并尝试了这个 curl 请求:

curl -X 'POST' 'http://localhost:5002/endpoint/' -H 'accept: application/json' -H 'Content-Type: application/json' -d '{"test_string": "test input string", "flatten": true}'

它从应用 B 返回正确的响应

我想我在应用程序 A 上格式化请求的方式可能存在问题,因为 curl 正在工作,我只使用终端中的 python 测试了我在应用程序 A 上的 3 行,它在我的 python 终端中工作。

剩下的唯一变量是 app A 是在本地运行的烧瓶应用程序,因为该代码片段在 python 终端中运行。从应用程序 A 调用应用程序 B 并且两个应用程序在不同端口上本地运行是否存在一些问题?


更新:好的,我已将问题缩小到 docker-compose 和 Redis。以下是如何复制它:

应用程序 B:app.py

from flask import Flask, abort
from flask_restx import Api, Resource, fields

app = Flask(__name__)
api = Api(app, version='1.0', title='something',
          description='something',
          )

ns = api.namespace('parse', description='something')

parse_raw = api.model('parse', {
    'input_string': fields.String(required=True, description='string')
})


@ns.route('/')
class Parser(Resource):
    @ns.doc('parse')
    @ns.expect(parse_raw)
    def post(self):
        '''Parse'''
        try:
            s = "yes"
        except Exception:
            abort(400, 'unsupported')

        return s, 200


if __name__ == '__main__':
    app.run(debug=True, host='0.0.0.0', port=5002)

应用程序 A:app.py

from flask import Flask
from flask_restx import Api, Resource
import requests

app = Flask(__name__)
api = Api(app, version='1.0', title='something',
          description='something',
          )

ns = api.namespace('parse', description='something')


@ns.route('/')
class Parser(Resource):
    @ns.doc('parse')
    def get(self):
        '''Parse'''
        headers = {
            'accept': 'application/json',
            'Content-Type': 'application/json',
        }

        data = '{"input_string": "SELECT * FROM table1"}'
        response = requests.post('http://0.0.0.0:5002/parse/', headers=headers, data=data)

        return response.text, 200


if __name__ == '__main__':
    app.run(debug=True, host='0.0.0.0', port=5000)

docker-compose.yaml

version: '3'
services:
  app:
    build:
      context: .
      dockerfile: Dockerfile
    ports:
      - "5000:5000"
  redis:
    image: "redis:alpine"

Dockerfile

FROM python:3.6-alpine
WORKDIR /app

ENV PYTHONHASHSEED=1

RUN apk add --no-cache --update make
COPY requirements.txt requirements.txt
RUN pip install -r requirements.txt

COPY . .

CMD ["python3", "app.py"]

要求.txt

redis
Flask~=1.1.2
flask-restx
tenacity
requests

您可以以正常方式运行应用程序 B,我如何运行应用程序 A:docker-compose up --build

您可以从终端 curl 应用程序 B:curl -X 'POST' \ 'http://localhost:5002/parse/' \ -H 'accept: application/json' \ -H 'Content-Type: application/json' \ -d '{ "input_string": "string" }'

您还可以从 python 终端运行代码而不是应用程序 A:

headers = {
            'accept': 'application/json',
            'Content-Type': 'application/json',
        }

        data = '{"input_string": "SELECT * FROM table1"}'
        response = requests.post('http://0.0.0.0:5002/parse/', headers=headers, data=data)

但是应用 A 不能调用应用 B

如果您通过运行 app.py 来运行应用程序 A,它可以正常工作,它只会使用 docker-compose + redis 中断,即使示例中甚至没有使用 redis

标签: pythonflaskdocker-composeredis

解决方案


弄清楚了。Docker 容器在不同的网络上运行,因此“localhost”将不起作用。将应用程序 B Docker 化并将其部署到与应用程序 A 相同的 docker 网络,然后将“localhost”更改为网络上 B 的容器名称来修复它。


推荐阅读