Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
wrr-cat
apollo
提交
7fb2cdce
apollo
项目概览
wrr-cat
/
apollo
与 Fork 源项目一致
从无法访问的项目Fork
通知
2
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,发现更多精彩内容 >>
提交
7fb2cdce
编写于
5月 18, 2016
作者:
L
lepdou
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #195 from lepdou/adminservice_healthcheck
admin server health check
上级
ef6daa88
56c36b72
变更
9
隐藏空白更改
内联
并排
Showing
9 changed file
with
161 addition
and
21 deletion
+161
-21
apollo-core/src/main/java/com/ctrip/apollo/core/enums/Env.java
...o-core/src/main/java/com/ctrip/apollo/core/enums/Env.java
+1
-1
apollo-portal/src/main/java/com/ctrip/apollo/portal/PortalSettings.java
...src/main/java/com/ctrip/apollo/portal/PortalSettings.java
+137
-7
apollo-portal/src/main/java/com/ctrip/apollo/portal/api/AdminServiceAPI.java
...ain/java/com/ctrip/apollo/portal/api/AdminServiceAPI.java
+9
-0
apollo-portal/src/main/java/com/ctrip/apollo/portal/controller/PortalAppController.java
...m/ctrip/apollo/portal/controller/PortalAppController.java
+2
-2
apollo-portal/src/main/java/com/ctrip/apollo/portal/controller/PortalEnvController.java
...m/ctrip/apollo/portal/controller/PortalEnvController.java
+1
-1
apollo-portal/src/main/java/com/ctrip/apollo/portal/service/PortalAppService.java
...ava/com/ctrip/apollo/portal/service/PortalAppService.java
+2
-2
apollo-portal/src/main/java/com/ctrip/apollo/portal/service/PortalConfigService.java
.../com/ctrip/apollo/portal/service/PortalConfigService.java
+6
-5
apollo-portal/src/main/java/com/ctrip/apollo/portal/service/PortalNamespaceService.java
...m/ctrip/apollo/portal/service/PortalNamespaceService.java
+2
-2
apollo-portal/src/main/resources/portal.properties
apollo-portal/src/main/resources/portal.properties
+1
-1
未找到文件。
apollo-core/src/main/java/com/ctrip/apollo/core/enums/Env.java
浏览文件 @
7fb2cdce
...
...
@@ -3,6 +3,6 @@ package com.ctrip.apollo.core.enums;
/**
* @author Jason Song(song_s@ctrip.com)
*/
public
enum
Env
{
public
enum
Env
{
LOCAL
,
DEV
,
FWS
,
FAT
,
UAT
,
LPT
,
PRO
,
TOOLS
}
apollo-portal/src/main/java/com/ctrip/apollo/portal/PortalSettings.java
浏览文件 @
7fb2cdce
package
com.ctrip.apollo.portal
;
import
java.util.ArrayList
;
import
java.util.HashMap
;
import
java.util.LinkedList
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.concurrent.ConcurrentHashMap
;
import
java.util.concurrent.Executors
;
import
java.util.concurrent.ScheduledExecutorService
;
import
java.util.concurrent.TimeUnit
;
import
java.util.concurrent.locks.Lock
;
import
java.util.concurrent.locks.ReentrantLock
;
import
javax.annotation.PostConstruct
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.beans.factory.annotation.Value
;
import
org.springframework.boot.actuate.health.Health
;
import
org.springframework.context.ApplicationContext
;
import
org.springframework.stereotype.Component
;
import
com.ctrip.apollo.core.enums.Env
;
import
com.ctrip.apollo.portal.api.AdminServiceAPI
;
@Component
public
class
PortalSettings
{
private
Logger
logger
=
LoggerFactory
.
getLogger
(
PortalSettings
.
class
);
private
static
final
int
HEALTH_CHECK_INTERVAL
=
5000
;
@Value
(
"#{'${apollo.portal.env}'.split(',')}"
)
private
List
<
String
>
env
;
private
List
<
String
>
allStrEnvs
;
@Autowired
ApplicationContext
applicationContext
;
private
List
<
Env
>
allEnvs
=
new
ArrayList
<
Env
>();
private
volatile
boolean
updatedFromLastHealthCheck
=
true
;
private
List
<
Env
>
envs
=
new
ArrayList
<
Env
>();
//for cache
private
List
<
Env
>
activeEnvs
=
new
LinkedList
<>();
//mark env up or down
private
Map
<
Env
,
Boolean
>
envStatusMark
=
new
ConcurrentHashMap
<>();
private
ScheduledExecutorService
healthCheckService
;
private
Lock
lock
=
new
ReentrantLock
();
@PostConstruct
private
void
postConstruct
()
{
for
(
String
e
:
env
)
{
envs
.
add
(
Env
.
valueOf
(
e
.
toUpperCase
()));
//init origin config envs
for
(
String
e
:
allStrEnvs
)
{
allEnvs
.
add
(
Env
.
valueOf
(
e
.
toUpperCase
()));
}
for
(
Env
env
:
allEnvs
)
{
envStatusMark
.
put
(
env
,
true
);
}
healthCheckService
=
Executors
.
newScheduledThreadPool
(
1
);
healthCheckService
.
scheduleWithFixedDelay
(
new
HealthCheckTask
(
applicationContext
),
1000
,
HEALTH_CHECK_INTERVAL
,
TimeUnit
.
MILLISECONDS
);
}
public
List
<
Env
>
getEnvs
()
{
public
List
<
Env
>
getActiveEnvs
()
{
if
(
updatedFromLastHealthCheck
)
{
lock
.
lock
();
//maybe refresh many times but not create a bad impression.
activeEnvs
=
refreshActiveEnvs
();
lock
.
unlock
();
}
return
activeEnvs
;
}
private
List
<
Env
>
refreshActiveEnvs
()
{
List
<
Env
>
envs
=
new
LinkedList
<>();
for
(
Env
env
:
allEnvs
)
{
if
(
envStatusMark
.
get
(
env
))
{
envs
.
add
(
env
);
}
}
logger
.
info
(
"refresh active envs"
);
return
envs
;
}
public
Env
getFirstEnv
(){
return
envs
.
get
(
0
);
public
Env
getFirstAliveEnv
()
{
return
activeEnvs
.
get
(
0
);
}
class
HealthCheckTask
implements
Runnable
{
private
static
final
int
ENV_DIED_THREADHOLD
=
2
;
private
Map
<
Env
,
Long
>
healthCheckFailCnt
=
new
HashMap
<>();
private
AdminServiceAPI
.
HealthAPI
healthAPI
;
public
HealthCheckTask
(
ApplicationContext
context
)
{
healthAPI
=
context
.
getBean
(
AdminServiceAPI
.
HealthAPI
.
class
);
for
(
Env
env
:
allEnvs
)
{
healthCheckFailCnt
.
put
(
env
,
0
l
);
}
}
public
void
run
()
{
logger
.
info
(
"admin server health check start..."
);
boolean
hasUpdateStatus
=
false
;
for
(
Env
env
:
allEnvs
)
{
try
{
if
(
isUp
(
env
))
{
//revive
if
(!
envStatusMark
.
get
(
env
))
{
envStatusMark
.
put
(
env
,
true
);
healthCheckFailCnt
.
put
(
env
,
0
l
);
hasUpdateStatus
=
true
;
logger
.
info
(
"env up again [env:{}]"
,
env
);
}
}
else
{
//maybe meta server up but admin server down
handleEnvDown
(
env
);
hasUpdateStatus
=
true
;
}
}
catch
(
Exception
e
)
{
//maybe meta server down
logger
.
warn
(
"health check fail. [env:{}]"
,
env
,
e
.
getMessage
());
handleEnvDown
(
env
);
hasUpdateStatus
=
true
;
}
}
if
(!
hasUpdateStatus
)
{
logger
.
info
(
"admin server health check OK"
);
}
updatedFromLastHealthCheck
=
hasUpdateStatus
;
}
private
boolean
isUp
(
Env
env
)
{
Health
health
=
healthAPI
.
health
(
env
);
return
"UP"
.
equals
(
health
.
getStatus
().
getCode
());
}
private
void
handleEnvDown
(
Env
env
)
{
long
failCnt
=
healthCheckFailCnt
.
get
(
env
);
healthCheckFailCnt
.
put
(
env
,
++
failCnt
);
if
(
failCnt
>=
ENV_DIED_THREADHOLD
)
{
envStatusMark
.
put
(
env
,
false
);
logger
.
error
(
"env down [env:{}]"
,
env
);
}
}
}
}
apollo-portal/src/main/java/com/ctrip/apollo/portal/api/AdminServiceAPI.java
浏览文件 @
7fb2cdce
...
...
@@ -10,6 +10,7 @@ import com.ctrip.apollo.core.dto.ItemDTO;
import
com.ctrip.apollo.core.dto.NamespaceDTO
;
import
com.ctrip.apollo.core.dto.ReleaseDTO
;
import
org.springframework.boot.actuate.health.Health
;
import
org.springframework.http.HttpEntity
;
import
org.springframework.http.HttpHeaders
;
import
org.springframework.http.MediaType
;
...
...
@@ -25,6 +26,14 @@ import java.util.List;
@Service
public
class
AdminServiceAPI
{
@Service
public
static
class
HealthAPI
extends
API
{
public
Health
health
(
Env
env
){
return
restTemplate
.
getForObject
(
getAdminServiceHost
(
env
)
+
"/health"
,
Health
.
class
);
}
}
@Service
public
static
class
AppAPI
extends
API
{
...
...
apollo-portal/src/main/java/com/ctrip/apollo/portal/controller/PortalAppController.java
浏览文件 @
7fb2cdce
...
...
@@ -47,7 +47,7 @@ public class PortalAppController {
throw
new
BadRequestException
(
"app id can not be empty."
);
}
MultiResponseEntity
<
EnvClusterInfo
>
response
=
MultiResponseEntity
.
ok
();
List
<
Env
>
envs
=
portalSettings
.
getEnvs
();
List
<
Env
>
envs
=
portalSettings
.
get
Active
Envs
();
for
(
Env
env
:
envs
)
{
try
{
response
.
addResponseEntity
(
RichResponseEntity
.
ok
(
appService
.
createEnvNavNode
(
env
,
appId
)));
...
...
@@ -84,7 +84,7 @@ public class PortalAppController {
@RequestMapping
(
value
=
"/{appId}/miss_envs"
)
public
MultiResponseEntity
<
Env
>
findMissEnvs
(
@PathVariable
String
appId
)
{
MultiResponseEntity
<
Env
>
response
=
MultiResponseEntity
.
ok
();
for
(
Env
env
:
portalSettings
.
getEnvs
())
{
for
(
Env
env
:
portalSettings
.
get
Active
Envs
())
{
try
{
appService
.
load
(
env
,
appId
);
}
catch
(
Exception
e
)
{
...
...
apollo-portal/src/main/java/com/ctrip/apollo/portal/controller/PortalEnvController.java
浏览文件 @
7fb2cdce
...
...
@@ -19,7 +19,7 @@ public class PortalEnvController {
@RequestMapping
(
value
=
""
,
method
=
RequestMethod
.
GET
)
public
List
<
Env
>
envs
(){
return
portalSettings
.
getEnvs
();
return
portalSettings
.
get
Active
Envs
();
}
}
apollo-portal/src/main/java/com/ctrip/apollo/portal/service/PortalAppService.java
浏览文件 @
7fb2cdce
...
...
@@ -41,7 +41,7 @@ public class PortalAppService {
//轮询环境直到能找到此app的信息
AppDTO
app
=
null
;
boolean
isCallAdminServiceError
=
false
;
for
(
Env
env
:
portalSettings
.
getEnvs
())
{
for
(
Env
env
:
portalSettings
.
get
Active
Envs
())
{
try
{
app
=
appAPI
.
loadApp
(
env
,
appId
);
break
;
...
...
@@ -71,7 +71,7 @@ public class PortalAppService {
}
public
void
createAppInAllEnvs
(
AppDTO
app
)
{
List
<
Env
>
envs
=
portalSettings
.
getEnvs
();
List
<
Env
>
envs
=
portalSettings
.
get
Active
Envs
();
for
(
Env
env
:
envs
)
{
try
{
appAPI
.
createApp
(
env
,
app
);
...
...
apollo-portal/src/main/java/com/ctrip/apollo/portal/service/PortalConfigService.java
浏览文件 @
7fb2cdce
package
com.ctrip.apollo.portal.service
;
import
java.util.LinkedList
;
import
java.util.List
;
import
java.util.Map
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
...
...
@@ -12,21 +9,25 @@ import org.springframework.util.CollectionUtils;
import
org.springframework.web.client.HttpClientErrorException
;
import
com.ctrip.apollo.common.utils.BeanUtils
;
import
com.ctrip.apollo.core.enums.Env
;
import
com.ctrip.apollo.core.dto.ItemChangeSets
;
import
com.ctrip.apollo.core.dto.ItemDTO
;
import
com.ctrip.apollo.core.dto.NamespaceDTO
;
import
com.ctrip.apollo.core.dto.ReleaseDTO
;
import
com.ctrip.apollo.core.enums.Env
;
import
com.ctrip.apollo.core.exception.BadRequestException
;
import
com.ctrip.apollo.core.exception.NotFoundException
;
import
com.ctrip.apollo.core.exception.ServiceException
;
import
com.ctrip.apollo.portal.api.AdminServiceAPI
;
import
com.ctrip.apollo.portal.entity.ItemDiffs
;
import
com.ctrip.apollo.portal.entity.NamespaceIdentifer
;
import
com.ctrip.apollo.portal.entity.form.NamespaceReleaseModel
;
import
com.ctrip.apollo.portal.entity.form.NamespaceTextModel
;
import
com.ctrip.apollo.portal.entity.form.NamespaceReleaseModel
;
import
com.ctrip.apollo.portal.service.txtresolver.ConfigTextResolver
;
import
java.util.LinkedList
;
import
java.util.List
;
import
java.util.Map
;
@Service
public
class
PortalConfigService
{
...
...
apollo-portal/src/main/java/com/ctrip/apollo/portal/service/PortalNamespaceService.java
浏览文件 @
7fb2cdce
...
...
@@ -48,7 +48,7 @@ public class PortalNamespaceService {
public
List
<
AppNamespaceDTO
>
findPublicAppNamespaces
(){
return
namespaceAPI
.
findPublicAppNamespaces
(
portalSettings
.
getFirstEnv
());
return
namespaceAPI
.
findPublicAppNamespaces
(
portalSettings
.
getFirst
Alive
Env
());
}
public
NamespaceDTO
createNamespace
(
Env
env
,
NamespaceDTO
namespace
){
...
...
@@ -56,7 +56,7 @@ public class PortalNamespaceService {
}
public
void
createAppNamespace
(
AppNamespaceDTO
appNamespace
)
{
for
(
Env
env
:
portalSettings
.
getEnvs
())
{
for
(
Env
env
:
portalSettings
.
get
Active
Envs
())
{
try
{
namespaceAPI
.
createAppNamespace
(
env
,
appNamespace
);
}
catch
(
HttpStatusCodeException
e
)
{
...
...
apollo-portal/src/main/resources/portal.properties
浏览文件 @
7fb2cdce
...
...
@@ -2,4 +2,4 @@ spring.application.name= apollo-portal
apollo.portal.env
=
dev,fat,uat
ctrip.appid
=
100003173
server.port
=
8080
logging.file
=
/opt/logs/100003173/apollo-portal.log
\ No newline at end of file
logging.file
=
/opt/logs/100003173/apollo-portal.log
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录