ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

w3cschool-Spring Cloud

2022-06-02 11:05:00  阅读:215  来源: 互联网

标签:服务 Spring springframework eureka w3cschool Cloud spring org cloud


https://www.w3cschool.cn/spring_cloud/spring_cloud-ryjs2ixg.html

Spring Cloud(一)服务的注册与发现(Eureka)

2021-02-19 14:41 更新

Spring Cloud是一个基于Spring Boot实现的云应用开发工具,它为基于JVM的云应用开发中涉及的配置管理、服务发现、断路器、智能路由、微代理、控制总线、全局锁、决策竞选、分布式会话和集群状态管理等操作提供了一种简单的开发方式。

 

Spring Cloud简介

Spring Cloud包含了多个子项目(针对分布式系统中涉及的多个不同开源产品),比如:Spring Cloud Config、Spring Cloud Netflix、Spring Cloud CloudFoundry、Spring Cloud AWS、Spring Cloud Security、Spring Cloud Commons、Spring Cloud Zookeeper、Spring Cloud CLI等项目。

 

微服务架构

 

微服务(Microservices Architecture)是一种架构风格,一个大型复杂软件应用由一个或多个微服务组成。系统中的各个微服务可被独立部署,各个微服务之间是松耦合的。每个微服务仅关注于完成一件任务并很好地完成该任务。在所有情况下,每个任务代表着一个小的业务能力。

微服务的概念源于2014年3月Martin Fowler所写的章“Microservices”http://martinfowler.com/articles/microservices.html

 

 

微服务架构(Microservices Architecture)

微服务架构的核心思想是,一个应用是由多个小的、相互独立的、微服务组成,这些服务运行在自己的进程中,开发和发布都没有依赖。不同服务通过一些轻量级交互机制来通信,例如 RPC、HTTP 等,服务可独立扩展伸缩,每个服务定义了明确的边界,不同的服务甚至可以采用不同的编程语言来实现,由独立的团队来维护。简单的来说,一个系统的不同模块转变成不同的服务!而且服务可以使用不同的技术加以实现!

 

微服务设计

那我们在微服务中应该怎样设计呢。以下是微服务的设计指南:

 

  • 职责单一原则(Single Responsibility Principle):把某一个微服务的功能聚焦在特定业务或者有限的范围内会有助于敏捷开发和服务的发布。
  • 设计阶段就需要把业务范围进行界定。
  • 需要关心微服务的业务范围,而不是服务的数量和规模尽量小。数量和规模需要依照业务功能而定。
  • 于SOA不同,某个微服务的功能、操作和消息协议尽量简单。
  • 项目初期把服务的范围制定相对宽泛,随着深入,进一步重构服务,细分微服务是个很好的做法。

 

 

关于微服务架构的取舍

 

  • 在合适的项目,合适的团队,采用微服务架构收益会大于成本。
  • 微服务架构有很多吸引人的地方,但在拥抱微服务之前,也需要认清它所带来的挑战。
  • 需要避免为了“微服务”而“微服务”。
  • 微服务架构引入策略 – 对传统企业而言,开始时可以考虑引入部分合适的微服务架构原则对已有系统进行改造或新建微服务应用,逐步探索及积累微服务架构经验,而非全盘实施微服务架构。

更多关于微服务架构内容-请参考我的另一篇文章:《什什么是微服务架构?》

 

服务治理

由于Spring Cloud为服务治理做了一层抽象接口,所以在Spring Cloud应用中可以支持多种不同的服务治理框架,比如:Netflix Eureka、Consul、Zookeeper。在Spring Cloud服务治理抽象层的作用下,我们可以无缝地切换服务治理实现,并且不影响任何其他的服务注册、服务发现、服务调用等逻辑。

 

Spring Cloud Eureka

Spring Cloud Eureka来实现服务治理。

Spring Cloud Eureka是Spring Cloud Netflix项目下的服务治理模块。而Spring Cloud Netflix项目是Spring Cloud的子项目之一,主要内容是对Netflix公司一系列开源产品的包装,它为Spring Boot应用提供了自配置的Netflix OSS整合。通过一些简单的注解,开发者就可以快速的在应用中配置一下常用模块并构建庞大的分布式系统。它主要提供的模块包括:服务发现(Eureka),断路器(Hystrix),智能路由(Zuul),客户端负载均衡(Ribbon)等。

 

Eureka Server

提供服务注册和发现

 

添加依赖

在项目 spring-cloud-eureka-service pom.xml中引入需要的依赖内容:

 

  1. <dependency>
  2. <groupId>org.springframework.cloud</groupId>
  3. <artifactId>spring-cloud-starter-eureka-server</artifactId>
  4. </dependency>

 

开启服务注册

通过 @EnableEurekaServer 注解启动一个服务注册中心提供给其他应用进行对话,这个注解需要在springboot工程的启动application类上加

 

  1. package io.ymq.example.eureka.server;
  2. import org.springframework.boot.SpringApplication;
  3. import org.springframework.boot.autoconfigure.SpringBootApplication;
  4. import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
  5. @SpringBootApplication
  6. @EnableEurekaServer
  7. public class EurekaServerApplication {
  8. public static void main(String[] args) {
  9. SpringApplication.run(EurekaServerApplication.class, args);
  10. }
  11. }

 

添加配置

在默认设置下,该服务注册中心也会将自己作为客户端来尝试注册它自己,所以我们需要禁用它的客户端注册行为,只需要在application.yml配置文件中增加如下信息:

 

  1. registerWithEureka: false
  2. fetchRegistry: false

完整配置

 

  1. server:
  2. port: 8761
  3. eureka:
  4. instance:
  5. hostname: localhost
  6. client:
  7. registerWithEureka: false
  8. fetchRegistry: false
  9. serviceUrl:
  10. defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/

 

访问服务

 

启动工程后,访问:http://localhost:8761/

可以看到下面的页面,其中还没有发现任何服务。

 System Status

 

Service Provider

 

  • 服务提供方
  • 将自身服务注册到 Eureka 注册中心,从而使服务消费方能够找到

 

添加依赖

在项目 spring-cloud-eureka-provider pom.xml中引入需要的依赖内容:

 

  1. <dependency>
  2. <groupId>org.springframework.cloud</groupId>
  3. <artifactId>spring-cloud-starter-eureka-server</artifactId>
  4. </dependency>

 

开启服务注册

在应用主类中通过加上 @EnableEurekaClient,但只有Eureka 可用,你也可以使用@EnableDiscoveryClient。需要配置才能找到Eureka注册中心服务器

 

  1. package io.ymq.example.eureka.provider;
  2. import org.springframework.boot.SpringApplication;
  3. import org.springframework.boot.autoconfigure.SpringBootApplication;
  4. import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
  5. import org.springframework.web.bind.annotation.RequestMapping;
  6. import org.springframework.web.bind.annotation.RestController;
  7. @SpringBootApplication
  8. @EnableEurekaClient
  9. @RestController
  10. public class EurekaProviderApplication {
  11. @RequestMapping("/")
  12. public String home() {
  13. return "Hello world";
  14. }
  15. public static void main(String[] args) {
  16. SpringApplication.run(EurekaProviderApplication.class, args);
  17. }
  18. }

 

添加配置

需要配置才能找到Eureka服务器。例:

完整配置

 

  1. eureka:
  2. client:
  3. serviceUrl:
  4. defaultZone: http://localhost:8761/eureka/
  5. spring:
  6. application:
  7. name: eureka-provider
  8. server:
  9. port: 8081

其中defaultZone是一个魔术字符串后备值,为任何不表示首选项的客户端提供服务URL(即它是有用的默认值)。 通过spring.application.name属性,我们可以指定微服务的名称后续在调用的时候只需要使用该名称就可以进行服务的访问

 

访问服务

启动该工程后,再次访问启动工程后:http://localhost:8761/

可以如下图内容,我们定义的服务被成功注册了。

 

Spring Cloud(二)Consul 服务治理实现

2019-04-17 13:57 更新

Spring Cloud Consul 项目是针对Consul的服务治理实现。Consul是一个分布式高可用的系统,具有分布式、高可用、高扩展性。

 

Consul 简介

Consul 是 HashiCorp 公司推出的开源工具,用于实现分布式系统的服务发现与配置。与其他分布式服务注册与发现的方案,Consul的方案更“一站式” ,内置了服务注册与发现框 架、具有以下性质:

 

  • 分布一致性协议实现、
  • 健康检查、
  • Key/Value存储、
  • 多数据中心方案,

不再需要依赖其他工具(比如ZooKeeper等)。

使用起来也较 为简单。Consul使用Go语言编写,因此具有天然可移植性(支持Linux、windows和Mac OS X);安装包仅包含一个可执行文件,方便部署,与Docker等轻量级容器可无缝配合 。 基于 Mozilla Public License 2.0 的协议进行开源. Consul 支持健康检查,并允许 HTTP 和 DNS 协议调用 API 存储键值对. 一致性协议采用 Raft 算法,用来保证服务的高可用. 使用 GOSSIP 协议管理成员和广播消息, 并且支持 ACL 访问控制.

 

Consul 的使用场景

 

  • docker 实例的注册与配置共享
  • coreos 实例的注册与配置共享
  • vitess 集群
  • SaaS 应用的配置共享
  • 与 confd 服务集成,动态生成 nginx 和 haproxy 配置文件

 

Consul 的优势

使用 Raft 算法来保证一致性, 比复杂的 Paxos 算法更直接. 相比较而言, zookeeper 采用的是 Paxos, 而 etcd 使用的则是 Raft. 支持多数据中心,内外网的服务采用不同的端口进行监听。 多数据中心集群可以避免单数据中心的单点故障,而其部署则需要考虑网络延迟, 分片等情况等. zookeeper 和 etcd 均不提供多数据中心功能的支持. 支持健康检查. etcd 不提供此功能. 支持 http 和 dns 协议接口. zookeeper 的集成较为复杂, etcd 只支持 http 协议. 官方提供web管理界面, etcd 无此功能.

 

Consul 的角色

client: 客户端, 无状态, 将 HTTP 和 DNS 接口请求转发给局域网内的服务端集群.server: 服务端, 保存配置信息, 高可用集群, 在局域网内与本地客户端通讯, 通过广域网与其他数据中心通讯. 每个数据中心的 server 数量推荐为 3 个或是 5 个.

由于Spring Cloud Consul项目的实现,我们可以轻松的将基于Spring Boot的微服务应用注册到Consul上,并通过此实现微服务架构中的服务治理。

 

搭建环境

参考

 

要想利用Consul提供的服务实现服务的注册与发现,我们需要搭建Consul Cluster 环境。

在Consul方案中,每个提供服务的节点上都要部署和运行Consul的agent,所有运行Consul agent节点的集合构成Consul Cluster。

Consul agent有两种运行模式:Server和Client。这里的Server和Client只是Consul集群层面的区分,与搭建在Cluster之上 的应用服务无关。

以Server模式运行的Consul agent节点用于维护Consul集群的状态,官方建议每个Consul Cluster至少有3个或以上的运行在Server mode的Agent,Client节点不限。

环境配置如下:

Centos 7.3

主机名称IP作用是否允许远程访问
node1 192.168.252.121 consul server
node2 192.168.252.122 consul client
node3 192.168.252.123 consul client

关闭防火墙

 

  1. systemctl stop firewalld.service

Consul 最新版的下载地址:
https://releases.hashicorp.com/consul/1.0.1/consul_1.0.1_linux_amd64.zip

下载,然后unzip 解压,得到唯一,一个可执行文件

 

  1. cd /opt/
  2. wget https://releases.hashicorp.com/consul/1.0.1/consul_1.0.1_linux_amd64.zip
  3. unzip consul_1.0.1_linux_amd64.zip
  4. cp consul /usr/local/bin/

查看是否安装成功

 

  1. [root@node1 opt]# consul

出现如下结果,表示安装成功

 

  1. Usage: consul [--version] [--help] <command> [<args>]
  2. Available commands are:
  3. agent Runs a Consul agent
  4. catalog Interact with the catalog
  5. event Fire a new event
  6. exec Executes a command on Consul nodes
  7. force-leave Forces a member of the cluster to enter the "left" state
  8. info Provides debugging information for operators.
  9. join Tell Consul agent to join cluster
  10. keygen Generates a new encryption key
  11. keyring Manages gossip layer encryption keys
  12. kv Interact with the key-value store
  13. leave Gracefully leaves the Consul cluster and shuts down
  14. lock Execute a command holding a lock
  15. maint Controls node or service maintenance mode
  16. members Lists the members of a Consul cluster
  17. monitor Stream logs from a Consul agent
  18. operator Provides cluster-level tools for Consul operators
  19. reload Triggers the agent to reload configuration files
  20. rtt Estimates network round trip time between nodes
  21. snapshot Saves, restores and inspects snapshots of Consul server state
  22. validate Validate config files/directories
  23. version Prints the Consul version
  24. watch Watch for changes in Consul

检查版本

 

  1. [root@node1 opt]# consul version

 

  1. Consul v1.0.1
  2. Protocol 2 spoken by default, understands 2 to 3 (agent will automatically use protocol >2 when speaking to compatible agents)

 

Consul常用命令

 

命令解释示例
agent 运行一个consul agent consul agent -dev
join 将agent加入到consul集群 consul join IP
members 列出consul cluster集群中的members consul members
leave 将节点移除所在集群 consul leave

 

consul agent 命令的常用选项

-data-dir

 

  • 作用:指定agent储存状态的数据目录
  • 这是所有agent都必须的
  • 对于server尤其重要,因为他们必须持久化集群的状态

-config-dir

 

  • 作用:指定service的配置文件和检查定义所在的位置
  • 通常会指定为”某一个路径/consul.d”(通常情况下,.d表示一系列配置文件存放的目录)

-config-file

 

  • 作用:指定一个要装载的配置文件
  • 该选项可以配置多次,进而配置多个配置文件(后边的会合并前边的,相同的值覆盖)

-dev

 

  • 作用:创建一个开发环境下的server节点
  • 该参数配置下,不会有任何持久化操作,即不会有任何数据写入到磁盘
  • 这种模式不能用于生产环境(因为第二条)

-bootstrap-expect

  • 作用:该命令通知consul server我们现在准备加入的server节点个数,该参数是为了延迟日志复制的启动直到我们指定数量的server节点成功的加入后启动。

-node

 

  • 作用:指定节点在集群中的名称
  • 该名称在集群中必须是唯一的(默认采用机器的host)
  • 推荐:直接采用机器的IP

-bind

 

  • 作用:指明节点的IP地址
  • 有时候不指定绑定IP,会报Failed to get advertise address: Multiple private IPs found. Please configure one. 的异常

-server

 

  • 作用:指定节点为server
  • 每个数据中心(DC)的server数推荐至少为1,至多为5
  • 所有的server都采用raft一致性算法来确保事务的一致性和线性化,事务修改了集群的状态,且集群的状态保存在每一台server上保证可用性
  • server也是与其他DC交互的门面(gateway)

-client

 

  • 作用:指定节点为client,指定客户端接口的绑定地址,包括:HTTP、DNS、RPC
  • 默认是127.0.0.1,只允许回环接口访问
  • 若不指定为-server,其实就是-client

-join

 

  • 作用:将节点加入到集群

-datacenter(老版本叫-dc,-dc已经失效)

 

  • 作用:指定机器加入到哪一个数据中心中

 

启动服务

我们尝试一下:

-dev表示开发模式运行,使用-client 参数可指定允许客户端使用什么ip去访问,例如-client 192.168.252.121 表示可以使用

http://192.168.252.121:8500/ui/ 去访问。

 

  1. consul agent -dev -client 192.168.252.121

Consul Cluster

 

Consul 的高可用

Consul Cluster集群架构图如下:

Consul Cluster集群架构

这边准备了三台Centos 7.3的虚拟机,主机规划如下,供参考:

主机名称IP作用是否允许远程访问
node1 192.168.252.121 consul server
node2 192.168.252.122 consul client
node3 192.168.252.123 consul client

 

搭建步骤

命令参数,参看上面详细介绍

在 node1 机器上启动 Consul

 

  1. cd /opt/
  2. mkdir data
  3. consul agent -data-dir /opt/data -node=192.168.252.121 -bind=0.0.0.0 -datacenter=dc1 -ui -client=192.168.252.121 -server -bootstrap-expect 1 > /dev/null 2>&1 &

在 node2 机器上启动 Consul,并且将node2节点加入到node1节点上

  1. cd /opt/
  2. mkdir data
  3. consul agent -data-dir /opt/data -node=192.168.252.122 -bind=0.0.0.0 -datacenter=dc1 -ui -client=192.168.252.122 -join=192.168.252.121 > /dev/null 2>&1 &

在 node3 机器上启动 Consul,并且将node3节点加入到node1节点上

 

  1. cd /opt/
  2. mkdir data
  3. consul agent -data-dir /opt/data -node=192.168.252.123 -bind=0.0.0.0 -datacenter=dc1 -ui -client=192.168.252.123 -join=192.168.252.121 > /dev/null 2>&1 &

 

在node1上查看当前集群节点:

 

  1. consul members -rpc-addr=192.168.252.123:8400
  2. consul leave -rpc-addr=192.168.252.123:8400

http://192.168.252.121:8500/ui/ 去访问。

 

Consul Cluster集群 nodes

 

项目示例

新建项目:spring-cloud-consul-client

 

添加依赖

在项目 spring-cloud-consul-client pom.xml中引入需要的依赖内容:

 

  1. <dependency>
  2. <groupId>org.springframework.cloud</groupId>
  3. <artifactId>spring-cloud-starter-consul-discovery</artifactId>
  4. </dependency>

 

开启服务注册

客户端注册Consul时,它提供有关自身的元数据,如主机和端口,ID,名称和标签。默认情况下,将创建一个HTTP 检查,每隔10秒Consul命中/health端点。如果健康检查失败,则服务实例被标记为关键。

 

  1. package io.ymq.example.consul;
  2. import org.springframework.boot.SpringApplication;
  3. import org.springframework.boot.autoconfigure.SpringBootApplication;
  4. import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
  5. import org.springframework.web.bind.annotation.RequestMapping;
  6. import org.springframework.web.bind.annotation.RestController;
  7. @SpringBootApplication
  8. @EnableDiscoveryClient
  9. @RestController
  10. public class ConsulApplication {
  11. @RequestMapping("/")
  12. public String home() {
  13. return "Hello world";
  14. }
  15. public static void main(String[] args) {
  16. SpringApplication.run(ConsulApplication.class, args);
  17. }
  18. }

 

配置文件

application.yml配置文件中增加如下信息:如果Consul客户端位于localhost:8500以外,则需要配置来定位客户端

 

  1. spring:
  2. application:
  3. name: consul-client
  4. cloud:
  5. consul:
  6. host: 192.168.252.121
  7. port: 8500
  8. discovery:
  9. healthCheckPath: /
  10. healthCheckInterval: 5s

 

如果Consul客户端位于localhost:8500以外的位置,则需要配置来定位客户端。例:

 

  1. host: 192.168.252.121
  2. port: 8500

HTTP健康检查路径 INSTALL

“10s”和“1m”分别表示10秒和1分

 

  1. discovery:
  2. healthCheckPath: ${management.context-path}/health
  3. healthCheckInterval: 15s

 

启动服务

spring-cloud-consul-client 项目根目录下,执行mvn clean package,把target 目录下 生成的 jar spring-cloud-consul-client-0.0.1-SNAPSHOT.jar 上传服务器,发布项目

打包命令

 

  1. mvn clean package

发布命令

 

  1. nohup java -jar spring-cloud-consul-client-0.0.1-SNAPSHOT.jar > /dev/null 2>&1 &

 

访问服务

http://192.168.252.121:8500/ui/#/dc1/nodes/192.168.252.121

 

Spring Cloud(三)服务提供者 Eureka + 服务消费者(rest + Ribbon)

2022-02-21 10:27 更新

Spring Cloud Ribbon是基于Netflix Ribbon实现的一套客户端负载均衡的工具。它是一个基于HTTP和TCP的客户端负载均衡器。它可以通过在客户端中配置ribbonServerList来设置服务端列表去轮询访问以达到均衡负载的作用。

 

Ribbon是什么?

Ribbon是Netflix发布的开源项目,主要功能是提供客户端的软件负载均衡算法,将Netflix的中间层服务连接在一起。Ribbon客户端组件提供一系列完善的配置项如连接超时,重试等。简单的说,就是在配置文件中列出Load Balancer(简称LB)后面所有的机器,Ribbon会自动的帮助你基于某种规则(如简单轮询,随即连接等)去连接这些机器。我们也很容易使用Ribbon实现自定义的负载均衡算法。

 

LB方案分类

目前主流的LB方案可分成两类:一种是集中式LB, 即在服务的消费方和提供方之间使用独立的LB设施(可以是硬件,如F5, 也可以是软件,如nginx), 由该设施负责把访问请求通过某种策略转发至服务的提供方;另一种是进程内LB,将LB逻辑集成到消费方,消费方从服务注册中心获知有哪些地址可用,然后自己再从这些地址中选择出一个合适的服务器。Ribbon就属于后者,它只是一个类库,集成于消费方进程,消费方通过它来获取到服务提供方的地址。

 

Ribbon的主要组件与工作流程

微服务架构的核心思想是,一个应用是由多个小的、相互独立的、微服务组成,这些服务运行在自己的进程中,开发和发布都没有依赖。 不同服务通过一些轻量级交互机制来通信,例如 RPC、HTTP 等,服务可独立扩展伸缩,每个服务定义了明确的边界,不同的服务甚至可以采用不同的编程语言来实现,由独立的团队来维护。 简单的来说,一个系统的不同模块转变成不同的服务!而且服务可以使用不同的技术加以实现!

 

Ribbon的核心组件

均为接口类型,有以下几个

ServerList

 

  • 用于获取地址列表。它既可以是静态的(提供一组固定的地址),也可以是动态的(从注册中心中定期查询地址列表)。

ServerListFilter

 

  • 仅当使用动态ServerList时使用,用于在原始的服务列表中使用一定策略过虑掉一部分地址。

IRule

 

  • 选择一个最终的服务地址作为LB结果。选择策略有轮询、根据响应时间加权、断路器(当Hystrix可用时)等。

Ribbon在工作时首选会通过ServerList来获取所有可用的服务列表,然后通过ServerListFilter过虑掉一部分地址,最后在剩下的地址中通过IRule选择出一台服务器作为最终结果。

 

Ribbon提供的主要负载均衡策略介绍

简单轮询负载均衡(RoundRobin)

以轮询的方式依次将请求调度不同的服务器,即每次调度执行i = (i + 1) mod n,并选出第i台服务器。

随机负载均衡 (Random)

随机选择状态为UP的Server

加权响应时间负载均衡 (WeightedResponseTime)

根据相应时间分配一个weight,相应时间越长,weight越小,被选中的可能性越低。

区域感知轮询负载均衡(ZoneAvoidanceRule)

复合判断server所在区域的性能和server的可用性选择server

 

 

准备工作

本次项目示例,改造第一篇文章中的项目,使用spring-cloud-eureka-service作为服务注册中心,spring-cloud-eureka-provider,复制三分,项目名称依次修改为spring-cloud-eureka-provider-1 [1-3]

 

改造 Provider

服务提供者

在项目:spring-cloud-eureka-provider-1spring-cloud-eureka-provider-2spring-cloud-eureka-provider-3 的启动类,都加入@Value("${server.port}"),修改home()方法, 来区分不同端口的Controller 响应,因为接下来,使用ribbon做均衡需要测试需要使用到

 

  1. package io.ymq.example.eureka.provider;
  2. import org.springframework.beans.factory.annotation.Value;
  3. import org.springframework.boot.SpringApplication;
  4. import org.springframework.boot.autoconfigure.SpringBootApplication;
  5. import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
  6. import org.springframework.web.bind.annotation.RequestMapping;
  7. import org.springframework.web.bind.annotation.RestController;
  8. @SpringBootApplication
  9. @EnableEurekaClient
  10. @RestController
  11. public class EurekaProviderApplication {
  12. @Value("${server.port}")
  13. String port;
  14. @RequestMapping("/")
  15. public String home() {
  16. return "Hello world ,port:" + port;
  17. }
  18. public static void main(String[] args) {
  19. SpringApplication.run(EurekaProviderApplication.class, args);
  20. }
  21. }

 

修改配置

在项目:spring-cloud-eureka-provider-1spring-cloud-eureka-provider-2spring-cloud-eureka-provider-3,修改server: port:端口依次为8081,8082,8083

 

  1. eureka:
  2. client:
  3. serviceUrl:
  4. defaultZone: http://localhost:8761/eureka/
  5. spring:
  6. application:
  7. name: eureka-provider
  8. server:
  9. port: 8081

 

Ribbon Consumer

服务消费者

 

添加依赖

新建 spring-cloud-ribbon-consumer

 

  1. <!-- 客户端负载均衡 -->
  2. <dependency>
  3. <groupId>org.springframework.cloud</groupId>
  4. <artifactId>spring-cloud-starter-ribbon</artifactId>
  5. </dependency>
  6. <!-- eureka客户端 -->
  7. <dependency>
  8. <groupId>org.springframework.cloud</groupId>
  9. <artifactId>spring-cloud-starter-eureka</artifactId>
  10. </dependency>

 

开启服务负载均衡

在工程的启动类中,通过@EnableDiscoveryClient向服务注册中心注册;并且向程序的ioc注入一个bean: restTemplate并通过@LoadBalanced注解表明这个restTemplate开启负载均衡的功能。

 

  1. package io.ymq.example.ribbon.consumer;
  2. import org.springframework.boot.SpringApplication;
  3. import org.springframework.boot.autoconfigure.SpringBootApplication;
  4. import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
  5. import org.springframework.cloud.client.loadbalancer.LoadBalanced;
  6. import org.springframework.context.annotation.Bean;
  7. import org.springframework.web.client.RestTemplate;
  8. @EnableDiscoveryClient
  9. @SpringBootApplication
  10. public class RibbonConsumerApplication {
  11. @LoadBalanced
  12. @Bean
  13. RestTemplate restTemplate() {
  14. return new RestTemplate();
  15. }
  16. public static void main(String[] args) {
  17. SpringApplication.run(RibbonConsumerApplication.class, args);
  18. }
  19. }

 

消费提供者方法

新建 ConsumerController 类,调用提供者的 home 方法

 

  1. package io.ymq.example.ribbon.consumer;
  2. import org.springframework.beans.factory.annotation.Autowired;
  3. import org.springframework.web.bind.annotation.GetMapping;
  4. import org.springframework.web.bind.annotation.RestController;
  5. import org.springframework.web.client.RestTemplate;
  6. /**
  7. * 描述:调用提供者的 `home` 方法
  8. *
  9. * @author yanpenglei
  10. * @create 2017-12-05 18:53
  11. **/
  12. @RestController
  13. public class ConsumerController {
  14. @Autowired
  15. private RestTemplate restTemplate;
  16. @GetMapping(value = "/hello")
  17. public String hello() {
  18. return restTemplate.getForEntity("http://eureka-provider/", String.class).getBody();
  19. }
  20. }

 

添加配置

完整配置 application.yml

指定服务的注册中心地址,配置自己的服务端口,服务名称

 

  1. eureka:
  2. client:
  3. serviceUrl:
  4. defaultZone: http://localhost:8761/eureka/
  5. spring:
  6. application:
  7. name: ribbon-consumer
  8. server:
  9. port: 9000

 

测试服务

 

启动服务

依次启动项目:

spring-cloud-eureka-service
spring-cloud-eureka-provider-1
spring-cloud-eureka-provider-2
spring-cloud-eureka-provider-3
spring-cloud-ribbon-consumer

启动该工程后,访问服务注册中心,查看服务是否都已注册成功:http://localhost:8761/

查看服务注册状态

 

负载均衡

在命令窗口curl http://localhost:9000/hello,发现Ribbon已经实现负载均衡

或者浏览器get 请求http://localhost:9000/hello F5 刷新

 

Spring Cloud(四)服务提供者 Eureka + 服务消费者 Feign

2019-04-17 13:57 更新

上一篇文章,讲述了如何通过RestTemplate + Ribbon去消费服务,这篇文章主要讲述如何通过Feign去消费服务。

 

Feign简介

Feign是一个声明式的伪Http客户端,它使得写Http客户端变得更简单。

使用Feign,只需要创建一个接口并注解,它具有可插拔的注解特性,可使用Feign 注解和JAX-RS注解,Feign支持可插拔的编码器和解码器,Feign默认集成了Ribbon,并和Eureka结合,默认实现了负载均衡的效果。

Feign 具有如下特性:

 

  • 可插拔的注解支持,包括Feign注解和JAX-RS注解
  • 支持可插拔的HTTP编码器和解码器
  • 支持Hystrix和它的Fallback
  • 支持Ribbon的负载均衡
  • 支持HTTP请求和响应的压缩Feign是一个声明式的Web Service客户端,它的目的就是让Web Service调用更加简单。它整合了RibbonHystrix,从而不再需要显式地使用这两个组件。Feign还提供了HTTP请求的模板,通过编写简单的接口和注解,就可以定义好HTTP请求的参数、格式、地址等信息。接下来,Feign会完全代理HTTP的请求,我们只需要像调用方法一样调用它就可以完成服务请求。

简而言之:Feign能干RibbonHystrix的事情,但是要用RibbonHystrix自带的注解必须要引入相应的jar包才可以。

 

准备工作

 

Eureka Service

导入第三篇文章中的项目:作为服务注册中心

spring-cloud-eureka-service

 

Eureka Provider

导入第三篇文章中的项目:作为服务的提供者

spring-cloud-eureka-provider-1
spring-cloud-eureka-provider-2
spring-cloud-eureka-provider-3

 

 

Feign Consumer

服务消费者

 

添加依赖

新建项目 spring-cloud-feign-consumer pom.xml中引入需要的依赖内容:

 

  1. <dependency>
  2. <groupId>org.springframework.cloud</groupId>
  3. <artifactId>spring-cloud-starter-feign</artifactId>
  4. </dependency>

 

开启Feign

在工程的启动类中,通过@EnableFeignClients 注解开启Feign的功能:

 

  1. package io.ymq.example.feign.consumer;
  2. import org.springframework.boot.SpringApplication;
  3. import org.springframework.boot.autoconfigure.SpringBootApplication;
  4. import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
  5. import org.springframework.cloud.netflix.feign.EnableFeignClients;
  6. @EnableFeignClients
  7. @EnableDiscoveryClient
  8. @SpringBootApplication
  9. public class FeignConsumerApplication {
  10. public static void main(String[] args) {
  11. SpringApplication.run(FeignConsumerApplication.class, args);
  12. }
  13. }

 

定义接口

通过@FeignClient("服务名"),来指定调用哪个服务。
比如在代码中调用了eureka-provider服务的 / 接口,/ 就是调用:服务提供者项目:spring-cloud-eureka-provider-1spring-cloud-eureka-provider-2spring-cloud-eureka-provider-3 的 home() 方法,代码如下:

 

  1. package io.ymq.example.feign.consumer;
  2. import org.springframework.cloud.netflix.feign.FeignClient;
  3. import org.springframework.web.bind.annotation.GetMapping;
  4. /**
  5. * 描述: 指定这个接口所要调用的 提供者服务名称 "eureka-provider"
  6. *
  7. * @author yanpenglei
  8. * @create 2017-12-06 15:13
  9. **/
  10. @FeignClient("eureka-provider")
  11. public interface HomeClient {
  12. @GetMapping("/")
  13. String consumer();
  14. }

 

消费方法

写一个 Controller,消费提供者的 home 方法

 

  1. package io.ymq.example.feign.consumer;
  2. import org.springframework.beans.factory.annotation.Autowired;
  3. import org.springframework.web.bind.annotation.GetMapping;
  4. import org.springframework.web.bind.annotation.RestController;
  5. /**
  6. * 描述:调用提供者的 `home` 方法
  7. *
  8. * @author yanpenglei
  9. * @create 2017-12-06 15:26
  10. **/
  11. @RestController
  12. public class ConsumerController {
  13. @Autowired
  14. private HomeClient homeClient;
  15. @GetMapping(value = "/hello")
  16. public String hello() {
  17. return homeClient.consumer();
  18. }
  19. }

 

添加配置

完整配置 application.yml

指定注册中心地址,配置自己的服务名称

 

  1. eureka:
  2. client:
  3. serviceUrl:
  4. defaultZone: http://localhost:8761/eureka/
  5. spring:
  6. application:
  7. name: feign-consumer
  8. server:
  9. port: 9000

 

测试服务

依次启动项目:

spring-cloud-eureka-service
spring-cloud-eureka-provider-1
spring-cloud-eureka-provider-2
spring-cloud-eureka-provider-3
spring-cloud-feign-consumer

启动该工程后,访问服务注册中心,查看服务是否都已注册成功:http://localhost:8761/

查看各个服务注册状态

 

负载均衡响应

在命令窗口curl http://localhost:9000/hello,发现Feign已经实现负载均衡

或者浏览器get 请求http://localhost:9000/hello F5 刷新

测试 Feign 负载均衡响应

 

Spring Cloud(五)断路器监控(Hystrix Dashboard)

2019-04-17 13:56 更新

在上两篇文章中讲了,服务提供者 Eureka + 服务消费者 Feign,服务提供者 Eureka + 服务消费者(rest + Ribbon),本篇文章结合,上两篇文章中代码进行修改加入 断路器监控(Hystrix Dashboard)

在微服务架构中,根据业务来拆分成一个个的服务,服务与服务之间可以相互调用(RPC),在Spring Cloud可以用RestTemplate+Ribbon和Feign来调用。为了保证其高可用,单个服务通常会集群部署。由于网络原因或者自身的原因,服务并不能保证100%可用,如果单个服务出现问题,调用这个服务就会出现线程阻塞,此时若有大量的请求涌入,Servlet容器的线程资源会被消耗完毕,导致服务瘫痪。服务与服务之间的依赖性,故障会传播,会对整个微服务系统造成灾难性的严重后果,这就是服务故障的“雪崩”效应。

针对上述问题,在Spring Cloud Hystrix中实现了线程隔离、断路器等一系列的服务保护功能。它也是基于Netflix的开源框架 Hystrix实现的,该框架目标在于通过控制那些访问远程系统、服务和第三方库的节点,从而对延迟和故障提供更强大的容错能力。Hystrix具备了服务降级、服务熔断、线程隔离、请求缓存、请求合并以及服务监控等强大功能。

 

什么是断路器

断路器模式源于Martin Fowler的Circuit Breaker一文。“断路器”本身是一种开关装置,用于在电路上保护线路过载,当线路中有电器发生短路时,“断路器”能够及时的切断故障电路,防止发生过载、发热、甚至起火等严重后果。

在分布式架构中,断路器模式的作用也是类似的,当某个服务单元发生故障(类似用电器发生短路)之后,通过断路器的故障监控(类似熔断保险丝),向调用方返回一个错误响应,而不是长时间的等待。这样就不会使得线程因调用故障服务被长时间占用不释放,避免了故障在分布式系统中的蔓延。

 

断路器示意图

SpringCloud Netflix实现了断路器库的名字叫Hystrix. 在微服务架构下,通常会有多个层次的服务调用. 下面是微服架构下, 浏览器端通过API访问后台微服务的一个示意图:

 hystrix 1

一个微服务的超时失败可能导致瀑布式连锁反映,下图中,Hystrix通过自主反馈实现的断路器, 防止了这种情况发生。

 hystrix 2

图中的服务B因为某些原因失败,变得不可用,所有对服务B的调用都会超时。当对B的调用失败达到一个特定的阀值(5秒之内发生20次失败是Hystrix定义的缺省值), 链路就会被处于open状态, 之后所有所有对服务B的调用都不会被执行, 取而代之的是由断路器提供的一个表示链路open的Fallback消息. Hystrix提供了相应机制,可以让开发者定义这个Fallbak消息.

open的链路阻断了瀑布式错误, 可以让被淹没或者错误的服务有时间进行修复。这个fallback可以是另外一个Hystrix保护的调用, 静态数据,或者合法的空值. Fallbacks可以组成链式结构,所以,最底层调用其它业务服务的第一个Fallback返回静态数据.

 

准备工作

在开始加入断路器之前,我们先拿之前两篇博客,构建的两个微服务代码为基础,进行下面的操作

建议先阅读以下两篇文章

Spring Cloud(四) 服务提供者 Eureka + 服务消费者 Feign
Spring Cloud(三) 服务提供者 Eureka + 服务消费者(rest + Ribbon)

 

Eureka Service

导入第三篇文章中的项目:作为服务注册中心

spring-cloud-eureka-service

 

Eureka Provider

导入第三篇文章中的项目:作为服务的提供者

spring-cloud-eureka-provider-1
spring-cloud-eureka-provider-2
spring-cloud-eureka-provider-3

 

Ribbon Hystrix

在 Ribbon中使用断路器

 

修改项目

复制 spring-cloud-ribbon-consumer 项目,修改名称为spring-cloud-ribbon-consumer-hystrix

 

添加依赖

在项目pom 加上hystrix的依赖

 

  1. <!-- hystrix 断路器 -->
  2. <dependency>
  3. <groupId>org.springframework.cloud</groupId>
  4. <artifactId>spring-cloud-starter-hystrix</artifactId>
  5. </dependency>

 

服务注册

在程序的启动类 RibbonConsumerApplication 通过 @EnableHystrix 开启 Hystrix 断路器监控

 

  1. package io.ymq.example.ribbon.consumer.hystrix;
  2. import org.springframework.boot.SpringApplication;
  3. import org.springframework.boot.autoconfigure.SpringBootApplication;
  4. import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
  5. import org.springframework.cloud.client.loadbalancer.LoadBalanced;
  6. import org.springframework.cloud.netflix.hystrix.EnableHystrix;
  7. import org.springframework.context.annotation.Bean;
  8. import org.springframework.web.client.RestTemplate;
  9. @EnableHystrix
  10. @EnableDiscoveryClient
  11. @SpringBootApplication
  12. public class RibbonConsumerApplication {
  13. @LoadBalanced
  14. @Bean
  15. RestTemplate restTemplate() {
  16. return new RestTemplate();
  17. }
  18. public static void main(String[] args) {
  19. SpringApplication.run(RibbonConsumerApplication.class, args);
  20. }
  21. }

 

 

消费提供者方法

修改 ConsumerController 类的,hello 方法,加上注解@HystrixCommand(fallbackMethod = "defaultStores") 该注解对该方法创建了熔断器的功能 ,并指定了defaultStores熔断方法,熔断方法直接返回了一个字符串, "feign + hystrix ,提供者服务挂了"

 

@HystrixCommand 表明该方法为hystrix包裹,可以对依赖服务进行隔离、降级、快速失败、快速重试等等hystrix相关功能 该注解属性较多,下面讲解其中几个

 

  • fallbackMethod 降级方法
  • commandProperties 普通配置属性,可以配置HystrixCommand对应属性,例如采用线程池还是信号量隔离、熔断器熔断规则等等
  • ignoreExceptions 忽略的异常,默认HystrixBadRequestException不计入失败
  • groupKey() 组名称,默认使用类名称
  • commandKey 命令名称,默认使用方法名

 

 

  1. package io.ymq.example.ribbon.consumer.hystrix;
  2. import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
  3. import org.springframework.beans.factory.annotation.Autowired;
  4. import org.springframework.web.bind.annotation.GetMapping;
  5. import org.springframework.web.bind.annotation.RestController;
  6. import org.springframework.web.client.RestTemplate;
  7. /**
  8. * 描述:调用提供者的 `home` 方法
  9. *
  10. * @author yanpenglei
  11. * @create 2017-12-05 18:53
  12. **/
  13. @RestController
  14. public class ConsumerController {
  15. @Autowired
  16. private RestTemplate restTemplate;
  17. @HystrixCommand(fallbackMethod = "defaultStores")
  18. @GetMapping(value = "/hello")
  19. public String hello() {
  20. return restTemplate.getForEntity("http://eureka-provider/", String.class).getBody();
  21. }
  22. public String defaultStores() {
  23. return "Ribbon + hystrix ,提供者服务挂了";
  24. }
  25. }

 

测试断路器

依次启动项目:

spring-cloud-eureka-service
spring-cloud-eureka-provider-1
spring-cloud-eureka-provider-2
spring-cloud-eureka-provider-3
spring-cloud-ribbon-consumer-hystrix

启动该工程后,访问服务注册中心,查看服务是否都已注册成功:http://localhost:8761/

查看各个服务注册状态

 

在命令窗口curl http://localhost:9000/hello,发现一切正常

或者浏览器get 请求http://localhost:9000/hello F5 刷新

eureka-provider 提供者服务响应

停止 spring-cloud-eureka-provider-1 提供者,端口为:8081服务

再次访问命令窗口curl http://localhost:9000/hello ,断路器已经生效,提示:Ribbon + hystrix ,提供者服务挂了

Ribbon + hystrix ,提供者服务挂了

 

Feign Hystrix

在 Feign中使用断路器

 

修改项目

复制spring-cloud-feign-consumer 项目,修改名称为spring-cloud-feign-consumer-hystrix

 

添加依赖

Feign是自带断路器的,如果在Dalston版本的Spring Cloud中,它没有默认打开。需要需要在配置文件中配置打开它,本项目我们是不需要打开的

 

  1. feign:
  2. hystrix:
  3. enabled: true

 

服务注册

修改 HomeClient类 ,@FeignClient 注解,加上fallbackFactory指定新建的HystrixClientFallbackFactory 工厂类

在程序的启动类 RibbonConsumerApplication 通过 @EnableHystrix 开启 Hystrix

 

  1. package io.ymq.example.feign.consumer.hystrix;
  2. import org.springframework.cloud.netflix.feign.FeignClient;
  3. import org.springframework.web.bind.annotation.GetMapping;
  4. /**
  5. * 描述: 指定这个接口所要调用的 提供者服务名称 "eureka-provider"
  6. *
  7. * @author yanpenglei
  8. * @create 2017-12-06 15:13
  9. **/
  10. @FeignClient(value ="eureka-provider",fallbackFactory = HystrixClientFallbackFactory.class)
  11. public interface HomeClient {
  12. @GetMapping("/")
  13. String consumer();
  14. }

新加的类 HystrixClientFallbackFactory.java

 

  1. package io.ymq.example.feign.consumer.hystrix;
  2. import feign.hystrix.FallbackFactory;
  3. import org.springframework.stereotype.Component;
  4. /**
  5. * 描述:
  6. *
  7. * @author yanpenglei
  8. * @create 2017-12-07 20:37
  9. **/
  10. @Component
  11. public class HystrixClientFallbackFactory implements FallbackFactory<HomeClient> {
  12. @Override
  13. public HomeClient create(Throwable throwable) {
  14. return () -> "feign + hystrix ,提供者服务挂了";
  15. }
  16. }

测试断路器

依次启动项目:

spring-cloud-eureka-service
spring-cloud-eureka-provider-1
spring-cloud-eureka-provider-2
spring-cloud-eureka-provider-3
spring-cloud-feign-consumer-hystrix

启动该工程后,访问服务注册中心,查看服务是否都已注册成功:http://localhost:8761/

查看各个服务注册状态

在命令窗口curl http://localhost:9000/hello,发现一切正常

或者浏览器get 请求http://localhost:9000/hello F5 刷新

eureka-provider 提供者服务响应

停止 spring-cloud-eureka-provider-1 提供者,端口为:8081服务

再次访问命令窗口curl http://localhost:9000/hello ,断路器已经生效,提示:Feign + hystrix ,提供者服务挂了

Feign + hystrix ,提供者服务挂了

 

Hystrix Dashboard

 

HD 简介

Hystrix Dashboard在微服务架构中为例保证程序的可用性,防止程序出错导致网络阻塞,出现了断路器模型。断路器的状况反应了一个程序的可用性和健壮性,它是一个重要指标。Hystrix Dashboard是作为断路器状态的一个组件,提供了数据监控和友好的图形化界面。

 

改造项目

复制项目 spring-cloud-ribbon-consumer-hystrix,修改名称 spring-cloud-ribbon-consumer-hystrix-dashboard 在它的基础上进行改造。Feign的改造和这一样。

pom的工程文件引入相应的依赖:

 

 

添加依赖

 

  1. <dependency>
  2. <groupId>org.springframework.cloud</groupId>
  3. <artifactId>spring-cloud-starter-hystrix</artifactId>
  4. </dependency>
  5. <dependency>
  6. <groupId>org.springframework.boot</groupId>
  7. <artifactId>spring-boot-starter-actuator</artifactId>
  8. </dependency>
  9. <dependency>
  10. <groupId>org.springframework.cloud</groupId>
  11. <artifactId>spring-cloud-starter-hystrix-dashboard</artifactId>
  12. </dependency>

 

 

开启 HD

修改 RibbonConsumerApplication.java 类

在程序的入口RibbonConsumerApplication类,加上@EnableHystrix注解开启断路器,这个是必须的,并且需要在程序中声明断路点@HystrixCommand;加上@EnableHystrixDashboard注解,开启HystrixDashboard

 

  1. package io.ymq.example.ribbon.consumer.hystrix;
  2. import org.springframework.boot.SpringApplication;
  3. import org.springframework.boot.autoconfigure.SpringBootApplication;
  4. import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
  5. import org.springframework.cloud.client.loadbalancer.LoadBalanced;
  6. import org.springframework.cloud.netflix.hystrix.EnableHystrix;
  7. import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard;
  8. import org.springframework.context.annotation.Bean;
  9. import org.springframework.web.client.RestTemplate;
  10. @EnableHystrix
  11. @EnableDiscoveryClient
  12. @EnableHystrixDashboard
  13. @SpringBootApplication
  14. public class RibbonConsumerApplication {
  15. @LoadBalanced
  16. @Bean
  17. RestTemplate restTemplate() {
  18. return new RestTemplate();
  19. }
  20. public static void main(String[] args) {
  21. SpringApplication.run(RibbonConsumerApplication.class, args);
  22. }
  23. }

 

声明断路点

声明断路点 @HystrixCommand(fallbackMethod = "defaultStores")

 

  1. package io.ymq.example.ribbon.consumer.hystrix;
  2. import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
  3. import org.springframework.beans.factory.annotation.Autowired;
  4. import org.springframework.stereotype.Component;
  5. import org.springframework.web.bind.annotation.GetMapping;
  6. import org.springframework.web.bind.annotation.RestController;
  7. import org.springframework.web.client.RestTemplate;
  8. /**
  9. * 描述:调用提供者的 `home` 方法
  10. *
  11. * @author yanpenglei
  12. * @create 2017-12-05 18:53
  13. **/
  14. @RestController
  15. public class ConsumerController {
  16. @Autowired
  17. private RestTemplate restTemplate;
  18. @HystrixCommand(fallbackMethod = "defaultStores")
  19. @GetMapping(value = "/hello")
  20. public String hello() {
  21. return restTemplate.getForEntity("http://eureka-provider/", String.class).getBody();
  22. }
  23. public String defaultStores() {
  24. return "feign + hystrix Dashboard ,提供者服务挂了";
  25. }
  26. }

@HystrixCommand 表明该方法为hystrix包裹,可以对依赖服务进行隔离、降级、快速失败、快速重试等等hystrix相关功能 该注解属性较多,下面讲解其中几个

 

  • fallbackMethod 降级方法
  • commandProperties 普通配置属性,可以配置HystrixCommand对应属性,例如采用线程池还是信号量隔离、熔断器熔断规则等等
  • ignoreExceptions 忽略的异常,默认HystrixBadRequestException不计入失败
  • groupKey() 组名称,默认使用类名称
  • commandKey 命令名称,默认使用方法名

 

 

测试服务

 

依次启动项目:

spring-cloud-eureka-service
spring-cloud-eureka-provider-1
spring-cloud-eureka-provider-2
spring-cloud-eureka-provider-3
spring-cloud-ribbon-consumer-hystrix-dashboard

启动该工程后,访问服务注册中心,查看服务是否都已注册成功:http://localhost:8761/

查看各个服务注册状态

Hystrix Dashboard 监控

可以访问 http://127.0.0.1:9090/hystrix ,获取Hystrix Dashboard信息,默认最大打开5个终端获取监控信息,可以增加delay参数指定获取监控数据间隔时间

 

在界面依次输入:http://127.0.0.1:9000/hystrix.stream 、2000 、hello 点确定。可以访问以下,图形化监控页面

 

Spring Cloud(六)服务网关 zuul 快速入门

2019-04-17 13:59 更新

服务网关是微服务架构中一个不可或缺的部分。通过服务网关统一向外系统提供REST API的过程中,除了具备服务路由、均衡负载功能之外,它还具备了权限控制等功能。Spring Cloud Netflix中的Zuul就担任了这样的一个角色,为微服务架构提供了前门保护的作用,同时将权限控制这些较重的非业务逻辑内容迁移到服务路由层面,使得服务集群主体能够具备更高的可复用性和可测试性。

路由在微服务体系结构的一个组成部分。例如,/可以映射到您的Web应用程序,/api/users映射到用户服务,并将/api/shop映射到商店服务。ZuulNetflix的基于JVM的路由器和服务器端负载均衡器。

Netflix使用Zuul进行以下操作:

 

  • 认证
  • 洞察
  • 压力测试
  • 金丝雀测试
  • 动态路由
  • 服务迁移
  • 负载脱落
  • 安全
  • 静态响应处理
  • 主动/主动流量管理

Zuul的规则引擎允许基本上写任何JVM语言编写规则和过滤器,内置JavaGroovy

 

什么是服务网关

服务网关 = 路由转发 + 过滤器

1、路由转发:接收一切外界请求,转发到后端的微服务上去;

2、过滤器:在服务网关中可以完成一系列的横切功能,例如权限校验、限流以及监控等,这些都可以通过过滤器完成(其实路由转发也是通过过滤器实现的)。

 

为什么需要服务网关

上述所说的横切功能(以权限校验为例)可以写在三个位置:

 

  • 每个服务自己实现一遍
  • 写到一个公共的服务中,然后其他所有服务都依赖这个服务
  • 写到服务网关的前置过滤器中,所有请求过来进行权限校验

第一种,缺点太明显,基本不用; 第二种,相较于第一点好很多,代码开发不会冗余,但是有两个缺点:

 

  • 由于每个服务引入了这个公共服务,那么相当于在每个服务中都引入了相同的权限校验的代码,使得每个服务的jar包大小无故增加了一些,尤其是对于使用docker镜像进行部署的场景,jar越小越好;
  • 由于每个服务都引入了这个公共服务,那么我们后续升级这个服务可能就比较困难,而且公共服务的功能越多,升级就越难,而且假设我们改变了公共服务中的权限校验的方式,想让所有的服务都去使用新的权限校验方式,我们就需要将之前所有的服务都重新引包,编译部署。

     

    而服务网关恰好可以解决这样的问题:

 

  • 将权限校验的逻辑写在网关的过滤器中,后端服务不需要关注权限校验的代码,所以服务的jar包中也不会引入权限校验的逻辑,不会增加jar包大小;
  • 如果想修改权限校验的逻辑,只需要修改网关中的权限校验过滤器即可,而不需要升级所有已存在的微服务。

     

    所以,需要服务网关!!!

 

服务网关技术选型

服务网关

引入服务网关后的微服务架构如上,总体包含三部分:服务网关、open-service和service。

1、总体流程:

 

  • 服务网关、open-service和service启动时注册到注册中心上去;
  • 用户请求时直接请求网关,网关做智能路由转发(包括服务发现,负载均衡)到open-service,这其中包含权限校验、监控、限流等操作
  • open-service聚合内部service响应,返回给网关,网关再返回给用户

     

    2、引入网关的注意点

 

  • 增加了网关,多了一层转发(原本用户请求直接访问open-service即可),性能会下降一些(但是下降不大,通常,网关机器性能会很好,而且网关与open-service的访问通常是内网访问,速度很快);
  • 网关的单点问题:在整个网络调用过程中,一定会有一个单点,可能是网关、nginx、dns服务器等。防止网关单点,可以在网关层前边再挂一台nginx,nginx的性能极高,基本不会挂,这样之后,网关服务就可以不断的添加机器。但是这样一个请求就转发了两次,所以最好的方式是网关单点服务部署在一台牛逼的机器上(通过压测来估算机器的配置),而且nginx与zuul的性能比较,根据国外的一个哥们儿做的实验来看,其实相差不大,zuul是netflix开源的一个用来做网关的开源框架;
  • 网关要尽量轻。

     

    3、服务网关基本功能

 

  • 智能路由:接收外部一切请求,并转发到后端的对外服务open-service上去;
  • 注意:我们只转发外部请求,服务之间的请求不走网关,这就表示全链路追踪、内部服务API监控、内部服务之间调用的容错、智能路由不能在网关完成;当然,也可以将所有的服务调用都走网关,那么几乎所有的功能都可以集成到网关中,但是这样的话,网关的压力会很大,不堪重负。
  • 权限校验:只校验用户向open-service服务的请求,不校验服务内部的请求。服务内部的请求有必要校验吗?
  • API监控:只监控经过网关的请求,以及网关本身的一些性能指标(例如,gc等);
  • 限流:与监控配合,进行限流操作;
  • API日志统一收集:类似于一个aspect切面,记录接口的进入和出去时的相关日志
  • 。。。后续补充

     

    4、技术选型

笔者准备自建一个轻量级的服务网关,技术选型如下:

 

  • 开发语言:java + groovy,groovy的好处是网关服务不需要重启就可以动态的添加filter来实现一些功能;
  • 微服务基础框架:springboot;
  • 网关基础组件:netflix zuul;
  • 服务注册中心:consul;
  • 权限校验:jwt;
  • API监控:prometheus + grafana;
  • API统一日志收集:logback + ELK;
  • 压力测试:Jmeter;
  • 。。。后续补充
  • 在后续的介绍中,会逐渐介绍各个知识点,并完成一个轻量级的服务网关!!!

     

     

    Spring Cloud Zuul

 

简单使用

新建项目 spring-cloud-zuul-service

 

添加依赖

 

  1. <dependency>
  2. <groupId>org.springframework.cloud</groupId>
  3. <artifactId>spring-cloud-starter-zuul</artifactId>
  4. </dependency>

 

开启服务注册

在程序的启动类 ZuulApplication 通过 @EnableZuulProxy 开启 Zuul 服务网关

 

  1. package io.ymq.example.zuul;
  2. import org.springframework.boot.SpringApplication;
  3. import org.springframework.boot.autoconfigure.SpringBootApplication;
  4. import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
  5. @EnableZuulProxy
  6. @SpringBootApplication
  7. public class ZuulApplication {
  8. public static void main(String[] args) {
  9. SpringApplication.run(ZuulApplication.class, args);
  10. }
  11. }

 

添加配置

配置文件 application.yml

 

  1. spring:
  2. application:
  3. name: zuul-service
  4. server:
  5. port: 9000
  6. zuul:
  7. routes:
  8. blog:
  9. path: /ymq/**
  10. url: http://www.ymq.io/about

 

测试访问

配置说明:

浏览器访问:http://127.0.0.1:9000/ymq 重定向到我的博客

浏览器访问

 

服务转发

 

准备工作

我们先拿之前两篇文章,构建的两个微服务代码为基础,进行下面的操作

建议先阅读以下两篇文章

Spring Cloud(四) 服务提供者 Eureka + 服务消费者 Feign
Spring Cloud(三) 服务提供者 Eureka + 服务消费者(rest + Ribbon)

http://www.ymq.io/2017/12/06/spring-cloud-feign/

http://www.ymq.io/2017/12/05/spring-cloud-ribbon-rest/

 

Eureka Service

导入第三篇文章中的项目:作为服务注册中心

spring-cloud-eureka-service

 

Eureka Provider

导入第三篇文章中的项目:作为服务的提供者

spring-cloud-eureka-provider-1
spring-cloud-eureka-provider-2
spring-cloud-eureka-provider-3

 

 

添加依赖

项目继续改造,添加依赖

 

  1. <dependency>
  2. <groupId>org.springframework.cloud</groupId>
  3. <artifactId>spring-cloud-starter-eureka</artifactId>
  4. </dependency>

 

修改配置

配置文件 application.yml

 

  1. spring:
  2. application:
  3. name: zuul-service
  4. server:
  5. port: 9000
  6. #zuul:
  7. # routes:
  8. # blog:
  9. # path: /ymq/**
  10. # url: http://www.ymq.io/about
  11. eureka:
  12. client:
  13. serviceUrl:
  14. defaultZone: http://localhost:8761/eureka/
  15. zuul:
  16. routes:
  17. api:
  18. path: /**
  19. serviceId: eureka-provider

配置说明:

浏览器访问:http://127.0.0.1:9000/ ,Zuul 会去 Eureka 服务注册中心,找到eureka-provider服务以均衡负载的方式访问

 

 

测试服务

 

依次启动项目:

spring-cloud-eureka-service
spring-cloud-eureka-provider-1
spring-cloud-eureka-provider-2
spring-cloud-eureka-provider-3
spring-cloud-zuul-service

启动该工程后,访问服务注册中心,查看服务是否都已注册成功:http://localhost:8761/

Spring Cloud(七)服务网关 Zuul Filter 使用

2019-04-17 13:59 更新

上一篇文章中,讲了Zuul 转发,动态路由,负载均衡,等等一些Zuul 的特性,这个一篇文章,讲Zuul Filter 使用,关于网关的作用,这里就不再次赘述了,重点是zuul的Filter ,我们可以实现安全控制,比如,只有请求参数中有token和密码的客户端才能访问服务端的资源。那么如何来实现Filter了?

 

Spring Cloud Zuul

 

zuul 执行流程

执行流程图

Zuul大部分功能都是通过过滤器来实现的。Zuul中定义了四种标准过滤器类型,这些过滤器类型对应于请求的典型生命周期。

PRE:这种过滤器在请求被路由之前调用。我们可利用这种过滤器实现身份验证、在集群中选择请求的微服务、记录调试信息等。

ROUTING:这种过滤器将请求路由到微服务。这种过滤器用于构建发送给微服务的请求,并使用Apache HttpClient或Netfilx Ribbon请求微服务。

OST:这种过滤器在路由到微服务以后执行。这种过滤器可用来为响应添加标准的HTTP Header、收集统计信息和指标、将响应从微服务发送给客户端等。

ERROR:在其他阶段发生错误时执行该过滤器。

除了默认的过滤器类型,Zuul还允许我们创建自定义的过滤器类型。例如,我们可以定制一种STATIC类型的过滤器,直接在Zuul中生成响应,而不将请求转发到后端的微服务。

 

准备工作

我们先拿之前两篇文章,构建的两个微服务代码为基础,进行下面的操作

建议先阅读以下两篇文章

Spring Cloud(四) 服务提供者 Eureka + 服务消费者 Feign
Spring Cloud(三) 服务提供者 Eureka + 服务消费者(rest + Ribbon)

http://www.ymq.io/2017/12/06/spring-cloud-feign/

http://www.ymq.io/2017/12/05/spring-cloud-ribbon-rest/

 

Eureka Service

导入第三篇文章中的项目:作为服务注册中心

spring-cloud-eureka-service

 

Eureka Provider

导入第三篇文章中的项目:作为服务的提供者

spring-cloud-eureka-provider-1
spring-cloud-eureka-provider-2
spring-cloud-eureka-provider-3

 

 

简单使用

新建项目 spring-cloud-zuul-filter

 

添加依赖

 

  1. <dependency>
  2. <groupId>org.springframework.cloud</groupId>
  3. <artifactId>spring-cloud-starter-zuul</artifactId>
  4. </dependency>

 

开启服务注册

在程序的启动类 ZuulFilterApplication 通过 @EnableZuulProxy 开启 Zuul 服务网关

 

  1. package io.ymq.example.zuul.filter;
  2. import org.springframework.boot.SpringApplication;
  3. import org.springframework.boot.autoconfigure.SpringBootApplication;
  4. import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
  5. import org.springframework.context.annotation.Bean;
  6. @EnableZuulProxy
  7. @SpringBootApplication
  8. public class ZuulFilterApplication {
  9. public static void main(String[] args) {
  10. SpringApplication.run(ZuulFilterApplication.class, args);
  11. }
  12. }

 

添加配置

配置文件 application.yml

 

  1. spring:
  2. application:
  3. name: zuul-service-filter
  4. server:
  5. port: 9000
  6. zuul:
  7. routes:
  8. api:
  9. path: /**
  10. serviceId: eureka-provider
  11. eureka:
  12. client:
  13. serviceUrl:
  14. defaultZone: http://localhost:8761/eureka/

 

TokenFilter

ZuulFilter 是Zuul中核心组件,通过继承该抽象类,覆写几个关键方法达到自定义调度请求的作用

TokenFilter 过滤器

 

  1. package io.ymq.example.zuul.filter;
  2. import com.netflix.zuul.ZuulFilter;
  3. import com.netflix.zuul.context.RequestContext;
  4. import org.apache.commons.lang.StringUtils;
  5. import org.slf4j.Logger;
  6. import org.slf4j.LoggerFactory;
  7. import javax.servlet.http.HttpServletRequest;
  8. /**
  9. * 描述: 过滤器 token
  10. *
  11. * @author yanpenglei
  12. * @create 2017-12-11 14:38
  13. **/
  14. public class TokenFilter extends ZuulFilter {
  15. private final Logger LOGGER = LoggerFactory.getLogger(TokenFilter.class);
  16. @Override
  17. public String filterType() {
  18. return "pre"; // 可以在请求被路由之前调用
  19. }
  20. @Override
  21. public int filterOrder() {
  22. return 0; // filter执行顺序,通过数字指定 ,优先级为0,数字越大,优先级越低
  23. }
  24. @Override
  25. public boolean shouldFilter() {
  26. return true;// 是否执行该过滤器,此处为true,说明需要过滤
  27. }
  28. @Override
  29. public Object run() {
  30. RequestContext ctx = RequestContext.getCurrentContext();
  31. HttpServletRequest request = ctx.getRequest();
  32. LOGGER.info("--->>> TokenFilter {},{}", request.getMethod(), request.getRequestURL().toString());
  33. String token = request.getParameter("token");// 获取请求的参数
  34. if (StringUtils.isNotBlank(token)) {
  35. ctx.setSendZuulResponse(true); //对请求进行路由
  36. ctx.setResponseStatusCode(200);
  37. ctx.set("isSuccess", true);
  38. return null;
  39. } else {
  40. ctx.setSendZuulResponse(false); //不对其进行路由
  41. ctx.setResponseStatusCode(400);
  42. ctx.setResponseBody("token is empty");
  43. ctx.set("isSuccess", false);
  44. return null;
  45. }
  46. }
  47. }

 

PasswordFilter

ZuulFilter 是Zuul中核心组件,通过继承该抽象类,覆写几个关键方法达到自定义调度请求的作用

PasswordFilter 过滤器

 

 

  1. package io.ymq.example.zuul.filter;
  2. import com.netflix.zuul.ZuulFilter;
  3. import com.netflix.zuul.context.RequestContext;
  4. import org.slf4j.Logger;
  5. import org.slf4j.LoggerFactory;
  6. import javax.servlet.http.HttpServletRequest;
  7. /**
  8. * 描述: 过滤器 Password
  9. *
  10. * @author yanpenglei
  11. * @create 2017-12-11 15:40
  12. **/
  13. public class PasswordFilter extends ZuulFilter {
  14. private final Logger LOGGER = LoggerFactory.getLogger(TokenFilter.class);
  15. @Override
  16. public String filterType() {
  17. return "post"; // 请求处理完成后执行的filter
  18. }
  19. @Override
  20. public int filterOrder() {
  21. return 1; // 优先级为0,数字越大,优先级越低
  22. }
  23. @Override
  24. public boolean shouldFilter() {
  25. RequestContext ctx = RequestContext.getCurrentContext();
  26. return (boolean) ctx.get("isSuccess");
  27. // 判断上一个过滤器结果为true,否则就不走下面过滤器,直接跳过后面的所有过滤器并返回 上一个过滤器不通过的结果。
  28. }
  29. @Override
  30. public Object run() {
  31. RequestContext ctx = RequestContext.getCurrentContext();
  32. HttpServletRequest request = ctx.getRequest();
  33. LOGGER.info("--->>> PasswordFilter {},{}", request.getMethod(), request.getRequestURL().toString());
  34. String username = request.getParameter("password");
  35. if (null != username && username.equals("123456")) {
  36. ctx.setSendZuulResponse(true);
  37. ctx.setResponseStatusCode(200);
  38. ctx.set("isSuccess", true);
  39. return null;
  40. } else {
  41. ctx.setSendZuulResponse(false);
  42. ctx.setResponseStatusCode(400);
  43. ctx.setResponseBody("The password cannot be empty");
  44. ctx.set("isSuccess", false);
  45. return null;
  46. }
  47. }
  48. }

 

开启过滤器

在程序的启动类 ZuulFilterApplication 添加 Bean

 

  1. @Bean
  2. public TokenFilter tokenFilter() {
  3. return new TokenFilter();
  4. }
  5. @Bean
  6. public PasswordFilter PasswordFilter() {
  7. return new PasswordFilter();
  8. }

 

filterType

filterType:返回一个字符串代表过滤器的类型,在zuul中定义了四种不同生命周期的过滤器类型,具体如下:

 

  • pre:路由之前
  • routing:路由之时
  • post: 路由之后
  • error:发送错误调用
  • filterOrder:过滤的顺序
  • shouldFilter:这里可以写逻辑判断,是否要过滤,本文true,永远过滤。
  • run:过滤器的具体逻辑。可用很复杂,包括查sql,nosql去判断该请求到底有没有权限访问。

 

测试服务

 

依次启动项目:

spring-cloud-eureka-service
spring-cloud-eureka-provider-1
spring-cloud-eureka-provider-2
spring-cloud-eureka-provider-3
spring-cloud-zuul-filter

启动该工程后,访问服务注册中心,查看服务是否都已注册成功:http://localhost:8761/

查看各个服务注册状态

查看 eureka 监控,看服务是否都注册成功

 

token 测试

访问:http://127.0.0.1:8761/

 

 

步骤一 提示 token is empty

访问:http://127.0.0.1:9000/

浏览器访问

步骤二 加上token ?token=token-uuid ,已经验证通过了,提示 The password cannot be empty

访问:http://127.0.0.1:9000/?token=token-uuid

token is empty

 

password 测试

![The password cannot be empty][3]

加上token 和 password &password=123456 ,已经验证通过

访问:http://127.0.0.1:9000/?token=token-uuid&password=123456

 

Spring Cloud(八)高可用的分布式配置中心 Spring Cloud Config

2019-04-17 14:01 更新

在分布式系统中,由于服务数量巨多,为了方便服务配置文件统一管理,实时更新,所以需要分布式配置中心组件。在Spring Cloud中,有分布式配置中心组件spring cloud config,它支持配置服务放在配置服务的内存中(即本地),也支持放在远程Git仓库中。在spring cloud config 组件中,分两个角色,一是config server,二是config client,业界也有些知名的同类开源产品,比如百度的disconf

相比较同类产品,SpringCloudConfig最大的优势是和Spring无缝集成,支持Spring里面EnvironmentPropertySource的接口,对于已有的Spring应用程序的迁移成本非常低,在配置获取的接口上是完全一致,结合SpringBoot可使你的项目有更加统一的标准(包括依赖版本和约束规范),避免了应为集成不同开软件源造成的依赖版本冲突。

 

Spring Cloud Config 简介

SpringCloudConfig就是我们通常意义上的配置中心,把应用原本放在本地文件的配置抽取出来放在中心服务器,从而能够提供更好的管理、发布能力。SpringCloudConfig分服务端和客户端,服务端负责将git svn中存储的配置文件发布成REST接口,客户端可以从服务端REST接口获取配置。但客户端并不能主动感知到配置的变化,从而主动去获取新的配置,这需要每个客户端通过POST方法触发各自的/refresh

SpringCloudBus通过一个轻量级消息代理连接分布式系统的节点。这可以用于广播状态更改(如配置更改)或其他管理指令。SpringCloudBus提供了通过POST方法访问的endpoint/bus/refresh,这个接口通常由git的钩子功能调用,用以通知各个SpringCloudConfig的客户端去服务端更新配置。

注意:这是工作的流程图,实际的部署中SpringCloudBus并不是一个独立存在的服务,这里单列出来是为了能清晰的显示出工作流程。

下图是SpringCloudConfig结合SpringCloudBus实现分布式配置的工作流

SpringCloudConfig结合SpringCloudBus实现分布式配置的工作流

 

服务端配置

 

Config Server

新建项目 spring-cloud-config-server

 

添加依赖

 

  1. <dependency>
  2. <groupId>org.springframework.cloud</groupId>
  3. <artifactId>spring-cloud-config-server</artifactId>
  4. </dependency>

 

开启服务注册

在程序的启动类 ConfigServerApplication 通过 @EnableConfigServer 开启 SpringCloudConfig 服务端

 

  1. package io.ymq.example.config.server;
  2. import org.springframework.boot.SpringApplication;
  3. import org.springframework.boot.autoconfigure.SpringBootApplication;
  4. import org.springframework.cloud.config.server.EnableConfigServer;
  5. @EnableConfigServer
  6. @SpringBootApplication
  7. public class ConfigServerApplication {
  8. public static void main(String[] args) {
  9. SpringApplication.run(ConfigServerApplication.class, args);
  10. }
  11. }

 

添加配置

配置文件 application.properties

 

  1. spring.application.name=config-server
  2. server.port=8888
  3. spring.cloud.config.label=master
  4. spring.cloud.config.server.git.uri=https://github.com/souyunku/spring-cloud-config.git
  5. spring.cloud.config.server.git.search-paths=spring-cloud-config
  6. #spring.cloud.config.server.git.username=your username
  7. #spring.cloud.config.server.git.password=your password

 

  • spring.cloud.config.server.git.uri:配置git仓库地址
  • spring.cloud.config.server.git.searchPaths:配置仓库路径
  • spring.cloud.config.label:配置仓库的分支
  • spring.cloud.config.server.git.username:访问git仓库的用户名
  • spring.cloud.config.server.git.password:访问git仓库的用户密码

Git仓库如果是私有仓库需要填写用户名密码,示例是公开仓库,所以不配置密码。

远程Git仓库

spring-cloud-config 文件夹下有 application-dev.properties,application-test.properties 三个文件,内容依次是:content=hello dev,content=hello test,content=hello pre

远程Git仓库

 

测试服务

启动程序 ConfigApplication 类

访问 Spring Cloud Config Server服务:

http://localhost:8888/springCloudConfig/dev/master

 

  1. {
  2. "name": "springCloudConfig",
  3. "profiles": [
  4. "dev"
  5. ],
  6. "label": "master",
  7. "version": "b6fbc2f77d1ead41d5668450e2601a03195eaf16",
  8. "state": null,
  9. "propertySources": [
  10. {
  11. "name": "https://github.com/souyunku/spring-cloud-config.git/application-dev.properties",
  12. "source": {
  13. "content": "hello dev"
  14. }
  15. }
  16. ]
  17. }

证明配置服务中心可以从远程程序获取配置信息。

http请求地址和资源文件映射如下:

 

 

  • /{application}/{profile}[/{label}]
  • /{application}-{profile}.yml
  • /{label}/{application}-{profile}.yml
  • /{application}-{profile}.properties
  • /{label}/{application}-{profile}.properties

 

 

客户端配置

 

Config Client

新建项目 spring-cloud-config-client

 

添加依赖

 

  1. <dependency>
  2. <groupId>org.springframework.cloud</groupId>
  3. <artifactId>spring-cloud-config-client</artifactId>
  4. </dependency>
  5. <dependency>
  6. <groupId>org.springframework.boot</groupId>
  7. <artifactId>spring-boot-starter-web</artifactId>
  8. </dependency>

 

开启服务注册

在程序的启动类 ConfigClientApplication 通过 @Value 获取服务端的 content 值的内容

 

  1. package io.ymq.example.config.client;
  2. @RestController
  3. @SpringBootApplication
  4. public class ConfigClientApplication {
  5. @Value("${content}")
  6. String content;
  7. @RequestMapping("/")
  8. public String home() {
  9. return "content:" + content;
  10. }
  11. public static void main(String[] args) {
  12. SpringApplication.run(ConfigClientApplication.class, args);
  13. }
  14. }

 

添加配置

配置文件 application.properties

 

  1. spring.application.name=config-client
  2. server.port=8088
  3. spring.cloud.config.label=master
  4. spring.cloud.config.profile=dev
  5. spring.cloud.config.uri=http://localhost:8888/
  • spring.cloud.config.label 指明远程仓库的分支
  • spring.cloud.config.profile
  • dev开发环境配置文件
  • test测试环境
  • pro正式环境
  • spring.cloud.config.uri= http://localhost:8888/ 指明配置服务中心的网址。

 

测试服务

启动程序 ConfigClientApplication 类

访问服务:http://localhost:8088/

 

Spring Cloud(九)高可用的分布式配置中心 Spring Cloud Config 集成 Eureka 服务

2019-04-17 13:58 更新

上一篇文章,讲了SpringCloudConfig 集成Git仓库,这一篇我们讲一下SpringCloudConfig 配和 Eureka 注册中心一起使用

在分布式系统中,由于服务数量巨多,为了方便服务配置文件统一管理,实时更新,所以需要分布式配置中心组件。在Spring Cloud中,有分布式配置中心组件spring cloud config ,它支持配置服务放在配置服务的内存中(即本地),也支持放在远程Git仓库中。在spring cloud config 组件中,分两个角色,一是config server,二是config client,业界也有些知名的同类开源产品,比如百度的disconf

相比较同类产品,SpringCloudConfig最大的优势是和Spring无缝集成,支持Spring里面Environment和PropertySource的接口,对于已有的pring应用程序的迁移成本非常低,在配置获取的接口上是完全一致,结合SpringBoot可使你的项目有更加统一的标准(包括依赖版本和约束规范),避免了应为集成不同开软件源造成的依赖版本冲突。

 

准备工作

我们先拿之前的代码为基础,进行下面的操作

Spring Cloud(四) 服务提供者 Eureka + 服务消费者 Feign

http://www.ymq.io/2017/12/06/spring-cloud-feign/

 

Eureka Service

导入第四篇文章中的项目:作为服务注册中心

spring-cloud-eureka-service

 

Eureka Provider

导入第四篇文章中的项目:作为服务的提供者

spring-cloud-eureka-provider-1
spring-cloud-eureka-provider-2
spring-cloud-eureka-provider-3

 

 

Eureka Consumer

导入第四篇文章中的项目:作为服务的消费者

spring-cloud-feign-consumer

 

服务端配置

 

Config Server

复制上一篇的项目 spring-cloud-config-server,添加 eureka依赖

https://github.com/souyunku/spring-cloud-examples/tree/master/spring-cloud-config/

 

添加依赖

 

  1. <dependency>
  2. <groupId>org.springframework.cloud</groupId>
  3. <artifactId>spring-cloud-starter-eureka</artifactId>
  4. </dependency>

 

开启服务注册

在程序的启动类 ConfigServerApplication.java 通过 @EnableEurekaClient 开启 Eureka 提供者服务

 

  1. package io.ymq.example.config.server;
  2. import org.springframework.boot.SpringApplication;
  3. import org.springframework.boot.autoconfigure.SpringBootApplication;
  4. import org.springframework.cloud.config.server.EnableConfigServer;
  5. import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
  6. @EnableConfigServer
  7. @EnableEurekaClient
  8. @SpringBootApplication
  9. public class ConfigServerApplication {
  10. public static void main(String[] args) {
  11. SpringApplication.run(ConfigServerApplication.class, args);
  12. }
  13. }

 

修改配置

修改配置文件 application.properties ,添加 eureka 注册中心地址 http://localhost:8761/eureka/

 

  1. spring.application.name=config-server
  2. server.port=8888
  3. spring.cloud.config.label=master
  4. spring.cloud.config.server.git.uri=https://github.com/souyunku/spring-cloud-config.git
  5. spring.cloud.config.server.git.search-paths=spring-cloud-config
  6. #spring.cloud.config.server.git.username=your username
  7. #spring.cloud.config.server.git.password=your password
  8. eureka.client.serviceUrl.defaultZone=http://localhost:8761/eureka/

 

  • spring.cloud.config.server.git.uri:配置git仓库地址
  • spring.cloud.config.server.git.searchPaths:配置仓库路径
  • spring.cloud.config.label:配置仓库的分支
  • spring.cloud.config.server.git.username:访问git仓库的用户名
  • spring.cloud.config.server.git.password:访问git仓库的用户密码

     

     

  • eureka.client.serviceUrl.defaultZone:eureka注册中心地址

Git仓库如果是私有仓库需要填写用户名密码,示例是公开仓库,所以不配置密码。

 

远程Git仓库

spring-cloud-config 文件夹下有 application-dev.properties,application-test.properties 三个文件,内容依次是:content=hello dev,content=hello test,content=hello pre

远程Git仓库

 

 

测试服务

启动程序 ConfigServerApplication 类

访问 Config Server 服务:http://localhost:8888/springCloudConfig/dev/master

 

  1. {
  2. "name": "springCloudConfig",
  3. "profiles": [
  4. "dev"
  5. ],
  6. "label": "master",
  7. "version": "b6fbc2f77d1ead41d5668450e2601a03195eaf16",
  8. "state": null,
  9. "propertySources": [
  10. {
  11. "name": "https://github.com/souyunku/spring-cloud-config.git/application-dev.properties",
  12. "source": {
  13. "content": "hello dev"
  14. }
  15. }
  16. ]
  17. }

证明配置服务中心可以从远程程序获取配置信息。

http请求地址和资源文件映射如下:

 

  • /{application}/{profile}[/{label}]
  • /{application}-{profile}.yml
  • /{label}/{application}-{profile}.yml
  • /{application}-{profile}.properties
  • /{label}/{application}-{profile}.properties

 

 

客户端端配置

 

config Client Eureka

修改已经导入的,第四篇文章中的项目:配置客户端的一些配置

spring-cloud-eureka-provider-1
spring-cloud-eureka-provider-2
spring-cloud-eureka-provider-3

 

添加依赖

 

  1. <dependency>
  2. <groupId>org.springframework.cloud</groupId>
  3. <artifactId>spring-cloud-config-client</artifactId>
  4. </dependency>

 

开启服务注册

在程序的启动类 EurekaProviderApplication ,通过 @Value 获取服务端的 content 值的内容

 

  1. package io.ymq.example.eureka.provider;
  2. import org.springframework.beans.factory.annotation.Value;
  3. import org.springframework.boot.SpringApplication;
  4. import org.springframework.boot.autoconfigure.SpringBootApplication;
  5. import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
  6. import org.springframework.web.bind.annotation.RequestMapping;
  7. import org.springframework.web.bind.annotation.RestController;
  8. @SpringBootApplication
  9. @EnableEurekaClient
  10. @RestController
  11. public class EurekaProviderApplication {
  12. @Value("${content}")
  13. String content;
  14. @Value("${server.port}")
  15. String port;
  16. @RequestMapping("/")
  17. public String home() {
  18. return "Hello world ,port:" + port+",content="+content;
  19. }
  20. public static void main(String[] args) {
  21. SpringApplication.run(EurekaProviderApplication.class, args);
  22. }
  23. }

 

添加配置

修改配置文件 application.properties 添加 Eureka 注册中心,配置从springCloudConfig 配置中心读取配置,指定springCloudConfigService 服务名称

 

  1. spring.application.name=eureka-provider
  2. server.port=8081
  3. spring.cloud.config.label=master
  4. spring.cloud.config.profile=dev
  5. #spring.cloud.config.uri=http://localhost:8888/
  6. eureka.client.serviceUrl.defaultZone=http://localhost:8761/eureka/
  7. spring.cloud.config.discovery.enabled=true
  8. spring.cloud.config.discovery.serviceId=config-server

 

  • spring.cloud.config.label 指明远程仓库的分支
  • spring.cloud.config.profile
  • dev开发环境配置文件
  • test测试环境
  • pro正式环境
  • #spring.cloud.config.uri= http://localhost:8888/ 指明配置服务中心的网址(注释掉)

     

     

  • spring.cloud.config.discovery.enabled=true 是从配置中心读取文件。
  • spring.cloud.config.discovery.serviceId=config-server 配置中心的servieId,服务名称,通过服务名称去 Eureka注册中心找服务

     

     

    测试服务

依次启动项目:

spring-cloud-eureka-service
spring-cloud-config-server
spring-cloud-eureka-provider-1
spring-cloud-eureka-provider-2
spring-cloud-eureka-provider-3
spring-cloud-feign-consumer

启动该工程后,访问服务注册中心,查看服务是否都已注册成功:http://localhost:8761/

查看各个服务注册状态

查看 eureka 监控,看服务是否都注册成功

命令窗口,通过curl http://127.0.0.1:9000/hello 访问服务,或者在浏览器访问http://127.0.0.1:9000/hello F5 刷新

 

Spring Cloud(十)高可用的分布式配置中心 Spring Cloud Config 中使用 Refresh

2019-04-17 14:01 更新

上一篇文章讲了SpringCloudConfig 集成Git仓库,配和 Eureka 注册中心一起使用,但是我们会发现,修改了Git仓库的配置后,需要重启服务,才可以得到最新的配置,这一篇我们尝试使用 Refresh 实现主动获取 Config Server 配置服务中心的最新配置

 

准备工作

把上一篇,示例代码下载,才可以进行一下的操作,下载地址在文章末尾

 

  • spring-cloud-eureka-service
  • spring-cloud-config-server
  • spring-cloud-eureka-provider-1
  • spring-cloud-eureka-provider-2
  • spring-cloud-eureka-provider-3
  • spring-cloud-feign-consumer

 

Config Client

修改第九篇文章项目

 

  • spring-cloud-eureka-provider-1
  • spring-cloud-eureka-provider-2
  • spring-cloud-eureka-provider-3

     

     

    添加依赖

 

  1. <!-- actuator 监控 -->
  2. <dependency>
  3. <groupId>org.springframework.boot</groupId>
  4. <artifactId>spring-boot-starter-actuator</artifactId>
  5. </dependency>

 

安全认证

在 application.properties 添加以下配置.关闭安全认证

 

  1. #关闭刷新安全认证
  2. management.security.enabled=false

值是false的话,除开health接口还依赖endpoints.health.sensitive的配置外,其他接口都不需要输入用户名和密码了

 

开启 refresh

在程序的启动类 EurekaProviderApplication 通过 @RefreshScope 开启 SpringCloudConfig 客户端的 refresh 刷新范围,来获取服务端的最新配置,@RefreshScope要加在声明@Controller声明的类上,否则refresh之后Conroller拿不到最新的值,会默认调用缓存。

 

  1. package io.ymq.example.eureka.provider;
  2. import org.springframework.beans.factory.annotation.Value;
  3. import org.springframework.boot.SpringApplication;
  4. import org.springframework.boot.autoconfigure.SpringBootApplication;
  5. import org.springframework.cloud.context.config.annotation.RefreshScope;
  6. import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
  7. import org.springframework.web.bind.annotation.RequestMapping;
  8. import org.springframework.web.bind.annotation.RestController;
  9. @RefreshScope
  10. @RestController
  11. @EnableEurekaClient
  12. @SpringBootApplication
  13. public class EurekaProviderApplication {
  14. @Value("${content}")
  15. String content;
  16. @Value("${server.port}")
  17. String port;
  18. @RequestMapping("/")
  19. public String home() {
  20. return "Hello world ,port:" + port+",content="+content;
  21. }
  22. public static void main(String[] args) {
  23. SpringApplication.run(EurekaProviderApplication.class, args);
  24. }
  25. }

 

测试服务

按照顺序依次启动项目

 

  • spring-cloud-eureka-service
  • spring-cloud-config-server
  • spring-cloud-eureka-provider-1
  • spring-cloud-eureka-provider-2
  • spring-cloud-eureka-provider-3
  • spring-cloud-feign-consumer

启动该工程后,访问服务注册中心,查看服务是否都已注册成功:http://localhost:8761/

查看服务注册情况

 

 

 

修改Git仓库

修改Git仓库配置,在 content=hello dev 后面加个 123456

修改Git仓库

 

访问服务

命令窗口,通过curl http://127.0.0.1:9000/hello 访问服务,或者在浏览器访问http://127.0.0.1:9000/hello F5 刷新

发现没有得到最新的值

访问服务

 

刷新配置

通过 Postman 发送 POST请求到:http://localhost:8081/refreshhttp://localhost:8083/refresh,我们可以看到以下内容:

刷新配置

 

访问服务

命令窗口,通过curl http://127.0.0.1:9000/hello 访问服务,或者在浏览器访问http://127.0.0.1:9000/hello F5 刷新

发现:服务8082 没有刷新到最新配置 因为没有手动触发更新

 

 

Spring Cloud(十一)高可用的分布式配置中心 Spring Cloud Bus 消息总线集成(RabbitMQ)

2019-04-17 14:01 更新

上一篇文章,留了一个悬念,Config Client 实现配置的实时更新,我们可以使用 /refresh 接口触发,如果所有客户端的配置的更改,都需要手动触发客户端 /refresh ,当服务越来越多的时候,那岂不是维护成本很高,显然不太合适,而使用Spring Cloud Bus 消息总线实现方案,可以优雅的解决以上问题,那就是通过消息代理中间件RabbitMQ 加 GitWebhooks來触发配置的更新,那具体是怎么实现的,我会通过图文形式介绍。

 

Spring Cloud Bus

Spring Cloud Bus 将分布式系统的节点通过轻量级消息代理连接起来。用于在集群中传播状态更改(例如配置更改事件)或其他管理指令。Spring Cloud Bus 的一个核心思想是通过分布式的启动器对 Spring Boot 应用进行扩展,也可以用来建立一个或多个应用之间的通信频道。目前唯一实现的方式是用 AMQP 消息代理作为通道,但是相同的基本功能集(还有一些取决于传输)在其他传输的路线图上

 

消息总线

消息总线是一种通信工具,可以在机器之间互相传输消息、文件等。消息总线扮演着一种消息路由的角色,拥有一套完备的路由机制来决定消息传输方向。发送段只需要向消息总线发出消息而不用管消息被如何转发。 Spring cloud bus 通过轻量消息代理连接各个分布的节点。管理和传播所有分布式项目中的消息,本质是利用了MQ的广播机制在分布式的系统中传播消息,目前常用的有KafkaRabbitMQ 。 下面是一个配置中心刷新配置的例子

架构图

[图片来源于网络如有侵权请私信删除]

 

  • 1、提交代码触发post请求给bus/refresh
  • 2、server端接收到请求并发送给Spring Cloud Bus
  • 3、Spring Cloud bus接到消息并通知给其它客户端
  • 4、其它客户端接收到通知,请求Server端获取最新配置
  • 5、全部客户端均获取到最新的配置

 

消息代理

消息代理(Message Broker)是一种消息验证、传输、路由的架构模式。消息代理是一个中间件产品,它的核心是一个消息的路由程序,用来实现接收和分发消息,并根据设定好的消息处理流来转发给正确的应用。它包括独立的通信和消息传递协议,能够实现组织内部和组织间的网络通信。设计代理的目的就是为了能够从应用程序中传入消息,并执行一些特别的操作。

和组织间的网络通信。设计代理的目的就是为了能够从应用程序中传入消息,并执行一些特别的操作。 现有的消息代理开源产品:

  • ActiveMQ
  • Kafka
  • RabbitMQ
  • RocketMQ

目前Spring Cloud Bus 支持 RabbitMQ 和 Kafka,spring-cloud-starter-bus-amqp 、spring-cloud-starter-bus-kafka

 

RabbitMQ简介

RabbitMQ是一个开源的AMQP实现,服务器端用Erlang语言编写,支持多种客户端,如:Python、Ruby、.NET、Java、JMS、C、PHP、ActionScript、XMPP、STOMP等,支持AJAX。用于在分布式系统中存储转发消息,在易用性、扩展性、高可用性等方面表现不俗。

AMQP,即Advanced message Queuing Protocol,高级消息队列协议,是应用层协议的一个开放标准,为面向消息的中间件设计。消息中间件主要用于组件之间的解耦,消息的发送者无需知道消息使用者的存在,反之亦然。

AMQP的主要特征是面向消息、队列、路由(包括点对点和发布/订阅)、可靠性、安全。

Github:https://github.com/rabbitmq
官网地址:http://www.rabbitmq.com

 

 

安装RabbitMQ

安装RabbitMQ 可以参考之前的文章

CentOs7.3 搭建 RabbitMQ 3.6 单机服务:
https://segmentfault.com/a/1190000010693696

CentOs7.3 搭建 RabbitMQ 3.6 Cluster 集群服务:
https://segmentfault.com/a/1190000010702020

Spring Boot 中使用 RabbitMQ: https://segmentfault.com/a/1190000011577243

 

准备工作

以下项目修改不做过多解释,部分代码不再展示,请阅读上篇文章,Spring Cloud(十)高可用的分布式配置中心 Spring Cloud Config 中使用 Refresh:http://www.ymq.io/2017/12/23/spring-cloud-config-eureka-refresh/

把上一篇,示例代码下载,才可以进行一下的操作,下载地址在文章末尾

 

  • spring-cloud-eureka-service
  • spring-cloud-config-server
  • spring-cloud-eureka-provider-1
  • spring-cloud-eureka-provider-2
  • spring-cloud-eureka-provider-3
  • spring-cloud-feign-consumer

     

     

    Config Server

在项目spring-cloud-config-server 进行以下操作

 

添加依赖

 

  1. <dependency>
  2. <groupId>org.springframework.cloud</groupId>
  3. <artifactId>spring-cloud-starter-bus-amqp</artifactId>
  4. </dependency>

 

添加配置

在 application.properties 添加以下配置.关闭安全认证

RabbitMQ 的 ymq用户是手动创建的,具体阅读上面 安装RabbitMQ 部分

 

  1. #关闭刷新安全认证
  2. management.security.enabled=false
  3. spring.rabbitmq.host=192.168.252.126
  4. spring.rabbitmq.port=5672
  5. spring.rabbitmq.username=ymq
  6. spring.rabbitmq.password=123456

 

Config Client

修改第上一篇文章项目

 

  • spring-cloud-eureka-provider-1
  • spring-cloud-eureka-provider-2
  • spring-cloud-eureka-provider-3

     

     

    添加依赖

 

  1. <dependency>
  2. <groupId>org.springframework.cloud</groupId>
  3. <artifactId>spring-cloud-starter-bus-amqp</artifactId>
  4. </dependency>

 

添加配置

在 application.properties 添加以下配置.关闭安全认证

 

  1. spring.rabbitmq.host=192.168.252.126
  2. spring.rabbitmq.port=5672
  3. spring.rabbitmq.username=ymq
  4. spring.rabbitmq.password=123456

 

测试服务

 

启动RabbitMQ

启动MQ服务

 

  1. $ service rabbitmq-server start
  2. Redirecting to /bin/systemctl start rabbitmq-server.service

查看MQ状态

 

  1. $ service rabbitmq-server status

 

  1. [root@node6 rabbitmq]# service rabbitmq-server status
  2. Redirecting to /bin/systemctl status rabbitmq-server.service
  3. ● rabbitmq-server.service - RabbitMQ broker
  4. Loaded: loaded (/usr/lib/systemd/system/rabbitmq-server.service; disabled; vendor preset: disabled)
  5. Active: active (running) since Fri 2017-12-29 17:44:10 CST; 9min ago
  6. Process: 2814 ExecStop=/usr/sbin/rabbitmqctl stop (code=exited, status=0/SUCCESS)
  7. Main PID: 2948 (beam)
  8. Status: "Initialized"
  9. CGroup: /system.slice/rabbitmq-server.service
  10. ├─2948 /usr/lib64/erlang/erts-8.0.3/bin/beam -W w -A 64 -P 1048576 -t 5000000 -stbt db -zdbbl 32000 -K true -- -root /usr/lib64/erlang -progname erl -- -home /var/lib/rabbitmq -- -pa /usr...
  11. ├─3131 /usr/lib64/erlang/erts-8.0.3/bin/epmd -daemon
  12. ├─3233 erl_child_setup 1024
  13. ├─3240 inet_gethost 4
  14. └─3241 inet_gethost 4
  15. Dec 29 17:44:08 node6 rabbitmq-server[2948]: RabbitMQ 3.6.10. Copyright (C) 2007-2017 Pivotal Software, Inc.
  16. Dec 29 17:44:08 node6 rabbitmq-server[2948]: ## ## Licensed under the MPL. See http://www.rabbitmq.com/
  17. Dec 29 17:44:08 node6 rabbitmq-server[2948]: ## ##
  18. Dec 29 17:44:08 node6 rabbitmq-server[2948]: ########## Logs: /var/log/rabbitmq/rabbit@node6.log
  19. Dec 29 17:44:08 node6 rabbitmq-server[2948]: ###### ## /var/log/rabbitmq/rabbit@node6-sasl.log
  20. Dec 29 17:44:08 node6 rabbitmq-server[2948]: ##########
  21. Dec 29 17:44:08 node6 rabbitmq-server[2948]: Starting broker...
  22. Dec 29 17:44:10 node6 rabbitmq-server[2948]: systemd unit for activation check: "rabbitmq-server.service"
  23. Dec 29 17:44:10 node6 systemd[1]: Started RabbitMQ broker.
  24. Dec 29 17:44:10 node6 rabbitmq-server[2948]: completed with 6 plugins.
  25. [root@node6 rabbitmq]#

 

启动项目

按照顺序依次启动项目

 

  • spring-cloud-eureka-service
  • spring-cloud-config-server
  • spring-cloud-eureka-provider-1
  • spring-cloud-eureka-provider-2
  • spring-cloud-eureka-provider-3
  • spring-cloud-feign-consumer

启动该工程后,访问服务注册中心,查看服务是否都已注册成功:http://127.0.0.1:8761/

查看服务注册情况

 

Exchanges

检查 springCloudBus

任何发送到Fanout Exchange 的消息都会被转发到与该Exchange绑定(Binding)的所有springCloudBus 队列Queue上。

 

检查Queues

浏览器打开 :http://192.168.252.128:15672/

检查 springCloudBus

 

修改配置

修改Git仓库配置,在 content=hello dev 后面加上 Spring Cloud Bus Test

修改git 仓库配置

 

查看 Config Server

通过 Postman 发送 GET 请求到:http://localhost:8888/springCloudConfig/dev/master 查看 Config Server 是否是最新的值

Config Server 已经是新的值

 

查看 Config Client

命令窗口,通过curl http://127.0.0.1:9000/hello 访问服务,或者在浏览器访问http://127.0.0.1:9000/hello F5 刷新

发现没有得到最新的值

因为我们没有主动触发Config Server bus/refresh接口

访问服务

 

刷新配置

通过 Postman 发送 POST请求到:http://localhost:8888/bus/refresh ,我们可以看到以下内容:

注意是 PSOT 请求

访问:http://localhost:8888/bus/refresh

 

三个Config Client 客户端控制台,分别会打印以下内容意思就是,收到远程更新请求,config.client,KEYS 刷新, key 是 content

 

  1. 2017-12-29 18:38:49.023 INFO 28944 --- [jeTgrKRGzgj9g-1] o.s.cloud.bus.event.RefreshListener : Received remote refresh request. Keys refreshed [config.client.version, content]
  2. 2017-12-29 18:38:49.025 INFO 28944 --- [nfoReplicator-0] com.netflix.discovery.DiscoveryClient : DiscoveryClient_EUREKA-PROVIDER/localhost:eureka-provider:8081: registering service...
  3. 2017-12-29 18:38:49.035 INFO 28944 --- [nfoReplicator-0] com.netflix.discovery.DiscoveryClient : DiscoveryClient_EUREKA-PROVIDER/localhost:eureka-provider:8081 - registration status: 204
  4. 2017-12-29 18:38:49.067 INFO 28944 --- [jeTgrKRGzgj9g-1] o.s.a.r.c.CachingConnectionFactory : Created new connection: SpringAMQP#31e87320:0/SimpleConnection@39151d4e [delegate=amqp://ymq@192.168.252.126:5672/, localPort= 64885]

 

再次查看 Config Client

访问:http://localhost:8081/ ,http://localhost:8082/ ,http://localhost:8083/ 已经刷新了配置

访问服务

 

扩展阅读

 

Git webhooks

现在虽然可以不用重启服务就更新配置了,但还是需要我们手动操作,这样还是不可取的。所以,这里就要用到Git的webhooks来达到自动更新配置。

打开git上配置仓库的地址,添加webhooks,上面Payload URL我写的域名,当然我没有部署,上面的Payload URL就填写我们的配置中心触发刷新的地址,当然这里不能写localhost啦,要外网访问地址才行。

还有这里面有个Secret的秘钥验证,如果这里填写的话,在配置文件上要写上encrypt.key与之对应。

添加webhooks

 

 

 

局部刷新

某些场景下(例如灰度发布),我们可能只想刷新部分微服务的配置,此时可通过/bus/refresh端点的destination参数来定位要刷新的应用程序。

例如:/bus/refresh?destination=customers:8000,这样消息总线上的微服务实例就会根据destination参数的值来判断是否需要要刷新。其中,customers:8000指的是各个微服务的ApplicationContext ID

destination参数也可以用来定位特定的微服务。例如:/bus/refresh?destination=customers:**,这样就可以触发customers微服务所有实例的配置刷新。

 

跟踪总线事件

一些场景下,我们可能希望知道Spring Cloud Bus事件传播的细节。此时,我们可以跟踪总线事件(RemoteApplicationEvent的子类都是总线事件)。

跟踪总线事件非常简单,只需设置spring.cloud.bus.trace.enabled=true,这样在/bus/refresh端点被请求后,访问/trace端点就可获得类似如下的结果:

发送 GET请求到:http://localhost:8888/trace

 

  1. [
  2. {
  3. "timestamp": 1514543931362,
  4. "info": {
  5. "method": "GET",
  6. "path": "/eureka-provider/dev/master",
  7. "headers": {
  8. "request": {
  9. "accept": "application/json, application/*+json",
  10. "user-agent": "Java/1.8.0_112",
  11. "host": "localhost:8888",
  12. "connection": "keep-alive"
  13. },
  14. "response": {
  15. "X-Application-Context": "config-server:8888",
  16. "Content-Type": "application/json;charset=UTF-8",
  17. "Transfer-Encoding": "chunked",
  18. "Date": "Fri, 29 Dec 2017 10:38:51 GMT",
  19. "status": "200"
  20. }
  21. },
  22. "timeTaken": "6002"
  23. }
  24. },
  25. {
  26. "timestamp": 1514543927451,
  27. "info": {
  28. "method": "GET",
  29. "path": "/eureka-provider/dev/master",
  30. "headers": {
  31. "request": {
  32. "accept": "application/json, application/*+json",
  33. "user-agent": "Java/1.8.0_112",
  34. "host": "localhost:8888",
  35. "connection": "keep-alive"
  36. },
  37. "response": {
  38. "X-Application-Context": "config-server:8888",
  39. "Content-Type": "application/json;charset=UTF-8",
  40. "Transfer-Encoding": "chunked",
  41. "Date": "Fri, 29 Dec 2017 10:38:47 GMT",
  42. "status": "200"
  43. }
  44. },
  45. "timeTaken": "4927"
  46. }
  47. },
  48. {
  49. "timestamp": 1514543925254,
  50. "info": {
  51. "method": "GET",
  52. "path": "/eureka-provider/dev/master",
  53. "headers": {
  54. "request": {
  55. "accept": "application/json, application/*+json",
  56. "user-agent": "Java/1.8.0_112",
  57. "host": "localhost:8888",
  58. "connection": "keep-alive"
  59. },
  60. "response": {
  61. "X-Application-Context": "config-server:8888",
  62. "Content-Type": "application/json;charset=UTF-8",
  63. "Transfer-Encoding": "chunked",
  64. "Date": "Fri, 29 Dec 2017 10:38:45 GMT",
  65. "status": "200"
  66. }
  67. },
  68. "timeTaken": "2862"
  69. }
  70. },
  71. {
  72. "timestamp": 1514543923565,
  73. "info": {
  74. "method": "POST",
  75. "path": "/bus/refresh",
  76. "headers": {
  77. "request": {
  78. "cache-control": "no-cache",
  79. "postman-token": "0e497ec1-0c03-4dc2-bb61-ce2a266227d3",
  80. "user-agent": "PostmanRuntime/7.1.1",
  81. "accept": "*/*",
  82. "host": "127.0.0.1:8888",
  83. "accept-encoding": "gzip, deflate",
  84. "content-length": "0",
  85. "connection": "keep-alive"
  86. },
  87. "response": {
  88. "X-Application-Context": "config-server:8888",
  89. "status": "200"
  90. }
  91. },
  92. "timeTaken": "6616"
  93. }
  94. }
  95. ]

 

 

 

标签:服务,Spring,springframework,eureka,w3cschool,Cloud,spring,org,cloud
来源: https://www.cnblogs.com/hanease/p/16336971.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有