欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Spring Cloud

程序员文章站 2022-05-06 08:00:37
...

Spring Cloud

Spring Cloud是一套完整的微服务解决方案,利用Spring Boot的开发便利性巧妙地简化了分布式系统基础设施的开发,为开发人员提供了快速构建分布式系统中一些常见模式的工具(如服务发现注册、配置中心、消息总线、负载均衡、断路器、数据监控等)。它将目前各家公司开发的比较成熟、经得起实际考验的服务框架组合起来,通过Spring Boot风格进行再封装屏蔽掉了复杂的配置和实现原理,最终给开发者留出了一套简单易懂、易部署和易维护的分布式系统开发工具包。

所需依赖

	<dependencyManagement>
		<dependencies>
			<dependency>
				<groupId>org.springframework.cloud</groupId>
				<artifactId>spring-cloud-dependencies</artifactId>
				<version>${spring-cloud.version}</version>
				<type>pom</type>
				<scope>import</scope>
			</dependency>
		</dependencies>
	</dependencyManagement>

微服务注册与发现

在分布式系统种,服务提供者、服务消费者和服务发现组件是三个重要的概念,服务提供者将自己的网络地址等信息注册到服务发现组件上,服务消费者从服务发现组件查询到服务提供者的网络地址并使用该地址调用服务提供者的接口。

在Spring Cloud中,有多种服务发现组件,例如Eureka、Consul和ZooKeeper等。

Eureka

Eurka是Netflix开源的服务发现组件,本身是一个基于REST的服务。它包含Server和Client两部分。Spring Cloud将它集成在子项目Spring Cloud Netlix中,从而实现微服务的注册与发现。

Eureka Server

提供服务发现的能力,各个微服务启动时,会向Eureka Server注册自己的信息(例如IP、端口、微服务名称等),Eureka Server会存储这些信息。多个Eureka Server之间通过复制实现服务注册表数据同步。

Eureka Client

微服务启动后,会周期性(默认30秒)地向Eureka Server发送心跳以续约自己的"租期"。如果Eureka Server在一定时间内没有接收到某个微服务实例的心跳,Eureka Server将会注销该实例(默认90秒)。它会缓存注册表的信息。

创建一个Eureka Server需要经过一下步骤

(1)依赖

	<dependency>
		<groupId>org.springframework.cloud</groupId>
		<artifactId>spring-cloud-starter-eureka-server</artifactId>
	</dependency>

(2)启动类加上@EnableEurekaServer注解

@SpringBootApplication
@EnableEurekaServer
public class SpringCloudDemoApplication {

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

}

(3)配置文件application.yml

server:
  port: 8080

eureka:
  instance:
     hostname: localhost
#     prefer-ip-address: true
  client:
    ### 是否注册到Eureka Server
    registerWithEureka: false
    ### 是否从Eureka Server获取注册信息
    fetchRegistry: false
    serviceUrl:
      ### Eureka Server交互地址
      defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/

(4)启动工程,访问http://localhost:8080/即可看到首页

再创建一个Eureka Client注册到Eureka Server

(1)依赖

	<dependency>
		<groupId>org.springframework.cloud</groupId>
		<artifactId>spring-cloud-starter-eureka</artifactId>
	</dependency>

(2)启动类加上@EnableEurekaServer注解

@SpringBootApplication
@EnableEurekaClient
public class SpringCloudClientApplication {

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

}

(3)配置文件application.yml

eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8080/eureka/
  instance:
    ### 将ip注册到Eureka Server
    prefer-ip-address: true
spring:
  application:
    ### 注册到Eureka Server的名称
    name: server-hi

(4)启动工程,再访问http://localhost:8080/即可看到服务已经被注册到Eureka Server

Eureka Server用户认证

所谓用户认证,就是用户必须登录后才能访问Eureka Server

(1)依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>

(2)配置文件application.yml添加一下内容

security:
  basic:
    enable: true
  user:
    name: user
    password: password

(3)这时如果要将服务注册到有用户认证的Eureka Server就需要修改defaultZone

defaultZone: http://user:[email protected]:8080/eureka/

Ribbon客户端侧负载均衡

Ribbon是Netflix发布的负载均衡器,它有助于控制HTTP和TCP客户端的行为。为Ribbon配置服务提供者地址列表后,Ribbon就可基于某种负载均衡算法,自动地帮助服务消费者去请求。Ribbon默认为我们提供了很多的负载均衡算法,例如轮询、随机等。

Ribbon实现的是客户端侧的负载均衡,所以在消费者端进行配置

(1)依赖

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-ribbon</artifactId>
</dependency>

(2)在实例化RestTemplate的方法上加上@loadBalanced注解,这个实例是用来调用服务提供者的API

	@Bean
	@LoadBalanced
	RestTemplate restTemplate() {
		return new RestTemplate();
	}

(3)在控制器需要实现负载均衡的方法中选择服务提供者

@GetMapping("/ribbon")
public void ribbonTest() {
    ServiceInstance serviceInstance  = this.loadBalancerClient.choose("<服务提供者serviceId>");
}

自定义Ribbon配置

Spring Cloud Camden后可以使用Java代码或属性自定义Ribbon的配置,两种方式是等价的。

Java代码方式

(1)创建一个Ribbon配置类,此类不能在带有@ComponentScan注解扫描的包中,因为这样该类的配置信息就会被所有带有@RibbonClient注解的客户端共享。

@Configuration
public class RibbonConfiguration {
  @Bean
  public IRule ribbonRule() {
    // 负载均衡规则,改为随机,除此,还有更多规则
    return new RandomRule();
  }
}

(2)创建一个带有@Configuration注解和@RibbonClient注解的空类,以为特定客户端指定特定配置类

@Configuration
@RibbonClient(name = "<服务提供者serviceId>", configuration = RibbonConfiguration.class)
public class TestConfiguration {
}

属性方式

只需在配置文件application.yml添加

<服务提供者serviceId>:
  ribbon:
    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule

即可实现与上面java代码配置一样的功能.

Feign实现声明式REST调用

Feign是Netflix开发的声明式、模板化的HTTP客户端,其灵感来自Retrofit、JAXRS-2. 0以及WebSocket。Feign可帮助我们更加便捷、优雅地调用HTTP API。在Spring Cloud中,使用Feeign非常简单——创建一个接口,并在接口上添加一些注解,代码就完成了。Feign支持多种注解,例如Feign自带的注解或者JAX-RS注解等。Spring Cloud对Feign进行了增强,使Feign支持了Spring MVC注解,并整合了Ribbon和Eureka,从而让Feign的使用更加方便。

(1)依赖

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-feign</artifactId>
</dependency>

(2)创建一个Feign接口

@FeignClient(name = "<服务提供者serviceId>")
public interface UserFeignClient {
  @RequestMapping(value = "/{id}", method = RequestMethod.GET)
  public User findById(@PathVariable("id") Long id);
}

(3)控制器添加引用

@RestController
public class MovieController {
  @Autowired
  private UserFeignClient userFeignClient;

  @GetMapping("/user/{id}")
  public User findById(@PathVariable Long id) {
    return this.userFeignClient.findById(id);
  }
}

(4)启动类添加@EnableFeignClients注解

@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients
public class SpringCloudClientApplication {

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

}

自定义Feign配置

(1)创建Feign配置类

public class FeignConfiguration {
  /**
   * 将契约改为feign原生的默认契约。这样就可以使用feign自带的注解了。
   * @return 默认的feign契约
   */
  @Bean
  public Contract feignContract() {
    return new feign.Contract.Default();
  }
}

(2)在接口中指定配置类

@FeignClient(name = "<服务提供者serviceId>", configuration = FeignConfiguration.class)
public interface UserFeignClient {
  /**
   * 使用feign自带的注解@RequestLine
   * @param id 用户id
   * @return 用户信息
   */
  @RequestLine("GET /{id}")
  public User findById(@Param("id") Long id);
}

为Feign添加日志

(1)在上面自定义Feign配置的基础上修改Feign配置类

@Configuration
public class FeignLogConfiguration {

  //NONE:不记录;BASIC:记录方法、URL、响应状态代码以及执行时间;HEADERS:在BASIC基础上增加
  //响应和请求的header;FULL:在HEADERS基础上增加body和元数据
  @Bean
  Logger.Level feignLoggerLevel() {
    return Logger.Level.BASIC;
  }
}

(2)配置文件application.yml添加以下内容

logging:
  level:
    <接口类全限定类名>: DEBUG # 将Feign接口的日志级别设置成DEBUG,因为Feign的Logger.Level只对DEBUG作出响应。

Feign构造多参数请求

GET请求

写法一

  @RequestMapping(value = "/get", method = RequestMethod.GET)
  public User get1(@RequestParam("id") Long id, @RequestParam("username") String username);

写法二

  @RequestMapping(value = "/get", method = RequestMethod.GET)
  public User get2(@RequestParam Map<String, Object> map);

调用则

  @GetMapping("/user/get2")
  public User get2(User user) {
    Map<String, Object> map = Maps.newHashMap();
    map.put("id", user.getId());
    map.put("username", user.getUsername());
    return this.userFeignClient.get2(map);
  }

POST请求

  @RequestMapping(value = "/post", method = RequestMethod.POST)
  public User post(@RequestBody User user);

Hystrix实现容错

当服务提供者响应过慢时,服务消费者会一直等待提供者的响应,直到超时。请求越来越多,就会引起服务器瘫痪。为了解决此问题,就必须有一个容错机制,该容错机制包含两点,设置网络请求超时和断路器模式。而Hystrix就是实现了这两种模式的类库,它是由Netflix开源的一个延迟和容错库,用于隔离访问远程系统、服务或者第三方库,防止级联失败,从而提升系统的可用性与容错性。

(1)依赖

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>

(2)启动类添加@EnableCircuitBreaker或@EnableHystrix开启断路器支持

@EnableDiscoveryClient
@SpringBootApplication
@EnableCircuitBreaker
public class SpringCloudDemoApplication {
  @Bean
  @LoadBalanced
  public RestTemplate restTemplate() {
    return new RestTemplate();
  }

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

(3)在控制器需要实现容错机制的方法添加特定的容错能力

  //提供出现异常的回退方法
  @HystrixCommand(fallbackMethod = "findByIdFallback")
  @GetMapping("/user/{id}")
  public User findById(@PathVariable Long id) {
    ...
  }

  /**
   * 如果想要获得导致fallback的原因,只需在fallback方法上添加Throwable参数即可。
   * @param id ID
   * @param throwable 异常
   * @return 用户
   */
  public User findByIdFallback(Long id, Throwable throwable) {
    ...
  }

上面使用@HystrixCommand注解提供回退方法,还可使用@HystrixProperty的commandProperties属性添加更多的策略

@HystrixProperty的commandProperties

  @HystrixCommand(fallbackMethod = "findByIdFallback",commandProperties = {
      @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "5000"),
      @HystrixProperty(name = "metrics.rollingStats.timeoutInMilliseconds", value = "10000")
  },threadPoolProperties = {
      @HystrixProperty(name = "coreSize", value = "1"),
      @HystrixProperty(name = "maxQueueSize", value = "10")
  })
  @GetMapping("/user/{id}")
  public User findById(@PathVariable Long id) {
    ...
  }

Feign整合Hystrix

前文使用注解属性实现回退,Feign可以使用接口形式实现同样的功能

修改前面的Feign接口

@FeignClient(name = "<服务提供方serviceId>", fallback = FeignClientFallback.class)
public interface UserFeignClient {
  @RequestMapping(value = "/{id}", method = RequestMethod.GET)
  public User findById(@PathVariable("id") Long id);

}

/**
 * 回退类FeignClientFallback需实现Feign Client接口
 */
@Component
class FeignClientFallback implements UserFeignClient {
  @Override
  public User findById(Long id) {
    ...
  }
}

如果需要知道回退原因,可使用@FeignClient注解的fallbackFactory属性

@FeignClient(name = "<服务提供方serviceId>", fallbackFactory = FeignClientFallbackFactory.class)
public interface UserFeignClient {
  @RequestMapping(value = "/{id}", method = RequestMethod.GET)
  public User findById(@PathVariable("id") Long id);
}

/**
 * UserFeignClient的fallbackFactory类,该类需实现FallbackFactory接口,并覆写create方法
 */
@Component
class FeignClientFallbackFactory implements FallbackFactory<UserFeignClient> {
  private static final Logger LOGGER = LoggerFactory.getLogger(FeignClientFallbackFactory.class);

  @Override
  public UserFeignClient create(Throwable cause) {
    return new UserFeignClient() {
      @Override
      public User findById(Long id) {
        // 日志最好放在各个fallback方法中,而不要直接放在create方法中。
        // 否则在引用启动时,就会打印该日志。
        // 详见https://github.com/spring-cloud/spring-cloud-netflix/issues/1471
        FeignClientFallbackFactory.LOGGER.info("fallback; reason was:", cause);
       ...
      }
    };
  }
}

Hystrix Dashboard可视化监控数据

(1)依赖

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-hystrix-dashboard</artifactId>
</dependency>

(2)启动类添加@EnableHystrixDashboard注解

@SpringBootApplication
@EnableHystrixDashboard
public class HystrixDashboardApplication {
  public static void main(String[] args) {
    SpringApplication.run(HystrixDashboardApplication.class, args);
  }
}

(3)配置文件application.yml

server:
  port: 8081

(4)访问http://localhost:8081/hystrix即可看到Hystrix Dashbroad主页

Turbine聚合监控数据

Turbine是一个聚合Hystrix监控数据的工具,它可将所有相关/hystrix.stream端点的数据聚合到一个组合的/turbine.stream中,从而让集群的监控更加方便。

(1)依赖

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-turbine</artifactId>
</dependency>

(2)启动类添加@EnableTurbine注解

@SpringBootApplication
@EnableTurbine
public class TurbineApplication {
  public static void main(String[] args) {
    SpringApplication.run(TurbineApplication.class, args);
  }
}

(3)配置文件application.yml

server:
  port: 8081
spring:
  application:
    name: <微服务serviceId>
eureka:
  client:
    service-url:
      defaultZone: http://localhost:8080/eureka
  instance:
    prefer-ip-address: true
turbine:
  appConfig: <监控服务serviceId1>,<监控服务serviceId2>
  clusterNameExpression: "'default'"

Zuul构建微服务网关

Zuul是Netflix开源的微服务网关,它可以和Eureka、Ribbon、Hystrix等组件配合使用。Zuul的核心是一系列的过滤器。

(1)依赖

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-zuul</artifactId>
</dependency>

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>

(2)在启动类上添加注解@EnableZuulProxy,声明一个Zuul代理。该代理使用Ribbon来定位注册在Eureka Server中的微服务;同时,该代理还整合了Hystrix,从而实现了容错,所有经过Zuul的请求都会在Hystrix命令中执行。

@SpringBootApplication
@EnableZuulProxy
public class ZuulApplication {
  public static void main(String[] args) {
    SpringApplication.run(ZuulApplication.class, args);
  }
}

(3)配置文件application.yml

server:
  port: 8040
spring:
  application:
    name: <微服务serviceId>
eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka/

默认情况下,Zuul会代理所有注册到Eureka Server的微服务,并且Zuul的路由规则如下:http://Zuul_HOST:ZUUL_PORT/微服务在Eureka上的serviceld/**会被转发到serviceld对应的微服务。而且,访问http://Zuul_HOST:ZUUL_PORT/routes还可以直观地看出从路径到微服务的映射。

路由配置

上述编写的网关会代理所有注册到Eureka Server的微服务,如果只是想代理部分微服务,可以根据以下设置

(1)自定义指定微服务的访问路径

zuul:
  routes:
    <指定的微服务serviceId: 指定路径>

(2)忽略指定微服务

zuul:
  ignored-services: <指定的微服务serviceId1,指定的微服务serviceId2, ...>

(3)忽略所有微服务,只路由指定微服务

zuul:
  ignored-services: '*'
    user-route:
      serviceId:<指定的微服务serviceId1, ...>
      path: <指定路径>

(4)同时指定微服务的service ld和对应路径

zuul:
  route:
    user-route:
      serviceId: <指定的微服务serviceId1, ...>
      path: <指定路径>

(5)同时指定path和URL
 

zuul:
  route:
    user-route:
      url: <指定的url>
      path: <指定路径>

(6)同时指定path和URL,并且不破坏Zuul的Hystrix、Ribbon特性。

zuul:
  route:
    user-route:
      serviceId: <指定的微服务serviceId1, ...>
      path: <指定路径>
ribbon:
  eureka:
    enabled: false #为Ribbon禁用Eureka
<指定的微服务serviceId>:
  rubbon:
    listOfServers:<指定url>

(7)路由前缀

示例1:

zuul:
  prefix: /api
    strip-prefix: false
    routes:
      <指定的微服务serviceId: 指定路径>

示例2:

zuul:
  routes:
    <指定的微服务serviceId>
      path:<指定路径>
      strip-prefix: false

(8)忽略某些路径

zuul:
  ignoredPatterns: <指定路径>
  routes:
    <指定的微服务serviceId:指定路径>

Header相关

设置敏感Header,就不会在同一系统的不同服务之间共享Header

zuul:
  routes:
  <指定的微服务serviceId>
    path: <指定路径>
    sensitive-headers: Cookie,Set-Cookie,Authorization
    url:<指定url>

如果想指定全局敏感Header使用

zuul:
  sensitive-headers: <指定的敏感信息>

设置忽略Header,被忽略的Header就不会传播到其它微服务

zuul:
  ignored-headers: Header1,Header2

上传文件

对于小文件无须处理即可上传,而大文件需要为上传路径添加/zuul前缀。也可使用zuul,servlet-path自定义前缀。

如果使用了Ribbon做了负载均衡,对于超大文件,须设置超时

hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds: 60000
ribbon:
  ConnectTimeout: 3000
  ReadTimeout: 60000

自定义Zuul过滤器

(1)自定义过滤器类

public class PreRequestLogFilter extends ZuulFilter {
  private static final Logger LOGGER = LoggerFactory.getLogger(PreRequestLogFilter.class);

  //返回过滤器类型(pre、route、post、error)
  @Override
  public String filterType() {
    return FilterConstants.PRE_TYPE;
  }

  //过滤器执行顺序
  @Override
  public int filterOrder() {
    return FilterConstants.PRE_DECORATION_FILTER_ORDER - 1;
  }

  //返回true执行该过滤器
  @Override
  public boolean shouldFilter() {
    return true;
  }

  //过滤器具体逻辑
  @Override
  public Object run() {
    RequestContext ctx = RequestContext.getCurrentContext();
    HttpServletRequest request = ctx.getRequest();
    PreRequestLogFilter.LOGGER.info(String.format("send %s request to %s", request.getMethod(), request.getRequestURL().toString()));
    return null;
  }
}

(1)启动类

@SpringBootApplication
@EnableZuulProxy
public class ZuulApplication {
  public static void main(String[] args) {
    SpringApplication.run(ZuulApplication.class, args);
  }

  @Bean
  public PreRequestLogFilter preRequestLogFilter() {
    return new PreRequestLogFilter();
  }
}

Spring Cloud Config统一管理微服务配置

Spring Cloud Config为分布式系统外部化配置提供了服务器端和客户端的支持,它包括Config Server和Config Client两部分。

Config Server是一个可横向扩展、集中式的配置服务器,它用于集中管理应用程序各个环境下的配置,默认使用Git存储配置内容,因此可以很方便地实现对配置的版本控制与内容审计。

Config Client是Confg Server的客户端,用于操作存储在Config Server中的配置属性。所有的微服务都指向Confg Server。各个微服务在启动时,会请求Config Server以获取所需要的配置属性,然后缓存这些属性以提高性能。

编写Config Server

(1)依赖

	<dependency>
		<groupId>org.springframework.cloud</groupId>
		<artifactId>spring-cloud-config-server</artifactId>
	</dependency>

(2)启动类添加@EnableConfigServer注解

@SpringBootApplication
@EnableConfigServer
public class ConfigServerApplication {

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

(3)配置文件application.yml

server:
  port: 8080
spring:
  application:
    name: <微服务serviceId>
  cloud:
    config:
      server:
        git:
          uri: <git仓库uri>      # 配置Git仓库的地址
          username:                                                         # Git仓库的账号
          password:                                                         # Git仓库的密码

(4)访问http://localhost:8080/<仓库文件名称>

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

  1. /{application}/{profile}[/{label}]
  2. /{application}-{profile}.yml
  3. /{label}/{application}-{profile}.yml
  4. /{application}-{profile}.properties
  5. /{label}/{application}-{profile}.properties

编写Config Client

(1)依赖

	<dependency>
		<groupId>org.springframework.cloud</groupId>
		<artifactId>spring-cloud-starter-config</artifactId>
	</dependency>

(2)配置文件application.yml

server:
  port: 8081

(2)配置文件bootstrap.yml

spring:
  application:
    name: <config server所获取的配置文件的{application}>
  cloud:
    config:
      uri: <config server 的 uri>
      profile= <config server所获取的配置文件中的{profile}>
      label: <Git仓库的分支>

(3)控制器

@RestController
public class ConfigClientController {
  @Value("${profile}")
  private String profile;

  @GetMapping("/profile")
  public String hello() {
    return this.profile;
  }
}

(4)访问http://localhost:8081/profile

Spring Cloud Bus自动刷新配置

Spring Cloud Bus使用轻量级的消息代理(例如Rabbitmq、 kafka等)连接分布式系统的节点,这样就可以广播传播状态的更改(例如配置的更新)或者其他的管理指令。可将Spring cloud Bus想象成一个分布式的Spring Boot Actuator。

只需将上面的Config Client稍作修改

(1)依赖

	<dependency>
		<groupId>org.springframework.cloud</groupId>
		<artifactId>spring-cloud-starter-bus-amqp</artifactId>
	</dependency>

(2)配置文件bootstrap.yml

spring:
  application:
    name: <config server所获取的配置文件的{application}>
  cloud:
    config:
      uri: <config server 的 uri>
      profile= <config server所获取的配置文件中的{profile}>
      label: <Git仓库的分支>
  rabbitmq:
    host: localhost
    port: 5672
    username: guest
    password: guest

Spring Cloud Config与Eureka配合使用

前文在微服务中指定了Config Server地址,这种方式无法利用服务发现组件的优势。

只需将上面的Config Client稍作修改

(1)配置文件bootstrap.yml

spring:
  application:
    name: <config server所获取的配置文件的{application}>
  cloud:
    config:
      uri: <config server 的 uri>
      profile= <config server所获取的配置文件中的{profile}>
      label: <Git仓库的分支>
      enabled: true
      service-id: <config server 的 serviceId>
eureka:
  client:
    serviceUrl:
      defaultZone: <Eureka Server 的 URL>

Spring Cloud Config用户认证

只需将上面的Config Server稍作修改

(1)依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>

(2)配置文件application.yml

server:
  port: 8080
spring:
  application:
    name: <微服务serviceId>
  cloud:
    config:
      server:
        git:
          uri: <git仓库uri>      # 配置Git仓库的地址
          username:                                                         # Git仓库的账号
          password:                                                         # Git仓库的密码
eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/
security:
  basic:
    enabled: true               # 开启基于HTTP basic的认证
  user:
    name: user                  # 配置登录的账号是user
    password: password123       # 配置登录的密码是password123

这时Config Client想要连接Config Server,有两种方式

spring:
  cloud:
    config:
      uri: http://user:[email protected]:8080/

spring:
  cloud:
    config:
      uri: http://localhost:8080/
      username: user
      password: password123

Spring Cloud Sleuth微服务追踪

Spring Cloud Sleuth 为Spring Cloud提供了分布式追踪的解决方案。

(1)依赖

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-sleuth</artifactId>
</dependency>

(2)配置文件application.yml

spring:
  application:
    name: <serviceId>
logging:
  level:
    root: INFO
    org.springframework.web.servlet.DispatcherServlet: DEBUG

Zipkin

Zipkin是Twiter开源的分布式跟踪系统,基于Dapper的论文设计而来。它的主要功能是收集系统的时序数据,从而追踪微服务架构的系统延时等问题。Zipkin还提供了一个非常友好的界面,来帮助分析追踪数据。

编写Zipkin Server

(1)依赖

<dependency>
    <groupId>io.zipkin.java</groupId>
    <artifactId>zipkin-autoconfigure-ui</artifactId>
</dependency>

<dependency>
    <groupId>io.zipkin.java</groupId>
    <artifactId>zipkin-server</artifactId>
</dependency>

(2)启动类添加@EnableZipkinServer注解

@SpringBootApplication
@EnableZipkinServer
public class ZipkinServerApplication {
  public static void main(String[] args) {
    SpringApplication.run(ZipkinServerApplication.class, args);
  }
}

(3)配置文件application.yml

server:
  port: 9411

(4)访问http://localhost:9411/

Spring Cloud Sleuth整合Zipkin

(1)依赖

    <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-sleuth-zipkin</artifactId>
    </dependency>

(2)配置文件application.yml

server:
  port: 8000
spring:
  application:
    name: <微服务serviceId>
  zipkin:
    base-url: http://localhost:9411   #Zipkin Server URL
  sleuth:
    sampler:
      percentage: 1.0                 #需采样的请求的百分比,默认0.1

整合消息中间件

只需将上面的Zipkin Server稍作修改

(1)依赖

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-sleuth-zipkin-stream</artifactId>
</dependency>

<dependency>
    <groupId>io.zipkin.java</groupId>
    <artifactId>zipkin-autoconfigure-ui</artifactId>
</dependency>

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-sleuth</artifactId>
</dependency>

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-stream-binder-rabbit</artifactId>
</dependency>

(2)配置文件application.yml

server:
  port: 9411
zipkin:
  collector:
    rabbitmq:
      addresses: localhost:5672
      password: guest
      username: guest
      queue: zipkin

接下来修改微服务

(1)依赖

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-sleuth</artifactId>
</dependency>

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-stream-binder-rabbit</artifactId>
</dependency>

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-sleuth-stream</artifactId>
</dependency>

(2)配置文件application.yml

server:
  port: 8000
spring:
  application:
    name: <微服务serviceId>
  zipkin:
    base-url: http://localhost:9411   #Zipkin Server URL
  sleuth:
    sampler:
      percentage: 1.0                 #需采样的请求的百分比,默认0.1
  rabbitmq:
    host: localhost
    port: 5672
    username: guest
    password: guest
  zipkin:
    rabbitmq:
      queue: zipkin

存储跟踪数据到Elasticsearch

(1)依赖

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-sleuth-zipkin-stream</artifactId>
</dependency>

<dependency>
    <groupId>io.zipkin.java</groupId>
    <artifactId>zipkin-autoconfigure-ui</artifactId>
</dependency>

<dependency>
    <groupId>io.zipkin.java</groupId>
    <artifactId>zipkin-autoconfigure-storage-elasticsearch-http</artifactId>
    <version>2.3.1</version>
</dependency>

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-stream-binder-rabbit</artifactId>
</dependency>

(2)配置文件application.yml

server:
  port: 9411
zipkin:
  collector:
    rabbitmq:
      addresses: localhost:5672
      password: guest
      username: guest
      queue: zipkin
  storage:
    type: elasticsearch
    elasticsearch:
      cluster: elasticsearch
      hosts: http://localhost:9200
      index: zipkin
      index-shards: 5
      index-replicas: 1

(3)访问http://localhost:9200/_search

注:本博客内容参考《Spring Cloud与Docker微服务架构实战》