Config Server是允许匿名访问的。为了防止配置内容的外泄,应该保护Config Server的安全。有多种方式做到这一点,例如通过物理网络安全,或者为Config Server添加用户认证等。
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-securityartifactId>
dependency>
server:
port: 8090
spring:
application:
name: cloud-config-server
# 安全保护
security:
user:
name: admin
password: admin
cloud:
config:
server:
git:
uri: https://gitee.com/cckevincyh/spring-cloud-demo.git
# 指定搜索根路径下的所有目录,若有多个路径使用逗号隔开
# {application} 映射到客户端的 spring.application.name;
# {profile} 映射到客户端上的 spring.profiles.active;
search-paths: 'cloud-config/default/common,cloud-config/{profile}/common,cloud-config/{profile}/{application}'
default-label: share-config
eureka:
client:
service-url:
defaultZone: http://localhost:8888/eureka/
需要添加下面这一部分:
spring:
# 安全保护
security:
user:
name: admin
password: admin
spring:
application:
#对应config server所获取的配置文件的{application}
name: cloud-service-member
cloud:
config:
# 配置中心服务地址
uri: http://localhost:8090/
# profile对应config server所获取的配置文件中的{profile}
profile: dev
#指定Git仓库的分支,对应config server所获取的配置文件的{label},读取config server中指定的default-label
#label: share-config
username: admin
password: admin
加入下面配置:
spring:
cloud:
config:
username: admin
password: admin
com.sun.jersey.api.client.ClientHandlerException: java.net.ConnectException: Connection refused: connect
at com.sun.jersey.client.apache4.ApacheHttpClient4Handler.handle(ApacheHttpClient4Handler.java:187) ~[jersey-apache-client4-1.19.1.jar:1.19.1]
at com.sun.jersey.api.client.filter.GZIPContentEncodingFilter.handle(GZIPContentEncodingFilter.java:123) ~[jersey-client-1.19.1.jar:1.19.1]
at com.netflix.discovery.EurekaIdentityHeaderFilter.handle(EurekaIdentityHeaderFilter.java:27) ~[eureka-client-1.9.8.jar:1.9.8]
at com.sun.jersey.api.client.Client.handle(Client.java:652) ~[jersey-client-1.19.1.jar:1.19.1]
at com.sun.jersey.api.client.WebResource.handle(WebResource.java:682) ~[jersey-client-1.19.1.jar:1.19.1]
at com.sun.jersey.api.client.WebResource.access$200(WebResource.java:74) ~[jersey-client-1.19.1.jar:1.19.1]
at com.sun.jersey.api.client.WebResource$Builder.get(WebResource.java:509) ~[jersey-client-1.19.1.jar:1.19.1]
at com.netflix.discovery.shared.transport.jersey.AbstractJerseyEurekaHttpClient.getApplicationsInternal(AbstractJerseyEurekaHttpClient.java:194) ~[eureka-client-1.9.8.jar:1.9.8]
at com.netflix.discovery.shared.transport.jersey.AbstractJerseyEurekaHttpClient.getApplications(AbstractJerseyEurekaHttpClient.java:165) ~[eureka-client-1.9.8.jar:1.9.8]
at com.netflix.discovery.shared.transport.decorator.EurekaHttpClientDecorator$6.execute(EurekaHttpClientDecorator.java:137) [eureka-client-1.9.8.jar:1.9.8]
at com.netflix.discovery.shared.transport.decorator.MetricsCollectingEurekaHttpClient.execute(MetricsCollectingEurekaHttpClient.java:73) ~[eureka-client-1.9.8.jar:1.9.8]
at com.netflix.discovery.shared.transport.decorator.EurekaHttpClientDecorator.getApplications(EurekaHttpClientDecorator.java:134) [eureka-client-1.9.8.jar:1.9.8]
at com.netflix.discovery.shared.transport.decorator.EurekaHttpClientDecorator$6.execute(EurekaHttpClientDecorator.java:137) [eureka-client-1.9.8.jar:1.9.8]
at com.netflix.discovery.shared.transport.decorator.RedirectingEurekaHttpClient.executeOnNewServer(RedirectingEurekaHttpClient.java:118) ~[eureka-client-1.9.8.jar:1.9.8]
at com.netflix.discovery.shared.transport.decorator.RedirectingEurekaHttpClient.execute(RedirectingEurekaHttpClient.java:79) ~[eureka-client-1.9.8.jar:1.9.8]
at com.netflix.discovery.shared.transport.decorator.EurekaHttpClientDecorator.getApplications(EurekaHttpClientDecorator.java:134) [eureka-client-1.9.8.jar:1.9.8]
at com.netflix.discovery.shared.transport.decorator.EurekaHttpClientDecorator$6.execute(EurekaHttpClientDecorator.java:137) [eureka-client-1.9.8.jar:1.9.8]
at com.netflix.discovery.shared.transport.decorator.RetryableEurekaHttpClient.execute(RetryableEurekaHttpClient.java:120) [eureka-client-1.9.8.jar:1.9.8]
at com.netflix.discovery.shared.transport.decorator.EurekaHttpClientDecorator.getApplications(EurekaHttpClientDecorator.java:134) [eureka-client-1.9.8.jar:1.9.8]
at com.netflix.discovery.shared.transport.decorator.EurekaHttpClientDecorator$6.execute(EurekaHttpClientDecorator.java:137) [eureka-client-1.9.8.jar:1.9.8]
at com.netflix.discovery.shared.transport.decorator.SessionedEurekaHttpClient.execute(SessionedEurekaHttpClient.java:77) [eureka-client-1.9.8.jar:1.9.8]
at com.netflix.discovery.shared.transport.decorator.EurekaHttpClientDecorator.getApplications(EurekaHttpClientDecorator.java:134) [eureka-client-1.9.8.jar:1.9.8]
at com.netflix.discovery.DiscoveryClient.getAndStoreFullRegistry(DiscoveryClient.java:1051) [eureka-client-1.9.8.jar:1.9.8]
at com.netflix.discovery.DiscoveryClient.fetchRegistry(DiscoveryClient.java:965) [eureka-client-1.9.8.jar:1.9.8]
at com.netflix.discovery.DiscoveryClient.<init>(DiscoveryClient.java:414) [eureka-client-1.9.8.jar:1.9.8]
at com.netflix.discovery.DiscoveryClient.<init>(DiscoveryClient.java:269) [eureka-client-1.9.8.jar:1.9.8]
客户端都是直接调用配置中心的server端来获取配置文件信息。这样就存在了一个问题,客户端和服务端的耦合性太高,如果server端要做集群,客户端只能通过原始的方式来路由,server端改变IP地址的时候,客户端也需要修改配置,不符合springcloud服务治理的理念。springcloud提供了这样的解决方案,我们只需要将server端当做一个服务注册到eureka中,client端去eureka中去获取配置中心server端的服务既可。
所以我们需要把我们的config server注册到eureka上去,然后让我们的config client端到eureka上去找到对应的config server去请求配置。
首先是在cloud-config-server的pom文件中加入依赖:
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-netflix-eureka-clientartifactId>
dependency>
然后还需要在application.yml加入配置:
eureka:
client:
service-url:
defaultZone: http://localhost:8888/eureka/
在启动类中加入注解@EnableEurekaClient
package com.cc.cloud.config.server;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.config.server.EnableConfigServer;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
@SpringBootApplication
@EnableConfigServer
@EnableEurekaClient
public class ConfigServerApp {
public static void main(String[] args) {
SpringApplication.run(ConfigServerApp.class, args);
}
}
在config client端就不在指定config server的uri了,而是通过eureka去查找对应的config server。
所以配置中去掉了spring.cloud.config.uri
直接指向server端地址的配置,增加了最后的下面两个配置:
spring.cloud.config.discovery.enabled
:开启Config服务发现支持spring.cloud.config.discovery.serviceId
:指定server端的name,也就是server端spring.application.name的值然后我们还需要把我们之前eureka client 注册的配置从application.yml中复制到bootstrap.yml中,因为我们必须要在启动的时候就去访问到eureka找到对应的config server。而之前是直接指定URI的形式,所以可以直接找到config server。
下面是cloud-service-member bootstrap.yml的配置:
spring:
application:
#对应config server所获取的配置文件的{application}
name: cloud-service-member
cloud:
config:
discovery:
enabled: true
service-id: cloud-config-server
# profile对应config server所获取的配置文件中的{profile}
profile: dev
#指定Git仓库的分支,对应config server所获取的配置文件的{label},读取config server中指定的default-label
#label: share-config
username: admin
password: admin
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8888/eureka/
下面是cloud-service-order bootstrap.yml的配置:
spring:
application:
#对应config server所获取的配置文件的{application}
name: cloud-service-order
cloud:
config:
discovery:
enabled: true
service-id: cloud-config-server
# profile对应config server所获取的配置文件中的{profile}
profile: dev
#指定Git仓库的分支,对应config server所获取的配置文件的{label},读取config server中指定的default-label
#label: share-config
username: admin
password: admin
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8888/eureka/
最后我们先启动两个config server,分别启动在8090和8091端口。我们访问eureka上可以查看到有两个config server注册上去了。
然后我们启动cloud-service-member服务,看到控制台打印如下:
2019-10-13 20:24:35.141 INFO [cloud-service-member,,,] 10996 --- [ main] c.c.c.ConfigServicePropertySourceLocator : Multiple Config Server Urls found listed.
2019-10-13 20:24:35.142 INFO [cloud-service-member,,,] 10996 --- [ main] c.c.c.ConfigServicePropertySourceLocator : Fetching config from server at : http://localhost:8091/
2019-10-13 20:24:42.657 INFO [cloud-service-member,,,] 10996 --- [ main] c.c.c.ConfigServicePropertySourceLocator : Located environment: name=cloud-service-member, profiles=[dev], label=null, version=9b9020b0a5693e9863e151ed1c4ff4822ade924c, state=null
2019-10-13 20:24:42.657 INFO [cloud-service-member,,,] 10996 --- [ main] b.c.PropertySourceBootstrapConfiguration : Located property source: CompositePropertySource {name='configService', propertySources=[MapPropertySource {name='configClient'}, MapPropertySource {name='https://gitee.com/cckevincyh/spring-cloud-demo.git/cloud-config/dev/cloud-service-member/application.yml'}, MapPropertySource {name='https://gitee.com/cckevincyh/spring-cloud-demo.git/cloud-config/dev/common/application.yml'}, MapPropertySource {name='https://gitee.com/cckevincyh/spring-cloud-demo.git/cloud-config/default/common/application.yml'}]}
2019-10-13 20:24:42.691 INFO [cloud-service-member,,,] 10996 --- [ main] com.cc.cloud.member.MemberApp : No active profile set, falling back to default profiles: default
2019-10-13 20:24:43.797 WARN [cloud-service-member,,,] 10996 --- [ main] o.s.boot.actuate.endpoint.EndpointId : Endpoint ID 'service-registry' contains invalid characters, please migrate to a valid format.
2019-10-13 20:24:43.867 WARN [cloud-service-member,,,] 10996 --- [ main] o.s.boot.actuate.endpoint.EndpointId : Endpoint ID 'hystrix.stream' contains invalid characters, please migrate to a valid format.
2019-10-13 20:24:44.074 INFO [cloud-service-member,,,] 10996 --- [ main] o.s.cloud.context.scope.GenericScope : BeanFactory id=cf4f10e6-c12a-356e-83e2-8e009fdfbe5f
2019-10-13 20:24:44.095 INFO [cloud-service-member,,,] 10996 --- [ main] trationDelegate$BeanPostProcessorChecker : Bean 'com.cc.cloud.member.feign.OrderFeign' of type [org.springframework.cloud.openfeign.FeignClientFactoryBean] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2019-10-13 20:24:44.399 INFO [cloud-service-member,,,] 10996 --- [ main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration' of type [org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration$$EnhancerBySpringCGLIB$$150876a1] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2019-10-13 20:24:44.884 INFO [cloud-service-member,,,] 10996 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8762 (http)
2019-10-13 20:24:44.909 INFO [cloud-service-member,,,] 10996 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
然后我们启动cloud-service-order服务,看到控制台打印如下:
2019-10-13 20:28:24.761 INFO [cloud-service-order,,,] 14440 --- [ main] c.c.c.ConfigServicePropertySourceLocator : Multiple Config Server Urls found listed.
2019-10-13 20:28:24.762 INFO [cloud-service-order,,,] 14440 --- [ main] c.c.c.ConfigServicePropertySourceLocator : Fetching config from server at : http://localhost:8090/
2019-10-13 20:28:31.485 INFO [cloud-service-order,,,] 14440 --- [ main] c.c.c.ConfigServicePropertySourceLocator : Located environment: name=cloud-service-order, profiles=[dev], label=null, version=9b9020b0a5693e9863e151ed1c4ff4822ade924c, state=null
2019-10-13 20:28:31.486 INFO [cloud-service-order,,,] 14440 --- [ main] b.c.PropertySourceBootstrapConfiguration : Located property source: CompositePropertySource {name='configService', propertySources=[MapPropertySource {name='configClient'}, MapPropertySource {name='https://gitee.com/cckevincyh/spring-cloud-demo.git/cloud-config/dev/cloud-service-order/application.yml'}, MapPropertySource {name='https://gitee.com/cckevincyh/spring-cloud-demo.git/cloud-config/dev/common/application.yml'}, MapPropertySource {name='https://gitee.com/cckevincyh/spring-cloud-demo.git/cloud-config/default/common/application.yml'}]}
2019-10-13 20:28:31.520 INFO [cloud-service-order,,,] 14440 --- [ main] com.cc.cloud.order.OrderApp : No active profile set, falling back to default profiles: default
2019-10-13 20:28:32.573 WARN [cloud-service-order,,,] 14440 --- [ main] o.s.boot.actuate.endpoint.EndpointId : Endpoint ID 'service-registry' contains invalid characters, please migrate to a valid format.
2019-10-13 20:28:32.651 WARN [cloud-service-order,,,] 14440 --- [ main] o.s.boot.actuate.endpoint.EndpointId : Endpoint ID 'hystrix.stream' contains invalid characters, please migrate to a valid format.
2019-10-13 20:28:32.960 INFO [cloud-service-order,,,] 14440 --- [ main] o.s.cloud.context.scope.GenericScope : BeanFactory id=4b217598-336e-3aa6-a4e7-d06d6b14a1d2
2019-10-13 20:28:32.992 INFO [cloud-service-order,,,] 14440 --- [ main] trationDelegate$BeanPostProcessorChecker : Bean 'com.cc.cloud.order.feign.MemberFeign' of type [org.springframework.cloud.openfeign.FeignClientFactoryBean] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2019-10-13 20:28:33.350 INFO [cloud-service-order,,,] 14440 --- [ main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration' of type [org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration$$EnhancerBySpringCGLIB$$3cdd02a4] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2019-10-13 20:28:33.853 INFO [cloud-service-order,,,] 14440 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8765 (http)
2019-10-13 20:28:33.883 INFO [cloud-service-order,,,] 14440 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
2019-10-13 20:28:33.884 INFO [cloud-service-order,,,] 14440 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet Engine: Apache Tomcat/9.0.13
可以看到控制台都打印出了: Multiple Config Server Urls found listed.
然后分别打印了Fetching config from server at : http://localhost:8090/
和 Fetching config from server at : http://localhost:8091/
。 当然可能不一定会拉取不同的config server,也有可能都拉取的同一个config server,可以尝试重启多次后应该可以看到会拉取不同的config server,这就可以说明达到了高可用的目的。
当然你也可以尝试关闭一台config server,而服务还能正常获取配置,说明也是达到了高可用。但是就算你两台config server都关掉还是能获取到配置的,这时候获取到的是client端本地的缓存。因为Server端负责从远端git(码云、GitHub等)拉取配置,并缓存在本地;Client端在启动时会以/{application}/{profile}[/{label}]
这种格式的URL获取自己在配置中心的外部配置文件,并缓存到本地。所以你应该关掉一台config server之后可以修改一下配置,然后再去请求refresh刷新配置,看看client端能不能请求到最新的配置。 关于refresh配置我们后面会讲到。
Spring Cloud入门教程(三):Config配置中心
Spring Cloud入门教程(八):统一配置中心(Config)
spring cloud config server—No instances found of configserver
springcloud(八):配置中心服务化和高可用
spring cloud config client启动报错,显示java.lang.IllegalStateException: No instances found of configserver
https://gitee.com/cckevincyh/spring-cloud-demo/tree/config-server-security/
https://gitee.com/cckevincyh/spring-cloud-demo/tree/config-server-ha/