When we commit new config change to Config Service, it automatically and successfully fetches the change:
12:24:48 {"log": "2020-05-13 12:24:43.168 INFO 1 --- [nio-8888-exec-3] .c.s.e.MultipleJGitEnvironmentRepository : Fetched for remote master and found 1 updates\n",
Then any service which started with Config Service awareness automatically fetch config every 5 minutes as I see from logs:
12:22:37 {"log":"2020-05-13 12:22:37.748 INFO 1 --- [ main] c.v.s.a.c.e.EnvironmentChangeListener : Event: org.springframework.boot.context.event.ApplicationStartedEvent
12:22:42 {"log":"2020-05-13 12:22:37.750 INFO 1 --- [ main] c.v.s.a.c.e.EnvironmentChangeListener : Event: org.springframework.boot.context.event.ApplicationReadyEvent
12:22:42 {"log":"2020-05-13 12:22:42.155 INFO 1 --- [oundedElastic-2] c.c.c.ConfigServicePropertySourceLocator : Fetching config from server at : http://<hidden>"
12:23:22 {"log":"2020-05-13 12:22:42.552 INFO 1 --- [oundedElastic-2] c.c.c.ConfigServicePropertySourceLocator : Located environment: name=api-gateway, profiles=[qa54-docker]
12:27:47 {"log":"2020-05-13 12:27:46.817 INFO 1 --- [oundedElastic-6] c.c.c.ConfigServicePropertySourceLocator : Fetching config from server at : http://<hidden>"
12:27:52 {"log":"2020-05-13 12:27:47.227 INFO 1 --- [oundedElastic-6] c.c.c.ConfigServicePropertySourceLocator : Located environment: name=api-gateway, profiles=[qa54-docker]
However, after the config change and successful fetch, routes are not refreshed automatically,
I decided to manually subscribe to EnvironmentChangeEvent
and manually fire off new RefreshRoutesEvent(this)
event to refresh routes, but EnvironmentChangeEvent
was never fired, so for test purpose, I just start logging all events which happens
I'm printing all events happening in the application:
@Override
public void onApplicationEvent(ApplicationEvent event) {
log.info("Event: " + event.toString());
}
As you can see from logs above the timeline is:
- Config Service: already running, no changes //starting API Gateway service
- API Gateway: 12:22:42 - sends ApplicationReadyEvent //initial scheduled config fetch, no changes expected
- API Gateway: 12:22:42 - Fetching config from server
- API Gateway: 12:23:22 - Located environment //Pushing changes to git for Config Service
- Config Service: 12:24:48 - Fetched for remote master and found 1 updates // after 5 min since past fetch, fetching again, expecting changes here!!!
- API Gateway: 12:27:47 - Fetching config from server
- API Gateway: 12:23:22 - Located environment //nothing?
Any hints? what am I doing wrong? How to make API Gateway automatically refresh routes if scheduled config fetch from Config Service contains changes?
Technical info: Spring Boot 2.2.5.RELEASE springCloudVersion "Hoxton.SR3" (both Config Service and API Gateway)
API Gateway bootstrap.yaml Part 1 - bundled with artefact:
spring:
application:
name: api-gateway
profiles:
active: qa54-docker
---
spring:
profiles: dev-docker | qa54-docker | prod250-docker
cloud:
config:
fail-fast: true
# defined as Docker ENV
uri: ${CONFIG_SERVICE_URL}
Part 2 - resolved by config service from GIT
---
spring:
profiles: qa54-docker
cloud:
gateway:
routes:
- id: notification
uri: http://<sensative_skipped>
predicates:
- Path=/notification/**
filters:
- RewritePath=/notification(?<path>.*), /$\{path}
cloud:
aws:
stack:
auto: false
region:
auto: true
credentials:
instance-profile: true
// Custom Actuator Info Contributer
actuator:
info:
docker-tag: ${DOCKER_TAG}
branch: ${GIT_BRANCH}
commit-hash: ${COMMIT_HASH}
env-name: ${ENV_NAME}
env-space: ${ENV_SPACE}
server:
port: ${SERVICE_PORT}
---
Config Service - Bootstrap.yaml
spring:
application:
name: config-service
profiles:
active: qa54-docker
---
spring:
profiles: qa54-docker
cloud:
config:
server:
git:
uri: <sensative_skipped>
aws-ssm-path: ${SSM_PATH_GIT_PRIVKEY}
fail-fast: true
security:
aws-ssm-base-path: ${SSM_BASE_PATH}
aws-regex-pattern: <<(.*?)>>
server:
port: ${SERVICE_PORT}
cloud:
aws:
stack:
auto: false
credentials:
instance-profile: true
// Custom Actuator Info Contributer
actuator:
info:
docker-tag: ${DOCKER_TAG}
branch: ${GIT_BRANCH}
commit-hash: ${COMMIT_HASH}
env-name: ${ENV_NAME}
env-space: ${ENV_SPACE}
---
Comment From: Bryksin
As a temporary fix, I created another scheduler, to imitate and automate the action of /actuator/refresh
@Slf4j
@Configuration
@EnableScheduling
public class RouteRefreshScheduler {
private ContextRefresher contextRefresher;
public RouteRefreshScheduler(ContextRefresher contextRefresher) {
this.contextRefresher = contextRefresher;
}
@Scheduled(initialDelay = 30000, fixedDelayString = "${scheduler.routes-refresh-delay}")
public void refreshRoutes() {
log.info("Refreshing Context with API Gateway Routes");
this.contextRefresher.refresh();
}
}
But I don't think it is a good solution to refresh it every scheduler tick regardless changes.
Ideally, the Config Service Client every scheduled fetch should detect if changes are present and if it present - refresh the context automatically which would trigger routes refresh. Or at least fire off some sort of event, stating that there are changes detected and developer will handle it manually
Possibly it does work like that if u add @RefreshScope
annotation but in case of API Gateway and Spring Boot - the beans for Gateway functionality created out of the box, so I'm not sure where can I add @RefreshScope
to make sure API Gateway routes are refreshed.
Comment From: spencergibb
ConfigService doesn't automatically fetch configuration. What you're seeing is likely a health indicator hitting config server. Unless you are using webhooks with config server monitor /monitor
and spring cloud bus, nothing is automatic.
Comment From: spring-projects-issues
If you would like us to look at this issue, please provide the requested information. If the information is not provided within the next 7 days this issue will be closed.
Comment From: Bryksin
I see @spencergibb, thank you for clarification, seems like you right, it is a health check every 5min, rather than pull changes. As we are not using Cloud BUS, it means it is clearly not getting changes, that's why there are no events about changes...
Looks like we need to start using Cloud BUS, but the only thing is that we heavily bound to AWS services, and I would not want to set up a custom rabbit cluster or any other queue, as we are using SQS
Seems like I need to wait for this? https://github.com/spring-cloud/spring-cloud-bus/issues/54 https://github.com/spring-cloud/spring-cloud-stream-starters/issues/8
Comment From: spencergibb
Yes, you would need the latter one.