Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in / Register
Toggle navigation
B
brpc
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
Packages
Packages
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
submodule
brpc
Commits
e784526a
Commit
e784526a
authored
Nov 28, 2019
by
jamesge
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Support multiple discovery nodes
parent
12e73e1d
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
86 additions
and
44 deletions
+86
-44
discovery_naming_service.cpp
src/brpc/policy/discovery_naming_service.cpp
+80
-39
discovery_naming_service.h
src/brpc/policy/discovery_naming_service.h
+6
-2
brpc_naming_service_unittest.cpp
test/brpc_naming_service_unittest.cpp
+0
-3
No files found.
src/brpc/policy/discovery_naming_service.cpp
View file @
e784526a
...
@@ -48,12 +48,32 @@ DEFINE_int32(discovery_reregister_threshold, 3, "The renew error threshold beyon
...
@@ -48,12 +48,32 @@ DEFINE_int32(discovery_reregister_threshold, 3, "The renew error threshold beyon
static
pthread_once_t
s_init_discovery_channel_once
=
PTHREAD_ONCE_INIT
;
static
pthread_once_t
s_init_discovery_channel_once
=
PTHREAD_ONCE_INIT
;
static
Channel
*
s_discovery_channel
=
NULL
;
static
Channel
*
s_discovery_channel
=
NULL
;
int
ParseNodesResult
(
const
butil
::
IOBuf
&
buf
,
std
::
string
*
server_addr
)
{
static
int
ListDiscoveryNodes
(
const
char
*
discovery_api_addr
,
std
::
string
*
servers
)
{
Channel
api_channel
;
ChannelOptions
channel_options
;
channel_options
.
protocol
=
PROTOCOL_HTTP
;
channel_options
.
timeout_ms
=
FLAGS_discovery_timeout_ms
;
channel_options
.
connect_timeout_ms
=
FLAGS_discovery_timeout_ms
/
3
;
if
(
api_channel
.
Init
(
discovery_api_addr
,
""
,
&
channel_options
)
!=
0
)
{
LOG
(
FATAL
)
<<
"Fail to init channel to "
<<
discovery_api_addr
;
return
-
1
;
}
Controller
cntl
;
cntl
.
http_request
().
uri
()
=
discovery_api_addr
;
api_channel
.
CallMethod
(
NULL
,
&
cntl
,
NULL
,
NULL
,
NULL
);
if
(
cntl
.
Failed
())
{
LOG
(
FATAL
)
<<
"Fail to access "
<<
cntl
.
http_request
().
uri
()
<<
": "
<<
cntl
.
ErrorText
();
return
-
1
;
}
servers
->
assign
(
"list://"
);
const
std
::
string
response
=
cntl
.
response_attachment
().
to_string
();
BUTIL_RAPIDJSON_NAMESPACE
::
Document
d
;
BUTIL_RAPIDJSON_NAMESPACE
::
Document
d
;
const
std
::
string
response
=
buf
.
to_string
();
d
.
Parse
(
response
.
c_str
());
d
.
Parse
(
response
.
c_str
());
if
(
!
d
.
IsObject
())
{
if
(
!
d
.
IsObject
())
{
LOG
(
ERROR
)
<<
"Fail to parse "
<<
buf
<<
" as json object"
;
LOG
(
ERROR
)
<<
"Fail to parse "
<<
response
<<
" as json object"
;
return
-
1
;
return
-
1
;
}
}
auto
itr
=
d
.
FindMember
(
"data"
);
auto
itr
=
d
.
FindMember
(
"data"
);
...
@@ -77,50 +97,39 @@ int ParseNodesResult(const butil::IOBuf& buf, std::string* server_addr) {
...
@@ -77,50 +97,39 @@ int ParseNodesResult(const butil::IOBuf& buf, std::string* server_addr) {
itr_status
->
value
.
GetUint
()
!=
0
)
{
itr_status
->
value
.
GetUint
()
!=
0
)
{
continue
;
continue
;
}
}
server_addr
->
assign
(
itr_addr
->
value
.
GetString
(),
servers
->
push_back
(
','
);
servers
->
append
(
itr_addr
->
value
.
GetString
(),
itr_addr
->
value
.
GetStringLength
());
itr_addr
->
value
.
GetStringLength
());
// Currently, we just use the first successful result
break
;
}
}
return
0
;
return
0
;
}
}
static
void
InitDiscoveryChannel
()
{
static
void
NewDiscoveryChannel
()
{
Channel
api_channel
;
// NOTE: Newly added discovery server is NOT detected until this server
// is restarted. The reasons for this design is that NS cluster rarely
// changes. Although we could detect new discovery servers by implmenenting
// a NamingService, however which is too heavy for solving such a rare case.
std
::
string
discovery_servers
;
if
(
ListDiscoveryNodes
(
FLAGS_discovery_api_addr
.
c_str
(),
&
discovery_servers
)
!=
0
)
{
LOG
(
ERROR
)
<<
"Fail to get discovery nodes from "
<<
FLAGS_discovery_api_addr
;
return
;
}
ChannelOptions
channel_options
;
ChannelOptions
channel_options
;
channel_options
.
protocol
=
PROTOCOL_HTTP
;
channel_options
.
protocol
=
PROTOCOL_HTTP
;
channel_options
.
timeout_ms
=
FLAGS_discovery_timeout_ms
;
channel_options
.
timeout_ms
=
FLAGS_discovery_timeout_ms
;
channel_options
.
connect_timeout_ms
=
FLAGS_discovery_timeout_ms
/
3
;
channel_options
.
connect_timeout_ms
=
FLAGS_discovery_timeout_ms
/
3
;
if
(
api_channel
.
Init
(
FLAGS_discovery_api_addr
.
c_str
(),
""
,
&
channel_options
)
!=
0
)
{
LOG
(
FATAL
)
<<
"Fail to init channel to "
<<
FLAGS_discovery_api_addr
;
return
;
}
Controller
cntl
;
cntl
.
http_request
().
uri
()
=
FLAGS_discovery_api_addr
;
api_channel
.
CallMethod
(
NULL
,
&
cntl
,
NULL
,
NULL
,
NULL
);
if
(
cntl
.
Failed
())
{
LOG
(
FATAL
)
<<
"Fail to access "
<<
cntl
.
http_request
().
uri
()
<<
": "
<<
cntl
.
ErrorText
();
return
;
}
std
::
string
discovery_addr
;
if
(
ParseNodesResult
(
cntl
.
response_attachment
(),
&
discovery_addr
)
!=
0
)
{
LOG
(
FATAL
)
<<
"Fail to parse nodes result from discovery api server"
;
return
;
}
s_discovery_channel
=
new
Channel
;
s_discovery_channel
=
new
Channel
;
if
(
s_discovery_channel
->
Init
(
discovery_
addr
.
c_str
(),
"
"
,
&
channel_options
)
!=
0
)
{
if
(
s_discovery_channel
->
Init
(
discovery_
servers
.
c_str
(),
"rr
"
,
&
channel_options
)
!=
0
)
{
LOG
(
FATAL
)
<<
"Fail to init channel to "
<<
discovery_addr
;
LOG
(
ERROR
)
<<
"Fail to init channel to "
<<
discovery_servers
;
return
;
return
;
}
}
}
}
Channel
*
Get
DiscoveryChannel
()
{
inline
Channel
*
GetOrNew
DiscoveryChannel
()
{
pthread_once
(
&
s_init_discovery_channel_once
,
Init
DiscoveryChannel
);
pthread_once
(
&
s_init_discovery_channel_once
,
New
DiscoveryChannel
);
return
s_discovery_channel
;
return
s_discovery_channel
;
}
}
bool
DiscoveryRegisterParam
::
IsValid
()
const
{
bool
DiscoveryRegisterParam
::
IsValid
()
const
{
return
!
appid
.
empty
()
&&
!
hostname
.
empty
()
&&
!
addrs
.
empty
()
&&
return
!
appid
.
empty
()
&&
!
hostname
.
empty
()
&&
!
addrs
.
empty
()
&&
!
env
.
empty
()
&&
!
zone
.
empty
()
&&
!
version
.
empty
();
!
env
.
empty
()
&&
!
zone
.
empty
()
&&
!
version
.
empty
();
...
@@ -138,7 +147,7 @@ DiscoveryClient::~DiscoveryClient() {
...
@@ -138,7 +147,7 @@ DiscoveryClient::~DiscoveryClient() {
}
}
}
}
int
ParseCommonResult
(
const
butil
::
IOBuf
&
buf
,
std
::
string
*
error_text
)
{
static
int
ParseCommonResult
(
const
butil
::
IOBuf
&
buf
,
std
::
string
*
error_text
)
{
const
std
::
string
s
=
buf
.
to_string
();
const
std
::
string
s
=
buf
.
to_string
();
BUTIL_RAPIDJSON_NAMESPACE
::
Document
d
;
BUTIL_RAPIDJSON_NAMESPACE
::
Document
d
;
d
.
Parse
(
s
.
c_str
());
d
.
Parse
(
s
.
c_str
());
...
@@ -161,6 +170,17 @@ int ParseCommonResult(const butil::IOBuf& buf, std::string* error_text) {
...
@@ -161,6 +170,17 @@ int ParseCommonResult(const butil::IOBuf& buf, std::string* error_text) {
}
}
int
DiscoveryClient
::
DoRenew
()
const
{
int
DiscoveryClient
::
DoRenew
()
const
{
// May create short connections which are OK.
ChannelOptions
channel_options
;
channel_options
.
protocol
=
PROTOCOL_HTTP
;
channel_options
.
timeout_ms
=
FLAGS_discovery_timeout_ms
;
channel_options
.
connect_timeout_ms
=
FLAGS_discovery_timeout_ms
/
3
;
Channel
chan
;
if
(
chan
.
Init
(
_current_discovery_server
,
&
channel_options
)
!=
0
)
{
LOG
(
FATAL
)
<<
"Fail to init channel to "
<<
_current_discovery_server
;
return
-
1
;
}
Controller
cntl
;
Controller
cntl
;
cntl
.
http_request
().
set_method
(
HTTP_METHOD_POST
);
cntl
.
http_request
().
set_method
(
HTTP_METHOD_POST
);
cntl
.
http_request
().
uri
()
=
"/discovery/renew"
;
cntl
.
http_request
().
uri
()
=
"/discovery/renew"
;
...
@@ -172,7 +192,7 @@ int DiscoveryClient::DoRenew() const {
...
@@ -172,7 +192,7 @@ int DiscoveryClient::DoRenew() const {
<<
"®ion="
<<
_params
.
region
<<
"®ion="
<<
_params
.
region
<<
"&zone="
<<
_params
.
zone
;
<<
"&zone="
<<
_params
.
zone
;
os
.
move_to
(
cntl
.
request_attachment
());
os
.
move_to
(
cntl
.
request_attachment
());
GetDiscoveryChannel
()
->
CallMethod
(
NULL
,
&
cntl
,
NULL
,
NULL
,
NULL
);
chan
.
CallMethod
(
NULL
,
&
cntl
,
NULL
,
NULL
,
NULL
);
if
(
cntl
.
Failed
())
{
if
(
cntl
.
Failed
())
{
LOG
(
ERROR
)
<<
"Fail to post /discovery/renew: "
<<
cntl
.
ErrorText
();
LOG
(
ERROR
)
<<
"Fail to post /discovery/renew: "
<<
cntl
.
ErrorText
();
return
-
1
;
return
-
1
;
...
@@ -219,15 +239,15 @@ void* DiscoveryClient::PeriodicRenew(void* arg) {
...
@@ -219,15 +239,15 @@ void* DiscoveryClient::PeriodicRenew(void* arg) {
return
NULL
;
return
NULL
;
}
}
int
DiscoveryClient
::
Register
(
const
DiscoveryRegisterParam
&
req
)
{
int
DiscoveryClient
::
Register
(
const
DiscoveryRegisterParam
&
params
)
{
if
(
_registered
.
load
(
butil
::
memory_order_relaxed
)
||
if
(
_registered
.
load
(
butil
::
memory_order_relaxed
)
||
_registered
.
exchange
(
true
,
butil
::
memory_order_release
))
{
_registered
.
exchange
(
true
,
butil
::
memory_order_release
))
{
return
0
;
return
0
;
}
}
if
(
!
req
.
IsValid
())
{
if
(
!
params
.
IsValid
())
{
return
-
1
;
return
-
1
;
}
}
_params
=
req
;
_params
=
params
;
if
(
DoRegister
()
!=
0
)
{
if
(
DoRegister
()
!=
0
)
{
return
-
1
;
return
-
1
;
...
@@ -239,7 +259,12 @@ int DiscoveryClient::Register(const DiscoveryRegisterParam& req) {
...
@@ -239,7 +259,12 @@ int DiscoveryClient::Register(const DiscoveryRegisterParam& req) {
return
0
;
return
0
;
}
}
int
DiscoveryClient
::
DoRegister
()
const
{
int
DiscoveryClient
::
DoRegister
()
{
Channel
*
chan
=
GetOrNewDiscoveryChannel
();
if
(
NULL
==
chan
)
{
LOG
(
ERROR
)
<<
"Fail to create discovery channel"
;
return
-
1
;
}
Controller
cntl
;
Controller
cntl
;
cntl
.
http_request
().
set_method
(
HTTP_METHOD_POST
);
cntl
.
http_request
().
set_method
(
HTTP_METHOD_POST
);
cntl
.
http_request
().
uri
()
=
"/discovery/register"
;
cntl
.
http_request
().
uri
()
=
"/discovery/register"
;
...
@@ -255,7 +280,7 @@ int DiscoveryClient::DoRegister() const {
...
@@ -255,7 +280,7 @@ int DiscoveryClient::DoRegister() const {
<<
"&version="
<<
_params
.
version
<<
"&version="
<<
_params
.
version
<<
"&metadata="
<<
_params
.
metadata
;
<<
"&metadata="
<<
_params
.
metadata
;
os
.
move_to
(
cntl
.
request_attachment
());
os
.
move_to
(
cntl
.
request_attachment
());
GetDiscoveryChannel
()
->
CallMethod
(
NULL
,
&
cntl
,
NULL
,
NULL
,
NULL
);
chan
->
CallMethod
(
NULL
,
&
cntl
,
NULL
,
NULL
,
NULL
);
if
(
cntl
.
Failed
())
{
if
(
cntl
.
Failed
())
{
LOG
(
ERROR
)
<<
"Fail to register "
<<
_params
.
appid
<<
": "
<<
cntl
.
ErrorText
();
LOG
(
ERROR
)
<<
"Fail to register "
<<
_params
.
appid
<<
": "
<<
cntl
.
ErrorText
();
return
-
1
;
return
-
1
;
...
@@ -266,10 +291,22 @@ int DiscoveryClient::DoRegister() const {
...
@@ -266,10 +291,22 @@ int DiscoveryClient::DoRegister() const {
<<
": "
<<
error_text
;
<<
": "
<<
error_text
;
return
-
1
;
return
-
1
;
}
}
_current_discovery_server
=
cntl
.
remote_side
();
return
0
;
return
0
;
}
}
int
DiscoveryClient
::
DoCancel
()
const
{
int
DiscoveryClient
::
DoCancel
()
const
{
// May create short connections which are OK.
ChannelOptions
channel_options
;
channel_options
.
protocol
=
PROTOCOL_HTTP
;
channel_options
.
timeout_ms
=
FLAGS_discovery_timeout_ms
;
channel_options
.
connect_timeout_ms
=
FLAGS_discovery_timeout_ms
/
3
;
Channel
chan
;
if
(
chan
.
Init
(
_current_discovery_server
,
&
channel_options
)
!=
0
)
{
LOG
(
FATAL
)
<<
"Fail to init channel to "
<<
_current_discovery_server
;
return
-
1
;
}
Controller
cntl
;
Controller
cntl
;
cntl
.
http_request
().
set_method
(
HTTP_METHOD_POST
);
cntl
.
http_request
().
set_method
(
HTTP_METHOD_POST
);
cntl
.
http_request
().
uri
()
=
"/discovery/cancel"
;
cntl
.
http_request
().
uri
()
=
"/discovery/cancel"
;
...
@@ -281,7 +318,7 @@ int DiscoveryClient::DoCancel() const {
...
@@ -281,7 +318,7 @@ int DiscoveryClient::DoCancel() const {
<<
"®ion="
<<
_params
.
region
<<
"®ion="
<<
_params
.
region
<<
"&zone="
<<
_params
.
zone
;
<<
"&zone="
<<
_params
.
zone
;
os
.
move_to
(
cntl
.
request_attachment
());
os
.
move_to
(
cntl
.
request_attachment
());
GetDiscoveryChannel
()
->
CallMethod
(
NULL
,
&
cntl
,
NULL
,
NULL
,
NULL
);
chan
.
CallMethod
(
NULL
,
&
cntl
,
NULL
,
NULL
,
NULL
);
if
(
cntl
.
Failed
())
{
if
(
cntl
.
Failed
())
{
LOG
(
ERROR
)
<<
"Fail to post /discovery/cancel: "
<<
cntl
.
ErrorText
();
LOG
(
ERROR
)
<<
"Fail to post /discovery/cancel: "
<<
cntl
.
ErrorText
();
return
-
1
;
return
-
1
;
...
@@ -305,12 +342,16 @@ int DiscoveryNamingService::GetServers(const char* service_name,
...
@@ -305,12 +342,16 @@ int DiscoveryNamingService::GetServers(const char* service_name,
LOG_ONCE
(
ERROR
)
<<
"Invalid parameters"
;
LOG_ONCE
(
ERROR
)
<<
"Invalid parameters"
;
return
-
1
;
return
-
1
;
}
}
Channel
*
chan
=
GetOrNewDiscoveryChannel
();
if
(
NULL
==
chan
)
{
LOG
(
ERROR
)
<<
"Fail to create discovery channel"
;
}
servers
->
clear
();
servers
->
clear
();
Controller
cntl
;
Controller
cntl
;
cntl
.
http_request
().
uri
()
=
butil
::
string_printf
(
cntl
.
http_request
().
uri
()
=
butil
::
string_printf
(
"/discovery/fetchs?appid=%s&env=%s&status=%s"
,
service_name
,
"/discovery/fetchs?appid=%s&env=%s&status=%s"
,
service_name
,
FLAGS_discovery_env
.
c_str
(),
FLAGS_discovery_status
.
c_str
());
FLAGS_discovery_env
.
c_str
(),
FLAGS_discovery_status
.
c_str
());
GetDiscoveryChannel
()
->
CallMethod
(
NULL
,
&
cntl
,
NULL
,
NULL
,
NULL
);
chan
->
CallMethod
(
NULL
,
&
cntl
,
NULL
,
NULL
,
NULL
);
if
(
cntl
.
Failed
())
{
if
(
cntl
.
Failed
())
{
LOG
(
ERROR
)
<<
"Fail to get /discovery/fetchs: "
<<
cntl
.
ErrorText
();
LOG
(
ERROR
)
<<
"Fail to get /discovery/fetchs: "
<<
cntl
.
ErrorText
();
return
-
1
;
return
-
1
;
...
...
src/brpc/policy/discovery_naming_service.h
View file @
e784526a
...
@@ -44,24 +44,28 @@ struct DiscoveryRegisterParam {
...
@@ -44,24 +44,28 @@ struct DiscoveryRegisterParam {
// ONE DiscoveryClient corresponds to ONE service instance.
// ONE DiscoveryClient corresponds to ONE service instance.
// If your program has multiple service instances to register,
// If your program has multiple service instances to register,
// you need multiple DiscoveryClient.
// you need multiple DiscoveryClient.
// Note:
Unregist
er is automatically called in dtor.
// Note:
Cancel to the serv
er is automatically called in dtor.
class
DiscoveryClient
{
class
DiscoveryClient
{
public
:
public
:
DiscoveryClient
();
DiscoveryClient
();
~
DiscoveryClient
();
~
DiscoveryClient
();
// Initialize this client.
// Returns 0 on success.
// NOTE: Calling more than once does nothing and returns 0.
int
Register
(
const
DiscoveryRegisterParam
&
req
);
int
Register
(
const
DiscoveryRegisterParam
&
req
);
private
:
private
:
static
void
*
PeriodicRenew
(
void
*
arg
);
static
void
*
PeriodicRenew
(
void
*
arg
);
int
DoCancel
()
const
;
int
DoCancel
()
const
;
int
DoRegister
()
const
;
int
DoRegister
();
int
DoRenew
()
const
;
int
DoRenew
()
const
;
private
:
private
:
bthread_t
_th
;
bthread_t
_th
;
butil
::
atomic
<
bool
>
_registered
;
butil
::
atomic
<
bool
>
_registered
;
DiscoveryRegisterParam
_params
;
DiscoveryRegisterParam
_params
;
butil
::
EndPoint
_current_discovery_server
;
};
};
class
DiscoveryNamingService
:
public
PeriodicNamingService
{
class
DiscoveryNamingService
:
public
PeriodicNamingService
{
...
...
test/brpc_naming_service_unittest.cpp
View file @
e784526a
...
@@ -46,9 +46,6 @@ DECLARE_string(discovery_api_addr);
...
@@ -46,9 +46,6 @@ DECLARE_string(discovery_api_addr);
DECLARE_string
(
discovery_env
);
DECLARE_string
(
discovery_env
);
DECLARE_int32
(
discovery_renew_interval_s
);
DECLARE_int32
(
discovery_renew_interval_s
);
// Defined in discovery_naming_service.cpp
int
ParseNodesResult
(
const
butil
::
IOBuf
&
buf
,
std
::
string
*
server_addr
);
}
// policy
}
// policy
}
// brpc
}
// brpc
...
...
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