Skip to content
Snippets Groups Projects
Commit 66845eb5 authored by Ming Deng's avatar Ming Deng Committed by GitHub
Browse files

Merge pull request #394 from Patrick0308/rest

Fix Rest Protocol
parents 3f9666be 4330dae0
No related branches found
No related tags found
No related merge requests found
......@@ -32,10 +32,8 @@ import (
)
var (
restConsumerConfig *rest_interface.RestConsumerConfig
restProviderConfig *rest_interface.RestProviderConfig
restConsumerServiceConfigMap map[string]*rest_interface.RestConfig
restProviderServiceConfigMap map[string]*rest_interface.RestConfig
restConsumerServiceConfigMap map[string]*rest_interface.RestServiceConfig
restProviderServiceConfigMap map[string]*rest_interface.RestServiceConfig
)
func init() {
......@@ -46,12 +44,12 @@ func init() {
func initConsumerRestConfig() {
consumerConfigType := config.GetConsumerConfig().RestConfigType
consumerConfigReader := extension.GetSingletonRestConfigReader(consumerConfigType)
restConsumerConfig = consumerConfigReader.ReadConsumerConfig()
restConsumerConfig := consumerConfigReader.ReadConsumerConfig()
if restConsumerConfig == nil {
return
}
restConsumerServiceConfigMap = make(map[string]*rest_interface.RestConfig, len(restConsumerConfig.RestConfigMap))
for key, rc := range restConsumerConfig.RestConfigMap {
restConsumerServiceConfigMap = make(map[string]*rest_interface.RestServiceConfig, len(restConsumerConfig.RestServiceConfigsMap))
for key, rc := range restConsumerConfig.RestServiceConfigsMap {
rc.Client = getNotEmptyStr(rc.Client, restConsumerConfig.Client, constant.DEFAULT_REST_CLIENT)
rc.RestMethodConfigsMap = initMethodConfigMap(rc, restConsumerConfig.Consumes, restConsumerConfig.Produces)
restConsumerServiceConfigMap[strings.TrimPrefix(key, "/")] = rc
......@@ -61,19 +59,19 @@ func initConsumerRestConfig() {
func initProviderRestConfig() {
providerConfigType := config.GetProviderConfig().RestConfigType
providerConfigReader := extension.GetSingletonRestConfigReader(providerConfigType)
restProviderConfig = providerConfigReader.ReadProviderConfig()
restProviderConfig := providerConfigReader.ReadProviderConfig()
if restProviderConfig == nil {
return
}
restProviderServiceConfigMap = make(map[string]*rest_interface.RestConfig, len(restProviderConfig.RestConfigMap))
for key, rc := range restProviderConfig.RestConfigMap {
restProviderServiceConfigMap = make(map[string]*rest_interface.RestServiceConfig, len(restProviderConfig.RestServiceConfigsMap))
for key, rc := range restProviderConfig.RestServiceConfigsMap {
rc.Server = getNotEmptyStr(rc.Server, restProviderConfig.Server, constant.DEFAULT_REST_SERVER)
rc.RestMethodConfigsMap = initMethodConfigMap(rc, restProviderConfig.Consumes, restProviderConfig.Produces)
restProviderServiceConfigMap[strings.TrimPrefix(key, "/")] = rc
}
}
func initMethodConfigMap(rc *rest_interface.RestConfig, consumes string, produces string) map[string]*rest_interface.RestMethodConfig {
func initMethodConfigMap(rc *rest_interface.RestServiceConfig, consumes string, produces string) map[string]*rest_interface.RestMethodConfig {
mcm := make(map[string]*rest_interface.RestMethodConfig, len(rc.RestMethodConfigs))
for _, mc := range rc.RestMethodConfigs {
mc.InterfaceName = rc.InterfaceName
......@@ -139,18 +137,18 @@ func parseParamsString2Map(params string) (map[int]string, error) {
return m, nil
}
func GetRestConsumerServiceConfig(path string) *rest_interface.RestConfig {
func GetRestConsumerServiceConfig(path string) *rest_interface.RestServiceConfig {
return restConsumerServiceConfigMap[path]
}
func GetRestProviderServiceConfig(path string) *rest_interface.RestConfig {
func GetRestProviderServiceConfig(path string) *rest_interface.RestServiceConfig {
return restProviderServiceConfigMap[path]
}
func SetRestConsumerServiceConfigMap(configMap map[string]*rest_interface.RestConfig) {
func SetRestConsumerServiceConfigMap(configMap map[string]*rest_interface.RestServiceConfig) {
restConsumerServiceConfigMap = configMap
}
func SetRestProviderServiceConfigMap(configMap map[string]*rest_interface.RestConfig) {
func SetRestProviderServiceConfigMap(configMap map[string]*rest_interface.RestServiceConfig) {
restProviderServiceConfigMap = configMap
}
......@@ -36,6 +36,15 @@ func TestGetRestConsumerServiceConfig(t *testing.T) {
initConsumerRestConfig()
serviceConfig := GetRestConsumerServiceConfig("UserProvider")
assert.NotEmpty(t, serviceConfig)
assert.NotEmpty(t, serviceConfig.RestMethodConfigsMap)
assert.NotEmpty(t, serviceConfig.RestMethodConfigsMap["GetUser"])
assert.Equal(t, serviceConfig.RestMethodConfigsMap["GetUser"].QueryParamsMap[1], "userid")
assert.Equal(t, serviceConfig.RestMethodConfigsMap["GetUser"].HeadersMap[3], "age")
assert.Equal(t, serviceConfig.RestMethodConfigsMap["GetUser"].PathParamsMap[4], "time")
assert.Equal(t, serviceConfig.RestMethodConfigsMap["GetUser"].Body, 0)
assert.Equal(t, serviceConfig.RestMethodConfigsMap["GetUser"].Produces, "application/xml")
assert.Equal(t, serviceConfig.RestMethodConfigsMap["GetUser"].Consumes, "application/xml")
assert.Equal(t, serviceConfig.Client, "resty1")
}
func TestGetRestProviderServiceConfig(t *testing.T) {
......@@ -44,4 +53,14 @@ func TestGetRestProviderServiceConfig(t *testing.T) {
initProviderRestConfig()
serviceConfig := GetRestProviderServiceConfig("UserProvider")
assert.NotEmpty(t, serviceConfig)
assert.NotEmpty(t, serviceConfig.RestMethodConfigsMap)
assert.NotEmpty(t, serviceConfig.RestMethodConfigsMap["GetUser"])
assert.Equal(t, serviceConfig.RestMethodConfigsMap["GetUser"].QueryParamsMap[1], "userid")
assert.Equal(t, serviceConfig.RestMethodConfigsMap["GetUser"].HeadersMap[3], "age")
assert.Equal(t, serviceConfig.RestMethodConfigsMap["GetUser"].PathParamsMap[4], "time")
assert.Equal(t, serviceConfig.RestMethodConfigsMap["GetUser"].Body, 0)
assert.Equal(t, serviceConfig.RestMethodConfigsMap["GetUser"].Produces, "application/xml")
assert.Equal(t, serviceConfig.RestMethodConfigsMap["GetUser"].Consumes, "application/xml")
assert.Equal(t, serviceConfig.Server, "go-restful1")
}
......@@ -7,6 +7,10 @@ request_timeout : "100ms"
# connect timeout
connect_timeout : "100ms"
check: true
rest_server: "resty"
rest_produces: "*/*"
rest_consumes: "*/*"
# application config
application:
organization : "ikurento.com"
......@@ -35,20 +39,27 @@ references:
"UserProvider":
registry: "hangzhouzk,shanghaizk"
filter: ""
protocol : "dubbo"
protocol : "rest"
version: "1.0"
group: "as"
interface : "com.ikurento.user.UserProvider"
url: "dubbo://127.0.0.1:20000/UserProvider"
cluster: "failover"
timeout: "3s"
rest_client: "resty1"
rest_produces: "application/xml"
rest_consumes: "application/xml"
methods :
- name: "GetUser"
retries: "3"
timeout: "5s"
rest_query_params: "1:userid,2:username"
rest_headrs: "3:age"
rest_headers: "3:age"
rest_path_params: "4:time,2:name"
rest_body: 0
rest_produces: "application/xml"
rest_consumes: "application/xml"
params:
"serviceid":
"soa.com.ikurento.user.UserProvider"
......@@ -58,43 +69,3 @@ shutdown_conf:
timeout: 60s
step_timeout: 10s
protocol_conf:
# when you choose the Dubbo protocol, the following configuration takes effect
dubbo:
reconnect_interval: 0
# reconnect_interval is the actual number of connections a session can use
connection_number: 2
# heartbeat_period is heartbeat interval between server and client connection.
# Effective by client configuration
heartbeat_period: "30s"
# when the session is inactive for more than session_timeout, the session may be closed
session_timeout: "30s"
# a reference has the size of the session connection pool
# that is the maximum number of sessions it may have
pool_size: 4
# dubbo-go uses getty as the network connection library.
# The following is the relevant configuration of getty
pool_ttl: 600
# gr_pool_size is recommended to be set to [cpu core number] * 100
gr_pool_size: 1200
# queue_len is recommended to be set to 64 or 128
queue_len: 64
# queue_number is recommended to be set to gr_pool_size / 20
queue_number: 60
# dubbo-go uses getty as the network connection library.
# The following is the relevant configuration of getty
getty_session_param:
compress_encoding: false
tcp_no_delay: true
tcp_keep_alive: true
keep_alive_period: "120s"
tcp_r_buf_size: 262144
tcp_w_buf_size: 65536
pkg_wq_size: 512
tcp_read_timeout: "1s"
tcp_write_timeout: "5s"
wait_timeout: "1s"
# maximum len of data per request
# this refers to the total amount of data requested or returned
max_msg_len: 102400
session_name: "client"
......@@ -24,6 +24,9 @@ registries :
username: ""
password: ""
rest_server: "go-restful"
rest_produces: "*/*"
rest_consumes: "*/*"
services:
"UserProvider":
......@@ -43,7 +46,7 @@ services:
execute.limit: "200"
# the name of RejectedExecutionHandler
execute.limit.rejected.handler: "default"
protocol : "dubbo"
protocol : "rest"
# equivalent to interface of dubbo.xml
interface : "com.ikurento.user.UserProvider"
loadbalance: "random"
......@@ -51,6 +54,9 @@ services:
group: "as"
warmup: "100"
cluster: "failover"
rest_server: "go-restful1"
rest_produces: "*/*"
rest_consumes: "*/*"
methods:
- name: "GetUser"
retries: 1
......@@ -60,41 +66,19 @@ services:
execute.limit: "200"
# the name of RejectedExecutionHandler
execute.limit.rejected.handler: "default"
rest_query_params: "1:userid,2:username"
rest_headers: "3:age"
rest_path_params: "4:time,2:name"
rest_body: 0
rest_produces: "application/xml"
rest_consumes: "application/xml"
protocols:
"dubbo":
name: "dubbo"
# while using dubbo protocol, ip cannot is 127.0.0.1, because client of java-dubbo will get 'connection refuse'
"rest":
name: "rest"
ip : "127.0.0.1"
port : 20000
#- name: "jsonrpc"
# ip: "127.0.0.1"
# port: 20001
shutdown_conf:
timeout: 60s
step_timeout: 10s
protocol_conf:
dubbo:
session_number: 700
session_timeout: "20s"
# gr_pool_size is recommended to be set to [cpu core number] * 10
gr_pool_size: 120
# queue_len is recommended to be set to 64 or 128
queue_len: 64
# queue_number is recommended to be set to gr_pool_size / 20
queue_number: 6
getty_session_param:
compress_encoding: false
tcp_no_delay: true
tcp_keep_alive: true
keep_alive_period: "120s"
tcp_r_buf_size: 262144
tcp_w_buf_size: 65536
pkg_wq_size: 512
tcp_read_timeout: "1s"
tcp_write_timeout: "5s"
wait_timeout: "1s"
max_msg_len: 1024
session_name: "server"
......@@ -20,10 +20,10 @@ package rest_interface
import "github.com/creasty/defaults"
type RestConsumerConfig struct {
Client string `default:"resty" yaml:"rest_client" json:"rest_client,omitempty" property:"rest_client"`
Produces string `default:"application/json" yaml:"rest_produces" json:"rest_produces,omitempty" property:"rest_produces"`
Consumes string `default:"application/json" yaml:"rest_consumes" json:"rest_consumes,omitempty" property:"rest_consumes"`
RestConfigMap map[string]*RestConfig `yaml:"references" json:"references,omitempty" property:"references"`
Client string `default:"resty" yaml:"rest_client" json:"rest_client,omitempty" property:"rest_client"`
Produces string `default:"application/json" yaml:"rest_produces" json:"rest_produces,omitempty" property:"rest_produces"`
Consumes string `default:"application/json" yaml:"rest_consumes" json:"rest_consumes,omitempty" property:"rest_consumes"`
RestServiceConfigsMap map[string]*RestServiceConfig `yaml:"references" json:"references,omitempty" property:"references"`
}
// UnmarshalYAML ...
......@@ -39,10 +39,10 @@ func (c *RestConsumerConfig) UnmarshalYAML(unmarshal func(interface{}) error) er
}
type RestProviderConfig struct {
Server string `default:"go-restful" yaml:"rest_server" json:"rest_server,omitempty" property:"rest_server"`
Produces string `default:"*/*" yaml:"rest_produces" json:"rest_produces,omitempty" property:"rest_produces"`
Consumes string `default:"*/*" yaml:"rest_consumes" json:"rest_consumes,omitempty" property:"rest_consumes"`
RestConfigMap map[string]*RestConfig `yaml:"services" json:"services,omitempty" property:"services"`
Server string `default:"go-restful" yaml:"rest_server" json:"rest_server,omitempty" property:"rest_server"`
Produces string `default:"*/*" yaml:"rest_produces" json:"rest_produces,omitempty" property:"rest_produces"`
Consumes string `default:"*/*" yaml:"rest_consumes" json:"rest_consumes,omitempty" property:"rest_consumes"`
RestServiceConfigsMap map[string]*RestServiceConfig `yaml:"services" json:"services,omitempty" property:"services"`
}
// UnmarshalYAML ...
......@@ -57,7 +57,7 @@ func (c *RestProviderConfig) UnmarshalYAML(unmarshal func(interface{}) error) er
return nil
}
type RestConfig struct {
type RestServiceConfig struct {
InterfaceName string `required:"true" yaml:"interface" json:"interface,omitempty" property:"interface"`
Url string `yaml:"url" json:"url,omitempty" property:"url"`
Path string `yaml:"rest_path" json:"rest_path,omitempty" property:"rest_path"`
......@@ -71,11 +71,11 @@ type RestConfig struct {
}
// UnmarshalYAML ...
func (c *RestConfig) UnmarshalYAML(unmarshal func(interface{}) error) error {
func (c *RestServiceConfig) UnmarshalYAML(unmarshal func(interface{}) error) error {
if err := defaults.Set(c); err != nil {
return err
}
type plain RestConfig
type plain RestServiceConfig
if err := unmarshal((*plain)(c)); err != nil {
return err
}
......
......@@ -51,7 +51,7 @@ func TestRestInvoker_Invoke(t *testing.T) {
assert.NoError(t, err)
con := config.ProviderConfig{}
config.SetProviderConfig(con)
configMap := make(map[string]*rest_interface.RestConfig)
configMap := make(map[string]*rest_interface.RestServiceConfig)
methodConfigMap := make(map[string]*rest_interface.RestMethodConfig)
queryParamsMap := make(map[int]string)
queryParamsMap[1] = "age"
......@@ -135,7 +135,7 @@ func TestRestInvoker_Invoke(t *testing.T) {
HeadersMap: headersMap,
}
configMap["com.ikurento.user.UserProvider"] = &rest_interface.RestConfig{
configMap["com.ikurento.user.UserProvider"] = &rest_interface.RestServiceConfig{
Server: "go-restful",
RestMethodConfigsMap: methodConfigMap,
}
......@@ -143,8 +143,8 @@ func TestRestInvoker_Invoke(t *testing.T) {
proxyFactory := extension.GetProxyFactory("default")
proto.Export(proxyFactory.GetInvoker(url))
time.Sleep(5 * time.Second)
configMap = make(map[string]*rest_interface.RestConfig)
configMap["com.ikurento.user.UserProvider"] = &rest_interface.RestConfig{
configMap = make(map[string]*rest_interface.RestServiceConfig)
configMap["com.ikurento.user.UserProvider"] = &rest_interface.RestServiceConfig{
RestMethodConfigsMap: methodConfigMap,
}
restClient := rest_client.GetRestyClient(&rest_interface.RestOptions{ConnectTimeout: 3 * time.Second, RequestTimeout: 3 * time.Second})
......@@ -165,24 +165,28 @@ func TestRestInvoker_Invoke(t *testing.T) {
assert.Equal(t, now.Unix(), res.Result().(*User).Time.Unix())
assert.Equal(t, int32(23), res.Result().(*User).Age)
assert.Equal(t, "username", res.Result().(*User).Name)
// test 1
inv = invocation.NewRPCInvocationWithOptions(invocation.WithMethodName("GetUserTwo"),
invocation.WithArguments([]interface{}{&User{1, &now, int32(23), "username"}}), invocation.WithReply(user))
res = invoker.Invoke(context.Background(), inv)
assert.NoError(t, res.Error())
assert.NotNil(t, res.Result())
assert.Equal(t, "username", res.Result().(*User).Name)
// test 2
inv = invocation.NewRPCInvocationWithOptions(invocation.WithMethodName("GetUserThree"),
invocation.WithArguments([]interface{}{&User{1, &now, int32(23), "username"}}), invocation.WithReply(user))
res = invoker.Invoke(context.Background(), inv)
assert.NoError(t, res.Error())
assert.NotNil(t, res.Result())
assert.Equal(t, "username", res.Result().(*User).Name)
// test 3
inv = invocation.NewRPCInvocationWithOptions(invocation.WithMethodName("GetUserFour"),
invocation.WithArguments([]interface{}{[]User{User{1, nil, int32(23), "username"}}}), invocation.WithReply(user))
res = invoker.Invoke(context.Background(), inv)
assert.NoError(t, res.Error())
assert.NotNil(t, res.Result())
assert.Equal(t, "username", res.Result().(*User).Name)
// test 4
inv = invocation.NewRPCInvocationWithOptions(invocation.WithMethodName("GetUserFive"), invocation.WithReply(user))
res = invoker.Invoke(context.Background(), inv)
assert.Error(t, res.Error(), "test error")
......
......@@ -27,6 +27,7 @@ import (
"github.com/apache/dubbo-go/common"
"github.com/apache/dubbo-go/common/constant"
"github.com/apache/dubbo-go/common/extension"
"github.com/apache/dubbo-go/common/logger"
"github.com/apache/dubbo-go/config"
"github.com/apache/dubbo-go/protocol"
"github.com/apache/dubbo-go/protocol/rest/rest_interface"
......@@ -63,10 +64,14 @@ func (rp *RestProtocol) Export(invoker protocol.Invoker) protocol.Exporter {
url := invoker.GetUrl()
serviceKey := url.ServiceKey()
exporter := NewRestExporter(serviceKey, invoker, rp.ExporterMap())
restConfig := GetRestProviderServiceConfig(strings.TrimPrefix(url.Path, "/"))
restServiceConfig := GetRestProviderServiceConfig(strings.TrimPrefix(url.Path, "/"))
if restServiceConfig == nil {
logger.Errorf("%s service doesn't has provider config", url.Path)
return nil
}
rp.SetExporterMap(serviceKey, exporter)
restServer := rp.getServer(url, restConfig)
restServer.Deploy(invoker, restConfig.RestMethodConfigsMap)
restServer := rp.getServer(url, restServiceConfig.Server)
restServer.Deploy(invoker, restServiceConfig.RestMethodConfigsMap)
return exporter
}
......@@ -78,15 +83,19 @@ func (rp *RestProtocol) Refer(url common.URL) protocol.Invoker {
if t, err := time.ParseDuration(requestTimeoutStr); err == nil {
requestTimeout = t
}
restConfig := GetRestConsumerServiceConfig(strings.TrimPrefix(url.Path, "/"))
restServiceConfig := GetRestConsumerServiceConfig(strings.TrimPrefix(url.Path, "/"))
if restServiceConfig == nil {
logger.Errorf("%s service doesn't has consumer config", url.Path)
return nil
}
restOptions := rest_interface.RestOptions{RequestTimeout: requestTimeout, ConnectTimeout: connectTimeout}
restClient := rp.getClient(restOptions, restConfig)
invoker := NewRestInvoker(url, &restClient, restConfig.RestMethodConfigsMap)
restClient := rp.getClient(restOptions, restServiceConfig.Client)
invoker := NewRestInvoker(url, &restClient, restServiceConfig.RestMethodConfigsMap)
rp.SetInvokers(invoker)
return invoker
}
func (rp *RestProtocol) getServer(url common.URL, restConfig *rest_interface.RestConfig) rest_interface.RestServer {
func (rp *RestProtocol) getServer(url common.URL, serverType string) rest_interface.RestServer {
restServer, ok := rp.serverMap[url.Location]
if !ok {
_, ok := rp.ExporterMap().Load(url.ServiceKey())
......@@ -96,7 +105,7 @@ func (rp *RestProtocol) getServer(url common.URL, restConfig *rest_interface.Res
rp.serverLock.Lock()
restServer, ok = rp.serverMap[url.Location]
if !ok {
restServer = extension.GetNewRestServer(restConfig.Server)
restServer = extension.GetNewRestServer(serverType)
restServer.Start(url)
rp.serverMap[url.Location] = restServer
}
......@@ -106,13 +115,13 @@ func (rp *RestProtocol) getServer(url common.URL, restConfig *rest_interface.Res
return restServer
}
func (rp *RestProtocol) getClient(restOptions rest_interface.RestOptions, restConfig *rest_interface.RestConfig) rest_interface.RestClient {
func (rp *RestProtocol) getClient(restOptions rest_interface.RestOptions, clientType string) rest_interface.RestClient {
restClient, ok := rp.clientMap[restOptions]
rp.clientLock.Lock()
if !ok {
restClient, ok = rp.clientMap[restOptions]
if !ok {
restClient = extension.GetNewRestClient(restConfig.Client, &restOptions)
restClient = extension.GetNewRestClient(clientType, &restOptions)
rp.clientMap[restOptions] = restClient
}
}
......
......@@ -52,8 +52,8 @@ func TestRestProtocol_Refer(t *testing.T) {
RequestTimeout: 5 * time.Second,
}
config.SetConsumerConfig(con)
configMap := make(map[string]*rest_interface.RestConfig)
configMap["com.ikurento.user.UserProvider"] = &rest_interface.RestConfig{
configMap := make(map[string]*rest_interface.RestServiceConfig)
configMap["com.ikurento.user.UserProvider"] = &rest_interface.RestServiceConfig{
Client: "resty",
}
SetRestConsumerServiceConfigMap(configMap)
......@@ -84,7 +84,7 @@ func TestRestProtocol_Export(t *testing.T) {
assert.NoError(t, err)
con := config.ProviderConfig{}
config.SetProviderConfig(con)
configMap := make(map[string]*rest_interface.RestConfig)
configMap := make(map[string]*rest_interface.RestServiceConfig)
methodConfigMap := make(map[string]*rest_interface.RestMethodConfig)
queryParamsMap := make(map[int]string)
queryParamsMap[1] = "age"
......@@ -104,7 +104,7 @@ func TestRestProtocol_Export(t *testing.T) {
QueryParamsMap: queryParamsMap,
Body: -1,
}
configMap["com.ikurento.user.UserProvider"] = &rest_interface.RestConfig{
configMap["com.ikurento.user.UserProvider"] = &rest_interface.RestServiceConfig{
Server: "go-restful",
RestMethodConfigsMap: methodConfigMap,
}
......
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment