Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
A
apollo
Project
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
openSource
apollo
Commits
bb68324d
Commit
bb68324d
authored
Apr 18, 2016
by
Jason Song
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Client side retry and logging to CAT
parent
7795a848
Hide whitespace changes
Inline
Side-by-side
Showing
18 changed files
with
343 additions
and
106 deletions
+343
-106
ConfigService.java
...-client/src/main/java/com/ctrip/apollo/ConfigService.java
+6
-2
PropertyChangeType.java
.../main/java/com/ctrip/apollo/enums/PropertyChangeType.java
+1
-13
ClientEnvironment.java
...src/main/java/com/ctrip/apollo/env/ClientEnvironment.java
+2
-1
AbstractConfig.java
.../main/java/com/ctrip/apollo/internals/AbstractConfig.java
+2
-0
AbstractConfigRepository.java
.../com/ctrip/apollo/internals/AbstractConfigRepository.java
+4
-0
ConfigServiceLocator.java
...java/com/ctrip/apollo/internals/ConfigServiceLocator.java
+52
-17
DefaultConfig.java
...c/main/java/com/ctrip/apollo/internals/DefaultConfig.java
+2
-1
LocalFileConfigRepository.java
...com/ctrip/apollo/internals/LocalFileConfigRepository.java
+11
-11
RemoteConfigRepository.java
...va/com/ctrip/apollo/internals/RemoteConfigRepository.java
+63
-22
SimpleConfig.java
...rc/main/java/com/ctrip/apollo/internals/SimpleConfig.java
+2
-0
DefaultConfigFactory.java
.../main/java/com/ctrip/apollo/spi/DefaultConfigFactory.java
+15
-4
ConfigUtil.java
...lient/src/main/java/com/ctrip/apollo/util/ConfigUtil.java
+4
-4
HttpUtil.java
...nt/src/main/java/com/ctrip/apollo/util/http/HttpUtil.java
+38
-4
BaseIntegrationTest.java
...ava/com/ctrip/apollo/integration/BaseIntegrationTest.java
+48
-3
ConfigIntegrationTest.java
...a/com/ctrip/apollo/integration/ConfigIntegrationTest.java
+69
-22
Apollo.java
apollo-core/src/main/java/com/ctrip/apollo/Apollo.java
+8
-0
ServiceDTO.java
...e/src/main/java/com/ctrip/apollo/core/dto/ServiceDTO.java
+12
-0
ApolloConfigDemo.java
apollo-demo/src/main/java/ApolloConfigDemo.java
+4
-2
No files found.
apollo-client/src/main/java/com/ctrip/apollo/ConfigService.java
View file @
bb68324d
...
...
@@ -4,6 +4,7 @@ import com.ctrip.apollo.core.ConfigConsts;
import
com.ctrip.apollo.internals.ConfigManager
;
import
com.ctrip.apollo.spi.ConfigFactory
;
import
com.ctrip.apollo.spi.ConfigRegistry
;
import
com.dianping.cat.Cat
;
import
org.codehaus.plexus.PlexusContainer
;
import
org.codehaus.plexus.component.repository.exception.ComponentLookupException
;
...
...
@@ -36,6 +37,7 @@ public class ConfigService {
* @return config instance
*/
public
static
Config
getConfig
(
String
namespace
)
{
Cat
.
logEvent
(
"Apollo.Client.Version"
,
Apollo
.
VERSION
);
return
getManager
().
getConfig
(
namespace
);
}
...
...
@@ -43,6 +45,7 @@ public class ConfigService {
try
{
return
s_instance
.
m_container
.
lookup
(
ConfigManager
.
class
);
}
catch
(
ComponentLookupException
ex
)
{
Cat
.
logError
(
ex
);
throw
new
IllegalStateException
(
"Unable to load ConfigManager!"
,
ex
);
}
}
...
...
@@ -51,6 +54,7 @@ public class ConfigService {
try
{
return
s_instance
.
m_container
.
lookup
(
ConfigRegistry
.
class
);
}
catch
(
ComponentLookupException
ex
)
{
Cat
.
logError
(
ex
);
throw
new
IllegalStateException
(
"Unable to load ConfigRegistry!"
,
ex
);
}
}
...
...
@@ -60,7 +64,7 @@ public class ConfigService {
}
/**
* Manually set the config for the namespace specified, use with caution
!
* Manually set the config for the namespace specified, use with caution
.
* @param namespace the namespace
* @param config the config instance
*/
...
...
@@ -78,7 +82,7 @@ public class ConfigService {
}
/**
* Manually set the config factory for the namespace specified, use with caution
!
* Manually set the config factory for the namespace specified, use with caution
.
* @param namespace the namespace
* @param factory the factory instance
*/
...
...
apollo-client/src/main/java/com/ctrip/apollo/enums/PropertyChangeType.java
View file @
bb68324d
...
...
@@ -5,17 +5,5 @@ package com.ctrip.apollo.enums;
* @author Jason Song(song_s@ctrip.com)
*/
public
enum
PropertyChangeType
{
NEW
(
"New"
),
MODIFIED
(
"Modified"
),
DELETED
(
"Deleted"
);
private
String
type
;
PropertyChangeType
(
String
type
)
{
this
.
type
=
type
;
}
public
String
getType
()
{
return
type
;
}
NEW
,
MODIFIED
,
DELETED
}
apollo-client/src/main/java/com/ctrip/apollo/env/
Apollo
.java
→
apollo-client/src/main/java/com/ctrip/apollo/env/
ClientEnvironment
.java
View file @
bb68324d
...
...
@@ -5,7 +5,7 @@ import com.google.common.base.Strings;
import
com.ctrip.apollo.core.enums.Env
;
import
com.ctrip.framework.foundation.Foundation
;
public
class
Apollo
{
public
class
ClientEnvironment
{
private
static
Env
s_env
;
private
static
String
s_appId
;
private
static
String
s_cluster
;
...
...
@@ -39,6 +39,7 @@ public class Apollo {
s_env
=
Env
.
LPT
;
break
;
case
"FAT"
:
case
"FWS"
:
s_env
=
Env
.
FAT
;
break
;
case
"UAT"
:
...
...
apollo-client/src/main/java/com/ctrip/apollo/internals/AbstractConfig.java
View file @
bb68324d
...
...
@@ -9,6 +9,7 @@ import com.ctrip.apollo.ConfigChangeListener;
import
com.ctrip.apollo.enums.PropertyChangeType
;
import
com.ctrip.apollo.model.ConfigChange
;
import
com.ctrip.apollo.model.ConfigChangeEvent
;
import
com.dianping.cat.Cat
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
...
...
@@ -36,6 +37,7 @@ public abstract class AbstractConfig implements Config {
try
{
listener
.
onChange
(
changeEvent
);
}
catch
(
Throwable
ex
)
{
Cat
.
logError
(
ex
);
logger
.
error
(
"Failed to invoke config change listener {}"
,
listener
.
getClass
(),
ex
);
}
}
...
...
apollo-client/src/main/java/com/ctrip/apollo/internals/AbstractConfigRepository.java
View file @
bb68324d
...
...
@@ -2,6 +2,8 @@ package com.ctrip.apollo.internals;
import
com.google.common.collect.Lists
;
import
com.dianping.cat.Cat
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
...
...
@@ -19,6 +21,7 @@ public abstract class AbstractConfigRepository implements ConfigRepository {
try
{
sync
();
}
catch
(
Throwable
ex
)
{
Cat
.
logError
(
ex
);
logger
.
error
(
"Sync config failed with repository {}"
,
this
.
getClass
(),
ex
);
}
}
...
...
@@ -42,6 +45,7 @@ public abstract class AbstractConfigRepository implements ConfigRepository {
try
{
listener
.
onRepositoryChange
(
namespace
,
newProperties
);
}
catch
(
Throwable
ex
)
{
Cat
.
logError
(
ex
);
logger
.
error
(
"Failed to invoke repository change listener {}"
,
listener
.
getClass
(),
ex
);
}
}
...
...
apollo-client/src/main/java/com/ctrip/apollo/internals/ConfigServiceLocator.java
View file @
bb68324d
package
com
.
ctrip
.
apollo
.
internals
;
import
com.google.common.collect.Lists
;
import
com.google.gson.reflect.TypeToken
;
import
com.ctrip.apollo.core.dto.ServiceDTO
;
import
com.ctrip.apollo.util.ConfigUtil
;
import
com.ctrip.apollo.util.http.HttpRequest
;
import
com.ctrip.apollo.util.http.HttpResponse
;
import
com.ctrip.apollo.util.http.HttpUtil
;
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.unidal.lookup.annotation.Inject
;
import
org.unidal.lookup.annotation.Named
;
import
java.
util.ArrayList
;
import
java.
lang.reflect.Type
;
import
java.util.List
;
import
java.util.concurrent.TimeUnit
;
import
java.util.concurrent.atomic.AtomicReference
;
@Named
(
type
=
ConfigServiceLocator
.
class
)
public
class
ConfigServiceLocator
{
private
static
final
Logger
logger
=
LoggerFactory
.
getLogger
(
ConfigServiceLocator
.
class
);
@Inject
private
HttpUtil
m_httpUtil
;
@Inject
private
ConfigUtil
m_configUtil
;
private
List
<
ServiceDTO
>
serviceCaches
=
new
ArrayList
<>();
private
AtomicReference
<
List
<
ServiceDTO
>>
m_configServices
;
private
Type
m_responseType
;
public
ConfigServiceLocator
()
{
List
<
ServiceDTO
>
initial
=
Lists
.
newArrayList
();
m_configServices
=
new
AtomicReference
<>(
initial
);
m_responseType
=
new
TypeToken
<
List
<
ServiceDTO
>>()
{
}.
getType
();
}
/**
* Get the config service info from remote meta server.
*
* @return the services dto
*/
public
List
<
ServiceDTO
>
getConfigServices
()
{
if
(
m_configServices
.
get
().
isEmpty
())
{
updateConfigServices
();
}
return
m_configServices
.
get
();
}
//TODO periodically update config services
private
void
updateConfigServices
()
{
String
domainName
=
m_configUtil
.
getMetaServerDomainName
();
String
url
=
domainName
+
"/services/config"
;
HttpRequest
request
=
new
HttpRequest
(
url
);
int
maxRetries
=
5
;
Throwable
exception
=
null
;
for
(
int
i
=
0
;
i
<
maxRetries
;
i
++)
{
Transaction
transaction
=
Cat
.
newTransaction
(
"Apollo.MetaService"
,
"getConfigService"
);
transaction
.
addData
(
"Url"
,
url
);
try
{
HttpResponse
<
List
<
ServiceDTO
>>
response
=
m_httpUtil
.
doGet
(
request
,
m_responseType
);
m_configServices
.
set
(
response
.
getBody
());
Cat
.
logEvent
(
"Apollo.Config.Services"
,
response
.
getBody
().
toString
());
transaction
.
setStatus
(
Message
.
SUCCESS
);
return
;
}
catch
(
Throwable
ex
)
{
Cat
.
logError
(
ex
);
transaction
.
setStatus
(
ex
);
exception
=
ex
;
}
finally
{
transaction
.
complete
();
}
try
{
HttpResponse
<
ServiceDTO
[]>
response
=
m_httpUtil
.
doGet
(
request
,
ServiceDTO
[].
class
);
ServiceDTO
[]
services
=
response
.
getBody
();
if
(
services
!=
null
&&
services
.
length
>
0
)
{
serviceCaches
.
clear
();
for
(
ServiceDTO
service
:
services
)
{
serviceCaches
.
add
(
service
);
}
try
{
TimeUnit
.
SECONDS
.
sleep
(
1
);
}
catch
(
InterruptedException
e
)
{
//ignore
}
}
catch
(
Throwable
ex
)
{
logger
.
error
(
"Get config services failed"
,
ex
);
throw
new
RuntimeException
(
"Get config services failed"
,
ex
);
}
return
serviceCaches
;
throw
new
RuntimeException
(
"Get config services failed"
,
exception
)
;
}
}
apollo-client/src/main/java/com/ctrip/apollo/internals/DefaultConfig.java
View file @
bb68324d
...
...
@@ -50,6 +50,7 @@ public class DefaultConfig extends AbstractConfig implements RepositoryChangeLis
}
catch
(
Throwable
ex
)
{
String
message
=
String
.
format
(
"Init Apollo Local Config failed - namespace: %s"
,
m_namespace
);
Cat
.
logError
(
ex
);
logger
.
error
(
message
,
ex
);
}
}
...
...
@@ -161,8 +162,8 @@ public class DefaultConfig extends AbstractConfig implements RepositoryChangeLis
try
{
properties
.
load
(
in
);
}
catch
(
IOException
ex
)
{
logger
.
error
(
"Load resource config for namespace {} failed"
,
namespace
,
ex
);
Cat
.
logError
(
ex
);
logger
.
error
(
"Load resource config for namespace {} failed"
,
namespace
,
ex
);
}
finally
{
try
{
in
.
close
();
...
...
apollo-client/src/main/java/com/ctrip/apollo/internals/LocalFileConfigRepository.java
View file @
bb68324d
...
...
@@ -34,7 +34,8 @@ public class LocalFileConfigRepository extends AbstractConfigRepository
/**
* Constructor.
* @param baseDir the base dir for this local file config repository
*
* @param baseDir the base dir for this local file config repository
* @param namespace the namespace
*/
public
LocalFileConfigRepository
(
File
baseDir
,
String
namespace
)
{
...
...
@@ -44,6 +45,7 @@ public class LocalFileConfigRepository extends AbstractConfigRepository
try
{
m_configUtil
=
m_container
.
lookup
(
ConfigUtil
.
class
);
}
catch
(
ComponentLookupException
ex
)
{
Cat
.
logError
(
ex
);
throw
new
IllegalStateException
(
"Unable to load component!"
,
ex
);
}
this
.
trySync
();
...
...
@@ -86,6 +88,7 @@ public class LocalFileConfigRepository extends AbstractConfigRepository
try
{
m_fileProperties
=
this
.
loadFromLocalCacheFile
(
m_baseDir
,
m_namespace
);
}
catch
(
Throwable
ex
)
{
Cat
.
logError
(
ex
);
ex
.
printStackTrace
();
//ignore
}
...
...
@@ -107,9 +110,8 @@ public class LocalFileConfigRepository extends AbstractConfigRepository
Properties
properties
=
m_fallback
.
getConfig
();
updateFileProperties
(
properties
);
}
catch
(
Throwable
ex
)
{
String
message
=
String
.
format
(
"Sync config from fallback repository %s failed"
,
m_fallback
.
getClass
());
logger
.
warn
(
message
,
ex
);
Cat
.
logError
(
ex
);
logger
.
warn
(
"Sync config from fallback repository {} failed"
,
m_fallback
.
getClass
(),
ex
);
}
}
...
...
@@ -136,9 +138,9 @@ public class LocalFileConfigRepository extends AbstractConfigRepository
properties
=
new
Properties
();
properties
.
load
(
in
);
}
catch
(
IOException
ex
)
{
logger
.
error
(
"Loading config from local cache file {} failed"
,
file
.
getAbsolutePath
(),
ex
);
Cat
.
logError
(
ex
);
throw
ex
;
throw
new
RuntimeException
(
String
.
format
(
"Loading config from local cache file %s failed"
,
file
.
getAbsolutePath
()),
ex
);
}
finally
{
try
{
if
(
in
!=
null
)
{
...
...
@@ -149,10 +151,8 @@ public class LocalFileConfigRepository extends AbstractConfigRepository
}
}
}
else
{
String
message
=
String
.
format
(
"Cannot read from local cache file %s"
,
file
.
getAbsolutePath
());
logger
.
error
(
message
);
throw
new
RuntimeException
(
message
);
throw
new
RuntimeException
(
String
.
format
(
"Cannot read from local cache file %s"
,
file
.
getAbsolutePath
()));
}
return
properties
;
...
...
@@ -170,8 +170,8 @@ public class LocalFileConfigRepository extends AbstractConfigRepository
out
=
new
FileOutputStream
(
file
);
m_fileProperties
.
store
(
out
,
"Persisted by DefaultConfig"
);
}
catch
(
IOException
ex
)
{
logger
.
error
(
"Persist local cache file {} failed"
,
file
.
getAbsolutePath
(),
ex
);
Cat
.
logError
(
ex
);
logger
.
error
(
"Persist local cache file {} failed"
,
file
.
getAbsolutePath
(),
ex
);
}
finally
{
if
(
out
!=
null
)
{
try
{
...
...
apollo-client/src/main/java/com/ctrip/apollo/internals/RemoteConfigRepository.java
View file @
bb68324d
...
...
@@ -10,6 +10,9 @@ import com.ctrip.apollo.util.ConfigUtil;
import
com.ctrip.apollo.util.http.HttpRequest
;
import
com.ctrip.apollo.util.http.HttpResponse
;
import
com.ctrip.apollo.util.http.HttpUtil
;
import
com.dianping.cat.Cat
;
import
com.dianping.cat.message.Message
;
import
com.dianping.cat.message.Transaction
;
import
org.codehaus.plexus.PlexusContainer
;
import
org.codehaus.plexus.component.repository.exception.ComponentLookupException
;
...
...
@@ -17,10 +20,12 @@ import org.slf4j.Logger;
import
org.slf4j.LoggerFactory
;
import
org.unidal.lookup.ContainerLoader
;
import
java.util.Collections
;
import
java.util.List
;
import
java.util.Properties
;
import
java.util.concurrent.Executors
;
import
java.util.concurrent.ScheduledExecutorService
;
import
java.util.concurrent.TimeUnit
;
import
java.util.concurrent.atomic.AtomicReference
;
/**
...
...
@@ -38,6 +43,7 @@ public class RemoteConfigRepository extends AbstractConfigRepository {
/**
* Constructor.
*
* @param namespace the namespace
*/
public
RemoteConfigRepository
(
String
namespace
)
{
...
...
@@ -49,6 +55,7 @@ public class RemoteConfigRepository extends AbstractConfigRepository {
m_httpUtil
=
m_container
.
lookup
(
HttpUtil
.
class
);
m_serviceLocator
=
m_container
.
lookup
(
ConfigServiceLocator
.
class
);
}
catch
(
ComponentLookupException
ex
)
{
Cat
.
logError
(
ex
);
throw
new
IllegalStateException
(
"Unable to load component!"
,
ex
);
}
this
.
m_executorService
=
Executors
.
newScheduledThreadPool
(
1
,
...
...
@@ -110,35 +117,65 @@ public class RemoteConfigRepository extends AbstractConfigRepository {
private
ApolloConfig
loadApolloConfig
()
{
String
appId
=
m_configUtil
.
getAppId
();
String
cluster
=
m_configUtil
.
getCluster
();
String
url
=
assembleUrl
(
getConfigServiceUrl
(),
appId
,
cluster
,
m_namespace
,
m_configCache
.
get
())
;
Cat
.
logEvent
(
"Apollo.Client.Config"
,
String
.
format
(
"%s-%s-%s"
,
appId
,
cluster
,
m_namespace
));
int
maxRetries
=
2
;
Throwable
exception
=
null
;
logger
.
info
(
"Loading config from {}"
,
url
);
HttpRequest
request
=
new
HttpRequest
(
url
);
List
<
ServiceDTO
>
configServices
=
getConfigServices
();
for
(
int
i
=
0
;
i
<
maxRetries
;
i
++)
{
List
<
ServiceDTO
>
randomConfigServices
=
Lists
.
newArrayList
(
configServices
);
Collections
.
shuffle
(
randomConfigServices
);
try
{
HttpResponse
<
ApolloConfig
>
response
=
m_httpUtil
.
doGet
(
request
,
ApolloConfig
.
class
);
if
(
response
.
getStatusCode
()
==
304
)
{
logger
.
info
(
"Config server responds with 304 HTTP status code."
);
return
m_configCache
.
get
();
}
for
(
ServiceDTO
configService
:
randomConfigServices
)
{
String
url
=
assembleUrl
(
configService
.
getHomepageUrl
(),
appId
,
cluster
,
m_namespace
,
m_configCache
.
get
());
logger
.
debug
(
"Loading config from {}"
,
url
);
HttpRequest
request
=
new
HttpRequest
(
url
);
Transaction
transaction
=
Cat
.
newTransaction
(
"Apollo.ConfigService"
,
"queryConfig"
);
transaction
.
addData
(
"Url"
,
url
);
try
{
logger
.
info
(
"Loaded config: {}"
,
response
.
getBody
());
HttpResponse
<
ApolloConfig
>
response
=
m_httpUtil
.
doGet
(
request
,
ApolloConfig
.
class
);
transaction
.
addData
(
"StatusCode"
,
response
.
getStatusCode
());
transaction
.
setStatus
(
Message
.
SUCCESS
);
if
(
response
.
getStatusCode
()
==
304
)
{
logger
.
debug
(
"Config server responds with 304 HTTP status code."
);
return
m_configCache
.
get
();
}
logger
.
debug
(
"Loaded config: {}"
,
response
.
getBody
());
return
response
.
getBody
();
}
catch
(
Throwable
ex
)
{
String
message
=
String
.
format
(
"Load Apollo Config failed - appId: %s, cluster: %s, namespace: %s"
,
appId
,
cluster
,
m_namespace
);
logger
.
error
(
message
,
ex
);
throw
new
RuntimeException
(
message
,
ex
);
return
response
.
getBody
();
}
catch
(
Throwable
ex
)
{
Cat
.
logError
(
ex
);
transaction
.
setStatus
(
ex
);
exception
=
ex
;
}
finally
{
transaction
.
complete
();
}
}
try
{
TimeUnit
.
SECONDS
.
sleep
(
1
);
}
catch
(
InterruptedException
e
)
{
//ignore
}
}
String
message
=
String
.
format
(
"Load Apollo Config failed - appId: %s, cluster: %s, namespace: %s, services: %s"
,
appId
,
cluster
,
m_namespace
,
configServices
);
logger
.
error
(
message
,
exception
);
throw
new
RuntimeException
(
message
,
exception
);
}
private
String
assembleUrl
(
String
uri
,
String
appId
,
String
cluster
,
String
namespace
,
ApolloConfig
previousConfig
)
{
String
path
=
"
/
config/%s/%s"
;
String
path
=
"config/%s/%s"
;
List
<
String
>
params
=
Lists
.
newArrayList
(
appId
,
cluster
);
if
(!
Strings
.
isNullOrEmpty
(
namespace
))
{
...
...
@@ -151,14 +188,18 @@ public class RemoteConfigRepository extends AbstractConfigRepository {
}
String
pathExpanded
=
String
.
format
(
path
,
params
.
toArray
());
if
(!
uri
.
endsWith
(
"/"
))
{
uri
+=
"/"
;
}
return
uri
+
pathExpanded
;
}
private
String
getConfigServiceUrl
()
{
private
List
<
ServiceDTO
>
getConfigServices
()
{
List
<
ServiceDTO
>
services
=
m_serviceLocator
.
getConfigServices
();
if
(
services
.
size
()
==
0
)
{
throw
new
RuntimeException
(
"No available config service"
);
}
return
services
.
get
(
0
).
getHomepageUrl
();
return
services
;
}
}
apollo-client/src/main/java/com/ctrip/apollo/internals/SimpleConfig.java
View file @
bb68324d
...
...
@@ -5,6 +5,7 @@ import com.google.common.collect.Maps;
import
com.ctrip.apollo.model.ConfigChange
;
import
com.ctrip.apollo.model.ConfigChangeEvent
;
import
com.dianping.cat.Cat
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
...
...
@@ -40,6 +41,7 @@ public class SimpleConfig extends AbstractConfig implements RepositoryChangeList
}
catch
(
Throwable
ex
)
{
String
message
=
String
.
format
(
"Init Apollo Simple Config failed - namespace: %s"
,
m_namespace
);
Cat
.
logError
(
message
,
ex
);
logger
.
error
(
message
,
ex
);
}
}
...
...
apollo-client/src/main/java/com/ctrip/apollo/spi/DefaultConfigFactory.java
View file @
bb68324d
...
...
@@ -5,12 +5,15 @@ import com.ctrip.apollo.core.utils.ClassLoaderUtil;
import
com.ctrip.apollo.internals.DefaultConfig
;
import
com.ctrip.apollo.internals.LocalFileConfigRepository
;
import
com.ctrip.apollo.internals.RemoteConfigRepository
;
import
com.dianping.cat.Cat
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
org.unidal.lookup.annotation.Named
;
import
java.io.File
;
import
java.io.IOException
;
import
java.nio.file.Files
;
/**
* @author Jason Song(song_s@ctrip.com)
...
...
@@ -26,10 +29,18 @@ public class DefaultConfigFactory implements ConfigFactory {
*/
public
DefaultConfigFactory
()
{
m_baseDir
=
new
File
(
ClassLoaderUtil
.
getClassPath
()
+
CONFIG_DIR
);
if
(!
m_baseDir
.
exists
())
{
if
(!
m_baseDir
.
mkdir
()){
logger
.
error
(
"Creating local cache dir failed."
);
}
this
.
checkLocalConfigCacheDir
(
m_baseDir
);
}
private
void
checkLocalConfigCacheDir
(
File
baseDir
)
{
if
(
baseDir
.
exists
())
{
return
;
}
try
{
Files
.
createDirectory
(
baseDir
.
toPath
());
}
catch
(
IOException
ex
)
{
Cat
.
logError
(
ex
);
logger
.
error
(
"Unable to create directory: "
+
baseDir
,
ex
);
}
}
...
...
apollo-client/src/main/java/com/ctrip/apollo/util/ConfigUtil.java
View file @
bb68324d
...
...
@@ -5,7 +5,7 @@ import com.google.common.base.Preconditions;
import
com.ctrip.apollo.core.ConfigConsts
;
import
com.ctrip.apollo.core.MetaDomainConsts
;
import
com.ctrip.apollo.core.enums.Env
;
import
com.ctrip.apollo.env.
Apollo
;
import
com.ctrip.apollo.env.
ClientEnvironment
;
import
org.unidal.lookup.annotation.Named
;
...
...
@@ -28,7 +28,7 @@ public class ConfigUtil {
* @throws IllegalStateException if app id is not set
*/
public
String
getAppId
()
{
String
appId
=
Apollo
.
getAppId
();
String
appId
=
ClientEnvironment
.
getAppId
();
Preconditions
.
checkState
(
appId
!=
null
,
"app.id is not set"
);
return
appId
;
}
...
...
@@ -38,7 +38,7 @@ public class ConfigUtil {
* @return the cluster name, or "default" if not specified
*/
public
String
getCluster
()
{
String
cluster
=
Apollo
.
getCluster
();
String
cluster
=
ClientEnvironment
.
getCluster
();
if
(
cluster
==
null
)
{
cluster
=
ConfigConsts
.
CLUSTER_NAME_DEFAULT
;
}
...
...
@@ -51,7 +51,7 @@ public class ConfigUtil {
* @throws IllegalStateException if env is set
*/
public
Env
getApolloEnv
()
{
Env
env
=
Apollo
.
getEnv
();
Env
env
=
ClientEnvironment
.
getEnv
();
Preconditions
.
checkState
(
env
!=
null
,
"env is not set"
);
return
env
;
}
...
...
apollo-client/src/main/java/com/ctrip/apollo/util/http/HttpUtil.java
View file @
bb68324d
package
com
.
ctrip
.
apollo
.
util
.
http
;
import
com.google.common.base.Charsets
;
import
com.google.common.base.Function
;
import
com.google.gson.Gson
;
import
com.ctrip.apollo.util.ConfigUtil
;
...
...
@@ -11,6 +12,7 @@ import org.unidal.lookup.annotation.Named;
import
java.io.IOException
;
import
java.io.InputStream
;
import
java.lang.reflect.Type
;
import
java.net.HttpURLConnection
;
import
java.net.URL
;
...
...
@@ -30,10 +32,43 @@ public class HttpUtil {
/**
* Do get operation for the http request.
*
* @return the http response
* @param httpRequest the request
* @param responseType the response type
* @return the response
* @throws RuntimeException if any error happened or response code is neither 200 nor 304
*/
public
<
T
>
HttpResponse
<
T
>
doGet
(
HttpRequest
httpRequest
,
Class
<
T
>
responseType
)
{
public
<
T
>
HttpResponse
<
T
>
doGet
(
HttpRequest
httpRequest
,
final
Class
<
T
>
responseType
)
{
Function
<
String
,
T
>
convertResponse
=
new
Function
<
String
,
T
>()
{
@Override
public
T
apply
(
String
input
)
{
return
gson
.
fromJson
(
input
,
responseType
);
}
};
return
doGetWithSerializeFunction
(
httpRequest
,
convertResponse
);
}
/**
* Do get operation for the http request.
*
* @param httpRequest the request
* @param responseType the response type
* @return the response
* @throws RuntimeException if any error happened or response code is neither 200 nor 304
*/
public
<
T
>
HttpResponse
<
T
>
doGet
(
HttpRequest
httpRequest
,
final
Type
responseType
)
{
Function
<
String
,
T
>
convertResponse
=
new
Function
<
String
,
T
>()
{
@Override
public
T
apply
(
String
input
)
{
return
gson
.
fromJson
(
input
,
responseType
);
}
};
return
doGetWithSerializeFunction
(
httpRequest
,
convertResponse
);
}
private
<
T
>
HttpResponse
<
T
>
doGetWithSerializeFunction
(
HttpRequest
httpRequest
,
Function
<
String
,
T
>
serializeFunction
)
{
InputStream
is
=
null
;
try
{
HttpURLConnection
conn
=
(
HttpURLConnection
)
new
URL
(
httpRequest
.
getUrl
()).
openConnection
();
...
...
@@ -60,7 +95,7 @@ public class HttpUtil {
if
(
statusCode
==
200
)
{
is
=
conn
.
getInputStream
();
String
content
=
Files
.
IO
.
INSTANCE
.
readFrom
(
is
,
Charsets
.
UTF_8
.
name
());
return
new
HttpResponse
<>(
statusCode
,
gson
.
fromJson
(
content
,
responseType
));
return
new
HttpResponse
<>(
statusCode
,
serializeFunction
.
apply
(
content
));
}
if
(
statusCode
==
304
)
{
...
...
@@ -82,7 +117,6 @@ public class HttpUtil {
}
}
}
}
}
apollo-client/src/test/java/com/ctrip/apollo/integration/BaseIntegrationTest.java
View file @
bb68324d
...
...
@@ -23,7 +23,9 @@ import org.unidal.lookup.ComponentTestCase;
import
java.io.File
;
import
java.io.IOException
;
import
java.net.ServerSocket
;
import
java.util.concurrent.TimeUnit
;
import
java.util.concurrent.atomic.AtomicInteger
;
import
javax.servlet.ServletException
;
import
javax.servlet.http.HttpServletRequest
;
...
...
@@ -33,7 +35,7 @@ import javax.servlet.http.HttpServletResponse;
* @author Jason Song(song_s@ctrip.com)
*/
public
class
BaseIntegrationTest
extends
ComponentTestCase
{
private
static
final
int
PORT
=
5678
;
private
static
final
int
PORT
=
findFreePort
()
;
private
static
final
String
metaServiceUrl
=
"http://localhost:"
+
PORT
;
private
static
final
String
someAppName
=
"someAppName"
;
private
static
final
String
someInstanceId
=
"someInstanceId"
;
...
...
@@ -86,23 +88,33 @@ public class BaseIntegrationTest extends ComponentTestCase {
@After
public
void
tearDown
()
throws
Exception
{
super
.
tearDown
();
if
(
server
!=
null
&&
server
.
isStarted
())
{
server
.
stop
();
}
super
.
tearDown
();
}
protected
ContextHandler
mockMetaServerHandler
()
{
return
mockMetaServerHandler
(
false
);
}
pr
ivate
ContextHandler
mockMetaServerHandler
(
)
{
pr
otected
ContextHandler
mockMetaServerHandler
(
final
boolean
failedAtFirstTime
)
{
final
ServiceDTO
someServiceDTO
=
new
ServiceDTO
();
someServiceDTO
.
setAppName
(
someAppName
);
someServiceDTO
.
setInstanceId
(
someInstanceId
);
someServiceDTO
.
setHomepageUrl
(
configServiceURL
);
final
AtomicInteger
counter
=
new
AtomicInteger
(
0
);
ContextHandler
context
=
new
ContextHandler
(
"/services/config"
);
context
.
setHandler
(
new
AbstractHandler
()
{
@Override
public
void
handle
(
String
target
,
Request
baseRequest
,
HttpServletRequest
request
,
HttpServletResponse
response
)
throws
IOException
,
ServletException
{
if
(
failedAtFirstTime
&&
counter
.
incrementAndGet
()
==
1
)
{
response
.
setStatus
(
HttpServletResponse
.
SC_INTERNAL_SERVER_ERROR
);
baseRequest
.
setHandled
(
true
);
return
;
}
response
.
setContentType
(
"application/json;charset=UTF-8"
);
response
.
setStatus
(
HttpServletResponse
.
SC_OK
);
...
...
@@ -150,4 +162,37 @@ public class BaseIntegrationTest extends ComponentTestCase {
}
}
/**
* Returns a free port number on localhost.
*
* Heavily inspired from org.eclipse.jdt.launching.SocketUtil (to avoid a dependency to JDT just because of this).
* Slightly improved with close() missing in JDT. And throws exception instead of returning -1.
*
* @return a free port number on localhost
* @throws IllegalStateException if unable to find a free port
*/
private
static
int
findFreePort
()
{
ServerSocket
socket
=
null
;
try
{
socket
=
new
ServerSocket
(
0
);
socket
.
setReuseAddress
(
true
);
int
port
=
socket
.
getLocalPort
();
try
{
socket
.
close
();
}
catch
(
IOException
e
)
{
// Ignore IOException on close()
}
return
port
;
}
catch
(
IOException
e
)
{
}
finally
{
if
(
socket
!=
null
)
{
try
{
socket
.
close
();
}
catch
(
IOException
e
)
{
}
}
}
throw
new
IllegalStateException
(
"Could not find a free TCP/IP port to start embedded Jetty HTTP Server on"
);
}
}
apollo-client/src/test/java/com/ctrip/apollo/integration/ConfigIntegrationTest.java
View file @
bb68324d
package
com
.
ctrip
.
apollo
.
integration
;
import
static
org
.
hamcrest
.
core
.
IsEqual
.
equalTo
;
import
static
org
.
junit
.
Assert
.
assertEquals
;
import
static
org
.
junit
.
Assert
.
assertThat
;
import
com.google.common.collect.ImmutableMap
;
import
com.google.common.collect.Lists
;
import
com.google.common.collect.Maps
;
import
com.ctrip.apollo.Config
;
import
com.ctrip.apollo.ConfigChangeListener
;
import
com.ctrip.apollo.ConfigService
;
import
com.ctrip.apollo.core.ConfigConsts
;
import
com.ctrip.apollo.core.dto.ApolloConfig
;
import
com.ctrip.apollo.core.utils.ClassLoaderUtil
;
import
com.ctrip.apollo.model.ConfigChangeEvent
;
import
org.eclipse.jetty.server.Request
;
import
org.eclipse.jetty.server.handler.AbstractHandler
;
import
org.eclipse.jetty.server.handler.ContextHandler
;
import
org.junit.After
;
import
org.junit.Before
;
import
org.junit.Test
;
import
java.io.File
;
import
java.io.FileOutputStream
;
...
...
@@ -12,28 +27,15 @@ import java.util.List;
import
java.util.Map
;
import
java.util.Properties
;
import
java.util.concurrent.TimeUnit
;
import
java.util.concurrent.atomic.AtomicInteger
;
import
javax.servlet.ServletException
;
import
javax.servlet.http.HttpServletRequest
;
import
javax.servlet.http.HttpServletResponse
;
import
org.eclipse.jetty.server.Request
;
import
org.eclipse.jetty.server.handler.AbstractHandler
;
import
org.eclipse.jetty.server.handler.ContextHandler
;
import
org.junit.After
;
import
org.junit.Before
;
import
org.junit.Test
;
import
com.ctrip.apollo.Config
;
import
com.ctrip.apollo.ConfigChangeListener
;
import
com.ctrip.apollo.ConfigService
;
import
com.ctrip.apollo.core.ConfigConsts
;
import
com.ctrip.apollo.core.dto.ApolloConfig
;
import
com.ctrip.apollo.core.utils.ClassLoaderUtil
;
import
com.ctrip.apollo.model.ConfigChangeEvent
;
import
com.google.common.collect.ImmutableMap
;
import
com.google.common.collect.Lists
;
import
com.google.common.collect.Maps
;
import
static
org
.
hamcrest
.
core
.
IsEqual
.
equalTo
;
import
static
org
.
junit
.
Assert
.
assertEquals
;
import
static
org
.
junit
.
Assert
.
assertThat
;
/**
* @author Jason Song(song_s@ctrip.com)
...
...
@@ -142,6 +144,36 @@ public class ConfigIntegrationTest extends BaseIntegrationTest {
}
@Test
public
void
testGetConfigWithNoLocalFileAndRemoteMetaServiceRetry
()
throws
Exception
{
String
someKey
=
"someKey"
;
String
someValue
=
"someValue"
;
ApolloConfig
apolloConfig
=
assembleApolloConfig
(
ImmutableMap
.
of
(
someKey
,
someValue
));
ContextHandler
configHandler
=
mockConfigServerHandler
(
HttpServletResponse
.
SC_OK
,
apolloConfig
);
boolean
failAtFirstTime
=
true
;
ContextHandler
metaServerHandler
=
mockMetaServerHandler
(
failAtFirstTime
);
startServerWithHandlers
(
metaServerHandler
,
configHandler
);
Config
config
=
ConfigService
.
getConfig
();
assertEquals
(
someValue
,
config
.
getProperty
(
someKey
,
null
));
}
@Test
public
void
testGetConfigWithNoLocalFileAndRemoteConfigServiceRetry
()
throws
Exception
{
String
someKey
=
"someKey"
;
String
someValue
=
"someValue"
;
ApolloConfig
apolloConfig
=
assembleApolloConfig
(
ImmutableMap
.
of
(
someKey
,
someValue
));
boolean
failedAtFirstTime
=
true
;
ContextHandler
handler
=
mockConfigServerHandler
(
HttpServletResponse
.
SC_OK
,
apolloConfig
,
failedAtFirstTime
);
startServerWithHandlers
(
handler
);
Config
config
=
ConfigService
.
getConfig
();
assertEquals
(
someValue
,
config
.
getProperty
(
someKey
,
null
));
}
@Test
public
void
testRefreshConfig
()
throws
Exception
{
final
String
someKey
=
"someKey"
;
final
String
someValue
=
"someValue"
;
...
...
@@ -183,12 +215,21 @@ public class ConfigIntegrationTest extends BaseIntegrationTest {
assertEquals
(
anotherValue
,
config
.
getProperty
(
someKey
,
null
));
}
private
ContextHandler
mockConfigServerHandler
(
final
int
statusCode
,
final
ApolloConfig
result
)
{
private
ContextHandler
mockConfigServerHandler
(
final
int
statusCode
,
final
ApolloConfig
result
,
final
boolean
failedAtFirstTime
)
{
ContextHandler
context
=
new
ContextHandler
(
"/config/*"
);
context
.
setHandler
(
new
AbstractHandler
()
{
AtomicInteger
counter
=
new
AtomicInteger
(
0
);
@Override
public
void
handle
(
String
target
,
Request
baseRequest
,
HttpServletRequest
request
,
HttpServletResponse
response
)
throws
IOException
,
ServletException
{
HttpServletResponse
response
)
throws
IOException
,
ServletException
{
if
(
failedAtFirstTime
&&
counter
.
incrementAndGet
()
==
1
)
{
response
.
setStatus
(
HttpServletResponse
.
SC_INTERNAL_SERVER_ERROR
);
baseRequest
.
setHandled
(
true
);
return
;
}
response
.
setContentType
(
"application/json;charset=UTF-8"
);
response
.
setStatus
(
statusCode
);
...
...
@@ -199,6 +240,12 @@ public class ConfigIntegrationTest extends BaseIntegrationTest {
});
return
context
;
}
private
ContextHandler
mockConfigServerHandler
(
int
statusCode
,
ApolloConfig
result
)
{
return
mockConfigServerHandler
(
statusCode
,
result
,
false
);
}
private
ApolloConfig
assembleApolloConfig
(
Map
<
String
,
String
>
configurations
)
{
...
...
apollo-core/src/main/java/com/ctrip/apollo/Apollo.java
0 → 100644
View file @
bb68324d
package
com
.
ctrip
.
apollo
;
/**
* @author Jason Song(song_s@ctrip.com)
*/
public
class
Apollo
{
public
final
static
String
VERSION
=
"java-0.0.1-SNAPSHOT"
;
}
apollo-core/src/main/java/com/ctrip/apollo/core/dto/ServiceDTO.java
View file @
bb68324d
package
com
.
ctrip
.
apollo
.
core
.
dto
;
import
com.google.common.base.MoreObjects
;
public
class
ServiceDTO
{
private
String
appName
;
...
...
@@ -31,4 +33,14 @@ public class ServiceDTO {
public
void
setInstanceId
(
String
instanceId
)
{
this
.
instanceId
=
instanceId
;
}
@Override
public
String
toString
()
{
return
MoreObjects
.
toStringHelper
(
this
)
.
omitNullValues
()
.
add
(
"appName"
,
appName
)
.
add
(
"instanceId"
,
instanceId
)
.
add
(
"homepageUrl"
,
homepageUrl
)
.
toString
();
}
}
apollo-demo/src/main/java/ApolloConfigDemo.java
View file @
bb68324d
import
com.google.common.base.Strings
;
import
com.ctrip.apollo.Config
;
import
com.ctrip.apollo.ConfigChangeListener
;
import
com.ctrip.apollo.ConfigService
;
...
...
@@ -37,8 +39,8 @@ public class ApolloConfigDemo implements ConfigChangeListener {
while
(
true
)
{
System
.
out
.
print
(
"> "
);
String
input
=
new
BufferedReader
(
new
InputStreamReader
(
System
.
in
)).
readLine
();
if
(
input
==
null
)
{
continue
;
if
(
Strings
.
isNullOrEmpty
(
input
)
)
{
continue
;
}
input
=
input
.
trim
();
if
(
input
.
equalsIgnoreCase
(
"quit"
))
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment