前言

在前一段时间遇见过这样一件事,我们的部分服务要部署在两个机房,而且两个机房并不互通,但是两个服务要通过mysql数据库实现配合工作,从无到有想到了两种实现方式。
这里注明一点的是mysql是与主服务部署一起的,而子服务是单独在另一个机房,因为一些特殊原因,两个机房并不能直接互相访问,但是两个机房部署了proxy代理和socks5代理。
在其间想到了两个解决方法,一是子服务的所有sql操作均放在主服务侧,然后子服务的curd操作通过GET和POST请求主服务,然后主服务实现具体的curd,但是这种方式对以后的服务变更并不太友好,可能只是一个小的修改就需要同时改变二者,第二种方式是子服务通过socks5直接连接mysql服务,这样只需要考虑延迟就可以直接无感使用,而且数据量并非过大时,这是最好的处理手段。只需要将最后的处理结果导入mysql就可以了。

proxy代理方式

这种方式仅是在进行http请求时增加了代理,其本质与普通http请求并无不同。
下面是实例代码

package mainimport ("crypto/tls""fmt""io/ioutil""net/http""net/url""time"
)/*1. 普通请求
*/
func RequestGeneral() {webUrl := "https://www.qiniu.com/"resp, err := http.Get(webUrl)if err != nil {fmt.Println(err)return}time.Sleep(time.Second * 3)defer resp.Body.Close()body, _ := ioutil.ReadAll(resp.Body)fmt.Println(string(body))
}
/*1. 代理请求2. 跳过https不安全验证
*/
func RequestNoHttps(webUrl, proxyUrl string) {// webUrl := "https://www.qiniu.com/"// proxyUrl := "http://xxx.xxx.xx.xx:xxx" //proxy代理的 ip:portproxy, _ := url.Parse(proxyUrl)tr := &http.Transport{Proxy:           http.ProxyURL(proxy),TLSClientConfig: &tls.Config{InsecureSkipVerify: true},}client := &http.Client{Transport: tr,Timeout:   time.Second * 5, //超时时间}resp, err := client.Get(webUrl)if err != nil {fmt.Println("出错了", err)return}defer resp.Body.Close()body, _ := ioutil.ReadAll(resp.Body)fmt.Println(string(body))
}func main() {webUrl := "https://www.qiniu.com/"proxyUrl := "http://xxx.xxx.xx.xx:xxx" //proxy代理的 ip:portRequestNoHttps(webUrl, proxyUrl)
}

不难发现只是在创建http请求时,在http.Transport内增加了proxy字段,并将对应的代理地址赋值进去,就可以实现http请求的代理。
但是这种方式在我们的服务内是并不是最优解,所以并未使用。

socks5代理

这种方式是我们最后使用的方案。

package dbximport ("context""fmt"proxy_mysql "github.com/go-sql-driver/mysql""github.com/sirupsen/logrus""golang.org/x/net/proxy""log""net""time"gorm_mysql "gorm.io/driver/mysql""gorm.io/gorm"
)type Config struct {DbUser   string `yaml:"dbUser"`DbPass   string `yaml:"dbPass"`DbUrl    string `yaml:"dbUrl"`DbPort   string `yaml:"dbPort"`DbSchema string `yaml:"dbSchema"`Dbsocks  string `yaml:"dbSocks"`
}// 使用自定义socks5代理拨号
func InitDBProxyUrl(con Config) string {logrus.Info("InitDBProxyUrl get Dbsocks:", conf.Dbsocks)dialer, err := proxy.SOCKS5("tcp", conf.Dbsocks, nil, proxy.Direct)checkErrFatal(err)// 此处自定义一个拨号(代理)proxy_mysql.RegisterDialContext("fixieDial", func(ctx context.Context, addr string) (net.Conn, error) {return dialer.Dial("tcp", addr)})dbUrl = fmt.Sprintf("%s:%s@fixieDial(%s:%s)/%s?parseTime=true&loc=Local&charset=utf8mb4",conf.dbUser,conf.dbPass,conf.dbUrl,conf.dbPort,conf.dbSchema,)return dbUrl
}// 普通tcp拨号
func InitDBUrl(con Config) string {dbUrl = fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?parseTime=true&loc=Local&charset=utf8mb4",conf.dbUser,conf.dbPass,conf.dbUrl,conf.dbPort,conf.dbSchema,)return dbUrl
}var db *gorm.DBfunc GetDb() *gorm.DB {return db
}// 使用socks5代理模式
func OpenProxyDB() {dbUrl := InitDBProxyUrl() // 使用自定义socks5代理var err errordb, err = gorm.Open(gorm_mysql.Open(dbUrl), &gorm.Config{})checkErrFatal(err)db.Debug()sqlDB, err := db.DB()checkErrFatal(err)sqlDB.SetMaxIdleConns(10)sqlDB.SetMaxOpenConns(10)sqlDB.SetConnMaxLifetime(time.Hour)
}func checkErrFatal(err error) {if err != nil {log.Fatalln(err)}
}

这里先是使用了"golang.org/x/net/proxy"模块,根据传入的socks5代理的IP和端口返回自定义代理拨号方法,然后利用"github.com/go-sql-driver/mysql"将得到的自定义方法注册进系统,然后使用"gorm.io/driver/mysql"驱动链接mysql,这里使用了两个mysql驱动,一个是为了注册socks5代理拨号,一个是为了使用gorm连接mysql。

虽然"github.com/go-sql-driver/mysql"本身也是可以直接连接mysql的,但是"gorm.io/driver/mysql"是为了使用gorm。

至于二者为什么是可以混合使用的,这不清楚,但是应该是上下文的关系,或者说是将自定义拨号方法临时注册进系统内部了。

因为如果不进行注册是无法这样使用的,而且使用tcpdump指令,也是可以检测到本机ip端口和代理ip端口之间的数据通信过程。

23:09:46.825460 IP xx.xx.xx.xx.xxxx > yy.yy.yy.yy.yyyy0: Flags [R.], seq 0, ack 3037942227, win 0, length 0
23:09:46.833522 IP yy.yy.yy.yy.yyyy2 > xx.xx.xx.xx.xxxx: Flags [S], seq 1928785681, win 29200, options [mss 1460,nop,nop,sackOK,nop,wscale 7], length 0
23:09:46.833524 IP yy.yy.yy.yy.yyyy1 > xx.xx.xx.xx.xxxx: Flags [S], seq 155678182, win 29200, options [mss 1460,nop,nop,sackOK,nop,wscale 7], length 0
23:09:46.833579 IP yy.yy.yy.yy.yyyy4 > xx.xx.xx.xx.xxxx: Flags [S], seq 1472247145, win 29200, options [mss 1460,nop,nop,sackOK,nop,wscale 7], length 0
23:09:46.833581 IP xx.xx.xx.xx.xxxx > yy.yy.yy.yy.yyyy2: Flags [R.], seq 0, ack 1928785682, win 0, length 0
23:09:46.833634 IP xx.xx.xx.xx.xxxx > yy.yy.yy.yy.yyyy4: Flags [R.], seq 0, ack 1472247146, win 0, length 0
23:09:46.833751 IP yy.yy.yy.yy.yyyy5 > xx.xx.xx.xx.xxxx: Flags [S], seq 2981254641, win 29200, options [mss 1460,nop,nop,sackOK,nop,wscale 7], length 0
23:09:46.833968 IP yy.yy.yy.yy.yyyy6 > xx.xx.xx.xx.xxxx: Flags [S], seq 1755001897, win 29200, options [mss 1460,nop,nop,sackOK,nop,wscale 7], length 0

这里为了安全就不暴露ip和具体端口了,但是依然可以看出二者之间的数据交换过程。
有需要的可以去建立个socks5代理环境测试下。

如下命令可以设置系统的代理为socks5

export http_proxy=socks5://xx.xx.xx.xx:xxxx

如下命令可以设置系统的代理为proxy

export http_proxy=http://yy.yy.yy.yy:yyyy

然后搞个curl或者什么来测试下,能找到这个文章说明这里应该对你不是难事,而且有测试条件。

golang 通过socks5代理连接mysql(gorm)相关推荐

  1. golang 使用socks代理 连接远程ssh服务器

    使用x/net/proxy包,如下所示: package mainimport ("log""golang.org/x/crypto/ssh""gol ...

  2. golang连接mysql操作示例增删改查(已经测试)

    golang本身没有提供连接mysql的驱动,但是定义了标准接口供第三方开发驱动.这里连接mysql可以使用第三方库,第三方库推荐使用https://github.com/Go-SQL-Driver/ ...

  3. go语言代码连接mysql_【mysql】golang连接mysql操作示例增删改查

    golang本身没有提供连接mysql的驱动,但是定义了标准接口供第三方开发驱动.这里连接mysql可以使用第三方库,第三方库推荐使用https://github.com/Go-SQL-Driver/ ...

  4. golang连接mysql操作示例增删改查

    golang本身没有提供连接mysql的驱动,但是定义了标准接口供第三方开发驱动.这里连接mysql可以使用第三方库,第三方库推荐使用https://github.com/Go-SQL-Driver/ ...

  5. golag mysql_golang连接mysql操作示例增删改查

    golang本身没有提供连接mysql的驱动,但是定义了标准接口供第三方开发驱动.这里连接mysql可以使用第三方库,第三方库推荐使用https://github.com/Go-SQL-Driver/ ...

  6. 安卓socks5代理客户端_内网Mysql代理浅析

    更多全球网络安全资讯尽在邑安全 www.eansec.com 0x00 使用场景 在渗透测试中,由于防火墙的原因,目标主机可能只开放了某一个业务端口,其余反连和直连的端口被全部禁用了,借用mssqlp ...

  7. 猜谜游戏、彩云词典爬虫、SOCKS5代理的 Go(Golang) 小实践,附带全代码解释

    猜谜游戏在编程语言实践都已经和 HelloWord 程序成为必不可少的新手实践环节,毕竟,它能够让我们基本熟悉 for 循环.变量定义.打印.if else 语句等等的使用,当我们基本熟悉该语言基础之 ...

  8. 用golang写socks5代理服务器2-ssh远程代理

    上次用golang来实现本地socks5代理,然而使用代理当然是为了和谐上网,所以这次来介绍用ssh来实现远程代理,用到官方ssh包 golang.org/x/crypto/ssh 用golang连接 ...

  9. go语言服务器连接mysql,golang中连接mysql数据库

    golang中连接mysql数据库,需要使用一个第三方类库github.com/go-sql-driver/mysql,在这个类库中就实现了mysql的连接池,并且只需要设置两个参数就可以实现 一般连 ...

最新文章

  1. 把window中换行符(^M)改为linux的换行符(\r)
  2. python函数映射教学,Python 序列与映射的解包操作
  3. GDCM:gdcm::Dumper的测试程序
  4. LeetCode 921. 使括号有效的最少添加(栈)
  5. 论文小综 | Using External Knowledge on VQA
  6. Uep的ajaxform和ajaxgrid组件获取数据源
  7. jQuery源码解读三选择器
  8. 决定薪资高低的到底什么?
  9. 关于使用Navicat
  10. python面向过程实践汉诺塔_递归汉诺塔-和递归汉诺塔相关的内容-阿里云开发者社区...
  11. linux asm 使用情况,在Linux 6上使用UDEV解决 ASM存储设备问题( single path)
  12. vue封装echarts示例
  13. Java如何对ArrayList里的元素排序
  14. 第一道web类CTF题——一起来撸猫
  15. Pascal VOCdata数据集读取(pytorch)
  16. 2020 android平板推荐,2020年2000元左右的平板哪一款好?2000元左右的平板推荐
  17. AUTOMATE THE BORING STUFF WITH PYTHON读书笔记 - 第19章:MANIPULATING IMAGES
  18. 判断输入数是奇数还是偶数
  19. 强大的虚拟音频器:Loopback for Mac
  20. 2022 年顶级商业和 IT 认证课程,让你获得职业信誉,提升竞争力

热门文章

  1. UWB高精度定位技术原理与应用分析
  2. php隐藏指定id的div,CSS_纯css3显示隐藏一个div特效的具体实现,复制代码代码如下: !DOCTYPE H - phpStudy...
  3. 怎么下载 GPT-3 模型
  4. odoo 创建向导wizard页面
  5. python用户名和密码登录_selenium登录账号密码
  6. 模仿360安全卫士项目笔记7
  7. 大学计算机英语句子,关于大学英语句子大全
  8. Sensor Flicker
  9. Xceed Ultimate Suite 2021.3
  10. 无领导群面中评分标准(一)