在 Kubernetes 上使用 Flask 搭建 Python 微服务( 三 )

abc的有用模块来创建抽象方法和抽象类 。因为UserRepository只是一个接口,所以我们可以使用abc模块 。
任何继承自abc.ABC的类都将变为抽象类,任何带有@abc.abstractmethod装饰器的函数都会变为一个抽象函数 。下面是UserRepository的结构:
 

  1. from abc import ABC, abstractmethod
     
  2. class UserRepository(ABC):
  3. @abstractmethod
  4. def fetch(self, name:Name) -> User:
  5. pass
 
UserRepository遵循仓储模式 。换句话说,它在User实体上提供适当的 CRUD 操作,而不会暴露底层数据存储语义 。在本例中,我们只需要fetch()操作,因为FindService只查找用户 。
因为UserRepository是一个抽象类,我们不能从抽象类创建实例对象 。创建对象必须依赖于一个具体类实现这个抽象类 。数据层UserRepositoryImpl提供了UserRepository的具体实现:
 
  1. class UserRepositoryImpl(UserRepository):
     
  2. def fetch(self, name:Name) -> User:
     
  3. pass
     
 
由于AddService将用户数据存储在一个 MySQL 数据库中,因此UserRepositoryImpl也必须连接到相同的数据库去检索数据 。下面是连接到数据库的代码 。注意,我们正在使用 MySQL 的连接库 。
 
  1. from mysql.connector import connect, Error
     
  2. class UserRepositoryImpl(UserRepository):
  3. def fetch(self, name:Name) -> User:
  4. try:
  5. with connect(
  6. host="mysqldb",
  7. user="root",
  8. password="admin",
  9. database="glarimy",
  10. ) as connection:
  11. with connection.cursor() as cursor:
  12. cursor.execute("SELECT * FROM ums_users where name=%s", (name.value,))
  13. row = cursor.fetchone()
  14. if cursor.rowcount == -1:
  15. raise UserNotFoundException()
  16. else:
  17. return User(Name(row[0]), PhoneNumber(row[1]), row[2])
  18. except Error as e:
  19. raise e
在上面的片段中,我们使用用户root/ 密码admin连接到一个名为mysqldb的数据库服务器,使用名为glarimy的数据库(模式) 。在演示代码中是可以包含这些信息的,但在生产中不建议这么做,因为这会暴露敏感信息 。
fetch()操作的逻辑非常直观,它对ums_users表执行 SELECT 查询 。回想一下,AddService正在将用户数据写入同一个表中 。如果 SELECT 查询没有返回记录,fetch()函数将抛出UserNotFoundException异常 。否则,它会从记录中构造User实体并将其返回给调用者 。这没有什么特殊的 。
应用层
最终,我们需要创建应用层 。此模型如图 2 所示 。它只包含两个类:控制器和一个 DTO 。
在 Kubernetes 上使用 Flask 搭建 Python 微服务

文章插图
图 2: 添加服务的应用层
众所周知,一个 DTO 只是一个没有任何业务逻辑的数据容器 。它主要用于在FindService和外部之间传输数据 。我们只是提供了在 REST 层中将UserRecord转换为字典以便用于 JSON 传输:
 
  1. class UserRecord:
     
  2. def toJSON(self):
     
  3. return {
     
  4. "name": self.name,
     
  5. "phone": self.phone,
     

  6. 推荐阅读