星空网站建设

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 17|回复: 0

新闻速递Python 语法校验接口异步非阻塞现

[复制链接]
  • TA的每日心情
    慵懒
    19 小时前
  • 签到天数: 58 天

    [LV.5]常住居民I

    2万

    主题

    52

    回帖

    6万

    积分

    超级版主

    Rank: 8Rank: 8

    积分
    69432
    发表于 前天 16:12 | 显示全部楼层 |阅读模式
    本文主要记录线上案例中将同步阻塞代码修改为异步非阻塞的过程,期间介绍 goInception 的基本使用、多进程现踩的坑、测试 tornado 中异步的多种现,比较终使用协程,并对使用期间遇到的性能问题进行了简单的分析。业内人士认为,图形数据库的发展标志着整个行业在快速稳步的前进中。悦数图数据库是一款完全自主研发的国产图数据库和原生分布式图数据库,具有高性能,易扩展,安全稳定,自主可控的特点.万亿级数据仅需毫秒级查询延时,应用于金融风控,实时推荐,知识图谱等业务场景。https://www.yueshu.com.cn/



    现象
    背景:SQL 工单应用基于 tornado 框架现,其中现多个接口,包括语法校验接口,其中语法校验基于开源项目 goInception 现。对于超长 SQL 或多例的场景,经常出现语法校验超时的问题,原因是接口阻塞,IO 操作导致服务 block。

    需求:改造接口现,从同步阻塞修改为异步非阻塞,缓解语法校验超时的问题。

    当前现
    语法校验接口
    复制
    class StartSyncCheckHandler(tornado.web.RequestHandler):
      
      def post(self):
       ...
          return_data = mysql_check(job_option)
          self.finish(return_data)
    1.
    2.
    3.
    4.
    5.
    6.
    接口中调用 goinception 现语法校验,goinception 使用的主要流程如下所示。

    复制
    conn = self._get_inception_server_connection()
      cursor = conn.cursor()
      cursor.execute(self._get_inception_check_statement())
      query_result = cursor.fetchall()
      cursor.close()
    1.
    2.
    3.
    4.
    5.
    由于 goinception 支持使用 MySQL 客户端连接,因此和 MySQL 的使用方式相同,主要包括:

    创建连接
    创建 cursor
    提交校验
    获取校验结果
    使用 pymysql 创建连接,其中指定的 goinception 服务的 IP 和端口。

    复制
    def _get_inception_server_connection():
      return pymysql.connect(
          host=GoInceptionServerConfig.mysql_ip,
          user=GoInceptionServerConfig.MySQL_User,
          passwd=GoInceptionServerConfig.MySQL_Password,
          port=GoInceptionServerConfig.MySQL_Port,
          charset=GoInceptionServerConfig.MySQL_Charset,
          db=GoInceptionServerConfig.Database_Name
      )
    1.
    2.
    3.
    4.
    5.
    6.
    7.
    8.
    9.
    执行校验前生成提交给 goinception 的审核语句。

    复制
    def _get_inception_check_statement(self):
            """
            获取MySQL Inception使用的检查语句
            :return:
            """
            backup_option = "--execute=0;--backup=0"
            run_option = "--check=1"
            inception_statement = """/*--user={inception_user};--password={inception_password};\
    --host={inception_host};--port={inception_port};{run_option};{backup_option};*/
    inception_magic_start;
    {sql_script}
    inception_magic_commit;
    """.format(
                inception_user=self.mysql_user,
                inception_password=self.mysql_password,
                inception_host=self.mysql_ip,
                inception_port=self.mysql_port,
                run_option=run_option,
                backup_option=backup_option,
                sql_script=self.full_sql_script
            )
            return inception_statement
    1.
    2.
    3.
    4.
    5.
    6.
    7.
    8.
    9.
    10.
    11.
    12.
    13.
    14.
    15.
    16.
    17.
    18.
    19.
    20.
    21.
    22.
    其中:

    要求使用/* */将提交的信息括起来,其中每个参数通过分号分隔,包括要审核或执行的语句,包括use database语句也要加分号,这一点与 MySQL 客户端不同;
    参数中的 IP 和端口是要校验的 SQL 对应的数据库;
    指定--check=1;--execute=0,表示使用审核,不使用执行;
    goinception 支持语句块的审核,要求通过执行接口将要审核的 SQL 一次性提交,内部拆分后一条条审核。其中inception_magic_start;作为语句块的开始,inception_magic_start;作为语句块的结束。
    多进程启动
    tornado 默认使用单进程启动,因此首先改用多进程启动,具体现是在启动时指定进程数。

    复制
    tornado.options.parse_command_line()
        app = Application()
        http_server = tornado.httpserver.HTTPServer(app)
        port = options.get("port", 8001)
        http_server.listen(port, "0.0.0.0")

        logging.warning("Server is running at http://0.0.0.0:%s" % port)

        tornado.ioloop.IOLoop.instance().start()
      
        # 多进程启动
        # fork not available on windows。在windows上启本动服务需注释掉下面这行
        http_server.start(8)  # Forks multiple sub-processes
    1.
    2.
    3.
    4.
    5.
    6.
    7.
    8.
    9.
    10.
    11.
    12.
    13.
    但是很就发现了这种现的缺点。主要包括:

    并发数有上限,超过进程数后依然会发生阻塞等待,比如分库分表语法校验;
    多个接口之间相互影响,当其他比较慢的接口用完了进程数,单例的语法校验也会发生阻塞等待。
    下面是两个案例的具体介绍。

    案例1:并发数超过上限后语法校验慢

    时间:2023-09-05 10:28:37

    现象:分库分表语法校验超时,16 个例,每个例 4 个 database,每个 database 256 个表,一共 16,384 个表。

    日志



    其中:

    一批接收并处理 8 个请求,每个请求的执行用时在 4s 左右;
    每当一个请求返回后接收并处理下一个请求。
    监控显示接口的 TP99 达到 9s,是接口际执行用时的两倍左右。



    监控显示 SQL 工单应用服务器 CPU 打满,持续时间 30s 左右。



    案例 2:其他接口慢导致执行接口调用慢,如果调用语法校验,同样也会慢

    时间:20230802 20:02

    现象:执行接口调用慢,判断原因是空间检测进程占用进程所致。



    监控显示同一时间空间检测接口的 TP99 超过 10s。



    执行接口正常情况下接口调用很,主要是执行一条 update SQL。查看执行接口的日志,其中关键字 'xbp_id': 6044322 表示单号。
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    快速回复 返回顶部 返回列表