【Spring Cloud 基础设施搭建系列】Spring Cloud Demo项目 Spring Cloud Config的用户认证和高可用

Spring Cloud Config的用户认证

Config Server是允许匿名访问的。为了防止配置内容的外泄,应该保护Config Server的安全。有多种方式做到这一点,例如通过物理网络安全,或者为Config Server添加用户认证等。

  1. 首先我们需要给我们的cloud-config-server的pom文件中添加依赖
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>
  1. 在application.yml文件中添加如下内容。
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
  1. 然后我们重启config server, 访问config server上的任何配置链接都会跳转到登录页面,要求你登录。

在这里插入图片描述

  1. 配置config client端,在bootstrap.yml中加入如下配置:
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
  1. 重启我们config client端的服务。只要服务能正常启动和访问,并且没有以下错误,说明已经配置成功了。
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]

Spring Cloud Config的高可用

客户端都是直接调用配置中心的server端来获取配置文件信息。这样就存在了一个问题,客户端和服务端的耦合性太高,如果server端要做集群,客户端只能通过原始的方式来路由,server端改变IP地址的时候,客户端也需要修改配置,不符合springcloud服务治理的理念。springcloud提供了这样的解决方案,我们只需要将server端当做一个服务注册到eureka中,client端去eureka中去获取配置中心server端的服务既可。

server端改造

所以我们需要把我们的config server注册到eureka上去,然后让我们的config client端到eureka上去找到对应的config server去请求配置。

首先是在cloud-config-server的pom文件中加入依赖:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</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);
    }
}

client端改造

在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/

发布了647 篇原创文章 · 获赞 816 · 访问量 98万+

猜你喜欢

转载自blog.csdn.net/cckevincyh/article/details/102537913