@@ -243,4 +243,161 @@ class OrderItemSchema(BaseModel):
243243` ` `
244244
245245# ## Marshalling and validating response payloads with pydantic
246+ 这里定义一下返回类型 [api.py](https://github.com/abunuwas/microservice-apis/blob/master/ch02/orders/api/api.py)
247+ ` ` ` Python
248+ from starlette.responses import Response
249+ from starlette import status
250+ from orders.api.schemas import (
251+ GetOrderSchema,
252+ CreateOrderSchema,
253+ GetOrdersSchema,
254+ )
255+
256+ @app.get("/orders", response_model=GetOrdersSchema)
257+ def get_orders():
258+ return [
259+ order
260+ ]
261+
262+ @app.post(
263+ "/orders",
264+ status_code=status.HTTP_201_CREATED,
265+ response_model=GetOrderSchema
266+ )
267+ def create_order(order_details: CreateOrderSchema):
268+ return order
269+ ` ` `
270+ 现在, 如果 response payload 中缺少了返回类型需要的属性, FastAPI 则会报错, 如果有多的属性, 则会被去除
271+
272+
273+ # ## Adding an in-memory list of orders to the API
274+ 现在通过一个简单的内存列表来管理订单状态
275+ ` ` ` Python
276+ import time
277+ import uuid
278+ from datetime import datetime
279+ from uuid import UUID
280+
281+ from fastapi import HTTPException
282+ from starlette.responses import Response
283+ from starlette import status
284+
285+ from orders.app import app
286+ from orders.api.schemas import GetOrderSchema, CreateOrderSchema
287+
288+ ORDERS = [] # in memory list
289+
290+ # 获取订单列表
291+ @app.get("/orders", respones_model=GetOrderSchema)
292+ def get_orders():
293+ return ORDERS # return order list
294+
295+ # 创建订单
296+ @app.post(
297+ "/orders",
298+ status_code=status.HTTP_201_CREATED,
299+ response_model=GetOrderSchema,
300+ )
301+ def create_order(order_details: CreateOrderSchema):
302+ # convert Pydantic model -> dict: v1 use .dict(); v2 use .model_dump()
303+ order = order_details.model_dump()
304+ order["id"] = uuid.uuid4()
305+
306+ # 获取订单
307+ @app.get("/orders/{order_id}", response_model=GetOrderSchema)
308+ def get_order(order_id: UUID):
309+ for order in ORDERS:
310+ if order["id"] == order_id:
311+ return order
312+ raise HTTPException(
313+ status_code=404,
314+ detail=f"Order with ID {order_id} not found",
315+ )
316+
317+ # 更新订单
318+ @app.put("/orders/{order_id}", response_model=GetOrderSchema)
319+ def update_order(order_id: UUID, order_details: CreateOrderSchema):
320+ for order in ORDERS:
321+ if order["id"] == order_id:
322+ order.update(order_details.model_dump())
323+ return order
324+ raise HTTPException(
325+ status_code=404,
326+ detail=f"Order with ID {order_id} not found",
327+ )
328+
329+ # 删除订单
330+ @app.delete(
331+ "/orders/{order_id}",
332+ status_code=status.HTTP_204_NO_CONTENT,
333+ response_class=Response
334+ )
335+ def delete_order(order_id: UUID):
336+ for index, order in enumerate(ORDERS):
337+ if order["id"] == order_id:
338+ ORDERS.pop(index)
339+ return Response(status_code=HTTPStatus.NO_CONTENT.value)
340+ raise HTTPException(
341+ status_code=404,
342+ detail=f"Order with ID {order_id} not found",
343+ )
344+
345+ # 取消订单
346+ @app.post("/orders/{order_id}/cancel", response_model=GetOrderSchema)
347+ def cancel_order(order_id: UUID):
348+ for order in ORDERS:
349+ if order["id"] == order_id:
350+ order["status"] = "cancelled"
351+ return order
352+ raise HTTPException(
353+ status_code=404,
354+ detail=f"Order with ID {order_id} not found",
355+ )
356+
357+ # 支付订单
358+ @app.get("/orders/{order_id}/pay", response_model=GetOrderSchema)
359+ def pay_order(order_id: UUID):
360+ for order in ORDERS:
361+ if order["id"] == order_id:
362+ order["status"] = "progress"
363+ return order
364+ raise HTTPException(
365+ status_code=404,
366+ detail=f"Order with ID {order_id} not found"<>
367+ )
368+ ` ` `
369+
370+
371+ # ## Microservice Principles
372+ 微服务设计原则 : 如何将系统拆分为微服务 *serivce decomposition*, 以及如何估计其质量
373+ 下面是三个设计原则 :
374+ - Database-per-service principle 服务独立数据库原则
375+ - Loose coupling principle 松耦合原则
376+ - Single Responsibility Principle (SRP) 单一职责原则
377+
378+ 遵循这些原则将帮助你避免构建一个"分布式单体应用"(distributed monolith)的风险
379+
380+ # ### Data-per-service principle
381+ 服务独立数据库原则是指, 每个微服务拥有一系列具体的数据, 并且其他微服务只能通过 API 访问.
382+
383+ 这并不意味着每个微服务都要连接到不同的数据库中, 可以是关系数据库中的不同 tables, 或者非关系数据库中的 collections, 关键是数据被某个服务拥有, 不能被其他服务直接访问.
384+
385+ 例如, 为了计算价格, orders service 从 Production database 中获取每个物品的价格, 它也需要知道用户是否有折扣优惠, 这个需要从 User database 获取. 然而, 不能直接诶访问这两个数据库, order service 需要从 products service 和 users service 获取数据.
386+
387+ # ### Loose coupling principle
388+ 松耦合原则要求在设计服务的时候, 必须清晰的关注分离点, 松耦合的服务不依赖另一个服务的实现细节, 这项原则有两个实际的应用 :
389+ - 每个服务都可以独立于其他服务工作 : 如果一个服务在不调用另一个服务的情况下无法完成一个简单的请求, 那么这两个服务之间没有清晰的关注点分离, 他们应被视为一个整体
390+ - 每个服务都可以在不影响其他服务工作的情况下进行更新 : 如果一个服务的更新需要其他服务, 那么这些服务之间存在紧密耦合, 需要重新设计
391+
392+ 例如, 一个基于历史数据计算销售预测的服务(Sales Forecast Service), 以及一个拥有历史销售数据的服务(Historical Data Service), 为了计算预测, 销售服务会调用历史数据服务的API来获取历史数据. 在这种情况下, 销售预测服务在不调用历史数据服务的情况下无法响应任何请求, 因此两个服务之间存在紧密耦合.
393+
394+ 解决方案是重新设计这两个服务, 使它们不相互依赖, 或者将它们合并成一个单一的服务.
395+
396+
397+ # ### Single responsibility principle
398+ 单一职责原则(SRP)指出, 我们要设计职责少、理想情况下只有一个职责的组件.
399+ 当应用于微服务设计架构时, 这意味着我们应努力围绕单一的业务能力或子域来设计服务.
400+
401+
402+
246403
0 commit comments