Golang进阶,揉碎数据库中间件,干货满满!(二)

本文涉及的产品
服务治理 MSE Sentinel/OpenSergo,Agent数量 不受限
简介: Golang进阶,揉碎数据库中间件,干货满满!(二)

七、权限管理实现原理#


重点关注的地方:


# server.go:381
// todo 用户白名单校验,只有指定的user、ip才能使用Proxy
if allowConnect := conn.IsAllowConnect(); allowConnect == false {
    err := mysql.NewError(mysql.ER_ACCESS_DENIED_ERROR, "ip address access denied by kingshard.")
    conn.writeError(err)
    conn.Close()
    return
  }


视频地址:https://www.bilibili.com/video/BV19g411N7NR?p=7


八、MySQL协议-Handshake!和中间件握手机制原理#


原理图:



重点关注的地方:

server.go:388


// todo 基于MySQL协议和客户端建立握手机制
  if err := conn.Handshake(); err != nil {
    golog.Error("server", "onConn", err.Error(), 0)
    conn.writeError(err)
    conn.Close()
    return
  }


backend_conn.go:101


// todo 这里其实Proxy和MySQL Server之间建立连接的逻辑
  // todo 大家看到这里不明白也没关系,因为想看懂这里需要了解MySQL协议,后面的视频中我会跟大家讲明白这件事
  // todo 大家只需要知道,执行过这里的代码之后呢,proxy和MySQL-Service之间就会建立一个Conn,
  // todo 并且Proxy会维护这个Conn,后续用户的SQL打过来之后,Proxy会将用户的SQL转发给这里获取到的Conn,进尔让MySQL的引擎去真正的执行这里的SQL
  // todo 读MySQL发过来的握手报文
  if err := c.readInitialHandshake(); err != nil {
    c.conn.Close()
    return err
  }
  // todo 写自己的信息(port、username、password、host)
  if err := c.writeAuthHandshake(); err != nil {
    c.conn.Close()
    return err
  }
  // todo 读取MySQL-Server发过来的ok报文
  if _, err := c.readOK(); err != nil {
    c.conn.Close()
    return err
  }


视频地址:https://www.bilibili.com/video/BV19g411N7NR?p=8


九、中间件不断接受处理客户端SQL原理#


重点关注的地方:

conn.go:279


// todo 下面的代码在一个无限循环中, 不断的接受客户端发送过来的sql语句
  for {
    // todo 根据MySQL协议解析数据包,获取出数据包中sql语句
    data, err := c.readPacket()
    if err != nil {
      return
    }
    if c.configVer != c.proxy.configVer {
      err := c.reloadConfig()
      if nil != err {
        golog.Error("ClientConn", "Run",
          err.Error(), c.connectionId,
        )
        c.writeError(err)
        return
      }
      c.configVer = c.proxy.configVer
      golog.Debug("ClientConn", "Run",
        fmt.Sprintf("config reload ok, ver:%d", c.configVer), c.connectionId,
      )
    }
    // 使用dispatch方法,继续处理数据包
      if err := c.dispatch(data); err != nil {
      c.proxy.counter.IncrErrLogTotal()
      golog.Error("ClientConn", "Run",
        err.Error(), c.connectionId,
      )
      c.writeError(err)
      if err == mysql.ErrBadConn {
        c.Close()
      }
    }
    if c.closed {
      return
    }
    c.pkg.Sequence = 0
  }
}


视频地址:https://www.bilibili.com/video/BV19g411N7NR?p=9


十、中间件是如何执行你的select语句的?#


重点关注的地方:

conn.go:279


// 使用dispatch方法,继续处理数据包
      if err := c.dispatch(data); err != nil {
      c.proxy.counter.IncrErrLogTotal()
      golog.Error("ClientConn", "Run",
        err.Error(), c.connectionId,
      )
      c.writeError(err)
      if err == mysql.ErrBadConn {
        c.Close()
      }
    }


conn.go:340


func (c *ClientConn) dispatch(data []byte) error {
  c.proxy.counter.IncrClientQPS()
  // todo MYSQL协议规定了,客户端发送过来的数据格式是:cmd+data
  // todo 其中的cmd就是sql的类型,类型都枚举在下面了,打眼一看都能懂
  cmd := data[0]
  // todo data部分就是sql详细内容
  data = data[1:]
  switch cmd {
  case mysql.COM_QUIT:
    c.handleRollback()
    c.Close()
    return nil
  case mysql.COM_QUERY: // todo select 语句
    return c.handleQuery(hack.String(data))
  case mysql.COM_PING: // todo ping 语句
    return c.writeOK(nil)
  case mysql.COM_INIT_DB:
    return c.handleUseDB(hack.String(data))
  case mysql.COM_FIELD_LIST:
    return c.handleFieldList(data)
  case mysql.COM_STMT_PREPARE:
    return c.handleStmtPrepare(hack.String(data))
  case mysql.COM_STMT_EXECUTE:// todo insert、update 语句
    return c.handleStmtExecute(data)
  case mysql.COM_STMT_CLOSE:
    return c.handleStmtClose(data)
  case mysql.COM_STMT_SEND_LONG_DATA:
    return c.handleStmtSendLongData(data)
  case mysql.COM_STMT_RESET:
    return c.handleStmtReset(data)
  case mysql.COM_SET_OPTION:
    return c.writeEOF(0)
  default:
    msg := fmt.Sprintf("command %d not supported now", cmd)
    golog.Error("ClientConn", "dispatch", msg, 0)
    return mysql.NewError(mysql.ER_UNKNOWN_ERROR, msg)
  }
  return nil
}


视频地址:https://www.bilibili.com/video/BV19g411N7NR?p=10


十一、读写分离实现原理#


重点关注的地方:

conn_pershard.go:97


// todo 从选出DB中获取一条可用的连接,如果是没有开事物且是读请求的话,executeDB.IsSlave一般为true
  conn, err := c.getBackendConn(executeDB.ExecNode, executeDB.IsSlave)
  defer c.closeConn(conn, false)
  if err != nil {
    return false, err
  }


视频地址:https://www.bilibili.com/video/BV19g411N7NR?p=11

相关实践学习
基于CentOS快速搭建LAMP环境
本教程介绍如何搭建LAMP环境,其中LAMP分别代表Linux、Apache、MySQL和PHP。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
8月前
|
Java Go 开发者
100天精通Golang(基础入门篇)——第15天:深入解析Go语言中函数的应用:从基础到进阶,助您精通函数编程!(进阶)
100天精通Golang(基础入门篇)——第15天:深入解析Go语言中函数的应用:从基础到进阶,助您精通函数编程!(进阶)
45 0
|
9月前
|
SQL 测试技术 Go
Golang实用进阶工具
Golang实用进阶工具
38 0
|
11月前
|
缓存 安全 Go
Golang 进阶文章一览
Golang 进阶文章一览
75 0
|
SQL 中间件 关系型数据库
Golang进阶,揉碎数据库中间件,干货满满!(二)
Golang进阶,揉碎数据库中间件,干货满满!(二)
276 0
Golang进阶,揉碎数据库中间件,干货满满!(二)
|
中间件 关系型数据库 MySQL
Golang进阶,揉碎数据库中间件,干货满满!(一)
Golang进阶,揉碎数据库中间件,干货满满!(一)
178 0
Golang进阶,揉碎数据库中间件,干货满满!(一)
|
1月前
|
监控 算法 Go
Golang深入浅出之-Go语言中的服务熔断、降级与限流策略
【5月更文挑战第4天】本文探讨了分布式系统中保障稳定性的重要策略:服务熔断、降级和限流。服务熔断通过快速失败和暂停故障服务调用来保护系统;服务降级在压力大时提供有限功能以保持整体可用性;限流控制访问频率,防止过载。文中列举了常见问题、解决方案,并提供了Go语言实现示例。合理应用这些策略能增强系统韧性和可用性。
110 0
|
1月前
|
前端开发 Go
Golang深入浅出之-Go语言中的异步编程与Future/Promise模式
【5月更文挑战第3天】Go语言通过goroutines和channels实现异步编程,虽无内置Future/Promise,但可借助其特性模拟。本文探讨了如何使用channel实现Future模式,提供了异步获取URL内容长度的示例,并警示了Channel泄漏、错误处理和并发控制等常见问题。为避免这些问题,建议显式关闭channel、使用context.Context、并发控制机制及有效传播错误。理解并应用这些技巧能提升Go语言异步编程的效率和健壮性。
52 5
Golang深入浅出之-Go语言中的异步编程与Future/Promise模式
|
1月前
|
Prometheus 监控 Cloud Native
Golang深入浅出之-Go语言中的分布式追踪与监控系统集成
【5月更文挑战第4天】本文探讨了Go语言中分布式追踪与监控的重要性,包括追踪的三个核心组件和监控系统集成。常见问题有追踪数据丢失、性能开销和监控指标不当。解决策略涉及使用OpenTracing或OpenTelemetry协议、采样策略以及聚焦关键指标。文中提供了OpenTelemetry和Prometheus的Go代码示例,强调全面可观测性对微服务架构的意义,并提示选择合适工具和策略以确保系统稳定高效。
158 5
|
1月前
|
监控 负载均衡 算法
Golang深入浅出之-Go语言中的协程池设计与实现
【5月更文挑战第3天】本文探讨了Go语言中的协程池设计,用于管理goroutine并优化并发性能。协程池通过限制同时运行的goroutine数量防止资源耗尽,包括任务队列和工作协程两部分。基本实现思路涉及使用channel作为任务队列,固定数量的工作协程处理任务。文章还列举了一个简单的协程池实现示例,并讨论了常见问题如任务队列溢出、协程泄露和任务调度不均,提出了解决方案。通过合理设置缓冲区大小、确保资源释放、优化任务调度以及监控与调试,可以避免这些问题,提升系统性能和稳定性。
55 6
|
1月前
|
负载均衡 算法 Go
Golang深入浅出之-Go语言中的服务注册与发现机制
【5月更文挑战第4天】本文探讨了Go语言中服务注册与发现的关键原理和实践,包括服务注册、心跳机制、一致性问题和负载均衡策略。示例代码演示了使用Consul进行服务注册和客户端发现服务的实现。在实际应用中,需要解决心跳失效、注册信息一致性和服务负载均衡等问题,以确保微服务架构的稳定性和效率。
35 3