mysql sock golang_golang thrift 总结一下网络上的一些坑
我们以hello world来大概分析一下golang中的thrift包,并且扒一扒网络上有关thrift的一些坑
查看源码,服务器定义如下:(详见simple_server.go文件)
type TSimpleServer struct{
quit chanstruct{}
stopped int64
processorFactory TProcessorFactory //实质是一个handler,用来相应客户端的请求
serverTransport TServerTransport //实质是一个socket
inputTransportFactory TTransportFactory //实质是传输协议的具体操作类(详细可见transport.go文件中TTransport结构体)
outputTransportFactory TTransportFactory //
inputProtocolFactory TProtocolFactory //实质是传输协议(有compact、simplejson、json、binary四种协议,默认是binary)
tputProtocolFactory TProtocolFactory //
}
在go语言中,创建一个thrift服务器有三种方法:(详见simple_server.go文件)
func NewTSimpleServer2(processor TProcessor, serverTransport TServerTransport) *TSimpleServer {returnNewTSimpleServerFactory2(NewTProcessorFactory(processor), serverTransport)
}
func NewTSimpleServer4(processor TProcessor, serverTransport TServerTransport, transportFactory TTransportFactory, protocolFactory TProtocolFactory)*TSimpleServer {returnNewTSimpleServerFactory4(NewTProcessorFactory(processor),
serverTransport,
transportFactory,
protocolFactory,
)
}
func NewTSimpleServer6(processor TProcessor, serverTransport TServerTransport, inputTransportFactory TTransportFactory, outputTransportFactory TTransportFactory, inputProtocolFactory TProtocolFactory, outputProtocolFactory TProtocolFactory)*TSimpleServer {returnNewTSimpleServerFactory6(NewTProcessorFactory(processor),
serverTransport,
inputTransportFactory,
outputTransportFactory,
inputProtocolFactory,
outputProtocolFactory,
)
}
这三个函数分别调用了工厂函数
NewTSimpleServerFactory2;
NewTSimpleServerFactory4;
NewTSimpleServerFactory6;
func NewTSimpleServerFactory2(processorFactory TProcessorFactory, serverTransport TServerTransport) *TSimpleServer {returnNewTSimpleServerFactory6(processorFactory,
serverTransport,
NewTTransportFactory(),
NewTTransportFactory(),
NewTBinaryProtocolFactoryDefault(),
NewTBinaryProtocolFactoryDefault(),
)
}
func NewTSimpleServerFactory4(processorFactory TProcessorFactory, serverTransport TServerTransport, transportFactory TTransportFactory, protocolFactory TProtocolFactory)*TSimpleServer {returnNewTSimpleServerFactory6(processorFactory,
serverTransport,
transportFactory,
transportFactory,
protocolFactory,
protocolFactory,
)
}
func NewTSimpleServerFactory6(processorFactory TProcessorFactory, serverTransport TServerTransport, inputTransportFactory TTransportFactory, outputTransportFactory TTransportFactory, inputProtocolFactory TProtocolFactory, outputProtocolFactory TProtocolFactory)*TSimpleServer {return &TSimpleServer{
processorFactory: processorFactory,
serverTransport: serverTransport,
inputTransportFactory: inputTransportFactory,
outputTransportFactory: outputTransportFactory,
inputProtocolFactory: inputProtocolFactory,
outputProtocolFactory: outputProtocolFactory,
quit: make(chanstruct{}, 1),
}
}
好啦!现在假如我们需要创建一个以二进制协议传输的thrift服务器,那么可以用如下代码简单实现:
serverTransport, err := thrift.NewTServerSocket("127.0.0.1:8808")if err !=nil {
fmt.Println("Error!", err)return}
handler := &rpcService{}
processor :=rpc.NewRpcServiceProcessor(handler)
server :=thrift.NewTSimpleServer2(processor, serverTransport)
fmt.Println("thrift server in localhost")
server.Serve()
另外我在网上查看这方面资料的时候,发现大家都用的NewTSimpleServer4这个函数,然后自己又创建一遍NewTTransportFactory以及NewTBinaryProtocolFactoryDefault。
现在我们分析一下源码,发现此举实乃多此一举。这是第一坑。
接下来说说如何用golang thrift编写客户端,查看网络上的一些写法,发现根本用不了,服务器会阻塞住!还是从源码来分析:
在thrift自动生成的代码中,会生成一个关于客户端的示例。
//Autogenerated by Thrift Compiler (0.9.3)//DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
package main
import ("flag"
"fmt"
"git.apache.org/thrift.git/lib/go/thrift"
"math"
"net"
"net/url"
"os"
"strconv"
"strings"
"vic/rpc")
func Usage() {
fmt.Fprintln(os.Stderr,"Usage of", os.Args[0], "[-h host:port] [-u url] [-f[ramed]] function [arg1 [arg2...]]:")
flag.PrintDefaults()
fmt.Fprintln(os.Stderr,"\nFunctions:")
fmt.Fprintln(os.Stderr,"Video request(string vid, string cid, string platform, string url, string clientVersion)")
fmt.Fprintln(os.Stderr)
os.Exit(0)
}
func main() {
flag.Usage=Usagevar host string
var port int
var protocol string
var urlString string
var framed bool
var useHttp bool
varparsedUrl url.URLvartrans thrift.TTransport
_=strconv.Atoi
_=math.Abs
flag.Usage=Usage
flag.StringVar(&host, "h", "localhost", "Specify host and port")
flag.IntVar(&port, "p", 9090, "Specify port")
flag.StringVar(&protocol, "P", "binary", "Specify the protocol (binary, compact, simplejson, json)")
flag.StringVar(&urlString, "u", "", "Specify the url")
flag.BoolVar(&framed, "framed", false, "Use framed transport")
flag.BoolVar(&useHttp, "http", false, "Use http")
flag.Parse()if len(urlString) > 0{
parsedUrl, err :=url.Parse(urlString)if err !=nil {
fmt.Fprintln(os.Stderr,"Error parsing URL:", err)
flag.Usage()
}
host=parsedUrl.Host
useHttp= len(parsedUrl.Scheme) <= 0 || parsedUrl.Scheme == "http"}else ifuseHttp {
_, err := url.Parse(fmt.Sprint("http://", host, ":", port))if err !=nil {
fmt.Fprintln(os.Stderr,"Error parsing URL:", err)
flag.Usage()
}
}
cmd := flag.Arg(0)varerr errorifuseHttp {
trans, err=thrift.NewTHttpClient(parsedUrl.String())
}else{
portStr :=fmt.Sprint(port)if strings.Contains(host, ":") {
host, portStr, err=net.SplitHostPort(host)if err !=nil {
fmt.Fprintln(os.Stderr,"error with host:", err)
os.Exit(1)
}
}
trans, err=thrift.NewTSocket(net.JoinHostPort(host, portStr))if err !=nil {
fmt.Fprintln(os.Stderr,"error resolving address:", err)
os.Exit(1)
}ifframed {
trans=thrift.NewTFramedTransport(trans)
}
}if err !=nil {
fmt.Fprintln(os.Stderr,"Error creating transport", err)
os.Exit(1)
}
defer trans.Close()varprotocolFactory thrift.TProtocolFactoryswitchprotocol {case "compact":
protocolFactory=thrift.NewTCompactProtocolFactory()break
case "simplejson":
protocolFactory=thrift.NewTSimpleJSONProtocolFactory()break
case "json":
protocolFactory=thrift.NewTJSONProtocolFactory()break
case "binary", "":
protocolFactory=thrift.NewTBinaryProtocolFactoryDefault()break
default:
fmt.Fprintln(os.Stderr,"Invalid protocol specified:", protocol)
Usage()
os.Exit(1)
}
client :=rpc.NewVideoServiceClientFactory(trans, protocolFactory)if err := trans.Open(); err !=nil {
fmt.Fprintln(os.Stderr,"Error opening socket to", host, ":", port, " ", err)
os.Exit(1)
}switchcmd {case "request":if flag.NArg()-1 != 5{
fmt.Fprintln(os.Stderr,"Request requires 5 args")
flag.Usage()
}
argvalue0 := flag.Arg(1)
value0 :=argvalue0
argvalue1 := flag.Arg(2)
value1 :=argvalue1
argvalue2 := flag.Arg(3)
value2 :=argvalue2
argvalue3 := flag.Arg(4)
value3 :=argvalue3
argvalue4 := flag.Arg(5)
value4 :=argvalue4
fmt.Print(client.Request(value0, value1, value2, value3, value4))
fmt.Print("\n")break
case "":
Usage()break
default:
fmt.Fprintln(os.Stderr,"Invalid function", cmd)
}
}
View Code
我们一部分一部分来分析分析:
flag.Usage =Usagevar host string
var port int
var protocol string
var urlString string
var framed bool
var useHttp bool
varparsedUrl url.URLvartrans thrift.TTransport
_=strconv.Atoi
_=math.Abs
flag.Usage=Usage
flag.StringVar(&host, "h", "localhost", "Specify host and port")
flag.IntVar(&port, "p", 9090, "Specify port")
flag.StringVar(&protocol, "P", "binary", "Specify the protocol (binary, compact, simplejson, json)")
flag.StringVar(&urlString, "u", "", "Specify the url")
flag.BoolVar(&framed, "framed", false, "Use framed transport")
flag.BoolVar(&useHttp, "http", false, "Use http")
flag.Parse()
这些代码是设置了一些程序的启动命令,例如默认地址是loacalhost,我们可以根据client.exe -h xxx.xxx.xxx.xxx之类的命令来修改
我们发现这些代码都不是我们需要的,pass,继续看
if len(urlString) > 0{
parsedUrl, err :=url.Parse(urlString)if err !=nil {
fmt.Fprintln(os.Stderr,"Error parsing URL:", err)
flag.Usage()
}
host=parsedUrl.Host
useHttp= len(parsedUrl.Scheme) <= 0 || parsedUrl.Scheme == "http"}else ifuseHttp {
_, err := url.Parse(fmt.Sprint("http://", host, ":", port))if err !=nil {
fmt.Fprintln(os.Stderr,"Error parsing URL:", err)
flag.Usage()
}
}
cmd := flag.Arg(0)varerr errorifuseHttp { trans, err = thrift.NewTHttpClient(parsedUrl.String())}else{
portStr :=fmt.Sprint(port)if strings.Contains(host, ":") {
host, portStr, err=net.SplitHostPort(host)if err !=nil {
fmt.Fprintln(os.Stderr,"error with host:", err)
os.Exit(1)
}
}
trans, err= thrift.NewTSocket(net.JoinHostPort(host, portStr))
if err !=nil {
fmt.Fprintln(os.Stderr,"error resolving address:", err)
os.Exit(1)
}ifframed {
trans=thrift.NewTFramedTransport(trans)
}
}
这部分主要作用是解析url参数,从中取得host以及port。并且用于生成一个TTransport,上面红线加粗的函数定义在源码中如下:
func NewTHttpClient(urlstr string) (TTransport, error) {returnNewTHttpClientWithOptions(urlstr, THttpClientOptions{})
}
func NewTSocket(hostPortstring) (*TSocket, error) {return NewTSocketTimeout(hostPort, 0)
}
细心的朋友们可能发现了端倪,第二个函数的返回值是一个TSocket指针,并不是TTransport,是不是有啥问题?不急,我们看看这两个结构体的定义就知道了:
type TTransport interface{
io.ReadWriteCloser
Flusher
ReadSizeProvider//Opens the transport for communication
Open() error//Returns true if the transport is open
IsOpen() bool}
原来TTransport是一个接口类型,而TSocket则实现了该接口!
目前为止,我们获得了创建客户端所需要的关键代码:
trans, err =thrift.NewTHttpClient(parsedUrl.String())
trans, err= thrift.NewTSocket(net.JoinHostPort(host, portStr))
OK,继续分析示例!
varprotocolFactory thrift.TProtocolFactoryswitchprotocol {case "compact":
protocolFactory=thrift.NewTCompactProtocolFactory()break
case "simplejson":
protocolFactory=thrift.NewTSimpleJSONProtocolFactory()break
case "json":
protocolFactory=thrift.NewTJSONProtocolFactory()break
case "binary", "":
protocolFactory=thrift.NewTBinaryProtocolFactoryDefault()break
default:
fmt.Fprintln(os.Stderr,"Invalid protocol specified:", protocol)
Usage()
os.Exit(1)
}
client := rpc.NewVideoServiceClientFactory(trans, protocolFactory)if err := trans.Open(); err !=nil {
fmt.Fprintln(os.Stderr,"Error opening socket to", host, ":", port, " ", err)
os.Exit(1)
}
switch语句是根据我们所输入的参数,选择传输协议。最后通过NewVideoServiceClientFactory函数 完成客户端的创建
最后,总结一下,假如我们要创建一个以二进制为传输协议,那么我们可以编写如下代码来完成:
transport, err := thrift.NewTSocket(net.JoinHostPort("127.0.0.1", "8808"))if err !=nil {
fmt.Fprintln(os.Stderr,"error resolving address:", err)
os.Exit(1)
}
protocolFactory :=thrift.NewTBinaryProtocolFactoryDefault()
client :=NewRpcServiceClientFactory(transport, protocolFactory)if err := transport.Open(); err !=nil {
fmt.Fprintln(os.Stderr,"Error opening socket to 127.0.0.1:8808", " ", err)
os.Exit(1)
}
defer transport.Close()
res, _ := client.SayHi(“World”)
有疑问加站长微信联系(非本文作者)
mysql sock golang_golang thrift 总结一下网络上的一些坑相关推荐
- mysql socket错误_解决Can’t connect to local MySQL server through socket ‘/tmp/mysql.sock’错误...
晚上清理mysql日志,强制重启了下mysql,然后mysql就登陆不上了... 以下方法来自网络,可以使用,已试. 刚安装完mysql,进行运行测试,报Can't connect to local ...
- qc linux mysql 安装教程_mysql5.7在centos上安装的完整教程以及相关的“坑”
安装前的准备 Step1: 如果你系统已经有mysql,如一般centos自带mysql5.1系列,那么你需要删除它,先检查一下系统是否自带mysql yum list installed | gre ...
- MySQL跑在CentOS 6 和 7上的性能比较
点击蓝色"程序猿DD"关注我哟 加个"星标",不忘签到哦 来源:yangyidba 关注我,回复口令获取可获取独家整理的学习资料: - 001 :领取<S ...
- mysql.sock 文件解析
在观察MySQL本地连接的时候,发现对mysql.sock是个啥我不明白,于是我提出了一个问题:mysql.sock到底存了什么信息? 根据多方查资料和自我思考,我有了自己的一些认识和结论,但结论并不 ...
- mysql socket错误处理_解决Can’t connect to local MySQL server through socket ‘/tmp/mysql.sock’错误...
晚上清理mysql日志,强制重启了下mysql,然后mysql就登陆不上了... 以下方法来自网络,可以使用,已试. 刚安装完mysql,进行运行测试,报Can't connect to local ...
- mysql.sock的问题
关于mysql.sock的一些问题: 连接数据库时报错:Can 't connect to local MySQL server through socket '/tmp/mysql.sock '(2 ...
- MySQL 系列(一) 生产标准线上环境安装配置案例及棘手问题解决
MySQL 系列(一) 生产标准线上环境安装配置案例及棘手问题解决 一.简介 MySQL是最流行的开放源码SQL数据库管理系统,它是由MySQL AB公司开发.发布并支持的.有以下特点: MySQL是 ...
- xampp mysql.sock_解决xampp自启动和mysql.sock问题
装了ubuntu好长一段时间了,都没去用,国庆的时候折腾了下,配置了一些基本的开发环境,一上手就感觉喜欢上了ubuntu,说不上为什么.为了搞本地的测试php测试环境而装了xampp,安装超简单,但是 ...
- mysql.sock的作用
这个mysql.sock应该是mysql的主机和客户机在同一host上的时候,使用unix domain socket做为通讯协议的载体,它比tcp快.通常遇到这个问题的原因就是你的mysql ser ...
最新文章
- 老李推荐:第3章3节《MonkeyRunner源码剖析》脚本编写示例: MonkeyImage API使用示例 1...
- linux变量inode,linux字符cdev和Inode的关系
- Python学习心得第一周-03练习1
- 上海科技大学ACL2018高分论文:混合高斯隐向量文法
- 粤教版管理计算机中的文件教案,最新粤教版初中信息技术第一册教案(全册).docx...
- cocos2d-x 中文 乱码问题
- Angular应用里的tsconfig.app.json
- 数据结构与算法--1.整型变量值互换
- django-配置静态文件路径
- 阿德莱德大学招聘博士后研究员
- 张大奕网店关联公司被行政处罚:因以不合格产品冒充合格产品
- 独家对话华为王成录:手机 HarmonyOS 开发者 Beta 版将如约而至
- 复赛全省第一,决赛发挥失误,他是如何挽回局势,保送北大的?
- 清单软件217天使用总结
- PCB线宽与电阻的计算
- JAVA金额大小写转换
- 短视频SDK技术选型
- AI基础原理篇(一)
- 软考中级 真题 2016年下半年 系统集成项目管理工程师 基础知识 上午试卷
- xmind各版本区别_制图心法 | 一文读懂XMind 8 和 XMind: ZEN的真正区别
热门文章
- python中对数组合并的方法
- Python基础教程:list深拷贝和浅拷贝
- Python中的高效的集合操作
- Python技巧:不要在for与while循环后写else块
- python函数注释,参数后面加冒号:,函数后面的箭头→是什么?
- Python语言防坑小技巧
- python装饰器的使用场景
- 性能不同的服务器可以组成云,多个服务器组成云
- linux 汇编 gdb报错:Invalid register `eip‘(64位系统没有eip只有rip寄存器)
- yunyang tensorfow-yolo3 训练时权重文件消失的原因和解决办法(max_to_keep)