单体应用拆分微服务面临的挑战
- 服务间通信:不同微服务可能运行在不同服务器、不同进程甚至不同语言环境下,需要可靠、高效通信机制。例如网络延迟、带宽限制、通信协议兼容性等问题。
- 数据一致性:单体应用数据集中管理,拆分后各微服务可能有自己独立数据库,在分布式事务场景下维护数据一致性困难,如跨微服务的订单创建与库存扣减操作。
- 服务治理:包括服务发现、负载均衡、容错处理等。随着微服务数量增加,如何确保服务间正常调用,一个服务故障不影响其他服务成为挑战。
- 部署与维护:从单体应用部署到多个微服务独立部署,复杂度增加,如版本管理、配置管理等。
微服务之间通信机制设计
- 基于RESTful API
- 技术:HTTP协议,简单通用,几乎所有编程语言都有支持HTTP请求库。
- 方案:各微服务提供RESTful接口,通过HTTP请求进行数据交互。例如订单微服务向库存微服务发送HTTP POST请求扣减库存。
- 消息队列(MQ)
- 技术:如RabbitMQ、Kafka等。
- 方案:用于异步通信场景。例如用户注册成功后,通过MQ发送消息通知邮件微服务发送欢迎邮件,解耦服务间直接依赖。
保障数据一致性技术与方案
- 分布式事务 - 两阶段提交(2PC)
- 技术:引入协调者,第一阶段协调者向所有参与者发送预提交请求,参与者执行操作并返回是否成功;第二阶段根据所有参与者反馈决定提交或回滚。
- 方案:例如订单创建与库存扣减场景,订单微服务作为协调者,与库存微服务完成2PC流程确保数据一致性。但2PC存在单点故障、性能瓶颈等问题。
- 最终一致性 - 事件溯源与CQRS(命令查询职责分离)
- 技术:记录所有对数据的操作事件,通过事件重建数据状态;CQRS将数据读写分离,读模型和写模型分开处理。
- 方案:如电商系统,订单创建事件记录后,库存微服务通过消费订单创建事件扣减库存,最终达到数据一致。
在Django应用中实现通信机制具体步骤与代码示例
- RESTful API实现
- 步骤:
- 安装Django REST framework库:
pip install djangorestframework
- 在Django项目中配置:在
settings.py
的INSTALLED_APPS
添加'rest_framework'
- 创建序列化器:如订单微服务中,为
Order
模型创建序列化器,在serializers.py
中:
from rest_framework import serializers
from.models import Order
class OrderSerializer(serializers.ModelSerializer):
class Meta:
model = Order
fields = '__all__'
- 创建视图:在`views.py`中:
from rest_framework.views import APIView
from rest_framework.response import Response
from.models import Order
from.serializers import OrderSerializer
class OrderView(APIView):
def get(self, request):
orders = Order.objects.all()
serializer = OrderSerializer(orders, many = True)
return Response(serializer.data)
def post(self, request):
serializer = OrderSerializer(data = request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status = 201)
return Response(serializer.errors, status = 400)
- 配置路由:在`urls.py`中:
from django.urls import path
from. import views
urlpatterns = [
path('orders/', views.OrderView.as_view(), name='order-list-create')
]
- 消息队列(以RabbitMQ为例)实现
- 步骤:
- 安装
pika
库:pip install pika
- 生产者(如用户注册成功发送邮件通知):在
views.py
中:
import pika
def register_user(request):
# 用户注册逻辑
connection = pika.BlockingConnection(pika.ConnectionParameters('localhost'))
channel = connection.channel()
channel.queue_declare(queue='email_notification')
message = 'User registered successfully'
channel.basic_publish(exchange='', routing_key='email_notification', body = message)
connection.close()
return HttpResponse('User registered')
- 消费者(邮件微服务接收消息发送邮件):创建`consumer.py`
import pika
def callback(ch, method, properties, body):
print("Received message: %r" % body)
# 发送邮件逻辑
connection = pika.BlockingConnection(pika.ConnectionParameters('localhost'))
channel = connection.channel()
channel.queue_declare(queue='email_notification')
channel.basic_consume(queue='email_notification', on_message_callback = callback, auto_ack = True)
print('Waiting for messages. To exit press CTRL+C')
channel.start_consuming()
在Django应用中实现保障数据一致性具体步骤与代码示例
- 最终一致性 - 事件溯源与CQRS示例
from django.db import models
class OrderCreatedEvent(models.Model):
order_id = models.IntegerField()
created_at = models.DateTimeField(auto_now_add = True)
- 订单创建时记录事件:在`views.py`中:
from.models import OrderCreatedEvent
def create_order(request):
# 创建订单逻辑
order = Order.objects.create(...)
OrderCreatedEvent.objects.create(order_id = order.id)
return HttpResponse('Order created')
- 库存微服务消费事件扣减库存(假设通过消息队列传递事件):在库存微服务`consumer.py`中:
import pika
from.models import Inventory
def callback(ch, method, properties, body):
order_id = int(body)
inventory = Inventory.objects.get(product_id = related_product_id)
inventory.quantity -= 1
inventory.save()
connection = pika.BlockingConnection(pika.ConnectionParameters('localhost'))
channel = connection.channel()
channel.queue_declare(queue='order_created_events')
channel.basic_consume(queue='order_created_events', on_message_callback = callback, auto_ack = True)
print('Waiting for order created events. To exit press CTRL+C')
channel.start_consuming()