Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
thythm
ribbon
提交
7c3e7164
R
ribbon
项目概览
thythm
/
ribbon
与 Fork 源项目一致
从无法访问的项目Fork
通知
3
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
R
ribbon
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
前往新版Gitcode,体验更适合开发者的 AI 搜索 >>
提交
7c3e7164
编写于
5月 22, 2019
作者:
E
elandau
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
config: Fix property resolution when config not loaded
上级
782fb40e
变更
8
隐藏空白更改
内联
并排
Showing
8 changed file
with
87 addition
and
147 deletion
+87
-147
ribbon-archaius/src/main/java/com/netflix/client/config/ArchaiusPropertyResolver.java
...a/com/netflix/client/config/ArchaiusPropertyResolver.java
+1
-1
ribbon-core/src/main/java/com/netflix/client/config/AbstractDefaultClientConfigImpl.java
...etflix/client/config/AbstractDefaultClientConfigImpl.java
+0
-4
ribbon-core/src/main/java/com/netflix/client/config/IClientConfig.java
...rc/main/java/com/netflix/client/config/IClientConfig.java
+0
-7
ribbon-core/src/main/java/com/netflix/client/config/PropertyResolver.java
...main/java/com/netflix/client/config/PropertyResolver.java
+0
-33
ribbon-core/src/main/java/com/netflix/client/config/PropertyUtils.java
...rc/main/java/com/netflix/client/config/PropertyUtils.java
+40
-0
ribbon-core/src/main/java/com/netflix/client/config/ReloadableClientConfig.java
...ava/com/netflix/client/config/ReloadableClientConfig.java
+43
-87
ribbon-core/src/test/java/com/netflix/client/config/ClientConfigTest.java
...test/java/com/netflix/client/config/ClientConfigTest.java
+0
-12
ribbon-core/src/test/java/com/netflix/client/config/DefaultClientConfigImplTest.java
...om/netflix/client/config/DefaultClientConfigImplTest.java
+3
-3
未找到文件。
ribbon-archaius/src/main/java/com/netflix/client/config/ArchaiusPropertyResolver.java
浏览文件 @
7c3e7164
...
...
@@ -64,7 +64,7 @@ public class ArchaiusPropertyResolver implements PropertyResolver {
if
(
type
.
equals
(
String
.
class
))
{
return
(
T
)
value
;
}
else
{
return
Property
Resolver
.
resolveWithValueOf
(
type
,
value
)
return
Property
Utils
.
resolveWithValueOf
(
type
,
value
)
.
orElseThrow
(()
->
new
IllegalArgumentException
(
"Unable to convert value to desired type "
+
type
));
}
});
...
...
ribbon-core/src/main/java/com/netflix/client/config/AbstractDefaultClientConfigImpl.java
浏览文件 @
7c3e7164
...
...
@@ -154,10 +154,6 @@ public abstract class AbstractDefaultClientConfigImpl extends ReloadableClientCo
super
(
resolver
);
}
protected
AbstractDefaultClientConfigImpl
(
PropertyResolver
resolver
,
String
clientName
)
{
super
(
resolver
,
clientName
);
}
public
void
setVipAddressResolver
(
VipAddressResolver
resolver
)
{
this
.
vipResolver
=
resolver
;
}
...
...
ribbon-core/src/main/java/com/netflix/client/config/IClientConfig.java
浏览文件 @
7c3e7164
...
...
@@ -147,13 +147,6 @@ public interface IClientConfig {
*/
<
T
>
Property
<
T
>
getDynamicProperty
(
IClientConfigKey
<
T
>
key
);
/**
* @return Get a property that is only scoped to this client.
*/
default
<
T
>
Property
<
T
>
getScopedProperty
(
IClientConfigKey
<
T
>
key
)
{
throw
new
UnsupportedOperationException
();
}
/**
* @return Return a dynamically updated property that is a mapping of all properties prefixed by the key name to an
* object with static method valueOf(Map{@literal <}String, String{@literal >})
...
...
ribbon-core/src/main/java/com/netflix/client/config/PropertyResolver.java
浏览文件 @
7c3e7164
package
com.netflix.client.config
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
java.lang.reflect.Method
;
import
java.util.Map
;
import
java.util.Optional
;
import
java.util.concurrent.ConcurrentHashMap
;
import
java.util.function.BiConsumer
;
/**
* Internal abstraction to decouple the property source from Ribbon's internal configuration.
*/
public
interface
PropertyResolver
{
Logger
LOG
=
LoggerFactory
.
getLogger
(
PropertyResolver
.
class
);
/**
* @return Get the value of a property or Optional.empty() if not set
*/
...
...
@@ -30,29 +22,4 @@ public interface PropertyResolver {
* @param action
*/
void
onChange
(
Runnable
action
);
/**
* Returns the internal property to the desiredn type
*/
Map
<
Class
<?>,
Optional
<
Method
>>
valueOfMethods
=
new
ConcurrentHashMap
<>();
static
<
T
>
Optional
<
T
>
resolveWithValueOf
(
Class
<
T
>
type
,
String
value
)
{
return
valueOfMethods
.
computeIfAbsent
(
type
,
ignore
->
{
try
{
return
Optional
.
of
(
type
.
getDeclaredMethod
(
"valueOf"
,
String
.
class
));
}
catch
(
NoSuchMethodException
e
)
{
return
Optional
.
empty
();
}
catch
(
Exception
e
)
{
LOG
.
warn
(
"Unable to determine if type "
+
type
+
" has a valueOf() static method"
,
e
);
return
Optional
.
empty
();
}
}).
map
(
method
->
{
try
{
return
(
T
)
method
.
invoke
(
null
,
value
);
}
catch
(
Exception
e
)
{
throw
new
RuntimeException
(
e
);
}
});
}
}
ribbon-core/src/main/java/com/netflix/client/config/PropertyUtils.java
0 → 100644
浏览文件 @
7c3e7164
package
com.netflix.client.config
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
java.lang.reflect.Method
;
import
java.util.Map
;
import
java.util.Optional
;
import
java.util.concurrent.ConcurrentHashMap
;
public
class
PropertyUtils
{
private
static
Logger
LOG
=
LoggerFactory
.
getLogger
(
PropertyUtils
.
class
);
private
PropertyUtils
()
{}
/**
* Returns the internal property to the desiredn type
*/
private
static
Map
<
Class
<?>,
Optional
<
Method
>>
valueOfMethods
=
new
ConcurrentHashMap
<>();
public
static
<
T
>
Optional
<
T
>
resolveWithValueOf
(
Class
<
T
>
type
,
String
value
)
{
return
valueOfMethods
.
computeIfAbsent
(
type
,
ignore
->
{
try
{
return
Optional
.
of
(
type
.
getDeclaredMethod
(
"valueOf"
,
String
.
class
));
}
catch
(
NoSuchMethodException
e
)
{
return
Optional
.
empty
();
}
catch
(
Exception
e
)
{
LOG
.
warn
(
"Unable to determine if type "
+
type
+
" has a valueOf() static method"
,
e
);
return
Optional
.
empty
();
}
}).
map
(
method
->
{
try
{
return
(
T
)
method
.
invoke
(
null
,
value
);
}
catch
(
Exception
e
)
{
throw
new
RuntimeException
(
e
);
}
});
}
}
ribbon-core/src/main/java/com/netflix/client/config/ReloadableClientConfig.java
浏览文件 @
7c3e7164
...
...
@@ -6,7 +6,6 @@ import org.slf4j.Logger;
import
org.slf4j.LoggerFactory
;
import
java.lang.reflect.Method
;
import
java.util.Collections
;
import
java.util.HashMap
;
import
java.util.List
;
import
java.util.Map
;
...
...
@@ -40,7 +39,7 @@ public abstract class ReloadableClientConfig implements IClientConfig {
// Map of raw property names (without namespace or client name) to values. All values are non-null and properly
// typed to match the key type
private
final
Map
<
IClientConfigKey
,
Optional
<
Object
>>
internalProperties
=
new
ConcurrentHashMap
<>();
private
final
Map
<
IClientConfigKey
,
Optional
<
?
>>
internalProperties
=
new
ConcurrentHashMap
<>();
private
final
Map
<
IClientConfigKey
,
ReloadableProperty
<?>>
dynamicProperties
=
new
ConcurrentHashMap
<>();
...
...
@@ -52,31 +51,13 @@ public abstract class ReloadableClientConfig implements IClientConfig {
private
final
PropertyResolver
resolver
;
private
String
clientName
;
private
String
clientName
=
DEFAULT_CLIENT_NAME
;
private
String
namespace
=
DEFAULT_NAMESPACE
;
private
boolean
isLoaded
=
false
;
/**
* @deprecated Use {@link #ReloadableClientConfig(PropertyResolver, String, String)}
*/
@Deprecated
protected
ReloadableClientConfig
(
PropertyResolver
resolver
)
{
this
(
resolver
,
DEFAULT_CLIENT_NAME
);
}
/**
* @deprecated Use {@link #ReloadableClientConfig(PropertyResolver, String, String)}
*/
@Deprecated
protected
ReloadableClientConfig
(
PropertyResolver
resolver
,
String
clientName
)
{
this
(
resolver
,
DEFAULT_NAMESPACE
,
DEFAULT_CLIENT_NAME
);
}
protected
ReloadableClientConfig
(
PropertyResolver
resolver
,
String
namespace
,
String
clientName
)
{
this
.
namespace
=
namespace
;
this
.
clientName
=
clientName
;
this
.
resolver
=
resolver
;
}
...
...
@@ -119,10 +100,14 @@ public abstract class ReloadableClientConfig implements IClientConfig {
@Override
public
void
loadProperties
(
String
clientName
)
{
Preconditions
.
checkState
(!
isLoaded
,
"Config '{}' can only be loaded once"
,
clientName
);
LOG
.
info
(
"Loading config for `{}`"
,
clientName
);
this
.
clientName
=
clientName
;
this
.
isLoaded
=
true
;
loadDefaultValues
();
resolver
.
onChange
(
this
::
reload
);
internalProperties
.
forEach
((
key
,
value
)
->
LOG
.
info
(
"{} : {} -> {}"
,
clientName
,
key
,
value
.
orElse
(
null
)));
}
/**
...
...
@@ -146,27 +131,29 @@ public abstract class ReloadableClientConfig implements IClientConfig {
}
/**
*
Create
an action that will refresh the cached value for key. Uses the current value as a reference and will
*
Register
an action that will refresh the cached value for key. Uses the current value as a reference and will
* update from the dynamic property source to either delete or set a new value.
*
* @param key - Property key without client name or namespace
* @param valueSupplier - Strategy for generating the value. Could potentially ready multiple property names, such
* as default and client specific
*/
private
<
T
>
Runnable
createAutoRefreshAction
(
final
IClientConfigKey
<
T
>
key
,
final
Supplier
<
Optional
<
T
>>
valueSupplier
)
{
final
AtomicReference
<
Optional
<
T
>>
current
=
new
AtomicReference
<>(
valueSupplier
.
get
());
return
()
->
{
final
Optional
<
T
>
next
=
valueSupplier
.
get
();
if
(!
next
.
equals
(
current
.
get
()))
{
LOG
.
debug
(
"New value {}: {} -> {}"
,
key
.
key
(),
current
.
get
(),
next
);
current
.
set
(
next
);
if
(
next
.
isPresent
())
{
internalProperties
.
put
(
key
,
(
Optional
<
Object
>)
next
);
}
else
{
internalProperties
.
put
(
key
,
Optional
.
empty
());
}
private
<
T
>
void
autoRefreshFromPropertyResolver
(
final
IClientConfigKey
<
T
>
key
)
{
changeActions
.
computeIfAbsent
(
key
,
ignore
->
{
final
Supplier
<
Optional
<
T
>>
valueSupplier
=
()
->
resolveFromPropertyResolver
(
key
);
final
Optional
<
T
>
current
=
valueSupplier
.
get
();
if
(
current
.
isPresent
())
{
internalProperties
.
put
(
key
,
current
);
}
};
final
AtomicReference
<
Optional
<
T
>>
previous
=
new
AtomicReference
<>(
current
);
return
()
->
{
final
Optional
<
T
>
next
=
valueSupplier
.
get
();
if
(!
next
.
equals
(
previous
.
get
()))
{
LOG
.
info
(
"New value {}: {} -> {}"
,
key
.
key
(),
previous
.
get
(),
next
);
previous
.
set
(
next
);
internalProperties
.
put
(
key
,
next
);
}
};
});
}
interface
ReloadableProperty
<
T
>
extends
Property
<
T
>
{
...
...
@@ -221,8 +208,12 @@ public abstract class ReloadableClientConfig implements IClientConfig {
public
final
<
T
>
T
get
(
IClientConfigKey
<
T
>
key
)
{
Optional
<
T
>
value
=
(
Optional
<
T
>)
internalProperties
.
get
(
key
);
if
(
value
==
null
)
{
set
(
key
,
null
);
value
=
(
Optional
<
T
>)
internalProperties
.
get
(
key
);
if
(!
isLoaded
)
{
return
null
;
}
else
{
set
(
key
,
null
);
value
=
(
Optional
<
T
>)
internalProperties
.
get
(
key
);
}
}
return
value
.
orElse
(
null
);
...
...
@@ -242,21 +233,13 @@ public abstract class ReloadableClientConfig implements IClientConfig {
public
final
<
T
>
Property
<
T
>
getDynamicProperty
(
IClientConfigKey
<
T
>
key
)
{
LOG
.
debug
(
"Get dynamic property key={} ns={} client={}"
,
key
.
key
(),
getNameSpace
(),
clientName
);
get
(
key
);
return
getOrCreateProperty
(
key
,
()
->
(
Optional
<
T
>)
internalProperties
.
get
(
key
),
key:
:
defaultValue
);
}
@Override
public
<
T
>
Property
<
T
>
getScopedProperty
(
IClientConfigKey
<
T
>
key
)
{
LOG
.
debug
(
"Get dynamic property key={} ns={} client={}"
,
key
.
key
(),
getNameSpace
(),
clientName
);
if
(
isLoaded
)
{
autoRefreshFromPropertyResolver
(
key
);
}
return
getOrCreateProperty
(
key
,
()
->
resolverScopedProperty
(
key
),
()
->
(
Optional
<
T
>)
internalProperties
.
getOrDefault
(
key
,
Optional
.
empty
()
),
key:
:
defaultValue
);
}
...
...
@@ -280,7 +263,7 @@ public abstract class ReloadableClientConfig implements IClientConfig {
* @param <T>
* @return
*/
private
<
T
>
Optional
<
T
>
resolveF
inalProperty
(
IClientConfigKey
<
T
>
key
)
{
private
<
T
>
Optional
<
T
>
resolveF
romPropertyResolver
(
IClientConfigKey
<
T
>
key
)
{
Optional
<
T
>
value
;
if
(!
StringUtils
.
isEmpty
(
clientName
))
{
value
=
resolver
.
get
(
clientName
+
"."
+
getNameSpace
()
+
"."
+
key
.
key
(),
key
.
type
());
...
...
@@ -292,28 +275,9 @@ public abstract class ReloadableClientConfig implements IClientConfig {
return
resolver
.
get
(
getNameSpace
()
+
"."
+
key
.
key
(),
key
.
type
());
}
/**
* Resolve a p
* @param key
* @param <T>
* @return
*/
private
<
T
>
Optional
<
T
>
resolverScopedProperty
(
IClientConfigKey
<
T
>
key
)
{
Optional
<
T
>
value
=
resolver
.
get
(
clientName
+
"."
+
getNameSpace
()
+
"."
+
key
.
key
(),
key
.
type
());
if
(
value
.
isPresent
())
{
return
value
;
}
return
getIfSet
(
key
);
}
@Override
public
<
T
>
Optional
<
T
>
getIfSet
(
IClientConfigKey
<
T
>
key
)
{
Optional
<
T
>
value
=
(
Optional
<
T
>)
internalProperties
.
get
(
key
);
if
(
value
==
null
)
{
return
Optional
.
empty
();
}
return
value
;
return
(
Optional
<
T
>)
internalProperties
.
getOrDefault
(
key
,
Optional
.
empty
());
}
private
<
T
>
T
resolveValueToType
(
IClientConfigKey
<
T
>
key
,
Object
value
)
{
...
...
@@ -343,11 +307,11 @@ public abstract class ReloadableClientConfig implements IClientConfig {
}
else
if
(
TimeUnit
.
class
.
equals
(
type
))
{
return
(
T
)
TimeUnit
.
valueOf
(
strValue
);
}
else
{
return
Property
Resolver
.
resolveWithValueOf
(
type
,
strValue
)
return
Property
Utils
.
resolveWithValueOf
(
type
,
strValue
)
.
orElseThrow
(()
->
new
IllegalArgumentException
(
"Unsupported value type `"
+
type
+
"'"
));
}
}
else
{
return
Property
Resolver
.
resolveWithValueOf
(
type
,
value
.
toString
())
return
Property
Utils
.
resolveWithValueOf
(
type
,
value
.
toString
())
.
orElseThrow
(()
->
new
IllegalArgumentException
(
"Incompatible value type `"
+
value
.
getClass
()
+
"` while expecting '"
+
type
+
"`"
));
}
}
catch
(
Exception
e
)
{
...
...
@@ -390,23 +354,15 @@ public abstract class ReloadableClientConfig implements IClientConfig {
}
@Override
public
final
<
T
>
IClientConfig
set
(
IClientConfigKey
<
T
>
key
,
T
value
)
{
public
<
T
>
IClientConfig
set
(
IClientConfigKey
<
T
>
key
,
T
value
)
{
Preconditions
.
checkArgument
(
key
!=
null
,
"key cannot be null"
);
// Make sure the value is property typed.
value
=
resolveValueToType
(
key
,
value
);
// Check if there's a dynamic config override available
value
=
resolveFinalProperty
(
key
).
orElse
(
value
);
// Cache the new value
internalProperties
.
put
(
key
,
Optional
.
ofNullable
(
value
));
// If this is the first time a property is seen and a client name has been specified then make sure
// we have the necessary refresh to pick up new values from dynamic config
if
(
isLoaded
)
{
changeActions
.
computeIfAbsent
(
key
,
ignore
->
createAutoRefreshAction
(
key
,
()
->
resolveFinalProperty
(
key
)))
.
run
();
internalProperties
.
put
(
key
,
Optional
.
ofNullable
(
resolveFromPropertyResolver
(
key
).
orElse
(
value
)));
autoRefreshFromPropertyResolver
(
key
);
}
else
{
internalProperties
.
put
(
key
,
Optional
.
ofNullable
(
value
));
}
cachedToString
=
null
;
...
...
ribbon-core/src/test/java/com/netflix/client/config/ClientConfigTest.java
浏览文件 @
7c3e7164
...
...
@@ -219,18 +219,6 @@ public class ClientConfigTest {
Assert
.
assertEquals
(
"value2"
,
prop
.
getOrDefault
().
getValue
());
}
@Test
public
void
testScopedProperty
()
{
ConfigurationManager
.
getConfigInstance
().
setProperty
(
"ribbon.foo.ScopePropertyTimeout"
,
"2000"
);
ConfigurationManager
.
getConfigInstance
().
setProperty
(
"testScopedProperty.ribbon.foo.ScopePropertyTimeout"
,
"1000"
);
DefaultClientConfigImpl
clientConfig
=
new
DefaultClientConfigImpl
();
clientConfig
.
loadProperties
(
"testScopedProperty"
);
Property
<
Integer
>
prop
=
clientConfig
.
getScopedProperty
(
new
CommonClientConfigKey
<
Integer
>(
"foo.ScopePropertyTimeout"
,
0
)
{});
Assert
.
assertEquals
(
1000
,
prop
.
get
().
get
().
intValue
());
}
@Test
public
void
testDynamicConfig
()
{
ConfigurationManager
.
getConfigInstance
().
setProperty
(
"testValueOf.ribbon.CustomValueOf"
,
"value"
);
...
...
ribbon-core/src/test/java/com/netflix/client/config/DefaultClientConfigImplTest.java
浏览文件 @
7c3e7164
...
...
@@ -27,13 +27,13 @@ public class DefaultClientConfigImplTest {
@Test
public
void
testTypedValue
()
{
ConfigurationManager
.
getConfigInstance
().
setProperty
(
"myclient.ribbon."
+
CommonClientConfigKey
.
ConnectTimeout
,
"1
000"
);
ConfigurationManager
.
getConfigInstance
().
setProperty
(
"myclient.ribbon."
+
CommonClientConfigKey
.
ConnectTimeout
,
"1
500"
);
DefaultClientConfigImpl
config
=
new
DefaultClientConfigImpl
();
config
.
loadProperties
(
"myclient"
);
assertEquals
(
1
0
00
,
config
.
get
(
CommonClientConfigKey
.
ConnectTimeout
).
intValue
());
assertEquals
(
1
5
00
,
config
.
get
(
CommonClientConfigKey
.
ConnectTimeout
).
intValue
());
config
.
set
(
CommonClientConfigKey
.
ConnectTimeout
,
2000
);
// The archaius property should override code override
assertEquals
(
1
0
00
,
config
.
get
(
CommonClientConfigKey
.
ConnectTimeout
).
intValue
());
assertEquals
(
1
5
00
,
config
.
get
(
CommonClientConfigKey
.
ConnectTimeout
).
intValue
());
}
@Test
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录