SpringCloud 配置总结

Spring Cloud 是一系列框架的有序集合,它利用 Spring Boot 的开发便利性简化了分布式系统的开发,比如服务发现、服务网关、服务路由、链路追踪等。Spring Cloud 并不重复造轮子,而是将市面上开发得比较好的模块集成进去,进行封装,从而减少了各模块的开发成本。换句话说:Spring Cloud 提供了构建分布式系统所需的“全家桶”。
Spring Cloud 常常被拿来和 Dubbo 比较,实际上 Dubbo 只实现了服务治理,接入 Dubbo 的服务能够实现自动上下线、能通过 Dubbo 协议(其实 Dubbo 还支持其他很多协议)互联,但是 Dubbo 并不提供网关、配置中心、链路追踪等一系列微服务架构常用的技术,需要单独引入。

Spring Cloud 的主要优点有:

  • 集大成者,Spring Cloud 包含了微服务架构的方方面面。
  • 约定优于配置,基于注解,没有配置文件。
  • 轻量级组件,Spring Cloud 整合的组件大多比较轻量级,且都是各自领域的佼佼者。
  • 开发简便,Spring Cloud 对各个组件进行了大量的封装,从而简化了开发。
  • 开发灵活,Spring Cloud 的组件都是解耦的,开发人员可以灵活按需选择组件。

接下来,我们看下它的缺点:

  • 项目结构复杂,每一个组件或者每一个服务都需要创建一个项目。
  • 部署门槛高,项目部署需要配合 Docker 等容器技术进行集群部署,而要想深入了解 Docker,学习成本高。

Context(应用上下文)

引导应用程序上下文
Spring Cloud Context:bootstrap context, encryption, refresh scope and environment endpoints
Spring Cloud Commons:a set of abstractions and common classes used in different Spring Cloud implementations

Bus(服务总线)

  • 通知配置文件的更改
  • 服务间通讯
  • 监控

配置实例

通知配置文件的更改

  1. 在本地安装 RabbitMQ
    一般来说访问端口号是 5672
  2. 创建 Spring Initializr 项目
    勾选 Eureka Discovery、Config Client 和 Stream Rabbit
    或者在已创建的 Config Client 项目中添加下面的依赖:
    1
    2
    3
    4
    <dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-bus-amqp</artifactId>
    </dependency>
  3. 为 ConfigClientApplication 应用类添加 @RefreshScope 注解
    如果不添加会导致本地看不到更新后的值。
  4. 添加 RabbitMQ 配置
    1
    2
    3
    4
    spring.rabbitmq.host=localhost
    spring.rabbitmq.port=5672
    # spring.rabbitmq.username= # 如果RabbitMQ中有用户名密码需要设置
    # spring.rabbitmq.password=
  5. 访问
    普通访问属性:localhost:8881/hi
    更新 git 仓库中的属性 foo 并提交
    然后刷新属性:localhost:8881/bus/refresh,注意要用 POST 方法访问
    刷新某个指定服务的属性:localhost:8881/bus/refresh?destination=config-client:**,刷新服务名为 config-client 的所有服务器,不管 ip。
    发送刷新请求后该服务就会去确认配置文件是否修改,如果修改了就会发送一个消息,由消息总线向其他服务传递,从而更新整个微服务集群中的配置。
  6. 出现授权问题
    1
    2
    3
    4
    5
    6
    7
    {
    "timestamp": 1515304345965,
    "status": 401,
    "error": "Unauthorized",
    "message": "Full authentication is required to access this resource.",
    "path": "/bus/refresh"
    }
    可以忽略权限拦截:
    1
    management.security.enabled=false
    或者添加一个 SpringBoot 的健康监控组件的依赖:
    1
    2
    3
    4
    5
    <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
    <version>1.5.7.RELEASE</version>
    </dependency>
    至于添加用户名密码等安全配置还是另外看 starter-security 模块的内容.

消息代理

  1. 配置和上边的一样
  2. 跟踪消息总线
    1
    spring.cloud.bus.trace.enabled=true
    这样每个服务实例发送的所有事件和所有的 ack 都将显示到 Spring Boot TraceRepository

Zuul(路由网关)

  1. 路由转发
  2. 过滤器
    Authentication
    Insights
    Stress Testing
    Canary Testing
    Dynamic Routing
    Service Migration
    Load Shedding
    Security
    Static Response handling
    Active/Active traffic management

路由转发

  1. 创建 Spring Initializr 应用
    勾选 Eureka Discovery 和 Zuul
  2. ServiceZuulApplication 类添加 @EnableZuulProxy@EnableEurekaClient 注解
  3. 添加配置
    1
    2
    3
    4
    5
    6
    7
    eureka.client.service-url.default-zone=http://localhost:8761/eureka/
    server.port=8769
    spring.application.name=service-zuul
    zuul.routes.api-a.path=/api-a/**
    zuul.routes.api-a.serviceId=service-ribbon
    zuul.routes.api-b.path=/api-b/**
    zuul.routes.api-b.serviceId=service-feign
  4. 访问
    这样配置后,访问http://localhost:8769/api-a/hi?name=forezp 链接就会被转发到 service-ribbon,访问 http://localhost:8769/api-b/hi?name=forezp 就会被转发到 service-feign

过滤

  1. 添加过滤器
  2. 访问
    请求必须带上 token 不然会被拦截:
    http://localhost:8769/api-a/hi?name=forezp&token=22

Config(分布式配置中心)

  • 将配置文件放在配置服务内存中(本地)
  • 远程保存配置文件到 Git 仓库
    有两种配置方式,一种将 Config Server 独立部署,Config Client 通过 ip 访问配置服务器(加入 starter-web 依赖),另一种将他们加入一个 Eureka 集群中,Config Client 可以通过服务名访问到 Config Server(改为加入 starter-eureka 依赖)。

Config Server

  1. 创建 Spring Initializr 项目
    勾选 Eureka Discovery 和 Config Server
  2. 然后添加配置
    1
    2
    3
    4
    5
    6
    spring.application.name=service-config
    server.port=8888

    spring.cloud.config.server.git.uri=https://github.com/tallate/springcloudconfig.git 仓库地址
    spring.cloud.config.server.git.search-paths=configs # 表示配置文件所在目录
    spring.cloud.config.label=master # 仓库分支
    因为是公开仓库可以不填写用户名和密码,如果是私有仓库,还需用加上下面两条:
    1
    2
    spring.cloud.config.server.git.username:访问git仓库的用户名
    spring.cloud.config.server.git.password:访问git仓库的用户密码
  3. 为 ServiceConfigApplication 类添加 @EnableConfigServer
  4. 访问配置
    请求链接:
    1
    /{application}/{profile}[/{label}]
    资源文件名:
    1
    2
    3
    4
    /{appli cation}-{profile}.yml
    /{label}/{application}-{profile}.yml
    /{application}-{profile}.properties
    /{label}/{application}-{profile}.properties
    比如在仓库中新建一个配置文件 config-client-dev.properties:
    1
    name = Mike
    访问链接就可以得到 Json 格式的该配置文件内容:
    1
    http://localhost:8888/config-client/dev

Config Client

  1. 创建 Spring Initializr 项目
    勾选 Eureka Discovery 和 Config Client
  2. 添加配置
    1
    2
    3
    4
    5
    spring.application.name=config-client
    spring.cloud.config.label=master # 远程仓库的分支
    spring.cloud.config.profile=dev # 开发环境配置文件,test测试环境,pro正式环境
    spring.cloud.config.uri=http://localhost:8888/ # 配置服务中心的地址
    server.port=8881
    因为是作为 Eureka 集群内的组件启动的,所以可以使用服务名直接访问配置中心,为此需要去掉 spring.cloud.config.uri 项,然后添加:
    1
    2
    spring.cloud.config.discovery.enabled 是从配置中心读取文件
    spring.cloud.config.discovery.serviceId 配置中心的servieId,即服务名
  3. 写服务接口,返回从配置中心读取的一个配置项的值
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    @SpringBootApplication
    @RestController
    public class ConfigClientApplication {

    public static void main(String[] args) {
    SpringApplication.run(ConfigClientApplication.class, args);
    }

    @Value("${foo}")
    private String foo;

    @RequestMapping("/hi")
    public String hi() {
    return foo;
    }
    }
  4. 访问配置项
    http://localhost:8881/hi

ZooKeeper

服务发现 Server 及 Client

加入依赖后使得 app 可以将其本身注册到 zookeeper 服务中(Server),且可以从 zookeeper 集群中定位其他服务(Client),如果要禁用 Client 功能,可以添加配置:

1
spring.cloud.zookeeper.discovery.enabled=false

服务端

  1. 依赖
    1
    2
    3
    4
    5
    6
    7
    8
    9
    <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-zookeeper-discovery</artifactId>
    </dependency>
  2. 配置
    1
    2
    # zookeeper对外开放的服务地址
    spring.cloud.zookeeper.connect-string=59.110.172.126:2181

Consul(服务注册和发现)

  • 服务注册
  • 健康检查

Consul 的配置

  1. 创建 Spring Initializr 项目
    勾选 Consul 和 Web
  2. 添加 @EnableDiscoveryClient 注解
  3. 添加配置
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    server.port=8502
    spring.cloud.consul.host=localhost
    spring.cloud.consul.port=8500

    # 健康检查接口地址

    spring.cloud.consul.discovery.health-check-path=/health
    spring.cloud.consul.discovery.health-check-interval=15s
    spring.cloud.consul.discovery.instance-id=consul-client
    spring.application.name=consul-client
  4. 为 Service 添加”/health”接口
    1
    2
    3
    4
    5
    //健康检查的实现REST部分
    @RequestMapping("/health")
    public String health() {
       return "hello health ";
    }
    之后 Consul 通过检查这个接口来判断服务是否健康。
  5. 查看
    一般 consul 启动后访问链接是 localhost:8500,可以看到服务已经注册到了其中。

参考

  1. 如何利用 Spring Cloud 构建起自我修复型分布式系统
  2. Spring Cloud 英文文档
  3. Spring Cloud 中文网

常用服务配置

  1. Spring Cloud 上下文:应用程序上下文服务
  2. Spring Cloud Bus
  3. 路由器和过滤器:Zuul
  4. Netflix/zuul
  5. Netflix Zuul 与 Nginx 的性能对比
  6. Spring Cloud Config
  7. Spring Cloud Zookeeper
  8. spring-cloud-zookeeper-sample
  9. Spring Cloud Consul