- VisualStudio2022插件的安装及使用-编程手把手系列文章
- pprof-在现网场景怎么用
- C#实现的下拉多选框,下拉多选树,多级节点
- 【学习笔记】基础数据结构:猫树
本文分享自华为云社区《Python微服务与容器化实践详解【从基础到高级应用】》,作者: 柠檬味拥抱.
在现代软件开发中,容器化和微服务架构已经成为主流。容器化技术使得应用程序可以在任何环境中一致运行,而微服务架构通过将应用拆分成多个独立的服务,从而提升了系统的可扩展性和维护性。本文将介绍如何在Python中实践容器化和微服务架构,并提供相关代码实例.
容器化技术主要依赖于Docker。Docker通过将应用及其依赖打包在一个独立的环境中,确保应用在不同环境中的一致性。以下是一个简单的Python应用Docker化的例子.
首先,我们创建一个简单的Flask应用.
# app.py from flask import Flask app = Flask(__name__) @app.route('/') def hello_world(): return 'Hello, Docker!' if __name__ == '__main__': app.run(host='0.0.0.0', port=5000)
接下来,我们创建一个Dockerfile来定义这个应用的容器.
# 使用官方Python基础镜像 FROM python:3.9-slim # 设置工作目录 WORKDIR /app # 复制当前目录内容到工作目录 COPY . /app # 安装依赖 RUN pip install flask # 暴露应用端口 EXPOSE 5000 # 运行应用 CMD ["python", "app.py"]
构建Docker镜像:
docker build -t python-flask-app .
运行容器:
docker run -d -p 5000:5000 python-flask-app
现在,可以在浏览器中访问http://localhost:5000,你将看到"Hello, Docker!".
微服务架构将一个单体应用拆分为多个独立的服务,每个服务负责特定的功能。这些服务通过HTTP或消息队列进行通信。以下示例展示了如何使用Flask构建简单的微服务架构.
# user_service.py from flask import Flask, jsonify app = Flask(__name__) @app.route('/users') def get_users(): users = [ {'id': 1, 'name': 'Alice'}, {'id': 2, 'name': 'Bob'} ] return jsonify(users) if __name__ == '__main__': app.run(host='0.0.0.0', port=5001)
# order_service.py from flask import Flask, jsonify app = Flask(__name__) @app.route('/orders') def get_orders(): orders = [ {'id': 1, 'item': 'Laptop', 'price': 1200}, {'id': 2, 'item': 'Phone', 'price': 800} ] return jsonify(orders) if __name__ == '__main__': app.run(host='0.0.0.0', port=5002)
为了管理多个容器,我们使用Docker Compose.
# docker-compose.yml version: '3' services: user-service: build: context: . dockerfile: Dockerfile-user ports: - "5001:5001" order-service: build: context: . dockerfile: Dockerfile-order ports: - "5002:5002"
构建并启动服务:
docker-compose up --build
现在,用户服务和订单服务分别运行在http://localhost:5001/users和http://localhost:5002/orders.
在微服务架构中,服务之间的通信通常通过HTTP或消息队列进行。以下示例展示了如何使用HTTP通信.
创建一个API网关来整合用户服务和订单服务.
# api_gateway.py from flask import Flask, jsonify import requests app = Flask(__name__) @app.route('/users') def get_users(): response = requests.get('http://user-service:5001/users') return jsonify(response.json()) @app.route('/orders') def get_orders(): response = requests.get('http://order-service:5002/orders') return jsonify(response.json()) if __name__ == '__main__': app.run(host='0.0.0.0', port=5000)
将API网关添加到Docker Compose文件中.
version: '3' services: user-service: build: context: . dockerfile: Dockerfile-user ports: - "5001:5001" order-service: build: context: . dockerfile: Dockerfile-order ports: - "5002:5002" api-gateway: build: context: . dockerfile: Dockerfile-gateway ports: - "5000:5000"
现在,可以通过API网关访问用户服务和订单服务:
http://localhost:5000/users
http://localhost:5000/orders
在微服务架构中,服务发现和负载均衡是关键组件。服务发现用于跟踪运行中的服务实例,负载均衡则在多个服务实例之间分发请求。以下示例展示了如何在Python微服务架构中实现服务发现和负载均衡.
Consul是一个流行的服务发现和配置工具。我们将使用Consul来注册和发现我们的服务.
首先,启动Consul代理:
docker run -d --name=consul -p 8500:8500 consul
我们需要在每个服务启动时将其注册到Consul。可以使用Python的requests库进行注册.
在user_service.py中添加注册逻辑:
# user_service.py import requests from flask import Flask, jsonify app = Flask(__name__) @app.route('/users') def get_users(): users = [ {'id': 1, 'name': 'Alice'}, {'id': 2, 'name': 'Bob'} ] return jsonify(users) def register_service(): payload = { "ID": "user-service", "Name": "user-service", "Address": "user-service", "Port": 5001 } requests.put('http://consul:8500/v1/agent/service/register', json=payload) if __name__ == '__main__': register_service() app.run(host='0.0.0.0', port=5001)
在order_service.py中添加注册逻辑:
# order_service.py import requests from flask import Flask, jsonify app = Flask(__name__) @app.route('/orders') def get_orders(): orders = [ {'id': 1, 'item': 'Laptop', 'price': 1200}, {'id': 2, 'item': 'Phone', 'price': 800} ] return jsonify(orders) def register_service(): payload = { "ID": "order-service", "Name": "order-service", "Address": "order-service", "Port": 5002 } requests.put('http://consul:8500/v1/agent/service/register', json=payload) if __name__ == '__main__': register_service() app.run(host='0.0.0.0', port=5002)
更新Docker Compose文件以包含Consul服务,并确保其他服务可以访问Consul.
version: '3' services: consul: image: consul ports: - "8500:8500" user-service: build: context: . dockerfile: Dockerfile-user depends_on: - consul environment: - CONSUL_HTTP_ADDR=consul:8500 ports: - "5001:5001" order-service: build: context: . dockerfile: Dockerfile-order depends_on: - consul environment: - CONSUL_HTTP_ADDR=consul:8500 ports: - "5002:5002" api-gateway: build: context: . dockerfile: Dockerfile-gateway depends_on: - consul - user-service - order-service environment: - CONSUL_HTTP_ADDR=consul:8500 ports: - "5000:5000"
为了实现负载均衡,可以使用Traefik,它是一个现代的HTTP反向代理和负载均衡器.
首先,添加Traefik到Docker Compose文件中:
version: '3' services: consul: image: consul ports: - "8500:8500" traefik: image: traefik:v2.5 command: - "--api.insecure=true" - "--providers.consulcatalog=true" - "--entrypoints.web.address=:80" ports: - "80:80" - "8080:8080" depends_on: - consul environment: - CONSUL_HTTP_ADDR=consul:8500 networks: - web user-service: build: context: . dockerfile: Dockerfile-user labels: - "traefik.enable=true" - "traefik.http.routers.user-service.rule=Host(`user-service.local`)" - "traefik.http.services.user-service.loadbalancer.server.port=5001" depends_on: - consul environment: - CONSUL_HTTP_ADDR=consul:8500 ports: - "5001:5001" networks: - web order-service: build: context: . dockerfile: Dockerfile-order labels: - "traefik.enable=true" - "traefik.http.routers.order-service.rule=Host(`order-service.local`)" - "traefik.http.services.order-service.loadbalancer.server.port=5002" depends_on: - consul environment: - CONSUL_HTTP_ADDR=consul:8500 ports: - "5002:5002" networks: - web api-gateway: build: context: . dockerfile: Dockerfile-gateway depends_on: - consul - user-service - order-service environment: - CONSUL_HTTP_ADDR=consul:8500 ports: - "5000:5000" networks: - web networks: web: external: true
现在,Traefik将自动从Consul获取服务信息并执行负载均衡。访问http://user-service.local和http://order-service.local将通过Traefik进行请求分发.
在微服务架构中,日志管理和监控是确保系统健康和排查问题的重要手段。以下示例展示了如何在Python微服务架构中实现日志管理和监控.
ELK(Elasticsearch、Logstash、Kibana)是一个流行的日志管理解决方案。我们将使用ELK Stack来收集和分析日志.
首先,添加ELK服务到Docker Compose文件中:
version: '3' services: elasticsearch: image: docker.elastic.co/elasticsearch/elasticsearch:7.13.3 environment: - discovery.type=single-node ports: - "9200:9200" - "9300:9300" logstash: image: docker.elastic.co/logstash/logstash:7.13.3 volumes: - ./logstash.conf:/usr/share/logstash/pipeline/logstash.conf ports: - "5044:5044" kibana: image: docker.elastic.co/kibana/kibana:7.13.3 ports: - "5601:5601"
创建logstash.conf文件来配置Logstash:
input { file { path => "/var/log/*.log" start_position => "beginning" } } output { elasticsearch { hosts => ["elasticsearch:9200"] } }
在Python应用中集成日志库(如logging)并将日志发送到Logstash.
在user_service.py和order_service.py中添加日志配置:
import logging logging.basicConfig(filename='/var/log/user_service.log', level=logging.INFO) logger = logging.getLogger(__name__) @app.route('/users') def get_users(): users = [ {'id': 1, 'name': 'Alice'}, {'id': 2, 'name': 'Bob'} ] logger.info('Fetched users: %s', users) return jsonify(users)
import logging logging.basicConfig(filename='/var/log/order_service.log', level=logging.INFO) logger = logging.getLogger(__name__) @app.route('/orders') def get_orders(): orders = [ {'id': 1, 'item': 'Laptop', 'price': 1200}, {'id': 2, 'item': 'Phone', 'price': 800} ] logger.info('Fetched orders: %s', orders) return jsonify(orders)
可以使用Prometheus和Grafana进行系统监控.
首先,添加Prometheus和Grafana到Docker Compose文件中:
version: '3' services: prometheus: image: prom/prometheus volumes: - ./prometheus.yml:/etc/prometheus/prometheus.yml ports: - "9090:9090" grafana: image: grafana/grafana ports: - "3000:3000"
创建prometheus.yml文件配置Prometheus:
global: scrape_interval: 15s scrape_configs: - job_name: 'flask' static_configs: - targets: ['user-service:5001', 'order-service:5002']
持续集成和持续部署(CI/CD)是现代软件开发流程的重要组成部分。通过自动化的构建、测试和部署流程,CI/CD能够显著提升开发效率和软件质量。以下是如何在Python微服务架构中实现CI/CD的示例.
GitHub Actions是GitHub提供的CI/CD平台,可以轻松集成到GitHub仓库中。我们将使用GitHub Actions来自动化构建和部署流程.
首先,在项目根目录下创建一个.github/workflows目录,并在其中创建一个CI/CD配置文件ci_cd.yml.
# .github/workflows/ci_cd.yml name: CI/CD Pipeline on: push: branches: - main jobs: build: runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v2 - name: Set up Docker Buildx uses: docker/setup-buildx-action@v1 - name: Build and push Docker images uses: docker/build-push-action@v2 with: push: true tags: | user-service:latest order-service:latest api-gateway:latest - name: Deploy to Docker Hub env: DOCKER_HUB_USERNAME: ${{ secrets.DOCKER_HUB_USERNAME }} DOCKER_HUB_PASSWORD: ${{ secrets.DOCKER_HUB_PASSWORD }} run: | echo $DOCKER_HUB_PASSWORD | docker login -u $DOCKER_HUB_USERNAME --password-stdin docker push user-service:latest docker push order-service:latest docker push api-gateway:latest
为了确保安全性,我们使用GitHub Secrets存储敏感信息,例如Docker Hub的凭据。在GitHub仓库中,进入Settings > Secrets and variables > Actions,添加以下Secrets:
DOCKER_HUB_USERNAME
DOCKER_HUB_PASSWORD
在微服务架构中,Kubernetes是一个流行的容器编排平台。我们将使用Kubernetes部署我们的微服务.
首先,创建Kubernetes配置文件.
# k8s/user-service.yaml apiVersion: apps/v1 kind: Deployment metadata: name: user-service spec: replicas: 2 selector: matchLabels: app: user-service template: metadata: labels: app: user-service spec: containers: - name: user-service image: user-service:latest ports: - containerPort: 5001 --- apiVersion: v1 kind: Service metadata: name: user-service spec: selector: app: user-service ports: - protocol: TCP port: 80 targetPort: 5001
# k8s/order-service.yaml apiVersion: apps/v1 kind: Deployment metadata: name: order-service spec: replicas: 2 selector: matchLabels: app: order-service template: metadata: labels: app: order-service spec: containers: - name: order-service image: order-service:latest ports: - containerPort: 5002 --- apiVersion: v1 kind: Service metadata: name: order-service spec: selector: app: order-service ports: - protocol: TCP port: 80 targetPort: 5002
# k8s/api-gateway.yaml apiVersion: apps/v1 kind: Deployment metadata: name: api-gateway spec: replicas: 2 selector: matchLabels: app: api-gateway template: metadata: labels: app: api-gateway spec: containers: - name: api-gateway image: api-gateway:latest ports: - containerPort: 5000 --- apiVersion: v1 kind: Service metadata: name: api-gateway spec: selector: app: api-gateway ports: - protocol: TCP port: 80 targetPort: 5000
确保Kubernetes集群已经配置好,并且kubectl工具可以访问集群。执行以下命令将服务部署到Kubernetes:
kubectl apply -f k8s/user-service.yaml kubectl apply -f k8s/order-service.yaml kubectl apply -f k8s/api-gateway.yaml
在GitHub Actions配置中添加步骤,以在推送到主分支时自动部署到Kubernetes.
- name: Set up K8s uses: azure/setup-kubectl@v1 with: version: 'v1.18.0' - name: Deploy to Kubernetes run: | kubectl apply -f k8s/user-service.yaml kubectl apply -f k8s/order-service.yaml kubectl apply -f k8s/api-gateway.yaml
在微服务架构中,故障排除和调试是非常重要的。我们可以通过日志管理、分布式追踪和调试工具来实现.
我们之前已经集成了Elastic Stack进行日志管理。通过Kibana,我们可以方便地查看和分析日志.
Jaeger是一个开源的端到端分布式追踪工具。它可以帮助我们追踪请求在各个服务中的流转情况,方便排查性能瓶颈和故障点.
首先,添加Jaeger到Docker Compose文件中:
version: '3' services: jaeger: image: jaegertracing/all-in-one:1.21 ports: - "6831:6831/udp" - "16686:16686"
在Python应用中集成Jaeger Client:
from jaeger_client import Config def init_tracer(service): config = Config( config={ 'sampler': {'type': 'const', 'param': 1}, 'logging': True, }, service_name=service, validate=True, ) return config.initialize_tracer() tracer = init_tracer('user-service')
通过这种方式,我们可以在Kibana中查看日志,在Jaeger中追踪请求,轻松定位问题.
通过本文的深入分析和实践示例,我们详细介绍了如何在Python中实现容器化和微服务架构。从基础的Docker和Flask入门,到使用Consul进行服务发现、Traefik进行负载均衡,再到Elastic Stack日志管理和Jaeger分布式追踪,涵盖了微服务架构的各个关键环节。通过这些实践,开发者可以构建出高可用、高扩展性的微服务系统,提升开发效率和软件质量.
点击关注,第一时间了解华为云新鲜技术~ 。
。
最后此篇关于从基础到高级应用,详解用Python实现容器化和微服务架构的文章就讲到这里了,如果你想了解更多关于从基础到高级应用,详解用Python实现容器化和微服务架构的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我正在通过 labrepl 工作,我看到了一些遵循此模式的代码: ;; Pattern (apply #(apply f %&) coll) ;; Concrete example user=> (a
我从未向应用商店提交过应用,但我会在不久的将来提交。 到目前为止,我对为 iPhone 而非 iPad 进行设计感到很自在。 我了解,通过将通用PAID 应用放到应用商店,客户只需支付一次就可以同时使
我有一个应用程序,它使用不同的 Facebook 应用程序(2 个不同的 AppID)在 Facebook 上发布并显示它是“通过 iPhone”/“通过 iPad”。 当 Facebook 应用程序
我有一个要求,我们必须通过将网站源文件保存在本地 iOS 应用程序中来在 iOS 应用程序 Webview 中运行网站。 Angular 需要服务器来运行应用程序,但由于我们将文件保存在本地,我们无法
所以我有一个单页客户端应用程序。 正常流程: 应用程序 -> OAuth2 服务器 -> 应用程序 我们有自己的 OAuth2 服务器,因此人们可以登录应用程序并获取与用户实体关联的 access_t
假设我有一个安装在用户设备上的 Android 应用程序 A,我的应用程序有一个 AppWidget,我们可以让其他 Android 开发人员在其中以每次安装成本为基础发布他们的应用程序推广广告。因此
Secrets of the JavaScript Ninja中有一个例子它提供了以下代码来绕过 JavaScript 的 Math.min() 函数,该函数需要一个可变长度列表。 Example:
当我分别将数组和对象传递给 function.apply() 时,我得到 NaN 的 o/p,但是当我传递对象和数组时,我得到一个数字。为什么会发生这种情况? 由于数组也被视为对象,为什么我无法使用它
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界. 这篇CFSDN的博客文章ASP转换格林威治时间函数DateDiff()应用由作者收集整理,如果你
我正在将列表传递给 map并且想要返回一个带有合并名称的 data.frame 对象。 例如: library(tidyverse) library(broom) mtcars %>% spl
我有一个非常基本的问题,但我不知道如何实现它:我有一个返回数据框,其中每个工具的返回值是按行排列的: tmp<-as.data.frame(t(data.frame(a=rnorm(250,0,1)
我正在使用我的 FB 应用创建群组并邀请用户加入我的应用群组,第一次一切正常。当我尝试创建另一个组时,出现以下错误: {"(OAuthException - #4009) (#4009) 在有更多用户
我们正在开发一款类似于“会说话的本”应用程序的 child 应用程序。它包含大量用于交互式动画的 JPEG 图像序列。 问题是动画在 iPad Air 上播放正常,但在 iPad 2 上播放缓慢或滞后
我关注 clojure 一段时间了,它的一些功能非常令人兴奋(持久数据结构、函数式方法、不可变状态)。然而,由于我仍在学习,我想了解如何在实际场景中应用,证明其好处,然后演化并应用于更复杂的问题。即,
我开发了一个仅使用挪威语的应用程序。该应用程序不使用本地化,因为它应该仅以一种语言(挪威语)显示。但是,我已在 Info.plist 文件中将“本地化 native 开发区域”设置为“no”。我还使用
读完 Anthony's response 后上a style-related parser question ,我试图说服自己编写单体解析器仍然可以相当紧凑。 所以而不是 reference ::
multicore 库中是否有类似 sapply 的东西?还是我必须 unlist(mclapply(..)) 才能实现这一点? 如果它不存在:推理是什么? 提前致谢,如果这是一个愚蠢的问题,我们深表
我喜欢在窗口中弹出结果,以便更容易查看和查找(例如,它们不会随着控制台继续滚动而丢失)。一种方法是使用 sink() 和 file.show()。例如: y <- rnorm(100); x <- r
我有一个如下所示的 spring mvc Controller @RequestMapping(value="/new", method=RequestMethod.POST) public Stri
我正在阅读 StructureMap关于依赖注入(inject),首先有两部分初始化映射,具体类类型的接口(interface),另一部分只是实例化(请求实例)。 第一部分需要配置和设置,这是在 Bo
我是一名优秀的程序员,十分优秀!