mirror of
https://github.com/smallnest/rpcx.git
synced 2026-04-22 23:27:06 +08:00
refactor to support other rpc clients
This commit is contained in:
Binary file not shown.
|
Before Width: | Height: | Size: 21 KiB |
@@ -94,6 +94,8 @@ type RPCClient interface {
|
|||||||
|
|
||||||
IsClosing() bool
|
IsClosing() bool
|
||||||
IsShutdown() bool
|
IsShutdown() bool
|
||||||
|
|
||||||
|
GetConn() net.Conn
|
||||||
}
|
}
|
||||||
|
|
||||||
// Client represents a RPC client.
|
// Client represents a RPC client.
|
||||||
@@ -129,6 +131,11 @@ func (c *Client) RemoteAddr() string {
|
|||||||
return c.Conn.RemoteAddr().String()
|
return c.Conn.RemoteAddr().String()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetConn returns the underlying conn.
|
||||||
|
func (c *Client) GetConn() net.Conn {
|
||||||
|
return c.Conn
|
||||||
|
}
|
||||||
|
|
||||||
// Option contains all options for creating clients.
|
// Option contains all options for creating clients.
|
||||||
type Option struct {
|
type Option struct {
|
||||||
// Group is used to select the services in the same group. Services set group info in their meta.
|
// Group is used to select the services in the same group. Services set group info in their meta.
|
||||||
|
|||||||
+81
-38
@@ -53,6 +53,15 @@ type XClient interface {
|
|||||||
DownloadFile(ctx context.Context, requestFileName string, saveTo io.Writer, meta map[string]string) error
|
DownloadFile(ctx context.Context, requestFileName string, saveTo io.Writer, meta map[string]string) error
|
||||||
Stream(ctx context.Context, meta map[string]string) (net.Conn, error)
|
Stream(ctx context.Context, meta map[string]string) (net.Conn, error)
|
||||||
Close() error
|
Close() error
|
||||||
|
|
||||||
|
RegisterCacheClientBuilder(network string, builder CacheClientBuilder)
|
||||||
|
}
|
||||||
|
|
||||||
|
type CacheClientBuilder interface {
|
||||||
|
setCachedClient(client RPCClient, k, servicePath, serviceMethod string)
|
||||||
|
findCachedClient(k, servicePath, serviceMethod string) RPCClient
|
||||||
|
deleteCachedClient(client RPCClient, k, servicePath, serviceMethod string)
|
||||||
|
generateClient(k, servicePath, serviceMethod string) (client RPCClient, err error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// KVPair contains a key and a string.
|
// KVPair contains a key and a string.
|
||||||
@@ -84,10 +93,11 @@ type xClient struct {
|
|||||||
servicePath string
|
servicePath string
|
||||||
option Option
|
option Option
|
||||||
|
|
||||||
mu sync.RWMutex
|
mu sync.RWMutex
|
||||||
servers map[string]string
|
servers map[string]string
|
||||||
discovery ServiceDiscovery
|
discovery ServiceDiscovery
|
||||||
selector Selector
|
selector Selector
|
||||||
|
cacheClientBuilders map[string]CacheClientBuilder
|
||||||
|
|
||||||
slGroup singleflight.Group
|
slGroup singleflight.Group
|
||||||
|
|
||||||
@@ -106,12 +116,13 @@ type xClient struct {
|
|||||||
// NewXClient creates a XClient that supports service discovery and service governance.
|
// NewXClient creates a XClient that supports service discovery and service governance.
|
||||||
func NewXClient(servicePath string, failMode FailMode, selectMode SelectMode, discovery ServiceDiscovery, option Option) XClient {
|
func NewXClient(servicePath string, failMode FailMode, selectMode SelectMode, discovery ServiceDiscovery, option Option) XClient {
|
||||||
client := &xClient{
|
client := &xClient{
|
||||||
failMode: failMode,
|
failMode: failMode,
|
||||||
selectMode: selectMode,
|
selectMode: selectMode,
|
||||||
discovery: discovery,
|
discovery: discovery,
|
||||||
servicePath: servicePath,
|
servicePath: servicePath,
|
||||||
cachedClient: make(map[string]RPCClient),
|
cachedClient: make(map[string]RPCClient),
|
||||||
option: option,
|
cacheClientBuilders: make(map[string]CacheClientBuilder),
|
||||||
|
option: option,
|
||||||
}
|
}
|
||||||
|
|
||||||
pairs := discovery.GetServices()
|
pairs := discovery.GetServices()
|
||||||
@@ -171,6 +182,12 @@ func NewBidirectionalXClient(servicePath string, failMode FailMode, selectMode S
|
|||||||
return client
|
return client
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *xClient) RegisterCacheClientBuilder(network string, builder CacheClientBuilder) {
|
||||||
|
c.mu.Lock()
|
||||||
|
c.mu.Unlock()
|
||||||
|
c.cacheClientBuilders[network] = builder
|
||||||
|
}
|
||||||
|
|
||||||
// SetSelector sets customized selector by users.
|
// SetSelector sets customized selector by users.
|
||||||
func (c *xClient) SetSelector(s Selector) {
|
func (c *xClient) SetSelector(s Selector) {
|
||||||
c.mu.RLock()
|
c.mu.RLock()
|
||||||
@@ -255,7 +272,7 @@ func (c *xClient) getCachedClient(k string, servicePath, serviceMethod string, a
|
|||||||
var needCallPlugin bool
|
var needCallPlugin bool
|
||||||
defer func() {
|
defer func() {
|
||||||
if needCallPlugin {
|
if needCallPlugin {
|
||||||
c.Plugins.DoClientConnected((client.(*Client)).Conn)
|
c.Plugins.DoClientConnected(client.GetConn())
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
c.mu.Lock()
|
c.mu.Lock()
|
||||||
@@ -302,20 +319,52 @@ func (c *xClient) getCachedClient(k string, servicePath, serviceMethod string, a
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *xClient) setCachedClient(client RPCClient, k, servicePath, serviceMethod string) {
|
func (c *xClient) setCachedClient(client RPCClient, k, servicePath, serviceMethod string) {
|
||||||
|
network, _ := splitNetworkAndAddress(k)
|
||||||
|
if builder, ok := c.cacheClientBuilders[network]; ok {
|
||||||
|
builder.setCachedClient(client, k, servicePath, serviceMethod)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
c.cachedClient[k] = client
|
c.cachedClient[k] = client
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *xClient) findCachedClient(k, servicePath, serviceMethod string) RPCClient {
|
func (c *xClient) findCachedClient(k, servicePath, serviceMethod string) RPCClient {
|
||||||
|
network, _ := splitNetworkAndAddress(k)
|
||||||
|
if builder, ok := c.cacheClientBuilders[network]; ok {
|
||||||
|
return builder.findCachedClient(k, servicePath, serviceMethod)
|
||||||
|
}
|
||||||
|
|
||||||
return c.cachedClient[k]
|
return c.cachedClient[k]
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *xClient) deleteCachedClient(client RPCClient, k, servicePath, serviceMethod string) {
|
func (c *xClient) deleteCachedClient(client RPCClient, k, servicePath, serviceMethod string) {
|
||||||
|
network, _ := splitNetworkAndAddress(k)
|
||||||
|
if builder, ok := c.cacheClientBuilders[network]; ok && client != nil {
|
||||||
|
builder.deleteCachedClient(client, k, servicePath, serviceMethod)
|
||||||
|
client.Close()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
delete(c.cachedClient, k)
|
delete(c.cachedClient, k)
|
||||||
if client != nil {
|
if client != nil {
|
||||||
client.Close()
|
client.Close()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *xClient) removeClient(k, servicePath, serviceMethod string, client RPCClient) {
|
||||||
|
c.mu.Lock()
|
||||||
|
cl := c.findCachedClient(k, servicePath, serviceMethod)
|
||||||
|
if cl == client {
|
||||||
|
c.deleteCachedClient(client, k, servicePath, serviceMethod)
|
||||||
|
}
|
||||||
|
c.mu.Unlock()
|
||||||
|
|
||||||
|
if client != nil {
|
||||||
|
client.UnregisterServerMessageChan()
|
||||||
|
client.Close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (c *xClient) generateClient(k, servicePath, serviceMethod string) (client RPCClient, err error) {
|
func (c *xClient) generateClient(k, servicePath, serviceMethod string) (client RPCClient, err error) {
|
||||||
client = &Client{
|
client = &Client{
|
||||||
option: c.option,
|
option: c.option,
|
||||||
@@ -339,51 +388,45 @@ func (c *xClient) generateClient(k, servicePath, serviceMethod string) (client R
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *xClient) getCachedClientWithoutLock(k, servicePath, serviceMethod string) (RPCClient, error) {
|
func (c *xClient) getCachedClientWithoutLock(k, servicePath, serviceMethod string) (RPCClient, error) {
|
||||||
client := c.cachedClient[k]
|
client := c.findCachedClient(k, servicePath, serviceMethod)
|
||||||
if client != nil {
|
if client != nil {
|
||||||
if !client.IsClosing() && !client.IsShutdown() {
|
if !client.IsClosing() && !client.IsShutdown() {
|
||||||
return client, nil
|
return client, nil
|
||||||
}
|
}
|
||||||
delete(c.cachedClient, k)
|
c.deleteCachedClient(client, k, servicePath, serviceMethod)
|
||||||
client.Close()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// double check
|
var needCallPlugin bool
|
||||||
client = c.cachedClient[k]
|
defer func() {
|
||||||
if client == nil || client.IsShutdown() {
|
if needCallPlugin {
|
||||||
network, addr := splitNetworkAndAddress(k)
|
c.Plugins.DoClientConnected(client.GetConn())
|
||||||
|
|
||||||
client = &Client{
|
|
||||||
option: c.option,
|
|
||||||
Plugins: c.Plugins,
|
|
||||||
}
|
}
|
||||||
err := client.Connect(network, addr)
|
}()
|
||||||
|
|
||||||
|
// double check
|
||||||
|
client = c.findCachedClient(k, servicePath, serviceMethod)
|
||||||
|
if client == nil || client.IsShutdown() {
|
||||||
|
generatedClient, err, _ := c.slGroup.Do(k, func() (interface{}, error) {
|
||||||
|
return c.generateClient(k, servicePath, serviceMethod)
|
||||||
|
})
|
||||||
|
c.slGroup.Forget(k)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
client = generatedClient.(RPCClient)
|
||||||
|
if c.Plugins != nil {
|
||||||
|
needCallPlugin = true
|
||||||
|
}
|
||||||
|
|
||||||
client.RegisterServerMessageChan(c.serverMessageChan)
|
client.RegisterServerMessageChan(c.serverMessageChan)
|
||||||
|
|
||||||
c.cachedClient[k] = client
|
c.setCachedClient(client, k, servicePath, serviceMethod)
|
||||||
}
|
}
|
||||||
|
|
||||||
return client, nil
|
return client, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *xClient) removeClient(k, servicePath, serviceMethod string, client RPCClient) {
|
|
||||||
c.mu.Lock()
|
|
||||||
cl := c.cachedClient[k]
|
|
||||||
if cl == client {
|
|
||||||
delete(c.cachedClient, k)
|
|
||||||
}
|
|
||||||
c.mu.Unlock()
|
|
||||||
|
|
||||||
if client != nil {
|
|
||||||
client.UnregisterServerMessageChan()
|
|
||||||
client.Close()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func splitNetworkAndAddress(server string) (string, string) {
|
func splitNetworkAndAddress(server string) (string, string) {
|
||||||
ss := strings.SplitN(server, "@", 2)
|
ss := strings.SplitN(server, "@", 2)
|
||||||
if len(ss) == 1 {
|
if len(ss) == 1 {
|
||||||
|
|||||||
Reference in New Issue
Block a user