Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
zhangjian1949
apollo
提交
a76372f0
apollo
项目概览
zhangjian1949
/
apollo
与 Fork 源项目一致
从无法访问的项目Fork
通知
3
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
apollo
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
a76372f0
编写于
4月 27, 2016
作者:
J
Jason Song
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
add public config support
上级
12a89acc
变更
19
隐藏空白更改
内联
并排
Showing
19 changed file
with
596 addition
and
114 deletion
+596
-114
.gitignore
.gitignore
+1
-0
apollo-biz/src/main/java/com/ctrip/apollo/biz/message/RedisMessageSender.java
...java/com/ctrip/apollo/biz/message/RedisMessageSender.java
+13
-2
apollo-biz/src/main/java/com/ctrip/apollo/biz/repository/AppNamespaceRepository.java
...m/ctrip/apollo/biz/repository/AppNamespaceRepository.java
+2
-0
apollo-biz/src/main/java/com/ctrip/apollo/biz/service/AppNamespaceService.java
...ava/com/ctrip/apollo/biz/service/AppNamespaceService.java
+7
-0
apollo-client/src/main/java/com/ctrip/apollo/internals/RemoteConfigRepository.java
...va/com/ctrip/apollo/internals/RemoteConfigRepository.java
+25
-11
apollo-client/src/main/java/com/ctrip/apollo/model/ConfigChangeEvent.java
...c/main/java/com/ctrip/apollo/model/ConfigChangeEvent.java
+2
-2
apollo-client/src/main/java/com/ctrip/apollo/util/ConfigUtil.java
...lient/src/main/java/com/ctrip/apollo/util/ConfigUtil.java
+8
-0
apollo-client/src/test/java/com/ctrip/apollo/BaseIntegrationTest.java
...t/src/test/java/com/ctrip/apollo/BaseIntegrationTest.java
+7
-0
apollo-client/src/test/java/com/ctrip/apollo/integration/ConfigIntegrationTest.java
...a/com/ctrip/apollo/integration/ConfigIntegrationTest.java
+1
-2
apollo-client/src/test/java/com/ctrip/apollo/internals/RemoteConfigRepositoryTest.java
...om/ctrip/apollo/internals/RemoteConfigRepositoryTest.java
+5
-0
apollo-configservice/src/main/java/com/ctrip/apollo/configservice/controller/ConfigController.java
...rip/apollo/configservice/controller/ConfigController.java
+43
-11
apollo-configservice/src/main/java/com/ctrip/apollo/configservice/controller/NotificationController.java
...ollo/configservice/controller/NotificationController.java
+35
-10
apollo-configservice/src/test/java/com/ctrip/apollo/configservice/controller/ConfigControllerTest.java
...apollo/configservice/controller/ConfigControllerTest.java
+177
-30
apollo-configservice/src/test/java/com/ctrip/apollo/configservice/controller/NotificationControllerTest.java
.../configservice/controller/NotificationControllerTest.java
+82
-13
apollo-configservice/src/test/java/com/ctrip/apollo/configservice/integration/ConfigControllerIntegrationTest.java
...gservice/integration/ConfigControllerIntegrationTest.java
+76
-0
apollo-configservice/src/test/java/com/ctrip/apollo/configservice/integration/NotificationControllerIntegrationTest.java
...ce/integration/NotificationControllerIntegrationTest.java
+80
-8
apollo-configservice/src/test/resources/integration-test/test-release.sql
...vice/src/test/resources/integration-test/test-release.sql
+20
-4
apollo-core/src/main/java/com/ctrip/apollo/core/dto/ApolloConfigNotification.java
...a/com/ctrip/apollo/core/dto/ApolloConfigNotification.java
+1
-21
apollo-demo/Demo.md
apollo-demo/Demo.md
+11
-0
未找到文件。
.gitignore
浏览文件 @
a76372f0
*.class
.DS_Store
# Mobile Tools for Java (J2ME)
.mtj.tmp/
...
...
apollo-biz/src/main/java/com/ctrip/apollo/biz/message/RedisMessageSender.java
浏览文件 @
a76372f0
package
com.ctrip.apollo.biz.message
;
import
com.dianping.cat.Cat
;
import
com.dianping.cat.message.Message
;
import
com.dianping.cat.message.Transaction
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
org.springframework.data.redis.core.RedisTemplate
;
/**
* @author Jason Song(song_s@ctrip.com)
*/
public
class
RedisMessageSender
implements
MessageSender
{
private
static
final
Logger
logger
=
LoggerFactory
.
getLogger
(
RedisMessageSender
.
class
);
private
RedisTemplate
<
String
,
String
>
redisTemplate
;
public
RedisMessageSender
(
...
...
@@ -15,12 +22,16 @@ public class RedisMessageSender implements MessageSender {
@Override
public
void
sendMessage
(
String
message
,
String
channel
)
{
logger
.
info
(
"Sending message {} to channel {}"
,
message
,
channel
);
Transaction
transaction
=
Cat
.
newTransaction
(
"Apollo.AdminService"
,
"RedisMessageSender"
);
try
{
redisTemplate
.
convertAndSend
(
channel
,
message
);
transaction
.
setStatus
(
Message
.
SUCCESS
);
}
catch
(
Throwable
ex
)
{
logger
.
error
(
"Sending message to redis failed"
,
ex
);
transaction
.
setStatus
(
ex
);
}
finally
{
transaction
.
complete
();
}
}
}
apollo-biz/src/main/java/com/ctrip/apollo/biz/repository/AppNamespaceRepository.java
浏览文件 @
a76372f0
...
...
@@ -8,4 +8,6 @@ public interface AppNamespaceRepository extends PagingAndSortingRepository<AppNa
AppNamespace
findByAppIdAndName
(
String
appId
,
String
namespaceName
);
AppNamespace
findByName
(
String
namespaceName
);
}
apollo-biz/src/main/java/com/ctrip/apollo/biz/service/AppNamespaceService.java
浏览文件 @
a76372f0
package
com.ctrip.apollo.biz.service
;
import
com.google.common.base.Preconditions
;
import
java.util.Objects
;
import
org.springframework.beans.factory.annotation.Autowired
;
...
...
@@ -27,6 +29,11 @@ public class AppNamespaceService {
return
Objects
.
isNull
(
appNamespaceRepository
.
findByAppIdAndName
(
appId
,
namespaceName
));
}
public
AppNamespace
findByNamespaceName
(
String
namespaceName
)
{
Preconditions
.
checkArgument
(
namespaceName
!=
null
,
"Namespace must not be null"
);
return
appNamespaceRepository
.
findByName
(
namespaceName
);
}
@Transactional
public
void
createDefaultAppNamespace
(
String
appId
,
String
createBy
)
{
if
(!
isAppNamespaceNameUnique
(
appId
,
appId
))
{
...
...
apollo-client/src/main/java/com/ctrip/apollo/internals/RemoteConfigRepository.java
浏览文件 @
a76372f0
...
...
@@ -134,6 +134,7 @@ public class RemoteConfigRepository extends AbstractConfigRepository {
private
ApolloConfig
loadApolloConfig
()
{
String
appId
=
m_configUtil
.
getAppId
();
String
cluster
=
m_configUtil
.
getCluster
();
String
dataCenter
=
m_configUtil
.
getDataCenter
();
Cat
.
logEvent
(
"Apollo.Client.ConfigInfo"
,
String
.
format
(
"%s-%s-%s"
,
appId
,
cluster
,
m_namespace
));
int
maxRetries
=
2
;
...
...
@@ -147,7 +148,7 @@ public class RemoteConfigRepository extends AbstractConfigRepository {
for
(
ServiceDTO
configService
:
randomConfigServices
)
{
String
url
=
assembleQueryConfigUrl
(
configService
.
getHomepageUrl
(),
appId
,
cluster
,
m_namespace
,
m_configCache
.
get
());
dataCenter
,
m_configCache
.
get
());
logger
.
debug
(
"Loading config from {}"
,
url
);
HttpRequest
request
=
new
HttpRequest
(
url
);
...
...
@@ -191,21 +192,30 @@ public class RemoteConfigRepository extends AbstractConfigRepository {
}
private
String
assembleQueryConfigUrl
(
String
uri
,
String
appId
,
String
cluster
,
String
namespace
,
ApolloConfig
previousConfig
)
{
String
dataCenter
,
ApolloConfig
previousConfig
)
{
Escaper
escaper
=
UrlEscapers
.
urlPathSegmentEscaper
();
String
path
=
"configs/%s/%s"
;
List
<
String
>
params
=
Lists
.
newArrayList
(
escaper
.
escape
(
appId
),
escaper
.
escape
(
cluster
));
List
<
String
>
pathParams
=
Lists
.
newArrayList
(
escaper
.
escape
(
appId
),
escaper
.
escape
(
cluster
));
Map
<
String
,
String
>
queryParams
=
Maps
.
newHashMap
();
if
(!
Strings
.
isNullOrEmpty
(
namespace
))
{
path
=
path
+
"/%s"
;
params
.
add
(
escaper
.
escape
(
namespace
));
pa
thPa
rams
.
add
(
escaper
.
escape
(
namespace
));
}
if
(
previousConfig
!=
null
)
{
path
=
path
+
"?releaseId=%s"
;
params
.
add
(
escaper
.
escape
(
String
.
valueOf
(
previousConfig
.
getReleaseId
())));
queryParams
.
put
(
"releaseId"
,
escaper
.
escape
(
String
.
valueOf
(
previousConfig
.
getReleaseId
())));
}
if
(!
Strings
.
isNullOrEmpty
(
dataCenter
))
{
queryParams
.
put
(
"dataCenter"
,
escaper
.
escape
(
dataCenter
));
}
String
pathExpanded
=
String
.
format
(
path
,
params
.
toArray
());
String
pathExpanded
=
String
.
format
(
path
,
pathParams
.
toArray
());
if
(!
queryParams
.
isEmpty
())
{
pathExpanded
+=
"?"
+
Joiner
.
on
(
"&"
).
withKeyValueSeparator
(
"="
).
join
(
queryParams
);
}
if
(!
uri
.
endsWith
(
"/"
))
{
uri
+=
"/"
;
}
...
...
@@ -215,18 +225,19 @@ public class RemoteConfigRepository extends AbstractConfigRepository {
private
void
scheduleLongPollingRefresh
()
{
final
String
appId
=
m_configUtil
.
getAppId
();
final
String
cluster
=
m_configUtil
.
getCluster
();
final
String
dataCenter
=
m_configUtil
.
getDataCenter
();
final
ExecutorService
longPollingService
=
Executors
.
newFixedThreadPool
(
2
,
ApolloThreadFactory
.
create
(
"RemoteConfigRepository-LongPolling"
,
true
));
longPollingService
.
submit
(
new
Runnable
()
{
@Override
public
void
run
()
{
doLongPollingRefresh
(
appId
,
cluster
,
longPollingService
);
doLongPollingRefresh
(
appId
,
cluster
,
dataCenter
,
longPollingService
);
}
});
}
private
void
doLongPollingRefresh
(
String
appId
,
String
cluster
,
private
void
doLongPollingRefresh
(
String
appId
,
String
cluster
,
String
dataCenter
,
ExecutorService
longPollingService
)
{
final
Random
random
=
new
Random
();
ServiceDTO
lastServiceDto
=
null
;
...
...
@@ -240,7 +251,7 @@ public class RemoteConfigRepository extends AbstractConfigRepository {
String
url
=
assembleLongPollRefreshUrl
(
lastServiceDto
.
getHomepageUrl
(),
appId
,
cluster
,
m_namespace
,
m_configCache
.
get
());
m_namespace
,
dataCenter
,
m_configCache
.
get
());
logger
.
debug
(
"Long polling from {}"
,
url
);
HttpRequest
request
=
new
HttpRequest
(
url
);
...
...
@@ -286,7 +297,7 @@ public class RemoteConfigRepository extends AbstractConfigRepository {
}
private
String
assembleLongPollRefreshUrl
(
String
uri
,
String
appId
,
String
cluster
,
String
namespace
,
String
namespace
,
String
dataCenter
,
ApolloConfig
previousConfig
)
{
Escaper
escaper
=
UrlEscapers
.
urlPathSegmentEscaper
();
Map
<
String
,
String
>
queryParams
=
Maps
.
newHashMap
();
...
...
@@ -296,6 +307,9 @@ public class RemoteConfigRepository extends AbstractConfigRepository {
if
(!
Strings
.
isNullOrEmpty
(
namespace
))
{
queryParams
.
put
(
"namespace"
,
escaper
.
escape
(
namespace
));
}
if
(!
Strings
.
isNullOrEmpty
(
dataCenter
))
{
queryParams
.
put
(
"dataCenter"
,
escaper
.
escape
(
dataCenter
));
}
if
(
previousConfig
!=
null
)
{
queryParams
.
put
(
"releaseId"
,
escaper
.
escape
(
previousConfig
.
getReleaseId
()));
}
...
...
apollo-client/src/main/java/com/ctrip/apollo/model/ConfigChangeEvent.java
浏览文件 @
a76372f0
...
...
@@ -18,8 +18,8 @@ public class ConfigChangeEvent {
*/
public
ConfigChangeEvent
(
String
namespace
,
Map
<
String
,
ConfigChange
>
changes
)
{
this
.
m_namespace
=
namespace
;
this
.
m_changes
=
changes
;
m_namespace
=
namespace
;
m_changes
=
changes
;
}
/**
...
...
apollo-client/src/main/java/com/ctrip/apollo/util/ConfigUtil.java
浏览文件 @
a76372f0
...
...
@@ -34,6 +34,14 @@ public class ConfigUtil {
return
appId
;
}
/**
* Get the data center info for the current application.
* @return the current data center, null if there is no such info.
*/
public
String
getDataCenter
()
{
return
Foundation
.
server
().
getDataCenter
();
}
/**
* Get the cluster name for the current application.
* @return the cluster name, or "default" if not specified
...
...
apollo-client/src/test/java/com/ctrip/apollo/BaseIntegrationTest.java
浏览文件 @
a76372f0
...
...
@@ -42,6 +42,7 @@ public abstract class BaseIntegrationTest extends ComponentTestCase {
private
static
final
String
configServiceURL
=
"http://localhost:"
+
PORT
;
protected
static
String
someAppId
;
protected
static
String
someClusterName
;
protected
static
String
someDataCenter
;
protected
static
int
refreshInterval
;
protected
static
TimeUnit
refreshTimeUnit
;
private
Server
server
;
...
...
@@ -59,6 +60,7 @@ public abstract class BaseIntegrationTest extends ComponentTestCase {
super
.
setUp
();
someAppId
=
"1003171"
;
someClusterName
=
"someClusterName"
;
someDataCenter
=
"someDC"
;
refreshInterval
=
5
;
refreshTimeUnit
=
TimeUnit
.
MINUTES
;
...
...
@@ -160,6 +162,11 @@ public abstract class BaseIntegrationTest extends ComponentTestCase {
public
Env
getApolloEnv
()
{
return
Env
.
LOCAL
;
}
@Override
public
String
getDataCenter
()
{
return
someDataCenter
;
}
}
/**
...
...
apollo-client/src/test/java/com/ctrip/apollo/integration/ConfigIntegrationTest.java
浏览文件 @
a76372f0
...
...
@@ -241,8 +241,7 @@ public class ConfigIntegrationTest extends BaseIntegrationTest {
ContextHandler
configHandler
=
mockConfigServerHandler
(
HttpServletResponse
.
SC_OK
,
apolloConfig
);
ContextHandler
pollHandler
=
mockPollNotificationHandler
(
pollTimeoutInMS
,
HttpServletResponse
.
SC_OK
,
new
ApolloConfigNotification
(
apolloConfig
.
getAppId
(),
apolloConfig
.
getCluster
(),
apolloConfig
.
getNamespace
()),
false
);
new
ApolloConfigNotification
(
apolloConfig
.
getNamespace
()),
false
);
startServerWithHandlers
(
configHandler
,
pollHandler
);
...
...
apollo-client/src/test/java/com/ctrip/apollo/internals/RemoteConfigRepositoryTest.java
浏览文件 @
a76372f0
...
...
@@ -186,6 +186,11 @@ public class RemoteConfigRepositoryTest extends ComponentTestCase {
public
String
getCluster
()
{
return
"someCluster"
;
}
@Override
public
String
getDataCenter
()
{
return
null
;
}
}
public
static
class
MockConfigServiceLocator
extends
ConfigServiceLocator
{
...
...
apollo-configservice/src/main/java/com/ctrip/apollo/configservice/controller/ConfigController.java
浏览文件 @
a76372f0
...
...
@@ -8,7 +8,9 @@ import com.google.common.collect.Maps;
import
com.google.gson.Gson
;
import
com.google.gson.reflect.TypeToken
;
import
com.ctrip.apollo.biz.entity.AppNamespace
;
import
com.ctrip.apollo.biz.entity.Release
;
import
com.ctrip.apollo.biz.service.AppNamespaceService
;
import
com.ctrip.apollo.biz.service.ConfigService
;
import
com.ctrip.apollo.core.ConfigConsts
;
import
com.ctrip.apollo.core.dto.ApolloConfig
;
...
...
@@ -37,6 +39,8 @@ import javax.servlet.http.HttpServletResponse;
public
class
ConfigController
{
@Autowired
private
ConfigService
configService
;
@Autowired
private
AppNamespaceService
appNamespaceService
;
private
Gson
gson
=
new
Gson
();
private
Type
configurationTypeReference
=
...
...
@@ -45,17 +49,17 @@ public class ConfigController {
@RequestMapping
(
value
=
"/{appId}/{clusterName}"
,
method
=
RequestMethod
.
GET
)
public
ApolloConfig
queryConfig
(
@PathVariable
String
appId
,
@PathVariable
String
clusterName
,
@RequestParam
(
value
=
"data
center"
,
required
=
false
)
String
datac
enter
,
@RequestParam
(
value
=
"data
Center"
,
required
=
false
)
String
dataC
enter
,
@RequestParam
(
value
=
"releaseId"
,
defaultValue
=
"-1"
)
String
clientSideReleaseId
,
HttpServletResponse
response
)
throws
IOException
{
return
this
.
queryConfig
(
appId
,
clusterName
,
ConfigConsts
.
NAMESPACE_DEFAULT
,
data
c
enter
,
return
this
.
queryConfig
(
appId
,
clusterName
,
ConfigConsts
.
NAMESPACE_DEFAULT
,
data
C
enter
,
clientSideReleaseId
,
response
);
}
@RequestMapping
(
value
=
"/{appId}/{clusterName}/{namespace}"
,
method
=
RequestMethod
.
GET
)
public
ApolloConfig
queryConfig
(
@PathVariable
String
appId
,
@PathVariable
String
clusterName
,
@PathVariable
String
namespace
,
@RequestParam
(
value
=
"data
center"
,
required
=
false
)
String
datac
enter
,
@RequestParam
(
value
=
"data
Center"
,
required
=
false
)
String
dataC
enter
,
@RequestParam
(
value
=
"releaseId"
,
defaultValue
=
"-1"
)
String
clientSideReleaseId
,
HttpServletResponse
response
)
throws
IOException
{
List
<
Release
>
releases
=
Lists
.
newLinkedList
();
...
...
@@ -66,13 +70,12 @@ public class ConfigController {
releases
.
add
(
currentAppRelease
);
}
//if namespace is not
appId itself, should check if it has its own configurations
//if namespace is not
'application', should check if it's a public configuration
if
(!
Objects
.
equals
(
ConfigConsts
.
NAMESPACE_DEFAULT
,
namespace
))
{
//TODO find id for this particular namespace, if not equal to current app id, then do more
if
(!
Objects
.
isNull
(
datacenter
))
{
//TODO load newAppId+datacenter+namespace configurations
Release
publicRelease
=
this
.
findPublicConfig
(
appId
,
namespace
,
dataCenter
);
if
(!
Objects
.
isNull
(
publicRelease
))
{
releases
.
add
(
publicRelease
);
}
//TODO if load from DC failed, then load newAppId+defaultCluster+namespace configurations
}
if
(
releases
.
isEmpty
())
{
...
...
@@ -81,7 +84,7 @@ public class ConfigController {
"Could not load configurations with appId: %s, clusterName: %s, namespace: %s"
,
appId
,
clusterName
,
namespace
));
Cat
.
logEvent
(
"Apollo.Config.NotFound"
,
assembleKey
(
appId
,
clusterName
,
namespace
,
data
c
enter
));
assembleKey
(
appId
,
clusterName
,
namespace
,
data
C
enter
));
return
null
;
}
...
...
@@ -92,17 +95,46 @@ public class ConfigController {
// Client side configuration is the same with server side, return 304
response
.
setStatus
(
HttpServletResponse
.
SC_NOT_MODIFIED
);
Cat
.
logEvent
(
"Apollo.Config.NotModified"
,
assembleKey
(
appId
,
clusterName
,
namespace
,
data
c
enter
));
assembleKey
(
appId
,
clusterName
,
namespace
,
data
C
enter
));
return
null
;
}
ApolloConfig
apolloConfig
=
new
ApolloConfig
(
appId
,
clusterName
,
namespace
,
mergedReleaseId
);
apolloConfig
.
setConfigurations
(
mergeReleaseConfigurations
(
releases
));
Cat
.
logEvent
(
"Apollo.Config.Found"
,
assembleKey
(
appId
,
clusterName
,
namespace
,
data
c
enter
));
Cat
.
logEvent
(
"Apollo.Config.Found"
,
assembleKey
(
appId
,
clusterName
,
namespace
,
data
C
enter
));
return
apolloConfig
;
}
/**
* @param applicationId the application which uses public config
* @param namespace the namespace
* @param dataCenter the datacenter
*/
private
Release
findPublicConfig
(
String
applicationId
,
String
namespace
,
String
dataCenter
)
{
AppNamespace
appNamespace
=
appNamespaceService
.
findByNamespaceName
(
namespace
);
//check whether the namespace's appId equals to current one
if
(
Objects
.
isNull
(
appNamespace
)
||
Objects
.
equals
(
applicationId
,
appNamespace
.
getAppId
()))
{
return
null
;
}
String
publicConfigAppId
=
appNamespace
.
getAppId
();
//try to load via data center
if
(!
Objects
.
isNull
(
dataCenter
))
{
Release
dataCenterRelease
=
configService
.
findRelease
(
publicConfigAppId
,
dataCenter
,
namespace
);
if
(!
Objects
.
isNull
(
dataCenterRelease
))
{
return
dataCenterRelease
;
}
}
//fallback to default release
return
configService
.
findRelease
(
publicConfigAppId
,
ConfigConsts
.
CLUSTER_NAME_DEFAULT
,
namespace
);
}
/**
* Merge configurations of releases.
* Release in lower index override those in higher index
...
...
apollo-configservice/src/main/java/com/ctrip/apollo/configservice/controller/NotificationController.java
浏览文件 @
a76372f0
...
...
@@ -6,14 +6,17 @@ import com.google.common.collect.Lists;
import
com.google.common.collect.Multimap
;
import
com.google.common.collect.Multimaps
;
import
com.ctrip.apollo.biz.entity.AppNamespace
;
import
com.ctrip.apollo.biz.message.MessageListener
;
import
com.ctrip.apollo.biz.message.Topics
;
import
com.ctrip.apollo.biz.service.AppNamespaceService
;
import
com.ctrip.apollo.core.ConfigConsts
;
import
com.ctrip.apollo.core.dto.ApolloConfigNotification
;
import
com.dianping.cat.Cat
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.http.HttpStatus
;
import
org.springframework.http.ResponseEntity
;
import
org.springframework.web.bind.annotation.RequestMapping
;
...
...
@@ -40,23 +43,22 @@ public class NotificationController implements MessageListener {
deferredResults
=
Multimaps
.
synchronizedSetMultimap
(
HashMultimap
.
create
());
@Autowired
private
AppNamespaceService
appNamespaceService
;
@RequestMapping
(
method
=
RequestMethod
.
GET
)
public
DeferredResult
<
ResponseEntity
<
ApolloConfigNotification
>>
pollNotification
(
@RequestParam
(
value
=
"appId"
)
String
appId
,
@RequestParam
(
value
=
"cluster"
)
String
cluster
,
@RequestParam
(
value
=
"namespace"
,
defaultValue
=
ConfigConsts
.
NAMESPACE_DEFAULT
)
String
namespace
,
@RequestParam
(
value
=
"data
center"
,
required
=
false
)
String
datac
enter
,
@RequestParam
(
value
=
"data
Center"
,
required
=
false
)
String
dataC
enter
,
@RequestParam
(
value
=
"releaseId"
,
defaultValue
=
"-1"
)
String
clientSideReleaseId
,
HttpServletResponse
response
)
{
List
<
String
>
watchedKeys
=
Lists
.
newArrayList
(
assembleKey
(
appId
,
cluster
,
namespace
));
//Listen more namespaces, since it's not the default namespace
//Listen
on
more namespaces, since it's not the default namespace
if
(!
Objects
.
equals
(
ConfigConsts
.
NAMESPACE_DEFAULT
,
namespace
))
{
//TODO find id for this particular namespace, if not equal to current app id, then do more
if
(!
Objects
.
isNull
(
datacenter
))
{
//TODO add newAppId+datacenter+namespace to listened keys
}
//TODO add newAppId+defaultCluster+namespace to listened keys
watchedKeys
.
addAll
(
this
.
findPublicConfigWatchKey
(
appId
,
namespace
,
dataCenter
));
}
ResponseEntity
<
ApolloConfigNotification
>
body
=
new
ResponseEntity
<>(
...
...
@@ -77,7 +79,7 @@ public class NotificationController implements MessageListener {
});
logger
.
info
(
"Listening {} from appId: {}, cluster: {}, namespace: {}, datacenter: {}"
,
watchedKeys
,
appId
,
cluster
,
namespace
,
data
c
enter
);
watchedKeys
,
appId
,
cluster
,
namespace
,
data
C
enter
);
return
deferredResult
;
}
...
...
@@ -85,6 +87,30 @@ public class NotificationController implements MessageListener {
return
String
.
format
(
"%s-%s-%s"
,
appId
,
cluster
,
namespace
);
}
private
List
<
String
>
findPublicConfigWatchKey
(
String
applicationId
,
String
namespace
,
String
dataCenter
)
{
List
<
String
>
publicWatchedKeys
=
Lists
.
newArrayList
();
AppNamespace
appNamespace
=
appNamespaceService
.
findByNamespaceName
(
namespace
);
//check whether the namespace's appId equals to current one
if
(
Objects
.
isNull
(
appNamespace
)
||
Objects
.
equals
(
applicationId
,
appNamespace
.
getAppId
()))
{
return
publicWatchedKeys
;
}
String
publicConfigAppId
=
appNamespace
.
getAppId
();
//watch data center config change
if
(!
Objects
.
isNull
(
dataCenter
))
{
publicWatchedKeys
.
add
(
assembleKey
(
publicConfigAppId
,
dataCenter
,
namespace
));
}
//watch default cluster config change
publicWatchedKeys
.
add
(
assembleKey
(
publicConfigAppId
,
ConfigConsts
.
CLUSTER_NAME_DEFAULT
,
namespace
));
return
publicWatchedKeys
;
}
@Override
public
void
handleMessage
(
String
message
,
String
channel
)
{
logger
.
info
(
"message received - channel: {}, message: {}"
,
channel
,
message
);
...
...
@@ -101,8 +127,7 @@ public class NotificationController implements MessageListener {
ResponseEntity
<
ApolloConfigNotification
>
notification
=
new
ResponseEntity
<>(
new
ApolloConfigNotification
(
keys
[
0
],
keys
[
1
],
keys
[
2
]),
HttpStatus
.
OK
);
new
ApolloConfigNotification
(
keys
[
2
]),
HttpStatus
.
OK
);
Collection
<
DeferredResult
<
ResponseEntity
<
ApolloConfigNotification
>>>
results
=
deferredResults
.
get
(
message
);
...
...
apollo-configservice/src/test/java/com/ctrip/apollo/configservice/controller/ConfigControllerTest.java
浏览文件 @
a76372f0
package
com.ctrip.apollo.configservice.controller
;
import
static
org
.
junit
.
Assert
.
assertEquals
;
import
static
org
.
junit
.
Assert
.
assertNull
;
import
static
org
.
mockito
.
Matchers
.
anyString
;
import
static
org
.
mockito
.
Matchers
.
eq
;
import
static
org
.
mockito
.
Mockito
.
mock
;
import
static
org
.
mockito
.
Mockito
.
times
;
import
static
org
.
mockito
.
Mockito
.
verify
;
import
static
org
.
mockito
.
Mockito
.
when
;
import
java.util.Map
;
import
com.google.common.collect.ImmutableMap
;
import
com.google.common.collect.Lists
;
import
com.google.gson.Gson
;
import
com.google.gson.JsonSyntaxException
;
import
javax.servlet.http.HttpServletResponse
;
import
com.ctrip.apollo.biz.entity.AppNamespace
;
import
com.ctrip.apollo.biz.entity.Release
;
import
com.ctrip.apollo.biz.service.AppNamespaceService
;
import
com.ctrip.apollo.biz.service.ConfigService
;
import
com.ctrip.apollo.core.ConfigConsts
;
import
com.ctrip.apollo.core.dto.ApolloConfig
;
import
org.junit.Before
;
import
org.junit.Test
;
...
...
@@ -20,13 +19,18 @@ import org.mockito.Mock;
import
org.mockito.runners.MockitoJUnitRunner
;
import
org.springframework.test.util.ReflectionTestUtils
;
import
com.ctrip.apollo.biz.entity.Release
;
import
com.ctrip.apollo.biz.service.ConfigService
;
import
com.ctrip.apollo.core.dto.ApolloConfig
;
import
com.google.common.collect.ImmutableMap
;
import
com.google.common.collect.Lists
;
import
com.google.gson.Gson
;
import
com.google.gson.JsonSyntaxException
;
import
java.util.Map
;
import
javax.servlet.http.HttpServletResponse
;
import
static
org
.
junit
.
Assert
.
assertEquals
;
import
static
org
.
junit
.
Assert
.
assertNull
;
import
static
org
.
mockito
.
Matchers
.
anyString
;
import
static
org
.
mockito
.
Matchers
.
eq
;
import
static
org
.
mockito
.
Mockito
.
mock
;
import
static
org
.
mockito
.
Mockito
.
times
;
import
static
org
.
mockito
.
Mockito
.
verify
;
import
static
org
.
mockito
.
Mockito
.
when
;
/**
* @author Jason Song(song_s@ctrip.com)
...
...
@@ -36,26 +40,34 @@ public class ConfigControllerTest {
private
ConfigController
configController
;
@Mock
private
ConfigService
configService
;
@Mock
private
AppNamespaceService
appNamespaceService
;
private
String
someAppId
;
private
String
someClusterName
;
private
String
someNamespaceName
;
private
String
defaultNamespaceName
;
private
String
somePublicNamespaceName
;
private
String
someDataCenter
;
private
String
someValidConfiguration
;
@Mock
private
Release
someRelease
;
@Mock
private
Release
somePublicRelease
;
@Before
public
void
setUp
()
throws
Exception
{
configController
=
new
ConfigController
();
ReflectionTestUtils
.
setField
(
configController
,
"configService"
,
configService
);
ReflectionTestUtils
.
setField
(
configController
,
"appNamespaceService"
,
appNamespaceService
);
someAppId
=
"1"
;
someClusterName
=
"someClusterName"
;
someNamespaceName
=
"someNamespaceName"
;
defaultNamespaceName
=
ConfigConsts
.
NAMESPACE_DEFAULT
;
somePublicNamespaceName
=
"somePublicNamespace"
;
someDataCenter
=
"someDC"
;
someValidConfiguration
=
"{\"apollo.bar\": \"foo\"}"
;
String
someValidConfiguration
=
"{\"apollo.bar\": \"foo\"}"
;
String
somePublicConfiguration
=
"{\"apollo.public.bar\": \"foo\"}"
;
when
(
someRelease
.
getConfigurations
()).
thenReturn
(
someValidConfiguration
);
when
(
somePublicRelease
.
getConfigurations
()).
thenReturn
(
somePublicConfiguration
);
}
@Test
...
...
@@ -64,17 +76,18 @@ public class ConfigControllerTest {
long
someServerSideNewReleaseId
=
2
;
HttpServletResponse
someResponse
=
mock
(
HttpServletResponse
.
class
);
when
(
configService
.
findRelease
(
someAppId
,
someClusterName
,
some
NamespaceName
))
when
(
configService
.
findRelease
(
someAppId
,
someClusterName
,
default
NamespaceName
))
.
thenReturn
(
someRelease
);
when
(
someRelease
.
getId
()).
thenReturn
(
someServerSideNewReleaseId
);
ApolloConfig
result
=
configController
.
queryConfig
(
someAppId
,
someClusterName
,
someNamespaceName
,
someDataCenter
,
String
.
valueOf
(
someClientSideReleaseId
),
someResponse
);
defaultNamespaceName
,
someDataCenter
,
String
.
valueOf
(
someClientSideReleaseId
),
someResponse
);
verify
(
configService
,
times
(
1
)).
findRelease
(
someAppId
,
someClusterName
,
some
NamespaceName
);
verify
(
configService
,
times
(
1
)).
findRelease
(
someAppId
,
someClusterName
,
default
NamespaceName
);
assertEquals
(
someAppId
,
result
.
getAppId
());
assertEquals
(
someClusterName
,
result
.
getCluster
());
assertEquals
(
some
NamespaceName
,
result
.
getNamespace
());
assertEquals
(
default
NamespaceName
,
result
.
getNamespace
());
assertEquals
(
String
.
valueOf
(
someServerSideNewReleaseId
),
result
.
getReleaseId
());
}
...
...
@@ -84,10 +97,12 @@ public class ConfigControllerTest {
long
someClientSideReleaseId
=
1
;
HttpServletResponse
someResponse
=
mock
(
HttpServletResponse
.
class
);
when
(
configService
.
findRelease
(
someAppId
,
someClusterName
,
someNamespaceName
)).
thenReturn
(
null
);
when
(
configService
.
findRelease
(
someAppId
,
someClusterName
,
defaultNamespaceName
))
.
thenReturn
(
null
);
ApolloConfig
result
=
configController
.
queryConfig
(
someAppId
,
someClusterName
,
someNamespaceName
,
someDataCenter
,
String
.
valueOf
(
someClientSideReleaseId
),
someResponse
);
defaultNamespaceName
,
someDataCenter
,
String
.
valueOf
(
someClientSideReleaseId
),
someResponse
);
assertNull
(
result
);
verify
(
someResponse
,
times
(
1
)).
sendError
(
eq
(
HttpServletResponse
.
SC_NOT_FOUND
),
anyString
());
...
...
@@ -99,19 +114,144 @@ public class ConfigControllerTest {
long
someServerSideReleaseId
=
someClientSideReleaseId
;
HttpServletResponse
someResponse
=
mock
(
HttpServletResponse
.
class
);
when
(
configService
.
findRelease
(
someAppId
,
someClusterName
,
some
NamespaceName
))
when
(
configService
.
findRelease
(
someAppId
,
someClusterName
,
default
NamespaceName
))
.
thenReturn
(
someRelease
);
when
(
someRelease
.
getId
()).
thenReturn
(
someServerSideReleaseId
);
ApolloConfig
result
=
configController
.
queryConfig
(
someAppId
,
someClusterName
,
some
NamespaceName
,
configController
.
queryConfig
(
someAppId
,
someClusterName
,
default
NamespaceName
,
someDataCenter
,
String
.
valueOf
(
someClientSideReleaseId
),
someResponse
);
assertNull
(
result
);
verify
(
someResponse
,
times
(
1
)).
setStatus
(
HttpServletResponse
.
SC_NOT_MODIFIED
);
}
@Test
public
void
testQueryConfigWithAppOwnNamespace
()
throws
Exception
{
String
someClientSideReleaseId
=
"1"
;
String
someServerSideReleaseId
=
"2"
;
String
someAppOwnNamespaceName
=
"someAppOwn"
;
HttpServletResponse
someResponse
=
mock
(
HttpServletResponse
.
class
);
AppNamespace
someAppOwnNamespace
=
assmbleAppNamespace
(
someAppId
,
someAppOwnNamespaceName
);
when
(
configService
.
findRelease
(
someAppId
,
someClusterName
,
someAppOwnNamespaceName
))
.
thenReturn
(
someRelease
);
when
(
appNamespaceService
.
findByNamespaceName
(
someAppOwnNamespaceName
))
.
thenReturn
(
someAppOwnNamespace
);
when
(
someRelease
.
getId
()).
thenReturn
(
Long
.
valueOf
(
someServerSideReleaseId
));
ApolloConfig
result
=
configController
.
queryConfig
(
someAppId
,
someClusterName
,
someAppOwnNamespaceName
,
someDataCenter
,
someClientSideReleaseId
,
someResponse
);
assertEquals
(
someServerSideReleaseId
,
result
.
getReleaseId
());
assertEquals
(
someAppId
,
result
.
getAppId
());
assertEquals
(
someClusterName
,
result
.
getCluster
());
assertEquals
(
someAppOwnNamespaceName
,
result
.
getNamespace
());
assertEquals
(
"foo"
,
result
.
getConfigurations
().
get
(
"apollo.bar"
));
}
@Test
public
void
testQueryConfigWithPubicNamespaceAndNoAppOverride
()
throws
Exception
{
String
someClientSideReleaseId
=
"1"
;
String
someServerSideReleaseId
=
"2"
;
HttpServletResponse
someResponse
=
mock
(
HttpServletResponse
.
class
);
String
somePublicAppId
=
"somePublicAppId"
;
AppNamespace
somePublicAppNamespace
=
assmbleAppNamespace
(
somePublicAppId
,
somePublicNamespaceName
);
when
(
configService
.
findRelease
(
someAppId
,
someClusterName
,
somePublicNamespaceName
))
.
thenReturn
(
null
);
when
(
appNamespaceService
.
findByNamespaceName
(
somePublicNamespaceName
))
.
thenReturn
(
somePublicAppNamespace
);
when
(
configService
.
findRelease
(
somePublicAppId
,
someDataCenter
,
somePublicNamespaceName
))
.
thenReturn
(
somePublicRelease
);
when
(
somePublicRelease
.
getId
()).
thenReturn
(
Long
.
valueOf
(
someServerSideReleaseId
));
ApolloConfig
result
=
configController
.
queryConfig
(
someAppId
,
someClusterName
,
somePublicNamespaceName
,
someDataCenter
,
someClientSideReleaseId
,
someResponse
);
assertEquals
(
someServerSideReleaseId
,
result
.
getReleaseId
());
assertEquals
(
someAppId
,
result
.
getAppId
());
assertEquals
(
someClusterName
,
result
.
getCluster
());
assertEquals
(
somePublicNamespaceName
,
result
.
getNamespace
());
assertEquals
(
"foo"
,
result
.
getConfigurations
().
get
(
"apollo.public.bar"
));
}
@Test
public
void
testQueryConfigWithPublicNamespaceAndNoAppOverrideAndNoDataCenter
()
throws
Exception
{
String
someClientSideReleaseId
=
"1"
;
String
someServerSideReleaseId
=
"2"
;
HttpServletResponse
someResponse
=
mock
(
HttpServletResponse
.
class
);
String
somePublicAppId
=
"somePublicAppId"
;
AppNamespace
somePublicAppNamespace
=
assmbleAppNamespace
(
somePublicAppId
,
somePublicNamespaceName
);
when
(
configService
.
findRelease
(
someAppId
,
someClusterName
,
somePublicNamespaceName
))
.
thenReturn
(
null
);
when
(
appNamespaceService
.
findByNamespaceName
(
somePublicNamespaceName
))
.
thenReturn
(
somePublicAppNamespace
);
when
(
configService
.
findRelease
(
somePublicAppId
,
someDataCenter
,
somePublicNamespaceName
))
.
thenReturn
(
null
);
when
(
configService
.
findRelease
(
somePublicAppId
,
ConfigConsts
.
CLUSTER_NAME_DEFAULT
,
somePublicNamespaceName
))
.
thenReturn
(
somePublicRelease
);
when
(
somePublicRelease
.
getId
()).
thenReturn
(
Long
.
valueOf
(
someServerSideReleaseId
));
ApolloConfig
result
=
configController
.
queryConfig
(
someAppId
,
someClusterName
,
somePublicNamespaceName
,
someDataCenter
,
someClientSideReleaseId
,
someResponse
);
assertEquals
(
someServerSideReleaseId
,
result
.
getReleaseId
());
assertEquals
(
someAppId
,
result
.
getAppId
());
assertEquals
(
someClusterName
,
result
.
getCluster
());
assertEquals
(
somePublicNamespaceName
,
result
.
getNamespace
());
assertEquals
(
"foo"
,
result
.
getConfigurations
().
get
(
"apollo.public.bar"
));
}
@Test
public
void
testQueryConfigWithPublicNamespaceAndAppOverride
()
throws
Exception
{
String
someAppSideReleaseId
=
"1"
;
String
somePublicAppSideReleaseId
=
"2"
;
HttpServletResponse
someResponse
=
mock
(
HttpServletResponse
.
class
);
String
somePublicAppId
=
"somePublicAppId"
;
AppNamespace
somePublicAppNamespace
=
assmbleAppNamespace
(
somePublicAppId
,
somePublicNamespaceName
);
when
(
someRelease
.
getConfigurations
()).
thenReturn
(
"{\"apollo.public.foo\": \"foo-override\"}"
);
when
(
somePublicRelease
.
getConfigurations
())
.
thenReturn
(
"{\"apollo.public.foo\": \"foo\", \"apollo.public.bar\": \"bar\"}"
);
when
(
configService
.
findRelease
(
someAppId
,
someClusterName
,
somePublicNamespaceName
))
.
thenReturn
(
someRelease
);
when
(
someRelease
.
getId
()).
thenReturn
(
Long
.
valueOf
(
someAppSideReleaseId
));
when
(
appNamespaceService
.
findByNamespaceName
(
somePublicNamespaceName
))
.
thenReturn
(
somePublicAppNamespace
);
when
(
configService
.
findRelease
(
somePublicAppId
,
someDataCenter
,
somePublicNamespaceName
))
.
thenReturn
(
somePublicRelease
);
when
(
somePublicRelease
.
getId
()).
thenReturn
(
Long
.
valueOf
(
somePublicAppSideReleaseId
));
ApolloConfig
result
=
configController
.
queryConfig
(
someAppId
,
someClusterName
,
somePublicNamespaceName
,
someDataCenter
,
someAppSideReleaseId
,
someResponse
);
assertEquals
(
String
.
format
(
"%s|%s"
,
someAppSideReleaseId
,
somePublicAppSideReleaseId
),
result
.
getReleaseId
());
assertEquals
(
someAppId
,
result
.
getAppId
());
assertEquals
(
someClusterName
,
result
.
getCluster
());
assertEquals
(
somePublicNamespaceName
,
result
.
getNamespace
());
assertEquals
(
"foo-override"
,
result
.
getConfigurations
().
get
(
"apollo.public.foo"
));
assertEquals
(
"bar"
,
result
.
getConfigurations
().
get
(
"apollo.public.bar"
));
}
@Test
public
void
testMergeConfigurations
()
throws
Exception
{
Gson
gson
=
new
Gson
();
...
...
@@ -148,4 +288,11 @@ public class ConfigControllerTest {
configController
.
mergeReleaseConfigurations
(
Lists
.
newArrayList
(
someRelease
));
}
private
AppNamespace
assmbleAppNamespace
(
String
appId
,
String
namespace
)
{
AppNamespace
appNamespace
=
new
AppNamespace
();
appNamespace
.
setAppId
(
appId
);
appNamespace
.
setName
(
namespace
);
return
appNamespace
;
}
}
apollo-configservice/src/test/java/com/ctrip/apollo/configservice/controller/NotificationControllerTest.java
浏览文件 @
a76372f0
package
com.ctrip.apollo.configservice.controller
;
import
com.google.common.collect.Lists
;
import
com.google.common.collect.Multimap
;
import
com.ctrip.apollo.biz.entity.AppNamespace
;
import
com.ctrip.apollo.biz.message.Topics
;
import
com.ctrip.apollo.biz.service.AppNamespaceService
;
import
com.ctrip.apollo.core.ConfigConsts
;
import
com.ctrip.apollo.core.dto.ApolloConfigNotification
;
import
org.junit.Before
;
...
...
@@ -15,10 +19,13 @@ import org.springframework.http.ResponseEntity;
import
org.springframework.test.util.ReflectionTestUtils
;
import
org.springframework.web.context.request.async.DeferredResult
;
import
java.util.List
;
import
javax.servlet.http.HttpServletResponse
;
import
static
org
.
junit
.
Assert
.
assertEquals
;
import
static
org
.
junit
.
Assert
.
assertTrue
;
import
static
org
.
mockito
.
Mockito
.
when
;
/**
* @author Jason Song(song_s@ctrip.com)
...
...
@@ -28,19 +35,26 @@ public class NotificationControllerTest {
private
NotificationController
controller
;
private
String
someAppId
;
private
String
someCluster
;
private
String
someNamespace
;
private
String
defaultNamespace
;
private
String
somePublicNamespace
;
private
String
someDataCenter
;
private
String
someReleaseId
;
@Mock
private
HttpServletResponse
response
;
private
Multimap
<
String
,
DeferredResult
<
ResponseEntity
<
ApolloConfigNotification
>>>
deferredResults
;
@Mock
private
AppNamespaceService
appNamespaceService
;
private
Multimap
<
String
,
DeferredResult
<
ResponseEntity
<
ApolloConfigNotification
>>>
deferredResults
;
@Before
public
void
setUp
()
throws
Exception
{
controller
=
new
NotificationController
();
ReflectionTestUtils
.
setField
(
controller
,
"appNamespaceService"
,
appNamespaceService
);
someAppId
=
"someAppId"
;
someCluster
=
"someCluster"
;
someNamespace
=
"someNamespace"
;
defaultNamespace
=
ConfigConsts
.
NAMESPACE_DEFAULT
;
somePublicNamespace
=
"somePublicNamespace"
;
someDataCenter
=
"someDC"
;
someReleaseId
=
"someRelease"
;
...
...
@@ -51,29 +65,78 @@ public class NotificationControllerTest {
@Test
public
void
testPollNotificationWithDefaultNamespace
()
throws
Exception
{
someNamespace
=
someAppId
;
//default namespace
DeferredResult
<
ResponseEntity
<
ApolloConfigNotification
>>
deferredResult
=
controller
.
pollNotification
(
someAppId
,
someCluster
,
some
Namespace
,
someDataCenter
,
someReleaseId
,
.
pollNotification
(
someAppId
,
someCluster
,
default
Namespace
,
someDataCenter
,
someReleaseId
,
response
);
String
key
=
String
.
format
(
"%s-%s-%s"
,
someAppId
,
someCluster
,
some
Namespace
);
String
key
=
String
.
format
(
"%s-%s-%s"
,
someAppId
,
someCluster
,
default
Namespace
);
assertEquals
(
1
,
deferredResults
.
size
());
assertTrue
(
deferredResults
.
get
(
key
).
contains
(
deferredResult
));
}
@Test
public
void
testPollNotificationWithPublicNamespace
()
throws
Exception
{
String
somePublicAppId
=
"somePublicAppId"
;
AppNamespace
somePublicAppNamespace
=
assmbleAppNamespace
(
somePublicAppId
,
somePublicNamespace
);
when
(
appNamespaceService
.
findByNamespaceName
(
somePublicNamespace
))
.
thenReturn
(
somePublicAppNamespace
);
DeferredResult
<
ResponseEntity
<
ApolloConfigNotification
>>
deferredResult
=
controller
.
pollNotification
(
someAppId
,
someCluster
,
somePublicNamespace
,
someDataCenter
,
someReleaseId
,
response
);
List
<
String
>
publicClusters
=
Lists
.
newArrayList
(
someDataCenter
,
ConfigConsts
.
CLUSTER_NAME_DEFAULT
);
assertEquals
(
3
,
deferredResults
.
size
());
String
key
=
String
.
format
(
"%s-%s-%s"
,
someAppId
,
someCluster
,
somePublicNamespace
);
assertTrue
(
deferredResults
.
get
(
key
).
contains
(
deferredResult
));
for
(
String
cluster
:
publicClusters
)
{
String
publicKey
=
String
.
format
(
"%s-%s-%s"
,
somePublicAppId
,
cluster
,
somePublicNamespace
);
assertTrue
(
deferredResults
.
get
(
publicKey
).
contains
(
deferredResult
));
}
}
@Test
public
void
testPollNotificationWithDefaultNamespaceAndHandleMessage
()
throws
Exception
{
someNamespace
=
someAppId
;
//default namespace
DeferredResult
<
ResponseEntity
<
ApolloConfigNotification
>>
deferredResult
=
controller
.
pollNotification
(
someAppId
,
someCluster
,
defaultNamespace
,
someDataCenter
,
someReleaseId
,
response
);
String
key
=
String
.
format
(
"%s-%s-%s"
,
someAppId
,
someCluster
,
defaultNamespace
);
controller
.
handleMessage
(
key
,
Topics
.
APOLLO_RELEASE_TOPIC
);
ResponseEntity
<
ApolloConfigNotification
>
response
=
(
ResponseEntity
<
ApolloConfigNotification
>)
deferredResult
.
getResult
();
ApolloConfigNotification
notification
=
response
.
getBody
();
assertEquals
(
HttpStatus
.
OK
,
response
.
getStatusCode
());
assertEquals
(
defaultNamespace
,
notification
.
getNamespace
());
}
@Test
public
void
testPollNotificationWithPublicNamespaceAndHandleMessage
()
throws
Exception
{
String
somePublicAppId
=
"somePublicAppId"
;
AppNamespace
somePublicAppNamespace
=
assmbleAppNamespace
(
somePublicAppId
,
somePublicNamespace
);
when
(
appNamespaceService
.
findByNamespaceName
(
somePublicNamespace
))
.
thenReturn
(
somePublicAppNamespace
);
DeferredResult
<
ResponseEntity
<
ApolloConfigNotification
>>
deferredResult
=
controller
.
pollNotification
(
someAppId
,
someCluster
,
someNamespace
,
someDataCenter
,
someReleaseId
,
.
pollNotification
(
someAppId
,
someCluster
,
some
Public
Namespace
,
someDataCenter
,
someReleaseId
,
response
);
String
key
=
String
.
format
(
"%s-%s-%s"
,
some
AppId
,
someCluster
,
some
Namespace
);
String
key
=
String
.
format
(
"%s-%s-%s"
,
some
PublicAppId
,
someDataCenter
,
somePublic
Namespace
);
controller
.
handleMessage
(
key
,
Topics
.
APOLLO_RELEASE_TOPIC
);
...
...
@@ -82,8 +145,14 @@ public class NotificationControllerTest {
ApolloConfigNotification
notification
=
response
.
getBody
();
assertEquals
(
HttpStatus
.
OK
,
response
.
getStatusCode
());
assertEquals
(
someAppId
,
notification
.
getAppId
());
assertEquals
(
someCluster
,
notification
.
getCluster
());
assertEquals
(
someNamespace
,
notification
.
getNamespace
());
assertEquals
(
somePublicNamespace
,
notification
.
getNamespace
());
}
private
AppNamespace
assmbleAppNamespace
(
String
appId
,
String
namespace
)
{
AppNamespace
appNamespace
=
new
AppNamespace
();
appNamespace
.
setAppId
(
appId
);
appNamespace
.
setName
(
namespace
);
return
appNamespace
;
}
}
apollo-configservice/src/test/java/com/ctrip/apollo/configservice/integration/ConfigControllerIntegrationTest.java
浏览文件 @
a76372f0
...
...
@@ -19,12 +19,18 @@ public class ConfigControllerIntegrationTest extends AbstractBaseIntegrationTest
private
String
someAppId
;
private
String
someCluster
;
private
String
someNamespace
;
private
String
somePublicNamespace
;
private
String
someDC
;
private
String
someDefaultCluster
;
@Before
public
void
setUp
()
throws
Exception
{
someAppId
=
"someAppId"
;
someCluster
=
"someCluster"
;
someNamespace
=
"someNamespace"
;
somePublicNamespace
=
"somePublicNamespace"
;
someDC
=
"someDC"
;
someDefaultCluster
=
ConfigConsts
.
CLUSTER_NAME_DEFAULT
;
}
@Test
...
...
@@ -83,4 +89,74 @@ public class ConfigControllerIntegrationTest extends AbstractBaseIntegrationTest
assertEquals
(
HttpStatus
.
NOT_MODIFIED
,
response
.
getStatusCode
());
}
@Test
@Sql
(
scripts
=
"/integration-test/test-release.sql"
,
executionPhase
=
Sql
.
ExecutionPhase
.
BEFORE_TEST_METHOD
)
@Sql
(
scripts
=
"/integration-test/cleanup.sql"
,
executionPhase
=
Sql
.
ExecutionPhase
.
AFTER_TEST_METHOD
)
public
void
testQueryPublicConfigWithDataCenterFoundAndNoOverride
()
throws
Exception
{
ResponseEntity
<
ApolloConfig
>
response
=
restTemplate
.
getForEntity
(
"{baseurl}/configs/{appId}/{clusterName}/{namespace}?dataCenter={dateCenter}"
,
ApolloConfig
.
class
,
getHostUrl
(),
someAppId
,
someCluster
,
somePublicNamespace
,
someDC
);
ApolloConfig
result
=
response
.
getBody
();
assertEquals
(
"993"
,
result
.
getReleaseId
());
assertEquals
(
someAppId
,
result
.
getAppId
());
assertEquals
(
someCluster
,
result
.
getCluster
());
assertEquals
(
somePublicNamespace
,
result
.
getNamespace
());
assertEquals
(
"someDC-v1"
,
result
.
getConfigurations
().
get
(
"k1"
));
assertEquals
(
"someDC-v2"
,
result
.
getConfigurations
().
get
(
"k2"
));
}
@Test
@Sql
(
scripts
=
"/integration-test/test-release.sql"
,
executionPhase
=
Sql
.
ExecutionPhase
.
BEFORE_TEST_METHOD
)
@Sql
(
scripts
=
"/integration-test/cleanup.sql"
,
executionPhase
=
Sql
.
ExecutionPhase
.
AFTER_TEST_METHOD
)
public
void
testQueryPublicConfigWithDataCenterFoundAndOverride
()
throws
Exception
{
ResponseEntity
<
ApolloConfig
>
response
=
restTemplate
.
getForEntity
(
"{baseurl}/configs/{appId}/{clusterName}/{namespace}?dataCenter={dateCenter}"
,
ApolloConfig
.
class
,
getHostUrl
(),
someAppId
,
someDefaultCluster
,
somePublicNamespace
,
someDC
);
ApolloConfig
result
=
response
.
getBody
();
assertEquals
(
"994|993"
,
result
.
getReleaseId
());
assertEquals
(
someAppId
,
result
.
getAppId
());
assertEquals
(
someDefaultCluster
,
result
.
getCluster
());
assertEquals
(
somePublicNamespace
,
result
.
getNamespace
());
assertEquals
(
"override-v1"
,
result
.
getConfigurations
().
get
(
"k1"
));
assertEquals
(
"someDC-v2"
,
result
.
getConfigurations
().
get
(
"k2"
));
}
@Test
@Sql
(
scripts
=
"/integration-test/test-release.sql"
,
executionPhase
=
Sql
.
ExecutionPhase
.
BEFORE_TEST_METHOD
)
@Sql
(
scripts
=
"/integration-test/cleanup.sql"
,
executionPhase
=
Sql
.
ExecutionPhase
.
AFTER_TEST_METHOD
)
public
void
testQueryPublicConfigWithDataCenterNotFoundAndNoOverride
()
throws
Exception
{
String
someDCNotFound
=
"someDCNotFound"
;
ResponseEntity
<
ApolloConfig
>
response
=
restTemplate
.
getForEntity
(
"{baseurl}/configs/{appId}/{clusterName}/{namespace}?dataCenter={dateCenter}"
,
ApolloConfig
.
class
,
getHostUrl
(),
someAppId
,
someCluster
,
somePublicNamespace
,
someDCNotFound
);
ApolloConfig
result
=
response
.
getBody
();
assertEquals
(
"992"
,
result
.
getReleaseId
());
assertEquals
(
someAppId
,
result
.
getAppId
());
assertEquals
(
someCluster
,
result
.
getCluster
());
assertEquals
(
somePublicNamespace
,
result
.
getNamespace
());
assertEquals
(
"default-v1"
,
result
.
getConfigurations
().
get
(
"k1"
));
assertEquals
(
"default-v2"
,
result
.
getConfigurations
().
get
(
"k2"
));
}
@Test
@Sql
(
scripts
=
"/integration-test/test-release.sql"
,
executionPhase
=
Sql
.
ExecutionPhase
.
BEFORE_TEST_METHOD
)
@Sql
(
scripts
=
"/integration-test/cleanup.sql"
,
executionPhase
=
Sql
.
ExecutionPhase
.
AFTER_TEST_METHOD
)
public
void
testQueryPublicConfigWithDataCenterNotFoundAndOverride
()
throws
Exception
{
String
someDCNotFound
=
"someDCNotFound"
;
ResponseEntity
<
ApolloConfig
>
response
=
restTemplate
.
getForEntity
(
"{baseurl}/configs/{appId}/{clusterName}/{namespace}?dataCenter={dateCenter}"
,
ApolloConfig
.
class
,
getHostUrl
(),
someAppId
,
someDefaultCluster
,
somePublicNamespace
,
someDCNotFound
);
ApolloConfig
result
=
response
.
getBody
();
assertEquals
(
"994|992"
,
result
.
getReleaseId
());
assertEquals
(
someAppId
,
result
.
getAppId
());
assertEquals
(
someDefaultCluster
,
result
.
getCluster
());
assertEquals
(
somePublicNamespace
,
result
.
getNamespace
());
assertEquals
(
"override-v1"
,
result
.
getConfigurations
().
get
(
"k1"
));
assertEquals
(
"default-v2"
,
result
.
getConfigurations
().
get
(
"k2"
));
}
}
apollo-configservice/src/test/java/com/ctrip/apollo/configservice/integration/NotificationControllerIntegrationTest.java
浏览文件 @
a76372f0
...
...
@@ -10,11 +10,13 @@ import org.junit.Test;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.http.HttpStatus
;
import
org.springframework.http.ResponseEntity
;
import
org.springframework.test.context.jdbc.Sql
;
import
java.util.concurrent.ExecutorService
;
import
java.util.concurrent.Executors
;
import
java.util.concurrent.Future
;
import
java.util.concurrent.TimeUnit
;
import
java.util.concurrent.atomic.AtomicBoolean
;
import
static
org
.
junit
.
Assert
.
assertEquals
;
...
...
@@ -26,40 +28,110 @@ public class NotificationControllerIntegrationTest extends AbstractBaseIntegrati
private
NotificationController
notificationController
;
private
String
someAppId
;
private
String
someCluster
;
private
String
someNamespace
;
private
String
defaultNamespace
;
private
String
somePublicNamespace
;
private
ExecutorService
executorService
;
@Before
public
void
setUp
()
throws
Exception
{
someAppId
=
"someAppId"
;
someCluster
=
ConfigConsts
.
CLUSTER_NAME_DEFAULT
;
someNamespace
=
"someNamespace"
;
defaultNamespace
=
ConfigConsts
.
NAMESPACE_DEFAULT
;
somePublicNamespace
=
"somePublicNamespace"
;
executorService
=
Executors
.
newSingleThreadExecutor
();
}
@Test
public
void
testPollNotification
()
throws
Exception
{
public
void
testPollNotification
WithDefaultNamespace
()
throws
Exception
{
Future
<
ResponseEntity
<
ApolloConfigNotification
>>
future
=
executorService
.
submit
(()
->
restTemplate
.
getForEntity
(
"{baseurl}/notifications?appId={appId}&cluster={clusterName}&namespace={namespace}"
,
ApolloConfigNotification
.
class
,
getHostUrl
(),
someAppId
,
someCluster
,
some
Namespace
));
getHostUrl
(),
someAppId
,
someCluster
,
default
Namespace
));
//wait for the request connected to server
TimeUnit
.
MILLISECONDS
.
sleep
(
500
);
notificationController
.
handleMessage
(
assembleKey
(
someAppId
,
someCluster
,
some
Namespace
),
notificationController
.
handleMessage
(
assembleKey
(
someAppId
,
someCluster
,
default
Namespace
),
Topics
.
APOLLO_RELEASE_TOPIC
);
ResponseEntity
<
ApolloConfigNotification
>
result
=
future
.
get
(
500
,
TimeUnit
.
MILLISECONDS
);
ApolloConfigNotification
notification
=
result
.
getBody
();
assertEquals
(
HttpStatus
.
OK
,
result
.
getStatusCode
());
assertEquals
(
someAppId
,
notification
.
getAppId
());
assertEquals
(
someCluster
,
notification
.
getCluster
());
assertEquals
(
someNamespace
,
notification
.
getNamespace
());
assertEquals
(
defaultNamespace
,
notification
.
getNamespace
());
}
@Test
(
timeout
=
5000L
)
@Sql
(
scripts
=
"/integration-test/test-release.sql"
,
executionPhase
=
Sql
.
ExecutionPhase
.
BEFORE_TEST_METHOD
)
@Sql
(
scripts
=
"/integration-test/cleanup.sql"
,
executionPhase
=
Sql
.
ExecutionPhase
.
AFTER_TEST_METHOD
)
public
void
testPollNotificationWthPublicNamespaceAndNoDataCenter
()
throws
Exception
{
String
publicAppId
=
"somePublicAppId"
;
AtomicBoolean
stop
=
new
AtomicBoolean
();
executorService
.
submit
((
Runnable
)
()
->
{
//wait for the request connected to server
while
(!
stop
.
get
()
&&
!
Thread
.
currentThread
().
isInterrupted
())
{
try
{
TimeUnit
.
MILLISECONDS
.
sleep
(
100
);
}
catch
(
InterruptedException
e
)
{
}
notificationController
.
handleMessage
(
assembleKey
(
publicAppId
,
ConfigConsts
.
CLUSTER_NAME_DEFAULT
,
somePublicNamespace
),
Topics
.
APOLLO_RELEASE_TOPIC
);
}
});
ResponseEntity
<
ApolloConfigNotification
>
result
=
restTemplate
.
getForEntity
(
"{baseurl}/notifications?appId={appId}&cluster={clusterName}&namespace={namespace}"
,
ApolloConfigNotification
.
class
,
getHostUrl
(),
someAppId
,
someCluster
,
somePublicNamespace
);
stop
.
set
(
true
);
ApolloConfigNotification
notification
=
result
.
getBody
();
assertEquals
(
HttpStatus
.
OK
,
result
.
getStatusCode
());
assertEquals
(
somePublicNamespace
,
notification
.
getNamespace
());
}
@Test
(
timeout
=
5000L
)
@Sql
(
scripts
=
"/integration-test/test-release.sql"
,
executionPhase
=
Sql
.
ExecutionPhase
.
BEFORE_TEST_METHOD
)
@Sql
(
scripts
=
"/integration-test/cleanup.sql"
,
executionPhase
=
Sql
.
ExecutionPhase
.
AFTER_TEST_METHOD
)
public
void
testPollNotificationWthPublicNamespaceAndDataCenter
()
throws
Exception
{
String
publicAppId
=
"somePublicAppId"
;
String
someDC
=
"someDC"
;
AtomicBoolean
stop
=
new
AtomicBoolean
();
executorService
.
submit
((
Runnable
)
()
->
{
//wait for the request connected to server
while
(!
stop
.
get
()
&&
!
Thread
.
currentThread
().
isInterrupted
())
{
try
{
TimeUnit
.
MILLISECONDS
.
sleep
(
100
);
}
catch
(
InterruptedException
e
)
{
}
notificationController
.
handleMessage
(
assembleKey
(
publicAppId
,
someDC
,
somePublicNamespace
),
Topics
.
APOLLO_RELEASE_TOPIC
);
}
});
ResponseEntity
<
ApolloConfigNotification
>
result
=
restTemplate
.
getForEntity
(
"{baseurl}/notifications?appId={appId}&cluster={clusterName}&namespace={namespace}&dataCenter={dataCenter}"
,
ApolloConfigNotification
.
class
,
getHostUrl
(),
someAppId
,
someCluster
,
somePublicNamespace
,
someDC
);
stop
.
set
(
true
);
ApolloConfigNotification
notification
=
result
.
getBody
();
assertEquals
(
HttpStatus
.
OK
,
result
.
getStatusCode
());
assertEquals
(
somePublicNamespace
,
notification
.
getNamespace
());
}
private
String
assembleKey
(
String
appId
,
String
cluster
,
String
namespace
)
{
return
String
.
format
(
"%s-%s-%s"
,
appId
,
cluster
,
namespace
);
}
...
...
apollo-configservice/src/test/resources/integration-test/test-release.sql
浏览文件 @
a76372f0
INSERT
INTO
App
(
AppId
,
Name
,
OwnerName
,
OwnerEmail
)
VALUES
(
'someAppId'
,
'someAppName'
,
'someOwnerName'
,
'someOwnerName@ctrip.com'
);
INSERT
INTO
App
(
AppId
,
Name
,
OwnerName
,
OwnerEmail
)
VALUES
(
'somePublicAppId'
,
'somePublicAppName'
,
'someOwnerName'
,
'someOwnerName@ctrip.com'
);
INSERT
INTO
Cluster
(
AppId
,
Name
)
VALUES
(
'someAppId'
,
'default'
);
INSERT
INTO
Cluster
(
AppId
,
Name
)
VALUES
(
'someAppId'
,
'someCluster'
);
INSERT
INTO
Cluster
(
AppId
,
Name
)
VALUES
(
'somePublicAppId'
,
'default'
);
INSERT
INTO
Cluster
(
AppId
,
Name
)
VALUES
(
'somePublicAppId'
,
'someDC'
);
INSERT
INTO
AppNamespace
(
AppId
,
Name
)
VALUES
(
'someAppId'
,
'
someAppId
'
);
INSERT
INTO
AppNamespace
(
AppId
,
Name
)
VALUES
(
'someAppId'
,
'
application
'
);
INSERT
INTO
AppNamespace
(
AppId
,
Name
)
VALUES
(
'someAppId'
,
'someNamespace'
);
INSERT
INTO
AppNamespace
(
AppId
,
Name
)
VALUES
(
'somePublicAppId'
,
'application'
);
INSERT
INTO
AppNamespace
(
AppId
,
Name
)
VALUES
(
'somePublicAppId'
,
'somePublicNamespace'
);
INSERT
INTO
Namespace
(
AppId
,
ClusterName
,
NamespaceName
)
VALUES
(
'someAppId'
,
'default'
,
'
someAppId
'
);
INSERT
INTO
Namespace
(
AppId
,
ClusterName
,
NamespaceName
)
VALUES
(
'someAppId'
,
'default'
,
'
application
'
);
INSERT
INTO
Namespace
(
AppId
,
ClusterName
,
NamespaceName
)
VALUES
(
'someAppId'
,
'someCluster'
,
'someNamespace'
);
INSERT
INTO
Namespace
(
AppId
,
ClusterName
,
NamespaceName
)
VALUES
(
'somePublicAppId'
,
'default'
,
'application'
);
INSERT
INTO
Namespace
(
AppId
,
ClusterName
,
NamespaceName
)
VALUES
(
'somePublicAppId'
,
'someDC'
,
'somePublicNamespace'
);
INSERT
INTO
Namespace
(
AppId
,
ClusterName
,
NamespaceName
)
VALUES
(
'someAppId'
,
'default'
,
'somePublicNamespace'
);
INSERT
INTO
RELEASE
(
id
,
Name
,
Comment
,
AppId
,
ClusterName
,
NamespaceName
,
Configurations
)
VALUES
(
990
,
'INTEGRATION-TEST-DEFAULT'
,
'First Release'
,
'someAppId'
,
'default'
,
'application'
,
'{"k1":"v1"}'
);
INSERT
INTO
RELEASE
(
id
,
Name
,
Comment
,
AppId
,
ClusterName
,
NamespaceName
,
Configurations
)
VALUES
(
991
,
'INTEGRATION-TEST-NAMESPACE'
,
'First Release'
,
'someAppId'
,
'someCluster'
,
'someNamespace'
,
'{"k2":"v2"}'
);
INSERT
INTO
RELEASE
(
id
,
Name
,
Comment
,
AppId
,
ClusterName
,
NamespaceName
,
Configurations
)
VALUES
(
990
,
'INTEGRATION-TEST-DEFAULT'
,
'First Release'
,
'someAppId'
,
'default'
,
'application'
,
'{"k1":"v1"}'
);
INSERT
INTO
RELEASE
(
id
,
Name
,
Comment
,
AppId
,
ClusterName
,
NamespaceName
,
Configurations
)
VALUES
(
991
,
'INTEGRATION-TEST-NAMESPACE'
,
'First Release'
,
'someAppId'
,
'someCluster'
,
'someNamespace'
,
'{"k2":"v2"}'
);
INSERT
INTO
RELEASE
(
id
,
Name
,
Comment
,
AppId
,
ClusterName
,
NamespaceName
,
Configurations
)
VALUES
(
992
,
'INTEGRATION-TEST-PUBLIC-DEFAULT'
,
'First Release'
,
'somePublicAppId'
,
'default'
,
'somePublicNamespace'
,
'{"k1":"default-v1", "k2":"default-v2"}'
);
INSERT
INTO
RELEASE
(
id
,
Name
,
Comment
,
AppId
,
ClusterName
,
NamespaceName
,
Configurations
)
VALUES
(
993
,
'INTEGRATION-TEST-PUBLIC-NAMESPACE'
,
'First Release'
,
'somePublicAppId'
,
'someDC'
,
'somePublicNamespace'
,
'{"k1":"someDC-v1", "k2":"someDC-v2"}'
);
INSERT
INTO
RELEASE
(
id
,
Name
,
Comment
,
AppId
,
ClusterName
,
NamespaceName
,
Configurations
)
VALUES
(
994
,
'INTEGRATION-TEST-DEFAULT-OVERRIDE-PUBLIC'
,
'First Release'
,
'someAppId'
,
'default'
,
'somePublicNamespace'
,
'{"k1":"override-v1"}'
);
apollo-core/src/main/java/com/ctrip/apollo/core/dto/ApolloConfigNotification.java
浏览文件 @
a76372f0
...
...
@@ -4,40 +4,20 @@ package com.ctrip.apollo.core.dto;
* @author Jason Song(song_s@ctrip.com)
*/
public
class
ApolloConfigNotification
{
private
String
appId
;
private
String
cluster
;
private
String
namespace
;
//for json converter
public
ApolloConfigNotification
()
{
}
public
ApolloConfigNotification
(
String
appId
,
String
cluster
,
String
namespace
)
{
this
.
appId
=
appId
;
this
.
cluster
=
cluster
;
public
ApolloConfigNotification
(
String
namespace
)
{
this
.
namespace
=
namespace
;
}
public
String
getAppId
()
{
return
appId
;
}
public
String
getCluster
()
{
return
cluster
;
}
public
String
getNamespace
()
{
return
namespace
;
}
public
void
setAppId
(
String
appId
)
{
this
.
appId
=
appId
;
}
public
void
setCluster
(
String
cluster
)
{
this
.
cluster
=
cluster
;
}
public
void
setNamespace
(
String
namespace
)
{
this
.
namespace
=
namespace
;
}
...
...
apollo-demo/Demo.md
0 → 100644
浏览文件 @
a76372f0
#Demo
## 1. 本地没有缓存文件,从服务端正常读取
## 2. 本地有缓存文件,从服务端正常读取
## 3. 本地没有缓存文件,从服务端读取失败
## 4. 本地有缓存文件,从服务端读取失败
## 5. 本地启动后,配置有新的发布
\ No newline at end of file
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录