当前位置: 首页 > news >正文

观澜做网站公司网上怎么做销售

观澜做网站公司,网上怎么做销售,企业做网站需要什么软件,上海比较好的装修公司文章目录 前言一、go-sql-driver/mysql1、驱动注册#xff1a;sql.Register2、驱动实现#xff1a;MysqlDriver3、RegisterDialContext 二、总结 前言 在上篇文章中我们知道#xff0c;database/sql只是提供了驱动相关的接口#xff0c;并没有相关的具体实现#xff0c;具… 文章目录 前言一、go-sql-driver/mysql1、驱动注册sql.Register2、驱动实现MysqlDriver3、RegisterDialContext 二、总结 前言 在上篇文章中我们知道database/sql只是提供了驱动相关的接口并没有相关的具体实现具体内容是由第三方实现的如go-sql-driver/mysqlhttps://github.com/go-sql-driver/mysql/本章中我们主要是探究这个驱动实现库的具体实现。以及它是如何与database/sql一起作用的。 一、go-sql-driver/mysql go-sql-driver作为一个三方驱动库主要就是实现database/sql中的驱动接口了因此主要的文件也就是driver.go、connector.go和connection.go几个文件了。因此本章的阅读业主要聚焦与这三个文件中的源码内容。 1、驱动注册sql.Register 通常我们都会这样调用database/sql的Open方法创建一个db实例 import (database/sql_ github.com/go-sql-driver/mysql )// ...db, err : sql.Open(mysql, user:password/dbname) if err ! nil {panic(err) }初看是不是觉得很奇怪在这段代码中我们没有直接使用到go-sql-driver的的任何东西但却需要引入这个包这是因为sql.Open方法中我们知道会检查获取对应的驱动而驱动的注册是由第三方驱动实现包调用Register方法完成的。 在go-sql-driver中的driver.go中我们发现init函数中会调用Register方法注册相应的驱动这也是上面的代码中为什么需要引入这个包的原因。 func init() {if driverName ! {sql.Register(driverName, MySQLDriver{})} }2、驱动实现MysqlDriver 在go-sql-driver中核心的driver.go中实现了具体的mysql驱动MysqlDriver // Open new Connection. // See https://github.com/go-sql-driver/mysql#dsn-data-source-name for how // the DSN string is formatted func (d MySQLDriver) Open(dsn string) (driver.Conn, error) {cfg, err : ParseDSN(dsn)if err ! nil {return nil, err}c : newConnector(cfg)return c.Connect(context.Background()) }在该方法中首先从数据源dsn中解析出对应的配置然后再构造对应的连接器调用连接器的Connect方法与mysql建立连接。 connector实现了driver.Connector接口其中Connect方法主要是与mysql进行交互包括拨号dial、认证、利用mysql协议发包与收包处理结果等 type connector struct {cfg *Config // immutable private copy.encodedAttributes string // Encoded connection attributes. }func newConnector(cfg *Config) *connector {encodedAttributes : encodeConnectionAttributes(cfg)return connector{cfg: cfg,encodedAttributes: encodedAttributes,} }// Connect implements driver.Connector interface. // Connect returns a connection to the database. func (c *connector) Connect(ctx context.Context) (driver.Conn, error) {var err error// Invoke beforeConnect if present, with a copy of the configurationcfg : c.cfgif c.cfg.beforeConnect ! nil {cfg c.cfg.Clone()err c.cfg.beforeConnect(ctx, cfg)if err ! nil {return nil, err}}// New mysqlConnmc : mysqlConn{maxAllowedPacket: maxPacketSize,maxWriteSize: maxPacketSize - 1,closech: make(chan struct{}),cfg: cfg,connector: c,}mc.parseTime mc.cfg.ParseTime// Connect to ServerdialsLock.RLock()dial, ok : dials[mc.cfg.Net]dialsLock.RUnlock()if ok {dctx : ctxif mc.cfg.Timeout 0 {var cancel context.CancelFuncdctx, cancel context.WithTimeout(ctx, c.cfg.Timeout)defer cancel()}mc.netConn, err dial(dctx, mc.cfg.Addr)} else {nd : net.Dialer{Timeout: mc.cfg.Timeout}mc.netConn, err nd.DialContext(ctx, mc.cfg.Net, mc.cfg.Addr)}if err ! nil {return nil, err}mc.rawConn mc.netConn// Enable TCP Keepalives on TCP connectionsif tc, ok : mc.netConn.(*net.TCPConn); ok {if err : tc.SetKeepAlive(true); err ! nil {c.cfg.Logger.Print(err)}}// Call startWatcher for context support (From Go 1.8)mc.startWatcher()if err : mc.watchCancel(ctx); err ! nil {mc.cleanup()return nil, err}defer mc.finish()mc.buf newBuffer(mc.netConn)// Set I/O timeoutsmc.buf.timeout mc.cfg.ReadTimeoutmc.writeTimeout mc.cfg.WriteTimeout// Reading Handshake Initialization PacketauthData, plugin, err : mc.readHandshakePacket()if err ! nil {mc.cleanup()return nil, err}if plugin {plugin defaultAuthPlugin}// Send Client Authentication PacketauthResp, err : mc.auth(authData, plugin)if err ! nil {// try the default auth plugin, if using the requested plugin failedc.cfg.Logger.Print(could not use requested auth plugin plugin: , err.Error())plugin defaultAuthPluginauthResp, err mc.auth(authData, plugin)if err ! nil {mc.cleanup()return nil, err}}if err mc.writeHandshakeResponsePacket(authResp, plugin); err ! nil {mc.cleanup()return nil, err}// Handle response to auth packet, switch methods if possibleif err mc.handleAuthResult(authData, plugin); err ! nil {// Authentication failed and MySQL has already closed the connection// (https://dev.mysql.com/doc/internals/en/authentication-fails.html).// Do not send COM_QUIT, just cleanup and return the error.mc.cleanup()return nil, err}if mc.cfg.MaxAllowedPacket 0 {mc.maxAllowedPacket mc.cfg.MaxAllowedPacket} else {// Get max allowed packet sizemaxap, err : mc.getSystemVar(max_allowed_packet)if err ! nil {mc.Close()return nil, err}mc.maxAllowedPacket stringToInt(maxap) - 1}if mc.maxAllowedPacket maxPacketSize {mc.maxWriteSize mc.maxAllowedPacket}// Handle DSN Paramserr mc.handleParams()if err ! nil {mc.Close()return nil, err}return mc, nil }// Driver implements driver.Connector interface. // Driver returns MySQLDriver{}. func (c *connector) Driver() driver.Driver {return MySQLDriver{} } 同时我们还注意到Connect方法中调用了一个startWatcher方法该方法从watcher通道中接收一个ctx并对这个ctx进行监听每次都会调用一个watchCancel方法将ctx传递Watcherwatcher监听到ctx.Done的信号后将会调用cancel方法启动清理工作。 func (mc *mysqlConn) startWatcher() {watcher : make(chan context.Context, 1)mc.watcher watcherfinished : make(chan struct{})mc.finished finishedgo func() {for {var ctx context.Contextselect {case ctx -watcher:case -mc.closech:return}select {case -ctx.Done():mc.cancel(ctx.Err())case -finished:case -mc.closech:return}}}() }cancel方法将会调用cleanup方法进行连接的清理工作可以看到在cleanup中调用了conn.Close将这个物理连接关闭掉。因此我们在使用QueryContext或者ExecContext时候如果ctx设置了超时时间或者主动cancel那么意味着这个连接将会被断掉。极端情况下大量连接同时超时意味着连接都将失效此时再有新的请求打进来则会重新建立新的连接会有一定的连接建立开销。由于连接池是database/sql维护的因此这也只是客户端或者说mysql sdk层面的失效mysql server接收到的sql执行是不会被中断的。 // finish is called when the query has canceled. func (mc *mysqlConn) cancel(err error) {mc.canceled.Set(err)mc.cleanup() }// Closes the network connection and unsets internal variables. Do not call this // function after successfully authentication, call Close instead. This function // is called before auth or on auth failure because MySQL will have already // closed the network connection. func (mc *mysqlConn) cleanup() {if mc.closed.Swap(true) {return}// Makes cleanup idempotentclose(mc.closech)conn : mc.rawConnif conn nil {return}if err : conn.Close(); err ! nil {mc.log(err)}// This function can be called from multiple goroutines.// So we can not mc.clearResult() here.// Caller should do it if they are in safe goroutine. }在实际项目中为了减少使用层面的超时导致连接失效这种情况我们也可以对mysql server设置一个wait_timeout时间并且调用QueryContext/ExecContext的超时时间要小于这个wait_timeout时间这样则不会由于某业务中有慢查的sql导致ctx超时从而频繁触发连接的重新建立。 3、RegisterDialContext 最后我们再看看下这个静态方法RegisterDialContext这个方法主要作用就是注册对应的协议的dialFunc便于在进行数据库连接时候找到真正的地址。 // RegisterDialContext registers a custom dial function. It can then be used by the // network address mynet(addr), where mynet is the registered new network. // The current context for the connection and its address is passed to the dial function. func RegisterDialContext(net string, dial DialContextFunc) {dialsLock.Lock()defer dialsLock.Unlock()if dials nil {dials make(map[string]DialContextFunc)}dials[net] dial }// DialContextFunc is a function which can be used to establish the network connection. // Custom dial functions must be registered with RegisterDialContext type DialContextFunc func(ctx context.Context, addr string) (net.Conn, error)二、总结 本篇文章我们看了go-sql-driver的具体实现整体上来说go-sql-driver都是实现database/sql的driver.Driver接口直接对接mysql服务端支持mysql协议的收发包在api层面query/exec两个方法都提供了带ctx的方法带ctx和不带ctx的api使用差异一点小小的切换可能导致不断频繁建立连接与关闭连接等最后我们也根据实际的情况提出解决此问题的方案。
http://www.hkea.cn/news/14352398/

相关文章:

  • 爱网之家优化模型
  • wordpress导航栏字体义乌网站建设优化案例
  • 邢台网站设计怎么做鄂尔多斯建设局网站
  • mvc在网站开发中的应用优化设计答案六年级上册
  • 企业网站建设流程步骤做网站如何备案
  • 做公装的什么网站好dz 一步一步教你做网站
  • 网站添加手机站wordpress手机图片站
  • 网站开发必须要要掌握的语言网站策划书模板大全
  • 佳木斯网站建设公司网站开发者工具
  • 深圳网站建设公司建设成都精品网站建设
  • 做网站与运营一般多少钱查询网站最新域名
  • 网站的制作视频网站建设是设
  • 网站建设写代码自己怎么创业做网站菠菜什么意思
  • 网站开发赚钱吗 知乎黑龙江网站备案管理局
  • 企业网站搜索引擎拓客哪个是网站建设里面的
  • 贵州网站集约化建设自然志wordpress免费
  • 大连网站设计破解网站后台账号密码
  • 公司设计网站多少钱网站开发json解析
  • 做网站维护的收入怎么确认精美驾校企业网站模板
  • 网站建设步骤完整版厦门市建设局网站摇号
  • 怎么做网站安全检测中国十大搜索引擎网站
  • 网站开发可选的方案有影视类网站建设
  • 广州金将令做网站怎么样长沙房产信息网查询
  • 做外贸阿里巴巴有哪些网站怎么建立免费个人网站
  • 工业智能科技网站设计大连模板建站系统
  • 媒体网站开发访问wap网站
  • 青岛大学春季高考有网站建设吗个人网站设计首页
  • python爬虫做网站淘宝运营培训内容
  • 做的漂亮的商务网站移动网络服务电话
  • 手机网站开发指南欧派网站谁做的