Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in
Toggle navigation
G
getty
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wei.xuan
getty
Commits
f16d6d53
Commit
f16d6d53
authored
Jul 30, 2018
by
AlexStocks
Browse files
Options
Browse Files
Download
Plain Diff
merge rpc
parents
11c18d3f
43189243
Show whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
573 additions
and
273 deletions
+573
-273
README.md
README.md
+15
-1
client.go
rpc/client.go
+94
-182
codec.go
rpc/codec.go
+46
-56
config.go
rpc/config.go
+8
-1
client.go
rpc/example/client/client.go
+9
-5
client_config.toml
rpc/example/client/client_config.toml
+10
-1
server_config.toml
rpc/example/server/server_config.toml
+2
-2
listener.go
rpc/listener.go
+12
-12
pool.go
rpc/pool.go
+349
-0
readwriter.go
rpc/readwriter.go
+3
-1
server.go
rpc/server.go
+25
-12
No files found.
README.md
View file @
f16d6d53
...
@@ -16,7 +16,21 @@ You can get code example in https://github.com/AlexStocks/getty-examples.
...
@@ -16,7 +16,21 @@ You can get code example in https://github.com/AlexStocks/getty-examples.
## RPC
## RPC
Support Json and Protobuf.
A open source, Go based, RPC framework.
Feature list:
-
1 Transport: TCP(√), UDP, Websocket
-
2 Codec: ProtoBuf(√), JSON(√)
-
3 Service Discovery: Service Publish(√), Service Watch(√), Service Notify(√)
-
4 Registry: ZooKeeper(√), Etcd(x)
-
5 Strategy: Failover(√), Failfast(√)
-
6 Load Balance: Random(√), RoundRobin(√)
-
7 Metrics: Invoke Statistics(x), User Auth(x)
##
## LICENCE
## LICENCE
...
...
rpc/client.go
View file @
f16d6d53
...
@@ -3,20 +3,21 @@ package rpc
...
@@ -3,20 +3,21 @@ package rpc
import
(
import
(
"fmt"
"fmt"
"math/rand"
"math/rand"
"
net
"
"
strings
"
"sync"
"sync"
"sync/atomic"
"time"
"time"
)
)
import
(
import
(
jerrors
"github.com/juju/errors"
)
import
(
"github.com/AlexStocks/getty"
"github.com/AlexStocks/getty"
"github.com/AlexStocks/goext/database/filter"
"github.com/AlexStocks/goext/database/filter/pool"
"github.com/AlexStocks/goext/database/registry"
"github.com/AlexStocks/goext/database/registry/etcdv3"
"github.com/AlexStocks/goext/database/registry/zookeeper"
"github.com/AlexStocks/goext/net"
"github.com/AlexStocks/goext/net"
log
"github.com/AlexStocks/log4go"
"github.com/AlexStocks/goext/sync/atomic"
jerrors
"github.com/juju/errors"
)
)
var
(
var
(
...
@@ -31,92 +32,95 @@ func init() {
...
@@ -31,92 +32,95 @@ func init() {
type
Client
struct
{
type
Client
struct
{
conf
*
ClientConfig
conf
*
ClientConfig
lock
sync
.
RWMutex
pool
*
gettyRPCClientConnPool
sessions
[]
*
rpcSession
sequence
gxatomic
.
Uint64
gettyClient
getty
.
Client
codecType
SerializeType
sequence
uint64
pendingLock
sync
.
RWMutex
pendingLock
sync
.
RWMutex
pendingResponses
map
[
uint64
]
*
PendingResponse
pendingResponses
map
[
uint64
]
*
PendingResponse
// registry
registry
gxregistry
.
Registry
sa
gxregistry
.
ServiceAttr
filter
gxfilter
.
Filter
}
}
func
NewClient
(
confFile
string
)
*
Client
{
func
NewClient
(
confFile
string
)
(
*
Client
,
error
)
{
conf
:=
loadClientConf
(
confFile
)
conf
:=
loadClientConf
(
confFile
)
c
:=
&
Client
{
c
:=
&
Client
{
pendingResponses
:
make
(
map
[
uint64
]
*
PendingResponse
),
pendingResponses
:
make
(
map
[
uint64
]
*
PendingResponse
),
conf
:
conf
,
conf
:
conf
,
gettyClient
:
getty
.
NewTCPClient
(
getty
.
WithServerAddress
(
gxnet
.
HostAddress
(
conf
.
ServerHost
,
conf
.
ServerPort
)),
getty
.
WithConnectionNumber
((
int
)(
conf
.
ConnectionNum
)),
),
codecType
:
JSON
,
}
c
.
gettyClient
.
RunEventLoop
(
c
.
newSession
)
idx
:=
1
for
{
idx
++
if
c
.
isAvailable
()
{
break
}
}
c
.
pool
=
newGettyRPCClientConnPool
(
c
,
conf
.
PoolSize
,
time
.
Duration
(
int
(
time
.
Second
)
*
conf
.
PoolTTL
))
if
idx
>
12000
{
if
len
(
c
.
conf
.
Registry
.
Addr
)
==
0
{
panic
(
"failed to create client in 2 minutes"
)
if
conf
.
codecType
=
String2CodecType
(
conf
.
CodecType
);
conf
.
codecType
==
gettyCodecUnknown
{
return
nil
,
jerrors
.
New
(
fmt
.
Sprintf
(
ErrIllegalConf
+
"codec type %s"
,
conf
.
CodecType
))
}
}
time
.
Sleep
(
1e6
)
if
conf
.
ServerPort
==
0
{
return
nil
,
jerrors
.
New
(
fmt
.
Sprintf
(
ErrIllegalConf
+
"both registry addr and ServerPort is nil"
))
}
}
log
.
Info
(
"client init ok"
)
return
c
_
,
err
:=
c
.
pool
.
getConn
(
conf
.
CodecType
,
gxnet
.
HostAddress
(
conf
.
ServerHost
,
conf
.
ServerPort
))
}
func
(
c
*
Client
)
SetCodecType
(
st
SerializeType
)
{
return
c
,
jerrors
.
Trace
(
err
)
c
.
codecType
=
st
}
}
func
(
c
*
Client
)
newSession
(
session
getty
.
Session
)
error
{
var
err
error
var
(
var
registry
gxregistry
.
Registry
ok
bool
addrList
:=
strings
.
Split
(
c
.
conf
.
Registry
.
Addr
,
","
)
tcpConn
*
net
.
TCPConn
switch
c
.
conf
.
Registry
.
Type
{
case
"etcd"
:
registry
,
err
=
gxetcd
.
NewRegistry
(
gxregistry
.
WithAddrs
(
addrList
...
),
gxregistry
.
WithTimeout
(
time
.
Duration
(
int
(
time
.
Second
)
*
c
.
conf
.
Registry
.
KeepaliveTimeout
)),
gxregistry
.
WithRoot
(
c
.
conf
.
Registry
.
Root
),
)
)
case
"zookeeper"
:
if
c
.
conf
.
GettySessionParam
.
CompressEncoding
{
registry
,
err
=
gxzookeeper
.
NewRegistry
(
session
.
SetCompressType
(
getty
.
CompressZip
)
gxregistry
.
WithAddrs
(
addrList
...
),
gxregistry
.
WithTimeout
(
time
.
Duration
(
int
(
time
.
Second
)
*
c
.
conf
.
Registry
.
KeepaliveTimeout
)),
gxregistry
.
WithRoot
(
c
.
conf
.
Registry
.
Root
),
)
default
:
return
nil
,
jerrors
.
New
(
fmt
.
Sprintf
(
ErrIllegalConf
+
"registry type %s"
,
c
.
conf
.
Registry
.
Type
))
}
}
if
err
!=
nil
{
if
tcpConn
,
ok
=
session
.
Conn
()
.
(
*
net
.
TCPConn
);
!
ok
{
return
nil
,
jerrors
.
Trace
(
err
)
panic
(
fmt
.
Sprintf
(
"%s, session.conn{%#v} is not tcp connection
\n
"
,
session
.
Stat
(),
session
.
Conn
()))
}
}
tcpConn
.
SetNoDelay
(
c
.
conf
.
GettySessionParam
.
TcpNoDelay
)
c
.
registry
=
registry
tcpConn
.
SetKeepAlive
(
c
.
conf
.
GettySessionParam
.
TcpKeepAlive
)
if
c
.
registry
!=
nil
{
if
c
.
conf
.
GettySessionParam
.
TcpKeepAlive
{
c
.
filter
,
err
=
gxpool
.
NewFilter
(
tcpConn
.
SetKeepAlivePeriod
(
c
.
conf
.
GettySessionParam
.
keepAlivePeriod
)
gxfilter
.
WithBalancerMode
(
gxfilter
.
SM_Hash
),
gxfilter
.
WithRegistry
(
c
.
registry
),
gxpool
.
WithTTL
(
time
.
Duration
(
int
(
time
.
Second
)
*
c
.
conf
.
Registry
.
KeepaliveTimeout
)),
)
if
err
==
nil
{
return
nil
,
jerrors
.
Trace
(
err
)
}
}
tcpConn
.
SetReadBuffer
(
c
.
conf
.
GettySessionParam
.
TcpRBufSize
)
tcpConn
.
SetWriteBuffer
(
c
.
conf
.
GettySessionParam
.
TcpWBufSize
)
session
.
SetName
(
c
.
conf
.
GettySessionParam
.
SessionName
)
session
.
SetMaxMsgLen
(
c
.
conf
.
GettySessionParam
.
MaxMsgLen
)
session
.
SetPkgHandler
(
NewRpcClientPackageHandler
())
session
.
SetEventListener
(
NewRpcClientHandler
(
c
))
session
.
SetRQLen
(
c
.
conf
.
GettySessionParam
.
PkgRQSize
)
session
.
SetWQLen
(
c
.
conf
.
GettySessionParam
.
PkgWQSize
)
session
.
SetReadTimeout
(
c
.
conf
.
GettySessionParam
.
tcpReadTimeout
)
session
.
SetWriteTimeout
(
c
.
conf
.
GettySessionParam
.
tcpWriteTimeout
)
session
.
SetCronPeriod
((
int
)(
c
.
conf
.
heartbeatPeriod
.
Nanoseconds
()
/
1e6
))
session
.
SetWaitTime
(
c
.
conf
.
GettySessionParam
.
waitTimeout
)
log
.
Debug
(
"client new session:%s
\n
"
,
session
.
Stat
())
return
nil
service
:=
gxregistry
.
Service
{
}
Attr
:
&
gxregistry
.
ServiceAttr
{
Group
:
c
.
conf
.
Registry
.
IDC
,
Role
:
gxregistry
.
SRT_Consumer
,
Protocol
:
c
.
conf
.
CodecType
,
},
Nodes
:
[]
*
gxregistry
.
Node
{
&
gxregistry
.
Node
{
ID
:
c
.
conf
.
Registry
.
NodeID
,
Address
:
c
.
conf
.
Host
,
Port
:
0
,
},
},
}
if
err
=
c
.
registry
.
Register
(
service
);
err
!=
nil
{
return
nil
,
jerrors
.
Trace
(
err
)
}
}
func
(
c
*
Client
)
Sequence
()
uint64
{
return
c
,
nil
return
atomic
.
AddUint64
(
&
c
.
sequence
,
1
)
}
}
func
(
c
*
Client
)
Call
(
service
,
method
string
,
args
interface
{},
reply
interface
{})
error
{
func
(
c
*
Client
)
Call
(
addr
,
protocol
,
service
,
method
string
,
args
interface
{},
reply
interface
{})
error
{
b
:=
&
GettyRPCRequest
{}
b
:=
&
GettyRPCRequest
{}
b
.
header
.
Service
=
service
b
.
header
.
Service
=
service
b
.
header
.
Method
=
method
b
.
header
.
Method
=
method
...
@@ -129,7 +133,7 @@ func (c *Client) Call(service, method string, args interface{}, reply interface{
...
@@ -129,7 +133,7 @@ func (c *Client) Call(service, method string, args interface{}, reply interface{
resp
:=
NewPendingResponse
()
resp
:=
NewPendingResponse
()
resp
.
reply
=
reply
resp
.
reply
=
reply
session
:=
c
.
selectSession
()
session
:=
c
.
selectSession
(
protocol
,
addr
)
if
session
==
nil
{
if
session
==
nil
{
return
errSessionNotExist
return
errSessionNotExist
}
}
...
@@ -142,115 +146,23 @@ func (c *Client) Call(service, method string, args interface{}, reply interface{
...
@@ -142,115 +146,23 @@ func (c *Client) Call(service, method string, args interface{}, reply interface{
return
jerrors
.
Trace
(
resp
.
err
)
return
jerrors
.
Trace
(
resp
.
err
)
}
}
func
(
c
*
Client
)
isAvailable
()
bool
{
if
c
.
selectSession
()
==
nil
{
return
false
}
return
true
}
func
(
c
*
Client
)
Close
()
{
func
(
c
*
Client
)
Close
()
{
c
.
lock
.
Lock
()
if
c
.
pool
!=
nil
{
if
c
.
gettyClient
!=
nil
{
c
.
pool
.
close
()
for
_
,
s
:=
range
c
.
sessions
{
log
.
Info
(
"close client session{%s, last active:%s, request number:%d}"
,
s
.
session
.
Stat
(),
s
.
session
.
GetActive
()
.
String
(),
s
.
reqNum
)
s
.
session
.
Close
()
}
}
c
.
gettyClient
.
Close
()
c
.
pool
=
nil
c
.
gettyClient
=
nil
if
c
.
registry
!=
nil
{
c
.
sessions
=
c
.
sessions
[
:
0
]
c
.
registry
.
Close
()
}
}
c
.
lock
.
Unlock
()
c
.
registry
=
nil
}
}
func
(
c
*
Client
)
selectSession
()
getty
.
Session
{
func
(
c
*
Client
)
selectSession
(
protocol
,
addr
string
)
getty
.
Session
{
c
.
lock
.
RLock
()
rpcConn
,
err
:=
c
.
pool
.
getConn
(
protocol
,
addr
)
defer
c
.
lock
.
RUnlock
()
if
err
!=
nil
{
if
c
.
sessions
==
nil
{
return
nil
return
nil
}
}
return
rpcConn
.
selectSession
()
count
:=
len
(
c
.
sessions
)
if
count
==
0
{
return
nil
}
return
c
.
sessions
[
rand
.
Int31n
(
int32
(
count
))]
.
session
}
func
(
c
*
Client
)
addSession
(
session
getty
.
Session
)
{
log
.
Debug
(
"add session{%s}"
,
session
.
Stat
())
if
session
==
nil
{
return
}
c
.
lock
.
Lock
()
c
.
sessions
=
append
(
c
.
sessions
,
&
rpcSession
{
session
:
session
})
c
.
lock
.
Unlock
()
}
func
(
c
*
Client
)
removeSession
(
session
getty
.
Session
)
{
if
session
==
nil
{
return
}
c
.
lock
.
Lock
()
defer
c
.
lock
.
Unlock
()
if
c
.
sessions
==
nil
{
return
}
for
i
,
s
:=
range
c
.
sessions
{
if
s
.
session
==
session
{
c
.
sessions
=
append
(
c
.
sessions
[
:
i
],
c
.
sessions
[
i
+
1
:
]
...
)
log
.
Debug
(
"delete session{%s}, its index{%d}"
,
session
.
Stat
(),
i
)
break
}
}
log
.
Info
(
"after remove session{%s}, left session number:%d"
,
session
.
Stat
(),
len
(
c
.
sessions
))
}
func
(
c
*
Client
)
updateSession
(
session
getty
.
Session
)
{
if
session
==
nil
{
return
}
c
.
lock
.
Lock
()
defer
c
.
lock
.
Unlock
()
if
c
.
sessions
==
nil
{
return
}
for
i
,
s
:=
range
c
.
sessions
{
if
s
.
session
==
session
{
c
.
sessions
[
i
]
.
reqNum
++
break
}
}
}
func
(
c
*
Client
)
getClientRpcSession
(
session
getty
.
Session
)
(
rpcSession
,
error
)
{
var
(
err
error
rpcSession
rpcSession
)
c
.
lock
.
Lock
()
defer
c
.
lock
.
Unlock
()
if
c
.
sessions
==
nil
{
return
rpcSession
,
errClientClosed
}
err
=
errSessionNotExist
for
_
,
s
:=
range
c
.
sessions
{
if
s
.
session
==
session
{
rpcSession
=
*
s
err
=
nil
break
}
}
return
rpcSession
,
jerrors
.
Trace
(
err
)
}
}
func
(
c
*
Client
)
heartbeat
(
session
getty
.
Session
)
error
{
func
(
c
*
Client
)
heartbeat
(
session
getty
.
Session
)
error
{
...
@@ -265,12 +177,12 @@ func (c *Client) transfer(session getty.Session, req *GettyRPCRequest, resp *Pen
...
@@ -265,12 +177,12 @@ func (c *Client) transfer(session getty.Session, req *GettyRPCRequest, resp *Pen
pkg
GettyPackage
pkg
GettyPackage
)
)
sequence
=
c
.
Sequence
(
)
sequence
=
c
.
sequence
.
Add
(
1
)
pkg
.
H
.
Magic
=
gettyPackageMagic
pkg
.
H
.
Magic
=
gettyPackageMagic
pkg
.
H
.
LogID
=
(
uint32
)(
randomID
())
pkg
.
H
.
LogID
=
(
uint32
)(
randomID
())
pkg
.
H
.
Sequence
=
sequence
pkg
.
H
.
Sequence
=
sequence
pkg
.
H
.
Command
=
gettyCmdHbRequest
pkg
.
H
.
Command
=
gettyCmdHbRequest
pkg
.
H
.
CodecType
=
c
.
codecType
pkg
.
H
.
CodecType
=
c
.
co
nf
.
co
decType
if
req
!=
nil
{
if
req
!=
nil
{
pkg
.
H
.
Command
=
gettyCmdRPCRequest
pkg
.
H
.
Command
=
gettyCmdRPCRequest
pkg
.
B
=
req
pkg
.
B
=
req
...
...
rpc/codec.go
View file @
f16d6d53
...
@@ -23,43 +23,6 @@ import (
...
@@ -23,43 +23,6 @@ import (
// getty command
// getty command
////////////////////////////////////////////
////////////////////////////////////////////
type
gettyCodecType
uint32
const
(
gettyCodecUnknown
gettyCodecType
=
0x00
gettyJson
=
0x01
gettyProtobuf
=
0x02
)
var
gettyCodecTypeStrings
=
[
...
]
string
{
"unknown"
,
"json"
,
"protobuf"
,
}
func
(
c
gettyCodecType
)
String
()
string
{
if
c
==
gettyJson
||
c
==
gettyProtobuf
{
return
gettyCodecTypeStrings
[
c
]
}
return
gettyCodecTypeStrings
[
gettyCodecUnknown
]
}
func
String2CodecType
(
codecType
string
)
gettyCodecType
{
switch
codecType
{
case
gettyCodecTypeStrings
[
gettyJson
]
:
return
gettyJson
case
gettyCodecTypeStrings
[
gettyProtobuf
]
:
return
gettyProtobuf
}
return
gettyCodecUnknown
}
////////////////////////////////////////////
// getty command
////////////////////////////////////////////
type
gettyCommand
uint32
type
gettyCommand
uint32
const
(
const
(
...
@@ -105,20 +68,50 @@ const (
...
@@ -105,20 +68,50 @@ const (
GettyFail
=
0x01
GettyFail
=
0x01
)
)
type
SerializeType
byte
////////////////////////////////////////////
// getty codec type
////////////////////////////////////////////
type
gettyCodecType
uint32
const
(
const
(
JSON
SerializeType
=
iota
gettyCodecUnknown
gettyCodecType
=
0x00
ProtoBuffer
gettyCodecJson
=
0x01
gettyCodecProtobuf
=
0x02
)
)
var
(
var
(
Codecs
=
map
[
SerializeType
]
Codec
{
gettyCodecStrings
=
[
...
]
string
{
JSON
:
&
JSONCodec
{},
"unknown"
,
ProtoBuffer
:
&
PBCodec
{},
"json"
,
"protobuf"
,
}
Codecs
=
map
[
gettyCodecType
]
Codec
{
gettyCodecJson
:
&
JSONCodec
{},
gettyCodecProtobuf
:
&
PBCodec
{},
}
}
)
)
func
(
c
gettyCodecType
)
String
()
string
{
if
c
==
gettyCodecJson
||
c
==
gettyCodecProtobuf
{
return
gettyCodecStrings
[
c
]
}
return
gettyCodecStrings
[
gettyCodecUnknown
]
}
func
String2CodecType
(
codecType
string
)
gettyCodecType
{
switch
codecType
{
case
gettyCodecStrings
[
gettyCodecJson
]
:
return
gettyCodecJson
case
gettyCodecStrings
[
gettyCodecProtobuf
]
:
return
gettyCodecProtobuf
}
return
gettyCodecUnknown
}
// Codec defines the interface that decode/encode body.
// Codec defines the interface that decode/encode body.
type
Codec
interface
{
type
Codec
interface
{
Encode
(
i
interface
{})
([]
byte
,
error
)
Encode
(
i
interface
{})
([]
byte
,
error
)
...
@@ -194,9 +187,9 @@ func init() {
...
@@ -194,9 +187,9 @@ func init() {
}
}
type
RPCPackage
interface
{
type
RPCPackage
interface
{
Marshal
(
Serialize
Type
,
*
bytes
.
Buffer
)
(
int
,
error
)
Marshal
(
gettyCodec
Type
,
*
bytes
.
Buffer
)
(
int
,
error
)
// @buf length should be equal to GettyPkg.GettyPackageHeader.Len
// @buf length should be equal to GettyPkg.GettyPackageHeader.Len
Unmarshal
(
sz
Serialize
Type
,
buf
*
bytes
.
Buffer
)
error
Unmarshal
(
sz
gettyCodec
Type
,
buf
*
bytes
.
Buffer
)
error
GetBody
()
[]
byte
GetBody
()
[]
byte
GetHeader
()
interface
{}
GetHeader
()
interface
{}
}
}
...
@@ -210,7 +203,7 @@ type GettyPackageHeader struct {
...
@@ -210,7 +203,7 @@ type GettyPackageHeader struct {
Code
GettyErrorCode
// error code
Code
GettyErrorCode
// error code
ServiceID
uint32
// service id
ServiceID
uint32
// service id
CodecType
Serialize
Type
CodecType
gettyCodec
Type
}
}
type
GettyPackage
struct
{
type
GettyPackage
struct
{
...
@@ -230,14 +223,14 @@ func (p *GettyPackage) Marshal() (*bytes.Buffer, error) {
...
@@ -230,14 +223,14 @@ func (p *GettyPackage) Marshal() (*bytes.Buffer, error) {
buf
*
bytes
.
Buffer
buf
*
bytes
.
Buffer
)
)
packLen
=
gettyPackageHeaderLen
packLen
=
rpcPackagePlaceholderLen
+
gettyPackageHeaderLen
if
p
.
B
!=
nil
{
if
p
.
B
!=
nil
{
buf
=
&
bytes
.
Buffer
{}
buf
=
&
bytes
.
Buffer
{}
length
,
err
=
p
.
B
.
Marshal
(
p
.
H
.
CodecType
,
buf
)
length
,
err
=
p
.
B
.
Marshal
(
p
.
H
.
CodecType
,
buf
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
jerrors
.
Trace
(
err
)
return
nil
,
jerrors
.
Trace
(
err
)
}
}
packLen
=
gettyPackageHeaderLen
+
length
packLen
=
rpcPackagePlaceholderLen
+
gettyPackageHeaderLen
+
length
}
}
buf0
:=
&
bytes
.
Buffer
{}
buf0
:=
&
bytes
.
Buffer
{}
err
=
binary
.
Write
(
buf0
,
binary
.
LittleEndian
,
uint16
(
packLen
))
err
=
binary
.
Write
(
buf0
,
binary
.
LittleEndian
,
uint16
(
packLen
))
...
@@ -283,7 +276,7 @@ func (p *GettyPackage) Unmarshal(buf *bytes.Buffer) (int, error) {
...
@@ -283,7 +276,7 @@ func (p *GettyPackage) Unmarshal(buf *bytes.Buffer) (int, error) {
}
}
if
int
(
packLen
)
>
rpcPackagePlaceholderLen
+
gettyPackageHeaderLen
{
if
int
(
packLen
)
>
rpcPackagePlaceholderLen
+
gettyPackageHeaderLen
{
if
err
:=
p
.
B
.
Unmarshal
(
p
.
H
.
CodecType
,
bytes
.
NewBuffer
(
buf
.
Next
(
int
(
packLen
)
-
gettyPackageHeaderLen
)));
err
!=
nil
{
if
err
:=
p
.
B
.
Unmarshal
(
p
.
H
.
CodecType
,
bytes
.
NewBuffer
(
buf
.
Next
(
int
(
packLen
)
-
rpcPackagePlaceholderLen
-
gettyPackageHeaderLen
)));
err
!=
nil
{
return
0
,
jerrors
.
Trace
(
err
)
return
0
,
jerrors
.
Trace
(
err
)
}
}
}
}
...
@@ -322,7 +315,7 @@ func NewGettyRPCRequest() RPCPackage {
...
@@ -322,7 +315,7 @@ func NewGettyRPCRequest() RPCPackage {
return
&
GettyRPCRequest
{}
return
&
GettyRPCRequest
{}
}
}
func
(
req
*
GettyRPCRequest
)
Marshal
(
sz
Serialize
Type
,
buf
*
bytes
.
Buffer
)
(
int
,
error
)
{
func
(
req
*
GettyRPCRequest
)
Marshal
(
sz
gettyCodec
Type
,
buf
*
bytes
.
Buffer
)
(
int
,
error
)
{
codec
:=
Codecs
[
sz
]
codec
:=
Codecs
[
sz
]
if
codec
==
nil
{
if
codec
==
nil
{
return
0
,
jerrors
.
Errorf
(
"can not find codec for %d"
,
sz
)
return
0
,
jerrors
.
Errorf
(
"can not find codec for %d"
,
sz
)
...
@@ -355,8 +348,7 @@ func (req *GettyRPCRequest) Marshal(sz SerializeType, buf *bytes.Buffer) (int, e
...
@@ -355,8 +348,7 @@ func (req *GettyRPCRequest) Marshal(sz SerializeType, buf *bytes.Buffer) (int, e
return
2
+
len
(
headerData
)
+
2
+
len
(
bodyData
),
nil
return
2
+
len
(
headerData
)
+
2
+
len
(
bodyData
),
nil
}
}
func
(
req
*
GettyRPCRequest
)
Unmarshal
(
sz
SerializeType
,
buf
*
bytes
.
Buffer
)
error
{
func
(
req
*
GettyRPCRequest
)
Unmarshal
(
sz
gettyCodecType
,
buf
*
bytes
.
Buffer
)
error
{
var
headerLen
uint16
var
headerLen
uint16
err
:=
binary
.
Read
(
buf
,
binary
.
LittleEndian
,
&
headerLen
)
err
:=
binary
.
Read
(
buf
,
binary
.
LittleEndian
,
&
headerLen
)
if
err
!=
nil
{
if
err
!=
nil
{
...
@@ -426,7 +418,7 @@ func NewGettyRPCResponse() RPCPackage {
...
@@ -426,7 +418,7 @@ func NewGettyRPCResponse() RPCPackage {
return
&
GettyRPCResponse
{}
return
&
GettyRPCResponse
{}
}
}
func
(
resp
*
GettyRPCResponse
)
Marshal
(
sz
Serialize
Type
,
buf
*
bytes
.
Buffer
)
(
int
,
error
)
{
func
(
resp
*
GettyRPCResponse
)
Marshal
(
sz
gettyCodec
Type
,
buf
*
bytes
.
Buffer
)
(
int
,
error
)
{
codec
:=
Codecs
[
sz
]
codec
:=
Codecs
[
sz
]
if
codec
==
nil
{
if
codec
==
nil
{
return
0
,
jerrors
.
Errorf
(
"can not find codec for %d"
,
sz
)
return
0
,
jerrors
.
Errorf
(
"can not find codec for %d"
,
sz
)
...
@@ -461,8 +453,7 @@ func (resp *GettyRPCResponse) Marshal(sz SerializeType, buf *bytes.Buffer) (int,
...
@@ -461,8 +453,7 @@ func (resp *GettyRPCResponse) Marshal(sz SerializeType, buf *bytes.Buffer) (int,
return
2
+
len
(
headerData
)
+
2
+
len
(
bodyData
),
nil
return
2
+
len
(
headerData
)
+
2
+
len
(
bodyData
),
nil
}
}
func
(
resp
*
GettyRPCResponse
)
Unmarshal
(
sz
SerializeType
,
buf
*
bytes
.
Buffer
)
error
{
func
(
resp
*
GettyRPCResponse
)
Unmarshal
(
sz
gettyCodecType
,
buf
*
bytes
.
Buffer
)
error
{
var
headerLen
uint16
var
headerLen
uint16
err
:=
binary
.
Read
(
buf
,
binary
.
LittleEndian
,
&
headerLen
)
err
:=
binary
.
Read
(
buf
,
binary
.
LittleEndian
,
&
headerLen
)
if
err
!=
nil
{
if
err
!=
nil
{
...
@@ -480,7 +471,6 @@ func (resp *GettyRPCResponse) Unmarshal(sz SerializeType, buf *bytes.Buffer) err
...
@@ -480,7 +471,6 @@ func (resp *GettyRPCResponse) Unmarshal(sz SerializeType, buf *bytes.Buffer) err
if
err
!=
nil
{
if
err
!=
nil
{
return
jerrors
.
Trace
(
err
)
return
jerrors
.
Trace
(
err
)
}
}
body
:=
make
([]
byte
,
bodyLen
)
body
:=
make
([]
byte
,
bodyLen
)
err
=
binary
.
Read
(
buf
,
binary
.
LittleEndian
,
body
)
err
=
binary
.
Read
(
buf
,
binary
.
LittleEndian
,
body
)
if
err
!=
nil
{
if
err
!=
nil
{
...
...
rpc/config.go
View file @
f16d6d53
...
@@ -32,7 +32,7 @@ type (
...
@@ -32,7 +32,7 @@ type (
RegistryConfig
struct
{
RegistryConfig
struct
{
Type
string
`default:"etcd" yaml:"type" json:"type,omitempty"`
Type
string
`default:"etcd" yaml:"type" json:"type,omitempty"`
Addr
string
`default:"
127.0.0.1:2379
" yaml:"addr" json:"addr,omitempty"`
Addr
string
`default:"" yaml:"addr" json:"addr,omitempty"`
KeepaliveTimeout
int
`default:"5" yaml:"keepalive_time" json:"keepalive_timeout,omitempty"`
KeepaliveTimeout
int
`default:"5" yaml:"keepalive_time" json:"keepalive_timeout,omitempty"`
Root
string
`default:"getty" yaml:"keepalive_time" json:"keepalive_timeout,omitempty"`
Root
string
`default:"getty" yaml:"keepalive_time" json:"keepalive_timeout,omitempty"`
IDC
string
`default:"idc-bj" yaml:"idc" json:"idc,omitempty"`
IDC
string
`default:"idc-bj" yaml:"idc" json:"idc,omitempty"`
...
@@ -74,8 +74,11 @@ type (
...
@@ -74,8 +74,11 @@ type (
ProfilePort
int
`default:"10086" yaml:"profile_port" json:"profile_port,omitempty"`
ProfilePort
int
`default:"10086" yaml:"profile_port" json:"profile_port,omitempty"`
// server
// server
// !!! Attention: If u wanna use registry, the ServerHost & ServerPort could be nil.
ServerHost
string
`default:"127.0.0.1" yaml:"server_host" json:"server_host,omitempty"`
ServerHost
string
`default:"127.0.0.1" yaml:"server_host" json:"server_host,omitempty"`
ServerPort
int
`default:"10000" yaml:"server_port" json:"server_port,omitempty"`
ServerPort
int
`default:"10000" yaml:"server_port" json:"server_port,omitempty"`
CodecType
string
`default:"json" yaml:"codec_type" json:"codec_type,omitempty"`
codecType
gettyCodecType
// session pool
// session pool
ConnectionNum
int
`default:"16" yaml:"connection_num" json:"connection_num,omitempty"`
ConnectionNum
int
`default:"16" yaml:"connection_num" json:"connection_num,omitempty"`
...
@@ -92,6 +95,10 @@ type (
...
@@ -92,6 +95,10 @@ type (
FailFastTimeout
string
`default:"5s" yaml:"fail_fast_timeout" json:"fail_fast_timeout,omitempty"`
FailFastTimeout
string
`default:"5s" yaml:"fail_fast_timeout" json:"fail_fast_timeout,omitempty"`
failFastTimeout
time
.
Duration
failFastTimeout
time
.
Duration
// Connection Pool
PoolSize
int
`default:"2" yaml:"pool_size" json:"pool_size,omitempty"`
PoolTTL
int
`default:"180" yaml:"pool_ttl" json:"pool_ttl,omitempty"`
// session tcp parameters
// session tcp parameters
GettySessionParam
GettySessionParam
`required:"true" yaml:"getty_session_param" json:"getty_session_param,omitempty"`
GettySessionParam
GettySessionParam
`required:"true" yaml:"getty_session_param" json:"getty_session_param,omitempty"`
...
...
rpc/example/client/client.go
View file @
f16d6d53
...
@@ -8,18 +8,22 @@ import (
...
@@ -8,18 +8,22 @@ import (
"github.com/AlexStocks/getty/rpc"
"github.com/AlexStocks/getty/rpc"
"github.com/AlexStocks/getty/rpc/example/data"
"github.com/AlexStocks/getty/rpc/example/data"
log
"github.com/AlexStocks/log4go"
log
"github.com/AlexStocks/log4go"
jerrors
"github.com/juju/errors"
)
)
func
main
()
{
func
main
()
{
log
.
LoadConfiguration
(
"client_log.xml"
)
log
.
LoadConfiguration
(
"client_log.xml"
)
client
:=
rpc
.
NewClient
(
"client_config.toml"
)
client
,
err
:=
rpc
.
NewClient
(
"client_config.toml"
)
if
err
!=
nil
{
panic
(
jerrors
.
ErrorStack
(
err
))
}
// client.SetCodecType(rpc.ProtoBuffer)//默认是json序列化
// client.SetCodecType(rpc.ProtoBuffer)//默认是json序列化
defer
client
.
Close
()
defer
client
.
Close
()
for
i
:=
0
;
i
<
100
;
i
++
{
for
i
:=
0
;
i
<
100
;
i
++
{
go
func
()
{
go
func
()
{
var
res
string
var
res
string
err
:=
client
.
Call
(
"TestRpc"
,
"Test"
,
data
.
TestABC
{
"aaa"
,
"bbb"
,
"ccc"
},
&
res
)
err
:=
client
.
Call
(
"
127.0.0.1:20000"
,
"json"
,
"
TestRpc"
,
"Test"
,
data
.
TestABC
{
"aaa"
,
"bbb"
,
"ccc"
},
&
res
)
if
err
!=
nil
{
if
err
!=
nil
{
log
.
Error
(
err
)
log
.
Error
(
err
)
return
return
...
@@ -31,7 +35,7 @@ func main() {
...
@@ -31,7 +35,7 @@ func main() {
for
i
:=
0
;
i
<
100
;
i
++
{
for
i
:=
0
;
i
<
100
;
i
++
{
go
func
()
{
go
func
()
{
var
result
int
var
result
int
err
:=
client
.
Call
(
"TestRpc"
,
"Add"
,
1
,
&
result
)
err
:=
client
.
Call
(
"
127.0.0.1:20000"
,
"json"
,
"
TestRpc"
,
"Add"
,
1
,
&
result
)
if
err
!=
nil
{
if
err
!=
nil
{
log
.
Error
(
err
)
log
.
Error
(
err
)
return
return
...
@@ -41,9 +45,9 @@ func main() {
...
@@ -41,9 +45,9 @@ func main() {
}
}
var
errInt
int
var
errInt
int
err
:=
client
.
Call
(
"TestRpc"
,
"Err"
,
2
,
&
errInt
)
err
=
client
.
Call
(
"127.0.0.1:20000"
,
"json"
,
"TestRpc"
,
"Err"
,
2
,
&
errInt
)
if
err
!=
nil
{
if
err
!=
nil
{
log
.
Error
(
err
)
log
.
Error
(
jerrors
.
ErrorStack
(
err
)
)
}
}
time
.
Sleep
(
20
*
time
.
Second
)
time
.
Sleep
(
20
*
time
.
Second
)
...
...
rpc/example/client/client_config.toml
View file @
f16d6d53
...
@@ -39,4 +39,13 @@ FailFastTimeout = "3s"
...
@@ -39,4 +39,13 @@ FailFastTimeout = "3s"
TcpWriteTimeout
=
"5s"
TcpWriteTimeout
=
"5s"
WaitTimeout
=
"1s"
WaitTimeout
=
"1s"
MaxMsgLen
=
128
MaxMsgLen
=
128
SessionName
=
"rpc-client"
SessionName
=
"getty-rpc-client"
# registry
[Registry]
Type
=
"etcd"
# Addr = "127.0.0.1:2379"
KeepaliveTimeout
=
5
Root
=
"/getty"
IDC
=
"bj-unicom"
NodeID
=
"n147"
rpc/example/server/server_config.toml
View file @
f16d6d53
...
@@ -32,12 +32,12 @@ FailFastTimeout = "3s"
...
@@ -32,12 +32,12 @@ FailFastTimeout = "3s"
TcpWriteTimeout
=
"5s"
TcpWriteTimeout
=
"5s"
WaitTimeout
=
"1s"
WaitTimeout
=
"1s"
MaxMsgLen
=
128
MaxMsgLen
=
128
SessionName
=
"rpc-server"
SessionName
=
"
getty-
rpc-server"
# registry
# registry
[Registry]
[Registry]
Type
=
"etcd"
Type
=
"etcd"
Addr
=
"127.0.0.1:2379"
#
Addr = "127.0.0.1:2379"
KeepaliveTimeout
=
5
KeepaliveTimeout
=
5
Root
=
"/getty"
Root
=
"/getty"
IDC
=
"bj-unicom"
IDC
=
"bj-unicom"
...
...
rpc/listener.go
View file @
f16d6d53
...
@@ -169,26 +169,26 @@ func (h *RpcServerHandler) callService(session getty.Session, req GettyRPCReques
...
@@ -169,26 +169,26 @@ func (h *RpcServerHandler) callService(session getty.Session, req GettyRPCReques
////////////////////////////////////////////
////////////////////////////////////////////
type
RpcClientHandler
struct
{
type
RpcClientHandler
struct
{
c
lient
*
Client
c
onn
*
gettyRPCClientConn
}
}
func
NewRpcClientHandler
(
client
*
Client
)
*
RpcClientHandler
{
func
NewRpcClientHandler
(
client
*
gettyRPCClientConn
)
*
RpcClientHandler
{
return
&
RpcClientHandler
{
c
lient
:
client
}
return
&
RpcClientHandler
{
c
onn
:
client
}
}
}
func
(
h
*
RpcClientHandler
)
OnOpen
(
session
getty
.
Session
)
error
{
func
(
h
*
RpcClientHandler
)
OnOpen
(
session
getty
.
Session
)
error
{
h
.
c
lient
.
addSession
(
session
)
h
.
c
onn
.
addSession
(
session
)
return
nil
return
nil
}
}
func
(
h
*
RpcClientHandler
)
OnError
(
session
getty
.
Session
,
err
error
)
{
func
(
h
*
RpcClientHandler
)
OnError
(
session
getty
.
Session
,
err
error
)
{
log
.
Info
(
"session{%s} got error{%v}, will be closed."
,
session
.
Stat
(),
err
)
log
.
Info
(
"session{%s} got error{%v}, will be closed."
,
session
.
Stat
(),
err
)
h
.
c
lient
.
removeSession
(
session
)
h
.
c
onn
.
removeSession
(
session
)
}
}
func
(
h
*
RpcClientHandler
)
OnClose
(
session
getty
.
Session
)
{
func
(
h
*
RpcClientHandler
)
OnClose
(
session
getty
.
Session
)
{
log
.
Info
(
"session{%s} is closing......"
,
session
.
Stat
())
log
.
Info
(
"session{%s} is closing......"
,
session
.
Stat
())
h
.
c
lient
.
removeSession
(
session
)
h
.
c
onn
.
removeSession
(
session
)
}
}
func
(
h
*
RpcClientHandler
)
OnMessage
(
session
getty
.
Session
,
pkg
interface
{})
{
func
(
h
*
RpcClientHandler
)
OnMessage
(
session
getty
.
Session
,
pkg
interface
{})
{
...
@@ -198,9 +198,9 @@ func (h *RpcClientHandler) OnMessage(session getty.Session, pkg interface{}) {
...
@@ -198,9 +198,9 @@ func (h *RpcClientHandler) OnMessage(session getty.Session, pkg interface{}) {
return
return
}
}
log
.
Debug
(
"get rpc response{%s}"
,
p
)
log
.
Debug
(
"get rpc response{%s}"
,
p
)
h
.
c
lient
.
updateSession
(
session
)
h
.
c
onn
.
updateSession
(
session
)
pendingResponse
:=
h
.
client
.
RemovePendingResponse
(
p
.
H
.
Sequence
)
pendingResponse
:=
h
.
c
onn
.
pool
.
rpcC
lient
.
RemovePendingResponse
(
p
.
H
.
Sequence
)
if
pendingResponse
==
nil
{
if
pendingResponse
==
nil
{
return
return
}
}
...
@@ -228,17 +228,17 @@ func (h *RpcClientHandler) OnMessage(session getty.Session, pkg interface{}) {
...
@@ -228,17 +228,17 @@ func (h *RpcClientHandler) OnMessage(session getty.Session, pkg interface{}) {
}
}
func
(
h
*
RpcClientHandler
)
OnCron
(
session
getty
.
Session
)
{
func
(
h
*
RpcClientHandler
)
OnCron
(
session
getty
.
Session
)
{
rpcSession
,
err
:=
h
.
c
lient
.
getClientRpcSession
(
session
)
rpcSession
,
err
:=
h
.
c
onn
.
getClientRpcSession
(
session
)
if
err
!=
nil
{
if
err
!=
nil
{
log
.
Error
(
"client.getClientSession(session{%s}) = error{%#v}"
,
session
.
Stat
(),
err
)
log
.
Error
(
"client.getClientSession(session{%s}) = error{%#v}"
,
session
.
Stat
(),
err
)
return
return
}
}
if
h
.
client
.
conf
.
sessionTimeout
.
Nanoseconds
()
<
time
.
Since
(
session
.
GetActive
())
.
Nanoseconds
()
{
if
h
.
c
onn
.
pool
.
rpcC
lient
.
conf
.
sessionTimeout
.
Nanoseconds
()
<
time
.
Since
(
session
.
GetActive
())
.
Nanoseconds
()
{
log
.
Warn
(
"session{%s} timeout{%s}, reqNum{%d}"
,
log
.
Warn
(
"session{%s} timeout{%s}, reqNum{%d}"
,
session
.
Stat
(),
time
.
Since
(
session
.
GetActive
())
.
String
(),
rpcSession
.
reqNum
)
session
.
Stat
(),
time
.
Since
(
session
.
GetActive
())
.
String
(),
rpcSession
.
reqNum
)
h
.
c
lient
.
removeSession
(
sessio
n
)
h
.
c
onn
.
removeSession
(
session
)
// -> h.conn.close() -> h.conn.pool.remove(h.con
n)
return
return
}
}
h
.
client
.
heartbeat
(
session
)
h
.
c
onn
.
pool
.
rpcC
lient
.
heartbeat
(
session
)
}
}
rpc/pool.go
0 → 100755
View file @
f16d6d53
package
rpc
import
(
"fmt"
"math/rand"
"net"
"strings"
"sync"
"time"
)
import
(
"github.com/AlexStocks/getty"
log
"github.com/AlexStocks/log4go"
jerrors
"github.com/juju/errors"
)
type
gettyRPCClientConn
struct
{
once
sync
.
Once
protocol
string
addr
string
created
int64
// 为0,则说明没有被创建或者被销毁了
pool
*
gettyRPCClientConnPool
lock
sync
.
RWMutex
gettyClient
getty
.
Client
sessions
[]
*
rpcSession
}
var
(
errClientPoolClosed
=
jerrors
.
New
(
"client pool closed"
)
)
func
newGettyRPCClientConn
(
pool
*
gettyRPCClientConnPool
,
protocol
,
addr
string
)
(
*
gettyRPCClientConn
,
error
)
{
c
:=
&
gettyRPCClientConn
{
protocol
:
protocol
,
addr
:
addr
,
pool
:
pool
,
gettyClient
:
getty
.
NewTCPClient
(
getty
.
WithServerAddress
(
addr
),
getty
.
WithConnectionNumber
((
int
)(
pool
.
rpcClient
.
conf
.
ConnectionNum
)),
),
}
c
.
gettyClient
.
RunEventLoop
(
c
.
newSession
)
idx
:=
1
for
{
idx
++
if
c
.
isAvailable
()
{
break
}
if
idx
>
5000
{
return
nil
,
jerrors
.
New
(
fmt
.
Sprintf
(
"failed to create client connection to %s in 5 seconds"
,
addr
))
}
time
.
Sleep
(
1e6
)
}
log
.
Info
(
"client init ok"
)
c
.
created
=
time
.
Now
()
.
Unix
()
return
c
,
nil
}
func
(
c
*
gettyRPCClientConn
)
newSession
(
session
getty
.
Session
)
error
{
var
(
ok
bool
tcpConn
*
net
.
TCPConn
conf
*
ClientConfig
)
conf
=
c
.
pool
.
rpcClient
.
conf
if
conf
.
GettySessionParam
.
CompressEncoding
{
session
.
SetCompressType
(
getty
.
CompressZip
)
}
if
tcpConn
,
ok
=
session
.
Conn
()
.
(
*
net
.
TCPConn
);
!
ok
{
panic
(
fmt
.
Sprintf
(
"%s, session.conn{%#v} is not tcp connection
\n
"
,
session
.
Stat
(),
session
.
Conn
()))
}
tcpConn
.
SetNoDelay
(
conf
.
GettySessionParam
.
TcpNoDelay
)
tcpConn
.
SetKeepAlive
(
conf
.
GettySessionParam
.
TcpKeepAlive
)
if
conf
.
GettySessionParam
.
TcpKeepAlive
{
tcpConn
.
SetKeepAlivePeriod
(
conf
.
GettySessionParam
.
keepAlivePeriod
)
}
tcpConn
.
SetReadBuffer
(
conf
.
GettySessionParam
.
TcpRBufSize
)
tcpConn
.
SetWriteBuffer
(
conf
.
GettySessionParam
.
TcpWBufSize
)
session
.
SetName
(
conf
.
GettySessionParam
.
SessionName
)
session
.
SetMaxMsgLen
(
conf
.
GettySessionParam
.
MaxMsgLen
)
session
.
SetPkgHandler
(
NewRpcClientPackageHandler
())
session
.
SetEventListener
(
NewRpcClientHandler
(
c
))
session
.
SetRQLen
(
conf
.
GettySessionParam
.
PkgRQSize
)
session
.
SetWQLen
(
conf
.
GettySessionParam
.
PkgWQSize
)
session
.
SetReadTimeout
(
conf
.
GettySessionParam
.
tcpReadTimeout
)
session
.
SetWriteTimeout
(
conf
.
GettySessionParam
.
tcpWriteTimeout
)
session
.
SetCronPeriod
((
int
)(
conf
.
heartbeatPeriod
.
Nanoseconds
()
/
1e6
))
session
.
SetWaitTime
(
conf
.
GettySessionParam
.
waitTimeout
)
log
.
Debug
(
"client new session:%s
\n
"
,
session
.
Stat
())
return
nil
}
func
(
c
*
gettyRPCClientConn
)
selectSession
()
getty
.
Session
{
c
.
lock
.
RLock
()
defer
c
.
lock
.
RUnlock
()
if
c
.
sessions
==
nil
{
return
nil
}
count
:=
len
(
c
.
sessions
)
if
count
==
0
{
return
nil
}
return
c
.
sessions
[
rand
.
Int31n
(
int32
(
count
))]
.
session
}
func
(
c
*
gettyRPCClientConn
)
addSession
(
session
getty
.
Session
)
{
log
.
Debug
(
"add session{%s}"
,
session
.
Stat
())
if
session
==
nil
{
return
}
c
.
lock
.
Lock
()
c
.
sessions
=
append
(
c
.
sessions
,
&
rpcSession
{
session
:
session
})
c
.
lock
.
Unlock
()
}
func
(
c
*
gettyRPCClientConn
)
removeSession
(
session
getty
.
Session
)
{
if
session
==
nil
{
return
}
c
.
lock
.
Lock
()
defer
c
.
lock
.
Unlock
()
if
c
.
sessions
==
nil
{
return
}
for
i
,
s
:=
range
c
.
sessions
{
if
s
.
session
==
session
{
c
.
sessions
=
append
(
c
.
sessions
[
:
i
],
c
.
sessions
[
i
+
1
:
]
...
)
log
.
Debug
(
"delete session{%s}, its index{%d}"
,
session
.
Stat
(),
i
)
break
}
}
log
.
Info
(
"after remove session{%s}, left session number:%d"
,
session
.
Stat
(),
len
(
c
.
sessions
))
if
len
(
c
.
sessions
)
==
0
{
c
.
close
()
// -> pool.remove(c)
}
}
func
(
c
*
gettyRPCClientConn
)
updateSession
(
session
getty
.
Session
)
{
if
session
==
nil
{
return
}
c
.
lock
.
Lock
()
defer
c
.
lock
.
Unlock
()
if
c
.
sessions
==
nil
{
return
}
for
i
,
s
:=
range
c
.
sessions
{
if
s
.
session
==
session
{
c
.
sessions
[
i
]
.
reqNum
++
break
}
}
}
func
(
c
*
gettyRPCClientConn
)
getClientRpcSession
(
session
getty
.
Session
)
(
rpcSession
,
error
)
{
var
(
err
error
rpcSession
rpcSession
)
c
.
lock
.
Lock
()
defer
c
.
lock
.
Unlock
()
if
c
.
sessions
==
nil
{
return
rpcSession
,
errClientClosed
}
err
=
errSessionNotExist
for
_
,
s
:=
range
c
.
sessions
{
if
s
.
session
==
session
{
rpcSession
=
*
s
err
=
nil
break
}
}
return
rpcSession
,
jerrors
.
Trace
(
err
)
}
func
(
c
*
gettyRPCClientConn
)
isAvailable
()
bool
{
if
c
.
selectSession
()
==
nil
{
return
false
}
return
true
}
func
(
c
*
gettyRPCClientConn
)
close
()
error
{
err
:=
jerrors
.
Errorf
(
"close gettyRPCClientConn{%#v} again"
,
c
)
c
.
once
.
Do
(
func
()
{
// delete @c from client pool
c
.
pool
.
remove
(
c
)
for
_
,
s
:=
range
c
.
sessions
{
log
.
Info
(
"close client session{%s, last active:%s, request number:%d}"
,
s
.
session
.
Stat
(),
s
.
session
.
GetActive
()
.
String
(),
s
.
reqNum
)
s
.
session
.
Close
()
}
c
.
gettyClient
.
Close
()
c
.
gettyClient
=
nil
c
.
sessions
=
c
.
sessions
[
:
0
]
c
.
created
=
0
err
=
nil
})
return
err
}
type
gettyRPCClientConnPool
struct
{
rpcClient
*
Client
size
int
// []*gettyRPCClientConn数组的size
ttl
int64
// 每个gettyRPCClientConn的有效期时间. pool对象会在getConn时执行ttl检查
sync
.
Mutex
connMap
map
[
string
][]
*
gettyRPCClientConn
// 从[]*gettyRPCClientConn 可见key是连接地址,而value是对应这个地址的连接数组
}
func
newGettyRPCClientConnPool
(
rpcClient
*
Client
,
size
int
,
ttl
time
.
Duration
)
*
gettyRPCClientConnPool
{
return
&
gettyRPCClientConnPool
{
rpcClient
:
rpcClient
,
size
:
size
,
ttl
:
int64
(
ttl
.
Seconds
()),
connMap
:
make
(
map
[
string
][]
*
gettyRPCClientConn
),
}
}
func
(
p
*
gettyRPCClientConnPool
)
close
()
{
p
.
Lock
()
connMap
:=
p
.
connMap
p
.
connMap
=
nil
p
.
Unlock
()
for
_
,
connArray
:=
range
connMap
{
for
_
,
conn
:=
range
connArray
{
conn
.
close
()
}
}
}
func
(
p
*
gettyRPCClientConnPool
)
getConn
(
protocol
,
addr
string
)
(
*
gettyRPCClientConn
,
error
)
{
var
builder
strings
.
Builder
builder
.
WriteString
(
addr
)
builder
.
WriteString
(
"@"
)
builder
.
WriteString
(
protocol
)
key
:=
builder
.
String
()
p
.
Lock
()
defer
p
.
Unlock
()
if
p
.
connMap
==
nil
{
return
nil
,
errClientPoolClosed
}
connArray
:=
p
.
connMap
[
key
]
now
:=
time
.
Now
()
.
Unix
()
for
len
(
connArray
)
>
0
{
conn
:=
connArray
[
len
(
connArray
)
-
1
]
connArray
=
connArray
[
:
len
(
connArray
)
-
1
]
p
.
connMap
[
key
]
=
connArray
if
d
:=
now
-
conn
.
created
;
d
>
p
.
ttl
{
conn
.
close
()
// -> pool.remove(c)
continue
}
p
.
Unlock
()
return
conn
,
nil
}
// create new conn
return
newGettyRPCClientConn
(
p
,
protocol
,
addr
)
}
func
(
p
*
gettyRPCClientConnPool
)
release
(
conn
*
gettyRPCClientConn
,
err
error
)
{
if
conn
==
nil
||
conn
.
created
==
0
{
return
}
if
err
!=
nil
{
conn
.
close
()
//
return
}
var
builder
strings
.
Builder
builder
.
WriteString
(
conn
.
addr
)
builder
.
WriteString
(
"@"
)
builder
.
WriteString
(
conn
.
protocol
)
key
:=
builder
.
String
()
p
.
Lock
()
defer
p
.
Unlock
()
if
p
.
connMap
==
nil
{
return
}
connArray
:=
p
.
connMap
[
key
]
if
len
(
connArray
)
>=
p
.
size
{
p
.
Unlock
()
conn
.
close
()
return
}
p
.
connMap
[
key
]
=
append
(
connArray
,
conn
)
}
func
(
p
*
gettyRPCClientConnPool
)
remove
(
conn
*
gettyRPCClientConn
)
{
if
conn
==
nil
||
conn
.
created
==
0
{
return
}
var
builder
strings
.
Builder
builder
.
WriteString
(
conn
.
addr
)
builder
.
WriteString
(
"@"
)
builder
.
WriteString
(
conn
.
protocol
)
key
:=
builder
.
String
()
p
.
Lock
()
defer
p
.
Unlock
()
if
p
.
connMap
==
nil
{
return
}
connArray
:=
p
.
connMap
[
key
]
if
len
(
connArray
)
>
0
{
for
idx
,
c
:=
range
connArray
{
if
conn
==
c
{
p
.
connMap
[
key
]
=
append
(
connArray
[
:
idx
],
connArray
[
idx
+
1
:
]
...
)
break
}
}
}
}
rpc/readwriter.go
View file @
f16d6d53
...
@@ -123,7 +123,9 @@ func (p *RpcClientPackageHandler) Read(ss getty.Session, data []byte) (interface
...
@@ -123,7 +123,9 @@ func (p *RpcClientPackageHandler) Read(ss getty.Session, data []byte) (interface
resp
:=
&
GettyRPCResponsePackage
{
resp
:=
&
GettyRPCResponsePackage
{
H
:
pkg
.
H
,
H
:
pkg
.
H
,
header
:
pkg
.
B
.
GetHeader
()
.
(
GettyRPCResponseHeader
),
header
:
pkg
.
B
.
GetHeader
()
.
(
GettyRPCResponseHeader
),
body
:
pkg
.
B
.
GetBody
(),
}
if
pkg
.
H
.
Command
!=
gettyCmdHbResponse
{
resp
.
body
=
pkg
.
B
.
GetBody
()
}
}
return
resp
,
length
,
nil
return
resp
,
length
,
nil
}
}
...
...
rpc/server.go
View file @
f16d6d53
...
@@ -26,19 +26,21 @@ type Server struct {
...
@@ -26,19 +26,21 @@ type Server struct {
conf
*
ServerConfig
conf
*
ServerConfig
serviceMap
map
[
string
]
*
service
serviceMap
map
[
string
]
*
service
tcpServerList
[]
getty
.
Server
tcpServerList
[]
getty
.
Server
// registry
registry
gxregistry
.
Registry
registry
gxregistry
.
Registry
sa
gxregistry
.
ServiceAttr
sa
gxregistry
.
ServiceAttr
nodes
[]
*
gxregistry
.
Node
nodes
[]
*
gxregistry
.
Node
}
}
var
(
var
(
ErrIllegalCo
decType
=
jerrors
.
New
(
"illegal codec type"
)
ErrIllegalCo
nf
=
"illegal conf: "
)
)
func
NewServer
(
confFile
string
)
(
*
Server
,
error
)
{
func
NewServer
(
confFile
string
)
(
*
Server
,
error
)
{
conf
:=
loadServerConf
(
confFile
)
conf
:=
loadServerConf
(
confFile
)
if
conf
.
codecType
=
String2CodecType
(
conf
.
CodecType
);
conf
.
codecType
==
gettyCodecUnknown
{
if
conf
.
codecType
=
String2CodecType
(
conf
.
CodecType
);
conf
.
codecType
==
gettyCodecUnknown
{
return
nil
,
ErrIllegalCodecType
return
nil
,
jerrors
.
New
(
fmt
.
Sprintf
(
ErrIllegalConf
+
"codec type %s"
,
conf
.
CodecType
))
}
}
s
:=
&
Server
{
s
:=
&
Server
{
...
@@ -46,9 +48,9 @@ func NewServer(confFile string) (*Server, error) {
...
@@ -46,9 +48,9 @@ func NewServer(confFile string) (*Server, error) {
conf
:
conf
,
conf
:
conf
,
}
}
if
len
(
s
.
conf
.
Registry
.
Addr
)
!=
0
{
var
err
error
var
err
error
var
registry
gxregistry
.
Registry
var
registry
gxregistry
.
Registry
if
len
(
s
.
conf
.
Registry
.
Addr
)
!=
0
{
addrList
:=
strings
.
Split
(
s
.
conf
.
Registry
.
Addr
,
","
)
addrList
:=
strings
.
Split
(
s
.
conf
.
Registry
.
Addr
,
","
)
switch
s
.
conf
.
Registry
.
Type
{
switch
s
.
conf
.
Registry
.
Type
{
case
"etcd"
:
case
"etcd"
:
...
@@ -63,13 +65,15 @@ func NewServer(confFile string) (*Server, error) {
...
@@ -63,13 +65,15 @@ func NewServer(confFile string) (*Server, error) {
gxregistry
.
WithTimeout
(
time
.
Duration
(
int
(
time
.
Second
)
*
s
.
conf
.
Registry
.
KeepaliveTimeout
)),
gxregistry
.
WithTimeout
(
time
.
Duration
(
int
(
time
.
Second
)
*
s
.
conf
.
Registry
.
KeepaliveTimeout
)),
gxregistry
.
WithRoot
(
s
.
conf
.
Registry
.
Root
),
gxregistry
.
WithRoot
(
s
.
conf
.
Registry
.
Root
),
)
)
default
:
return
nil
,
jerrors
.
New
(
fmt
.
Sprintf
(
ErrIllegalConf
+
"registry type %s"
,
s
.
conf
.
Registry
.
Type
))
}
}
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
jerrors
.
Trace
(
err
)
return
nil
,
jerrors
.
Trace
(
err
)
}
}
if
registry
!=
nil
{
s
.
registry
=
registry
s
.
registry
=
registry
if
s
.
registry
!=
nil
{
s
.
sa
=
gxregistry
.
ServiceAttr
{
s
.
sa
=
gxregistry
.
ServiceAttr
{
Group
:
s
.
conf
.
Registry
.
IDC
,
Group
:
s
.
conf
.
Registry
.
IDC
,
Role
:
gxregistry
.
SRT_Provider
,
Role
:
gxregistry
.
SRT_Provider
,
...
@@ -86,7 +90,9 @@ func NewServer(confFile string) (*Server, error) {
...
@@ -86,7 +90,9 @@ func NewServer(confFile string) (*Server, error) {
&
gxregistry
.
Node
{
&
gxregistry
.
Node
{
ID
:
s
.
conf
.
Registry
.
NodeID
+
"-"
+
net
.
JoinHostPort
(
s
.
conf
.
Host
,
p
),
ID
:
s
.
conf
.
Registry
.
NodeID
+
"-"
+
net
.
JoinHostPort
(
s
.
conf
.
Host
,
p
),
Address
:
s
.
conf
.
Host
,
Address
:
s
.
conf
.
Host
,
Port
:
int32
(
port
)})
Port
:
int32
(
port
),
},
)
}
}
}
}
}
}
...
@@ -210,9 +216,16 @@ func (s *Server) Init() {
...
@@ -210,9 +216,16 @@ func (s *Server) Init() {
}
}
func
(
s
*
Server
)
Stop
()
{
func
(
s
*
Server
)
Stop
()
{
for
_
,
tcpServer
:=
range
s
.
tcpServerList
{
if
s
.
registry
!=
nil
{
s
.
registry
.
Close
()
}
list
:=
s
.
tcpServerList
s
.
tcpServerList
=
nil
if
list
!=
nil
{
for
_
,
tcpServer
:=
range
list
{
tcpServer
.
Close
()
tcpServer
.
Close
()
}
}
}
}
}
func
(
s
*
Server
)
initSignal
()
{
func
(
s
*
Server
)
initSignal
()
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment