springboot2新版springcloud微服务全家桶实战

sb2.0新版springcloud微服务实战:Eureka+Zuul+Feign/Ribbon+Hystrix Turbine+SpringConfig+sleuth+zipkin

springboot 版本是 2.0.3.RELEASE ,springcloud 版本是 Finchley.RELEASEjavascript

本篇文章是springboot2.x升级后的升级springcloud专贴,由于以前版本更新已经很久了,好多人评论可不能够出个新版本,你们必定要注意,这是springboot2.x版本的,springboot1.x的请参考 点击查看文章,基本组件都不变就是升级jar包版本,主要就是hystrix-dashboard使用有点变化。还有一点要注意的是sc默认使用的是eureka1.9.x版本,你们必定要主要,不要本身手动改成2.x版本,由于2.x版本尚未正式发布,并且中止开发了,官方还在积极的维护1.x版本(并非网传的闭源)。php

相信如今已经有不少小伙伴已经或者准备使用springcloud微服务了,接下来为你们搭建一个微服务框架,后期能够本身进行扩展。会提供一个小案例: 服务提供者和服务消费者 ,消费者会调用提供者的服务,新建的项目都是用springboot,附源码下载,推荐使用coding地址下载,由于能够切换分支,后期能够及时更新。java

coding仓库地址(推荐下载): coding地址 远程配置仓库地址 远程配置仓库地址nginx

若是有问题请在下边评论,或者496832428加群交流。git

Eureka/Consul/Zookeeper:服务发现 (根据状况选择一个,eureka已经宣布闭源)
Hystrix:断路器
Zuul:智能路由
Ribbon/Feign:客户端负载均衡 (Feign用的更多)
Turbine&hystrix-dashboard:集群监控
Springcloud-config:远程获取配置文件web

接下来,咱们开始搭建项目,首先咱们到spring为咱们提供的一个网站快速搭建springboot项目,点击访问,我这里用的是gradle,若是各位客官喜欢用maven,好吧你能够到http://mvnrepository.com/查看对应的依赖,点我访问
spring

1.png

1、搭建eureka-server服务sc-eureka-server

使用 spring-cloud-consul 做为服务发现 请参考 点击查看使用springcloud consul 做为服务发现数据库

eureka-server做为服务发现的核心,第一个搭建,后面的服务都要注册到eureka-server上,意思是告诉eureka-server本身的服务地址是啥。固然还能够用zookeeper或者springconsul。bootstrap

  • 1.修改build.gradle文件

若是是maven项目请对应的修改pom.xml后端

//加入阿里的私服仓库地址 maven { url "http://maven.aliyun.com/nexus/content/groups/public/" } //加入阿里的私服仓库地址 maven { url "http://maven.aliyun.com/nexus/content/groups/public/" }
//加入依赖  compile('org.springframework.cloud:spring-cloud-starter-netflix-eureka-server') //加入security,是由于访问eureka-server须要用户名和密码访问,为了安全 compile('org.springframework.boot:spring-boot-starter-security') //加入依赖  compile('org.springframework.cloud:spring-cloud-starter-netflix-eureka-server') //加入security,是由于访问eureka-server须要用户名和密码访问,为了安全 compile('org.springframework.boot:spring-boot-starter-security')

还有几点须要修改的,你们对应图片看看,就是springboot打包的时候会提示找不到主类。

2.png
  • 2.修改 application.yml,建议用yml。
server:
  port: 8761
eureka:
  datacenter: trmap
  environment: product
  server:
      # 关闭自我保护
      enable-self-preservation: false
      # 清理服务器
      eviction-interval-timer-in-ms: 5000
  client:
    healthcheck:
      enabled: true
    service-url:
      defaultZone: http://root:booszy@localhost:8761/eureka/
    register-with-eureka: false
    fetch-registry: false
spring:
  security:
    basic:
      enabled: true
    user:
      name: root
      password: booszy
  • 3.修改程序的主类,建议修改类名,要加如eureka的 @EnableEurekaServer 注解,而后运行main方法。
@EnableEurekaServer @SpringBootApplication public class Sb2scEurekaApplication { public static void main(String[] args) { SpringApplication.run(Sb2scEurekaApplication.class, args); } } @EnableEurekaServer @SpringBootApplication public class Sb2scEurekaApplication { public static void main(String[] args) { SpringApplication.run(Sb2scEurekaApplication.class, args); } }

4.png

http://localhost:8761/ 这个是eureka-server的页面地址,密码在yml配置文件中,到这里,说明eureka-server搭建好了,简单吧,这一步必定要成功,不然后面的就不能继续进行下去了,后边基本相似。

2、搭建config-server服务sc-config-server

springcloud-config-server是用来将远程git仓库的配置文件动态拉下来,这样配置文件就能够动态的维护了。固然也能够选择本地仓库。

新建一个springboot项目,修改maven私服地址,并加入一下依赖。

  • 1.修改build.gradle文件
compile('org.springframework.cloud:spring-cloud-config-server') compile('org.springframework.cloud:spring-cloud-starter-netflix-eureka-client') //链接config-server也须要用户名和密码 compile('org.springframework.boot:spring-boot-starter-security') compile('org.springframework.boot:spring-boot-starter-actuator') compile('org.springframework.cloud:spring-cloud-config-server') compile('org.springframework.cloud:spring-cloud-starter-netflix-eureka-client') //链接config-server也须要用户名和密码 compile('org.springframework.boot:spring-boot-starter-security') compile('org.springframework.boot:spring-boot-starter-actuator')
  • 2.修改application.yml文件
server:
  port: 8800
spring:
  security:
    basic:
      enabled: true
    user:
      name: root
      password: booszy
  application:
    name: sc-config-server
  cloud:
    config:
      server:
        git:
          uri: https://git.coding.net/yirenyishi/springcloud-config-profile
          searchPaths: '{application}'
eureka:
  client:
    service-url:
      defaultZone: http://root:booszy@localhost:8761/eureka/
  instance:
    prefer-ip-address: true
    instance-id: ${spring.application.name}:${spring.application.instance_id:${server.port}}
    appname: sc-config-server
  • 3.修改启动类

修改启动类,要加入这三个注解,由于要注册到eureka-server上,因此须要@EnableDiscoveryClient这个注解

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

而后运行启动springboot项目,等启动成功后访问eureka的页面,会发现sc-config-server已经注册到上面了,若是启动报错,请检查错误信息。


3.png

3、搭建服务提供者服务sc-provider

编写一个服务提供者,为下边的消费者提供服务,用到了spring-webflux(spring新出的非阻塞式框架)不是springmvc,固然大家公司用什么你仍是继续用什么。

  • 注意 : 这里除了application.xml,还须要一个bootstrap.yml, 由于bootstrap.yml得加载顺序是在application.xml前边,服务注册和config配置必须放到bootstrap.yml。
    1. 修改build.gradle文件
compile('org.springframework.cloud:spring-cloud-starter-netflix-eureka-client')
compile('org.springframework.cloud:spring-cloud-starter-config')
compile('org.springframework.boot:spring-boot-starter-webflux')
compile('org.springframework.boot:spring-boot-starter-actuator')
  • 2.编写配置文件bootstrap.yml

** 注意 : 这里除了application.xml,还须要一个bootstrap.yml*

application.xml我是放到远程仓库地址的,你们能够直接到个人远程仓库,根据项目名(sc-provider-config)查询。配置文件的仓库地址:点击访问

eureka:
  client:
    service-url:
      defaultZone: http://root:booszy@localhost:8761/eureka/
  instance:
    prefer-ip-address: true
    instance-id: ${spring.application.name}:${spring.application.instance_id:${server.port}}
    appname: sc-provider

spring:
application:
name: sc-provider
cloud:
config:
discovery:
enabled: true
service-id: sc-config-server
fail-fast: true
username: root
password: booszy
profile: csdn

  • 3.编写代码

编写主类

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

新建IndexController进行测试,这里只是为了测试,案例代码使用的是webflux,若是想使用springmvc,修改jar包依赖便可。

@RestController @RequestMapping("test") public class IndexController { //返回一个实体 @GetMapping("{msg}") public Mono<String> sayHelloWorld(@PathVariable("msg") String msg) { System.out.println("come on " + msg); return Mono.just("sc-provider receive : " +msg); } //返回一个列表 @GetMapping("list") public Flux<Integer> list() { List<Integer> list = new ArrayList<>(); list.add(8); list.add(22); list.add(75); list.add(93); Flux<Integer> userFlux = Flux.fromIterable(list); return userFlux; } } @RestController @RequestMapping("test") public class IndexController { //返回一个实体 @GetMapping("{msg}") public Mono<String> sayHelloWorld(@PathVariable("msg") String msg) { System.out.println("come on " + msg); return Mono.just("sc-provider receive : " +msg); } //返回一个列表 @GetMapping("list") public Flux<Integer> list() { List<Integer> list = new ArrayList<>(); list.add(8); list.add(22); list.add(75); list.add(93); Flux<Integer> userFlux = Flux.fromIterable(list); return userFlux; } }

运行springboot项目,去eureka-server查看,有没有注册上。


5.png

咱们的sc-provider已经注册到eureka上了,访问接口,成功。


6.png

4、搭建消费者服务sc-consumer

消费者要访问服务提供者的服务,这里用的是经过RestTemplate/feign请求resetful接口,使用ribbon作客户端负载均衡,hystrix作错误处理,feign和ribbon二选一,案例中ribbon和feign都有,也能够都用。
仍是熟悉的配方,熟悉的味道,新建springboot项目,添加项目依赖。

  • 1.修改build.gradle文件
compile('org.springframework.cloud:spring-cloud-starter-netflix-eureka-client')
compile('org.springframework.cloud:spring-cloud-starter-config')
compile('org.springframework.boot:spring-boot-starter-webflux')
compile('org.springframework.boot:spring-boot-starter-actuator')
compile('org.springframework.cloud:spring-cloud-starter-openfeign')
compile('org.springframework.cloud:spring-cloud-starter-netflix-hystrix')
  • 2.修改bootstrap.yml文件

application.yml 在git仓库,请前往git仓库查看。

eureka:
  client:
    service-url:
      defaultZone: http://root:booszy@localhost:8761/eureka/
  instance:
    prefer-ip-address: true
    instance-id: ${spring.application.name}:${spring.application.instance_id:${server.port}}
    appname: sc-consumer

spring:
application:
name: sc-consumer
cloud:
config:
discovery:
enabled: true
service-id: sc-config-server
fail-fast: true
username: root
password: booszy
profile: csdn
#新版配置,不然后面dashboard没法找到hystrix.stream
management:
endpoints:
web:
exposure:
include: ‘*’

  • 3.编写代码

启动类代码

@RibbonClient 指定服务使用的负载均衡类型,name不指定服务则为全部的服务打开负载均衡,也能够在用yml中进行配置。
@EnableHystrix 是支持hystrix打开断路器,在规定时间内失败参数超过必定参数,就会打开断路器,不会发起请求,而是直接进入到错误处理方法。


@EnableDiscoveryClient @EnableFeignClients @EnableCircuitBreaker @EnableHystrix @SpringBootApplication public class Sb2scConsumerApplication { // ribbon须要配置,负载均衡 @Autowired private RestTemplateBuilder builder; @EnableDiscoveryClient @EnableFeignClients @EnableCircuitBreaker @EnableHystrix @SpringBootApplication public class Sb2scConsumerApplication { // ribbon须要配置,负载均衡 @Autowired private RestTemplateBuilder builder;<span class="hljs-comment">// ribbon须要配置,负载均衡</span> <span class="hljs-meta">@Bean</span> <span class="hljs-meta">@LoadBalanced</span> <span class="hljs-function"><span class="hljs-keyword">public</span> RestTemplate <span class="hljs-title">restTemplate</span><span class="hljs-params">()</span> </span>{ <span class="hljs-keyword">return</span> builder.build(); } <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{ SpringApplication.run(Sb2scConsumerApplication.class, args); } <span class="hljs-comment">// ribbon须要配置,负载均衡</span> <span class="hljs-meta">@Bean</span> <span class="hljs-meta">@LoadBalanced</span> <span class="hljs-function"><span class="hljs-keyword">public</span> RestTemplate <span class="hljs-title">restTemplate</span><span class="hljs-params">()</span> </span>{ <span class="hljs-keyword">return</span> builder.build(); } <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{ SpringApplication.run(Sb2scConsumerApplication.class, args); }

}

1.ribbon案例

ribbon不须要单独依赖,新建 RibbonController
ribbon一个坑,不能接受List类型,要使用数组接收。
@HystrixCommand(fallbackMethod="fallbackMethod")
若是请求失败,会进入fallbackMethod这个方法,fallbackMethod这个方法要求参数和返回值与回调他的方法保持一致。


@RestController public class RibbonController { @RestController public class RibbonController {<span class="hljs-meta">@Autowired</span> <span class="hljs-keyword">private</span> RestTemplate restTemplate; <span class="hljs-meta">@Autowired</span> <span class="hljs-keyword">private</span> LoadBalancerClient loadBalancerClient; <span class="hljs-meta">@GetMapping</span>(<span class="hljs-string">"/ribbon/{wd}"</span>) <span class="hljs-meta">@HystrixCommand</span>(fallbackMethod=<span class="hljs-string">"fallbackMethod"</span>) <span class="hljs-function"><span class="hljs-keyword">public</span> Mono&lt;String&gt; <span class="hljs-title">sayHelloWorld</span><span class="hljs-params">(@PathVariable(<span class="hljs-string">"wd"</span>)</span> String parm) </span>{ String res = <span class="hljs-keyword">this</span>.restTemplate.getForObject(<span class="hljs-string">"http://sc-provider/test/"</span> + parm, String.class); <span class="hljs-keyword">return</span> Mono.just(res); } <span class="hljs-function"><span class="hljs-keyword">public</span> Mono&lt;String&gt; <span class="hljs-title">fallbackMethod</span><span class="hljs-params">(@PathVariable(<span class="hljs-string">"wd"</span>)</span> String parm) </span>{ <span class="hljs-keyword">return</span> Mono.just(<span class="hljs-string">"fallback"</span>); } <span class="hljs-meta">@Autowired</span> <span class="hljs-keyword">private</span> RestTemplate restTemplate; <span class="hljs-meta">@Autowired</span> <span class="hljs-keyword">private</span> LoadBalancerClient loadBalancerClient; <span class="hljs-meta">@GetMapping</span>(<span class="hljs-string">"/ribbon/{wd}"</span>) <span class="hljs-meta">@HystrixCommand</span>(fallbackMethod=<span class="hljs-string">"fallbackMethod"</span>) <span class="hljs-function"><span class="hljs-keyword">public</span> Mono&lt;String&gt; <span class="hljs-title">sayHelloWorld</span><span class="hljs-params">(@PathVariable(<span class="hljs-string">"wd"</span>)</span> String parm) </span>{ String res = <span class="hljs-keyword">this</span>.restTemplate.getForObject(<span class="hljs-string">"http://sc-provider/test/"</span> + parm, String.class); <span class="hljs-keyword">return</span> Mono.just(res); } <span class="hljs-function"><span class="hljs-keyword">public</span> Mono&lt;String&gt; <span class="hljs-title">fallbackMethod</span><span class="hljs-params">(@PathVariable(<span class="hljs-string">"wd"</span>)</span> String parm) </span>{ <span class="hljs-keyword">return</span> Mono.just(<span class="hljs-string">"fallback"</span>); }

运行springboot项目,先看有没有注册到eureka-server上。


7.png

注册成功后,访问接口,测试是否正确。

8.png

ribbon使用就是这么简单,ribbon是springboot自带,因此不须要单独添加依赖。

2.feign案例

在实际开发中,feign使用的仍是挺多的,feign底层仍是使用了ribbon。废话很少说,直接上步骤,在服务消费者中使用feign访问服务提供者。

  • 1配置文件
ribbon:
  ReadTimeout:  30000
  ConnectTimeout:  15000
hystrix:
  command:
    default:
      execution:
        isolation:
          thread:
            timeoutInMilliseconds: 10000

feign的默认请求超时时间是1s,因此常常会出现超时的问题,这里我设置的是10s,由于个人数据库服务器在美国,因此有时候请求会比较慢。ribbon的请求时间也要设置,由于feign用的是ribbon。这里贴的是application.yml文件中的一小段

  • 2 编码

一、主类注解

@EnableFeignClients
@EnableCircuitBreaker
@EnableHystrix

这三个都要,hystrix主要做用是断路器,会进如fein的fallback中。 主类代码在上面已经贴出来了

二、编写feign接口,MFeignClient.class

name是指要请求的服务名称。这里请求的是服务提供者
fallback 是指请求失败,进入断路器的类,和使用ribbon是同样的。
configuration 是feign的一些配置,例如编码器等。


@FeignClient(name = "sc-provider",fallback = MFeignClientFallback.class, configuration = MFeignConfig.class) public interface MFeignClient { // 这是被请求微服务的地址,也就是provider的地址 @GetMapping(value = "/test/{msg}") String sayHelloWorld(@PathVariable("msg") String msg); @FeignClient(name = "sc-provider",fallback = MFeignClientFallback.class, configuration = MFeignConfig.class) public interface MFeignClient { // 这是被请求微服务的地址,也就是provider的地址 @GetMapping(value = "/test/{msg}") String sayHelloWorld(@PathVariable("msg") String msg);<span class="hljs-meta">@GetMapping</span>(value = <span class="hljs-string">"/test/list"</span>) <span class="hljs-function">List&lt;Integer&gt; <span class="hljs-title">list</span><span class="hljs-params">()</span></span>; <span class="hljs-meta">@GetMapping</span>(value = <span class="hljs-string">"/test/list"</span>) Integer[] array(); <span class="hljs-meta">@GetMapping</span>(value = <span class="hljs-string">"/test/list"</span>) <span class="hljs-function">List&lt;Integer&gt; <span class="hljs-title">list</span><span class="hljs-params">()</span></span>; <span class="hljs-meta">@GetMapping</span>(value = <span class="hljs-string">"/test/list"</span>) Integer[] array();

}

  • 3 MFeignConfig.class feign的配置

这里配置了feign的打印日志等级

@Configuration public class MFeignConfig { @Bean Logger.Level feignLoggerLevel() { return Logger.Level.FULL; } } @Configuration public class MFeignConfig { @Bean Logger.Level feignLoggerLevel() { return Logger.Level.FULL; } }
  • 4 MFeignClientFallback.class ,断路器回调方法

断路器要实现上边定义的MFeignClient接口,请求失败,进入断路器时,会回调这里的方法。


@Component public class MFeignClientFallback implements MFeignClient{ @Override public String sayHelloWorld(String msg) { return "fallback"; } @Component public class MFeignClientFallback implements MFeignClient{ @Override public String sayHelloWorld(String msg) { return "fallback"; }<span class="hljs-meta">@Override</span> <span class="hljs-function"><span class="hljs-keyword">public</span> List&lt;Integer&gt; <span class="hljs-title">list</span><span class="hljs-params">()</span> </span>{ <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> ArrayList&lt;&gt;(); } <span class="hljs-meta">@Override</span> <span class="hljs-keyword">public</span> Integer[] array() { <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> Integer[<span class="hljs-number">0</span>]; } <span class="hljs-meta">@Override</span> <span class="hljs-function"><span class="hljs-keyword">public</span> List&lt;Integer&gt; <span class="hljs-title">list</span><span class="hljs-params">()</span> </span>{ <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> ArrayList&lt;&gt;(); } <span class="hljs-meta">@Override</span> <span class="hljs-keyword">public</span> Integer[] array() { <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> Integer[<span class="hljs-number">0</span>]; }

}

  • 5 在controller中使用feign

@RestController public class FeignController { @RestController public class FeignController {<span class="hljs-meta">@Autowired</span> <span class="hljs-keyword">private</span> MFeignClient feignClient; <span class="hljs-meta">@GetMapping</span>(<span class="hljs-string">"/feign/{wd}"</span>) <span class="hljs-function"><span class="hljs-keyword">public</span> Mono&lt;String&gt; <span class="hljs-title">sayHelloWorld</span><span class="hljs-params">(@PathVariable(<span class="hljs-string">"wd"</span>)</span> String parm) </span>{ String result = feignClient.sayHelloWorld(parm); <span class="hljs-keyword">return</span> Mono.just(result); } <span class="hljs-meta">@GetMapping</span>(<span class="hljs-string">"/feign/list"</span>) <span class="hljs-function"><span class="hljs-keyword">public</span> Flux&lt;Integer&gt; <span class="hljs-title">list</span><span class="hljs-params">()</span> </span>{ List&lt;Integer&gt; list = feignClient.list(); Flux&lt;Integer&gt; userFlux = Flux.fromIterable(list); <span class="hljs-keyword">return</span> userFlux; } <span class="hljs-meta">@GetMapping</span>(<span class="hljs-string">"/feign/array"</span>) <span class="hljs-function"><span class="hljs-keyword">public</span> Flux&lt;Integer&gt; <span class="hljs-title">array</span><span class="hljs-params">()</span> </span>{ Integer[] arrays = feignClient.array(); Flux&lt;Integer&gt; userFlux = Flux.fromArray(arrays); <span class="hljs-keyword">return</span> userFlux; } <span class="hljs-meta">@Autowired</span> <span class="hljs-keyword">private</span> MFeignClient feignClient; <span class="hljs-meta">@GetMapping</span>(<span class="hljs-string">"/feign/{wd}"</span>) <span class="hljs-function"><span class="hljs-keyword">public</span> Mono&lt;String&gt; <span class="hljs-title">sayHelloWorld</span><span class="hljs-params">(@PathVariable(<span class="hljs-string">"wd"</span>)</span> String parm) </span>{ String result = feignClient.sayHelloWorld(parm); <span class="hljs-keyword">return</span> Mono.just(result); } <span class="hljs-meta">@GetMapping</span>(<span class="hljs-string">"/feign/list"</span>) <span class="hljs-function"><span class="hljs-keyword">public</span> Flux&lt;Integer&gt; <span class="hljs-title">list</span><span class="hljs-params">()</span> </span>{ List&lt;Integer&gt; list = feignClient.list(); Flux&lt;Integer&gt; userFlux = Flux.fromIterable(list); <span class="hljs-keyword">return</span> userFlux; } <span class="hljs-meta">@GetMapping</span>(<span class="hljs-string">"/feign/array"</span>) <span class="hljs-function"><span class="hljs-keyword">public</span> Flux&lt;Integer&gt; <span class="hljs-title">array</span><span class="hljs-params">()</span> </span>{ Integer[] arrays = feignClient.array(); Flux&lt;Integer&gt; userFlux = Flux.fromArray(arrays); <span class="hljs-keyword">return</span> userFlux; }

}

9.png

5、用zuul作路由转发和负载均衡

这些微服务都是隐藏在后端的,用户是看不到,或者不是直接接触,能够用nginx或者zuul进行路由转发和负载均衡,zuul负载均衡默认用的是ribbon。

  • 1.修改build.gradle文件
compile('org.springframework.cloud:spring-cloud-starter-netflix-eureka-client')
    compile('org.springframework.cloud:spring-cloud-starter-config')
    compile('org.springframework.cloud:spring-cloud-starter-netflix-zuul')
    compile('org.springframework.boot:spring-boot-starter-actuator')
  • 2.修改bootstrap.yml

仍是原来的配方,application.yml在git仓库

eureka:
  client:
    service-url:
      defaultZone: http://root:booszy@localhost:8761/eureka/
  instance:
    prefer-ip-address: true
    instance-id: ${spring.application.name}:${spring.application.instance_id:${server.port}}
    appname: sc-zuul

spring:
application:
name: sc-zuul
cloud:
config:
discovery:
enabled: true
service-id: sc-config-server
fail-fast: true
username: root
password: booszy
profile: csdn

  • 3.启动类

@RefreshScope这个注解是当application.yml配置文件发生变化的时候,不须要手动的进行重启,调用localhost:8400/refresh,就会加载新的配置文件,固然正在访问的客户并不影响仍是使用旧的配置文件,由于不是重启,后来的用户会使用新的配置文件。注意这块的刷新要用post请求

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

启动springboot项目,访问eureka-server


10.png

这时候,咱们就要经过zuul访问微服务了,而不是直接去访问微服务。
应该访问地址http://localhost:8400/sc-consumer/feign/list,这块你要换成你的zuul地址。

可是有些人就会说,这样之后用户请求会不会太长,比较反感,因此能够经过配置进行修改访问地址。

zuul: routes: springcloud-consumer-config: /consumer/** springcloud-provider-config: /provider/** zuul: routes: springcloud-consumer-config: /consumer/** springcloud-provider-config: /provider/**

在application.yml中加入这样一段配置,其实就是nginx中的反向代理,使用一下简短的能够代理这个微服务。这个时候咱们就能够这样去访问了http://localhost:8400/consumer/feign/list,是否是简短了不少

11.png

6、用hystrix-turbine-dashboard 作集群监控

项目在生产环境中,每一个服务的访问量都不通,有些服务的访问量比较大,有时候有些服务挂了,不能继续服务,须要重启的时候,咱们并不知道,因此这时候就须要使用hystrix-turbine-dashboard作一个监控,监控全部的微服务,能够看到这个接口实时访问量,和健康情况。
新建一个springboot项目,老套路,加入以下依赖

  • 1 添加依赖
compile('org.springframework.cloud:spring-cloud-starter-netflix-eureka-client')
compile('org.springframework.boot:spring-boot-starter-actuator')
compile('org.springframework.cloud:spring-cloud-starter-netflix-hystrix')
compile('org.springframework.cloud:spring-cloud-starter-netflix-hystrix-dashboard')
compile('org.springframework.cloud:spring-cloud-starter-netflix-turbine')
  • 2 修改application.yml配置文件
    注意:是application.yml,这里不须要bootstrap.yml
server: port: 8900 eureka: client: service-url: defaultZone: http://root:booszy@localhost:8761/eureka/ instance: prefer-ip-address: true instance-id: ${spring.application.name}:${spring.application.instance_id:${server.port}} appname: sc-dashboard turbine: aggregator: clusterConfig: default appConfig: sc-consumer clusterNameExpression: "'default'" spring: application: name: sc-dashboard #management: # endpoints: # web: # exposure: # include: '*' server: port: 8900 eureka: client: service-url: defaultZone: http://root:booszy@localhost:8761/eureka/ instance: prefer-ip-address: true instance-id: ${spring.application.name}:${spring.application.instance_id:${server.port}} appname: sc-dashboard turbine: aggregator: clusterConfig: default appConfig: sc-consumer clusterNameExpression: "'default'" spring: application: name: sc-dashboard #management: # endpoints: # web: # exposure: # include: '*'

appConfig 后面是要检测的注册在eureka上的服务名,必需要有

  • 3 修改主类

@EnableTurbine ,@EnableHystrixDashboard 一个都不能少

@EnableDiscoveryClient @SpringBootApplication @EnableTurbine @EnableHystrixDashboard public class Sb2scDashboardApplication { public static void main(String[] args) { SpringApplication.run(Sb2scDashboardApplication.class, args); } } @EnableDiscoveryClient @SpringBootApplication @EnableTurbine @EnableHystrixDashboard public class Sb2scDashboardApplication { public static void main(String[] args) { SpringApplication.run(Sb2scDashboardApplication.class, args); } }
  • 4 访问测试

这块的端口是8900,访问地址http://localhost:8900/hystrix,看到的是下面的页面。

13.png

而后在那个网址的输入框里输网址http://localhost:8900/turbine.stream,点击monitor stream。刚打开的时候多是空的,什么也没有,这并不表示你已经错了。这时候你访问消费者服务的接口,例如访问http://localhost:8400/consumer/feign/list,多访问几回,而后看控制台有没有出现一个监控面板,没有就等会刷新一次,若是一直不出现,应该是配置有问题。

12.png

7、使用sleuth+zipkin 实现链路追踪服务

在使用微服务的时候,咱们发现,有时候排错很差排查,因此就给你们整个这个链路追踪,很方便知道是哪个服务调用哪个服务出现了问题。由于有些项目可能服务比较多。

  • 1 添加依赖

新建一个springboot项目
虽然其余服务调用zipkin不是从eureka上动态过去服务地址,而是硬编码,可是这块仍是考虑吧zipkin注册到eureka上。

compile('org.springframework.cloud:spring-cloud-starter-netflix-eureka-client')
compile group: 'io.zipkin.java', name: 'zipkin-server', version: '2.9.3'
compile group: 'io.zipkin.java', name: 'zipkin-autoconfigure-ui', version: '2.9.3'
compile('org.springframework.boot:spring-boot-starter-actuator')

若是提示log4j有冲突,要排除依赖

configurations { compile.exclude module: 'log4j' compile.exclude module: 'slf4j-log4j12' compile.exclude module: 'spring-boot-starter-logging' } configurations { compile.exclude module: 'log4j' compile.exclude module: 'slf4j-log4j12' compile.exclude module: 'spring-boot-starter-logging' }
  • 2 修改application配置文件
server:
  port: 9411
spring:
  application:
    name: sc-sc-zipkin
  profiles:
    active: csdn
eureka:
  client:
    service-url:
      defaultZone: http://root:booszy@localhost:8761/eureka/
  instance:
    prefer-ip-address: true
    instance-id: ${spring.application.name}:${spring.application.instance_id:${server.port}}
    appname: sc-zipkin
management:
  metrics:
    web:
      server:
        auto-time-requests: false
  • 3 主类注解添加

@EnableZipkinServer 主要是这个注解
启动服务后访问http://localhost:9411,就能够打开zipkin的控制台页面,这时候应该是什么都没有

@EnableDiscoveryClient @SpringBootApplication @EnableZipkinServer public class Sb2scZipkinApplication { public static void main(String[] args) { SpringApplication.run(Sb2scZipkinApplication.class, args); } } @EnableDiscoveryClient @SpringBootApplication @EnableZipkinServer public class Sb2scZipkinApplication { public static void main(String[] args) { SpringApplication.run(Sb2scZipkinApplication.class, args); } }
  • 4 其余服务中调用

这里咱们在消费者服务和提供者服务里都加入以下依赖

....
compile group: 'org.springframework.cloud', name: 'spring-cloud-starter-sleuth', version: '1.3.1.RELEASE'
compile group: 'org.springframework.cloud', name: 'spring-cloud-sleuth-zipkin', version: '1.3.1.RELEASE'
...

而后修改配置文件,bootstrap.yml、
这块zipkin的地址是硬编码的,目前还没发现怎么从服务注册中心eureka上动态获取,之后有解决方案,会更新帖子
sleuth这个是配置提取率,能够配置也能够不配置

spring: zipkin: base-url: http://localhost:9411 sleuth: sampler: percentage: 1.0 spring: zipkin: base-url: http://localhost:9411 sleuth: sampler: percentage: 1.0

启动服务,而后访问消费者服务的接口,这时候访问zipkin的控制台http://localhost:9411

14.png

点击依赖分析,能够看到调用服务链,由于这块只涉及到两个服务,因此只有两个,在实际生产环境中,这块可能有不少,到时候看起来就特别直观了。

15.png