程序员程序园SpringCloud

SpringCloud Consul Finchley架构测试

2019-04-29  本文已影响29人  DONG999

整体图

image.png

1. 搭建Consul Server Cluster

REF sites:

https://github.com/hashicorp/consul
https://www.consul.io/downloads.html

过程略(ACL)
[root@hadoopnode3 ~]# consul members -http-addr=10.0.0.8:8500
Node     Address            Status  Type    Build  Protocol  DC   Segment
node104  10.0.0.104:8301  alive   server  1.4.4  2         dc1  <all>
node19   10.0.0.19:8301     alive   server  1.4.4  2         dc1  <all>
node9    10.0.0.9:8301     alive   server  1.4.4  2         dc1  <all>
node8   10.0.0.8:8301     alive   client  1.4.4  2         dc1  <default>

2. 搭建基础maven parent projects in STS/eclipse

image.png
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.sc</groupId>
    <artifactId>spring-boot-cloud-consul</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>pom</packaging>
    <name>${project.artifactId}</name>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.4.RELEASE</version>
        <relativePath/>
    </parent>

    <modules>
        <module>consul-gateway</module>       
        <module>consul-auth-service</module>
        <module>consul-service-a</module>
        <module>consul-service-b</module>
        <module>consul-common</module>
  </modules>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <java.version>1.8</java.version>
        <docker.plugin.version>1.0.0</docker.plugin.version>
        <docker.image.prefix>spring-boot-cloud-consul</docker.image.prefix>
        <spring.cloud.version>Finchley.SR1</spring.cloud.version>
        <spring-boot-admin.version>2.0.4</spring-boot-admin.version>
        <!--spring-boot.version>2.0.4.RELEASE</spring-boot.version-->
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <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>
            
            <!-- 
             <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>${spring-boot.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            -->
        </dependencies>
    </dependencyManagement>

    <build>
        <pluginManagement>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                    <executions>
                        <execution>
                            <goals>
                                <goal>repackage</goal>
                            </goals>
                        </execution>
                    </executions>
                </plugin>
                <plugin>
                    <groupId>com.spotify</groupId>
                    <artifactId>docker-maven-plugin</artifactId>
                    <version>${docker.plugin.version}</version>
                    <executions>
                        <execution>
                            <phase>package</phase>
                            <goals>
                                <goal>build</goal>
                            </goals>
                        </execution>
                    </executions>
                    <configuration>
                        <imageName>${docker.image.prefix}/${project.artifactId}</imageName>
                        <dockerDirectory>${project.basedir}/</dockerDirectory>
                        <resources>
                            <resource>
                                <targetPath>/</targetPath>
                                <directory>${project.build.directory}</directory>
                                <include>${project.build.finalName}.jar</include>
                            </resource>
                        </resources>
                    </configuration>
                </plugin>
            </plugins>
        </pluginManagement>
    </build>
</project>

3. OAuth2认证项目 - consul-auth-service


│   Dockerfile
│   pom.xml

├───src
│   ├───main
│   │   ├───java
│   │   │   └───com
│   │   │       └───sc
│   │   │           └───auth
│   │   │               │   AuthApplication.java
│   │   │               │
│   │   │               ├───config
│   │   │               │       OAuthConfiguration.java
│   │   │               │       ResourceServerConfiguration.java
│   │   │               │       WebSecurityConfigurer.java
│   │   │               │
│   │   │               ├───controller
│   │   │               │       UserController.java
│   │   │               │
│   │   │               ├───entity
│   │   │               │       Authority.java
│   │   │               │       OAuthUser.java
│   │   │               │       User.java
│   │   │               │
│   │   │               ├───jpa
│   │   │               │       AuthorityJPA.java
│   │   │               │       UserJPA.java
│   │   │               │
│   │   │               └───service
│   │   │                       AuthUserDetailsService.java
│   │   │
│   │   └───resources
│   │           application.yml
│   │           bootstrap.yml
│   │           oauth2.sql
主要是提供oauth2 server side 认证. oauth2 信息包括用户表创建都在mysql, 参考oauth2.sql
参考配置:
        //data init script - oauth_client_details
        /**
        clients.jdbc(dataSource).passwordEncoder(passwordEncoder)
            .withClient("client").secret("secret")
                .authorizedGrantTypes("password", "refresh_token").scopes("read", "write")
                .accessTokenValiditySeconds(3600) // 1 hour
                .refreshTokenValiditySeconds(2592000) // 30 days
                .and()
                .withClient("service-a").secret("password")
                .authorizedGrantTypes("client_credentials", "refresh_token").scopes("server")
                .and()
                .withClient("service-b").secret("password")
                .authorizedGrantTypes("client_credentials", "refresh_token").scopes("server")
                .and()
                .withClient("client_code") // client_id
                .secret("secret_code") // client_secret
                .authorizedGrantTypes("authorization_code") // 该client允许的授权类型
                .scopes("app"); // 允许的授权范围 ;
        */

4. SpringCloud Gateway 项目 - consul-gateway

用户限流, 负载平衡, 功能转向等, 主要是配置
image.png
Spring Cloud Consul Config- support dynamic updates
image.png
server:
  port: 8900
 
spring:        
    #限流redis server 
  redis:
    host: 10.0.0.119
    port: 6379
    database: 0
    
  cloud:
    gateway:
      discovery:
        locator:
          # 是否用service name 自动发现
          enabled: false
          lowerCaseServiceId: true
                
      default-filters:
      #全局配置    
      # 熔断降级配置
      - name: Hystrix
        args:
          name : default
          fallbackUri: 'forward:/defaultfallback'    
          
      #RequestRateLimiter can not be global until 2.1.0
      #https://github.com/spring-cloud/spring-cloud-gateway/pull/720   
      
      routes:
      - id: auth-service
        uri: lb://consul-auth-service
        predicates:
        - Path=/uaa/**
        filters:
        - StripPrefix=1
      
      
      - id: service-a
        uri: lb://consul-service-a
        predicates:
        - Path=/svca/**
        filters:
        - StripPrefix=1
        # redis限流 , filter名称必须是RequestRateLimiter
        - name: RequestRateLimiter
          args:
                           # 使用SpEL名称引用Bean,与上面新建的RateLimiterConfig类中的bean的name相同
            key-resolver: '#{@urlPathKeyResolver}'
                            # 每秒最大访问次数
            redis-rate-limiter.replenishRate: 4
                            # 令牌桶最大容量
            redis-rate-limiter.burstCapacity: 4 
          
      - id: svcb
        uri: lb://consul-service-b
        predicates:
        - Path=/svcb/**
        filters:
        - StripPrefix=1
        - name: Hystrix
          args:
            name: fallback
            fallbackUri: 'forward:/fallback'        

      - id: rewritepath_route
        uri: https://blog.csdn.net
        predicates:
        - Path=/csdn/**
        filters:
        - RewritePath=/csdn/(?<segment>.*), /$\{segment}    
        
      - id: limit_route
        uri: http://www.baidu.com
        predicates:
        - Path=/baidu/**
        - After=2019-04-10T08:00:00.001-07:00[America/Denver]
        filters:
        - name: RequestRateLimiter
          args:
            key-resolver: '#{@remoteAddrKeyResolver}'
            redis-rate-limiter.replenishRate: 1
            redis-rate-limiter.burstCapacity: 1       



  sleuth:
    sampler:
      percentage: 1
      probability: 1.0 # 将采样比例设置为 1.0,也就是全部都需要。默认是 0.1
    integration:
      enabled: false
    scheduled:
      skip-pattern: "^org.*HystrixStreamTask$"
    web:
      client:
        enabled: true #web开启sleuth功能
      
  zipkin:
    base-url: http://${ZIPKIN-SERVER:zipkin-server}:9411      

#totally customized vars
#not solved, https://github.com/spring-cloud/spring-cloud-security/issues/61
authserver:
    #hostname: auth-service
    hostname: AUTH-SERVICE
    port: 8001
    contextPath: 

#https://docs.spring.io/spring-security-oauth2-boot/docs/current-SNAPSHOT/reference/htmlsingle/
security:
  oauth2:
    resource:
      user-info-uri: http://${authserver.hostname}:${authserver.port}${authserver.contextPath}/current
      #prefer-token-info: true # Use the token info, can be set to false to use the user info.

#HystrixDashboard
management:
  endpoints:
    web:
      exposure:
        #include: hystrix.stream, info, health
        include: "*"
      cors:
        allowed-origins: "*"
        allowed-methods: "*"
      #base-path: actuator //by default

turbine:
  app-config: consul-service-a,consul-service-b
  aggregator:
    clusterConfig: default
  clusterNameExpression: new String("default")
  combine-host: true
  instanceUrlSuffix:
    default: actuator/hystrix.stream  

hystrix:
  command:
    default:
      execution:
        isolation:
          thread:
            timeoutInMilliseconds: 3000 #默认:(方法上记得要加上@HystrixCommand,否则无效)
#          strategy: SEMAPHORE
feign:
  hystrix:
    enabled: true 
              
ribbon:
  ReadTimeout: 5000
  ConnectTimeout: 5000
  #https://github.com/spring-cloud/spring-cloud-security/issues/61
  http:
    client:
      enabled: true  
      

    
logging:
  level:
    root: INFO
    org.springframework: INFO   

5. 具体子项目实现demo - consul-service-a&consul-service-b

重点是测试Feigh client and Ribbon client
FeignClient需要配置Oauth2 client信息传递
package com.sc.svca.client;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;



@FeignClient(name = "consul-service-b", fallback = FeignServiceBClient.ServiceBClientFallback.class)
public interface FeignServiceBClient {

    @GetMapping(value = "/test")
    String test();
    
    @RequestMapping(value = "/hi",method = RequestMethod.GET)
    String sayHiFromClientOne(@RequestParam(value = "name") String name);
    
    //String getSessionId(@RequestHeader("X-Auth-Token") String token);

    @Component
    class ServiceBClientFallback implements FeignServiceBClient {

        private static final Logger LOGGER = LoggerFactory.getLogger(ServiceBClientFallback.class);

        @Override
        public String test() {
            LOGGER.info("now flow into callback method...");
            return "SERVICE B FAILED! - FALLING BACK";
        }
        
        @Override
        public String sayHiFromClientOne(String name) {
            return "SERVICE sayHiFromClientOne  FAILED! - FALLING BACK - with parameter - name:" + name;
            //SERVICE sayHiFromClientOne  FAILED! - FALLING BACK - with parameter - name:abc
            
        }
    }
}
Ribbon Client也需要公用consul-common模块的oauth2 client配置
package com.sc.svca.service;

import javax.servlet.http.HttpServletRequest;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.sc.cmn.config.RestTemplateClient;

 

/**
   RestTemplate(Oauth2 supported)+Ribbon 
 **/
@Service
public class RibbonUserServiceClient extends RestTemplateClient {

    //@Autowired
    //RestTemplate restTemplate;

    @HystrixCommand(fallbackMethod = "userIdNotFound")
    public String getCurrUserId(HttpServletRequest request) {

        String userId = getRestObject("consul-auth-service", "/getCurrUserId", getHeaders(request), null, String.class);
 
        return userId;
    }

    public String userIdNotFound(HttpServletRequest request) {
        return "can not find any userId logged in!";
    } 
}
consul-service-a sample
package com.sc.svca;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.hystrix.EnableHystrix;
import org.springframework.cloud.netflix.turbine.EnableTurbine;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableOAuth2Client;

import com.netflix.hystrix.contrib.metrics.eventstream.HystrixMetricsStreamServlet;
import com.sc.cmn.config.FeignHystrixConcurrencyStrategy;

@EnableTurbine //Notes: 开启turbine,@EnableTurbine注解包含了@EnableDiscoveryClient注解
//@EnableTurbineStream # 不可共存
@EnableDiscoveryClient 
@EnableFeignClients
@SpringBootApplication
@EnableCircuitBreaker //Note: 如果不加,Dashboard无法接收到来自Feign内部断路器的监控数据
@EnableHystrix //Note: 开启断路器
//@EnableHystrixDashboard //Hystrix仪表板, server UI part, now using standalone version
@EnableOAuth2Client
@ComponentScan({"com.sc.cmn","com.sc.svca"})
public class ServiceAApplication {
    
     /**
      * http://localhost:8764/turbine.stream
        * 访问地址 http://localhost:8762/actuator/hystrix.stream
        * @param args
     */

    public static void main(String[] args) {
        SpringApplication.run(ServiceAApplication.class, args);
    }
    
 
    @Bean
    public FeignHystrixConcurrencyStrategy feignHystrixConcurrencyStrategy() {
        return new FeignHystrixConcurrencyStrategy();
    } 
    
    @Bean
    public ServletRegistrationBean getServlet(){
        HystrixMetricsStreamServlet streamServlet = new HystrixMetricsStreamServlet();
        ServletRegistrationBean registrationBean = new ServletRegistrationBean(streamServlet);
        registrationBean.setLoadOnStartup(1);
        registrationBean.addUrlMappings("/actuator/hystrix.stream");
        registrationBean.setName("HystrixMetricsStreamServlet");
        return registrationBean;
    }
    

}
Controller测试部分sample
package com.sc.svca.controller;

import java.security.Principal;

import javax.servlet.http.HttpServletRequest;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import com.sc.cmn.util.ResponseModel;
import com.sc.svca.client.FeignServiceBClient;
import com.sc.svca.service.RibbonServiceBClient;
import com.sc.svca.service.RibbonUserServiceClient;

/**
 * curl -X POST -vu client:secret http://gateway-server:8900/uaa/oauth/token -H "Accept: application/json" -d "password=password&username=admin&grant_type=password&scope=read%20write"
 * 
 *
 */
//Spring Cloud Consul Config support dynamic change, add @RefreshScope
@RefreshScope
@RestController
public class ServiceAController {

    private static final Logger log = LoggerFactory.getLogger(ServiceAController.class);

    //from application.yml config
    @Value("${msg:unknown}")
    private String msg;
    
    //from consul config
    @Value("${my.consul.val}")
    String myConsulVal;

    //@Autowired
    //EurekaDiscoveryClient discoveryClient;
    //replace eureka with consul
    @Autowired
    private DiscoveryClient discoveryClient;
    
    @Autowired
    private FeignServiceBClient serviceBClient;

    @Autowired
    private RibbonUserServiceClient userService;

    @GetMapping(value = "/")
    public String printServiceA() {

        log.info(discoveryClient.getInstances("consul-service-a").toString());      

        ServiceInstance serviceInstance = discoveryClient.getInstances("consul-service-a").get(0);

        return serviceInstance.getServiceId() + " (" + serviceInstance.getHost() + ":" + serviceInstance.getPort() + ")"
                + "===>name:" + msg + "<br/>";
        
        //consul-service-a (10.0.0.63:8901)===>name:test_string<br/>

    }

    @Value("${server.port}")
    String port;

    @RequestMapping("/hi2")
    public String home(@RequestParam(value = "name", defaultValue = "defName") String name) {
        return "hi " + name + " ,i am from port:" + port + ", get consul config my.consul.val=" + myConsulVal;
        /**
         * dynamic config change on Consul
         * 
            [root@hadoopnode4 sts]#  curl -i -H "Authorization: Bearer 8cb5bd5b-86c7-4f06-991c-ccc358060bfc" http://10.0.0.8:8900/svca/hi2
            hi defName ,i am from port:8901, get consul config my.consul.val=myVal
            
            [updated on Consul console...]
            
            [root@hadoopnode4 sts]#  curl -i -H "Authorization: Bearer 8cb5bd5b-86c7-4f06-991c-ccc358060bfc" http://10.0.0.8:8900/svca/hi2
            hi defName ,i am from port:8901, get consul config my.consul.val=myVal_new
         * 
         */
    }

    /**
     * way 1 - feign fallback
     * 
     * the name parameter must be provided when calling
     * 
     * [root@hadoopnode4 ~]# curl -i -H "Authorization: Bearer
     * a8914a80-c6c0-46ae-9828-2bb7c8cb521a" http://10.0.0.63:8080/hi?name=abc
     * 
     * @param name
     * @return
     */
    @GetMapping(value = "/hi")
    public String sayHi(@RequestParam String name) {

        log.info("calling into svca-hi with name======>" + name);
        return serviceBClient.sayHiFromClientOne(name);
    }

    /**
     * 
     * [root@hadoopnode4 ~]# curl -i -H "Authorization: Bearer
     * 1c76f4f5-cf95-428c-ae96-c45715c8f7ae" http://10.0.0.63:8901/test
     * {"status":200,"msg":"�功","data":{},"perm":null}
     * 
     * @return
     */
    @GetMapping(value = "/test")
    public String test() {
        return serviceBClient.test();
    }

    @Autowired
    RibbonServiceBClient serviceBService;

    /**
     * way 2 - ribbon fallback
     * 
     * [root@hadoopnode4 ~]# curl -X POST -i -H "Authorization: Bearer
     * 1c76f4f5-cf95-428c-ae96-c45715c8f7ae" http://10.0.0.63:8901/hitest -d
     * 'name=zhou&b=2&c=3'
     * 
     * {"status":200,"msg":"�功","data":{"b":"2","c":"3","name":"zhou"}}[root@hadoopnode4
     * ~]#
     * 
     * @return
     */
    @RequestMapping(value = "/hitest", method = RequestMethod.POST)
    public ResponseModel hiTest(HttpServletRequest request) {
        // request.getParameter("name") //hib?name=abc
        return serviceBService.hiService(request);
    }

    @RequestMapping(value = "/hib")
    public String hiB(HttpServletRequest request) {
        return serviceBService.hi(request);
    }


    @RequestMapping(value = "/getCurrUserId")
    public String getCurrUserId(HttpServletRequest request) {
        return userService.getCurrUserId(request);
    }

    @GetMapping(path = "/current")
    public Principal getCurrentAccount(Principal principal) {
        return principal;
    }
    
    
    @Autowired
    private LoadBalancerClient loadBalancer;
 

    /**
     * 获取所有服务
     */
    @RequestMapping("/services")
    public Object services() {
        // 获取对应服务名称的所有实例信息
        return discoveryClient.getInstances("consul-service-b");
        //[{"serviceId":"consul-a","host":"10.0.0.63","port":8201,"secure":false,"metadata":{"secure":"false"},"uri":"http://10.0.0.63:8201","scheme":null}]
    }
 
    @Autowired
    RestTemplate restTemplate;
    
    /**
     * Demo for invalid call, without token passed
     * error":"invalid_token
     * 
     * @return
     */
    @RequestMapping("/callB")
    public String call() {
        ServiceInstance serviceInstance = loadBalancer.choose("consul-service-b");
        log.info("serviceInstance.getUri:" + serviceInstance.getUri());
        log.info("serviceInstance.getServiceId:" + serviceInstance.getServiceId());

        String callServiceResult = restTemplate.getForObject(serviceInstance.getUri().toString() + "/hi",
                String.class);
        log.info("callServiceResult:" + callServiceResult);
        return callServiceResult;
    }
    
    

}
基础pom配置
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <parent>
        <groupId>com.sc</groupId>
        <artifactId>spring-boot-cloud-consul</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>

    <artifactId>consul-service-a</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>
    <name>${project.artifactId}</name>

    <dependencies>

        <!-- 加入common依赖 -->
        <dependency>
            <groupId>com.sc</groupId>
            <artifactId>consul-common</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-consul-discovery</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-consul-config</artifactId>
        </dependency>
        
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-security</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency> 

        <!-- HYSTRIX -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
        </dependency>
        <!-- now used stand-alone dashboard version
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
        </dependency>
         -->
         
        <!-- RIBBON -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
        </dependency>
        
        <!-- spring-boot-starter-actuator中实现了Hystrix metrics stream。暴露/hystrix.stream作为一个管理端点 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        

        <!--
             分布式服务调用链路跟踪实现的核心依赖 Spring 应用在监测到 classpath 中有 Sleuth 和 Zipkin 后, 会自动在 
            WebClient 或者 RestTemplate 的调用过程中向 HTTP 请求注入追踪信息, 并向 Zipkin Server 发送这些信息。 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-sleuth</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-zipkin</artifactId>
        </dependency>

        <!-- Hystrix Turbine将每个服务Hystrix Dashboard数据进行了整合 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-turbine</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.cloud</groupId>
                    <artifactId>
                        spring-cloud-starter-netflix-eureka-client
                    </artifactId>
                </exclusion>
            </exclusions>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>



    <build>
        <finalName>${project.artifactId}</finalName>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
            <!-- <plugin> <groupId>com.spotify</groupId> <artifactId>docker-maven-plugin</artifactId> 
                </plugin> -->
        </plugins>
    </build>

</project>
连接注册consul部分yml配置
 
# document: https://docs.spring.io/spring-security-oauth2-boot/docs/current-SNAPSHOT/reference/htmlsingle/

security:
  oauth2:
    client:
      clientId: service-a  #clientId from OAUTH2 definition in db
      clientSecret: ${SVCA_CLIENT_SECRET_OAUTH2:password} 
      accessTokenUri: http://${authserver.hostname}:${authserver.port}${authserver.contextPath}/oauth/token
      grant-type: client_credentials,password
      scope: server

spring:  
  profiles:
    active: consul-dev  #consul 配置key profile
  application:
    name: consul-service-a
  cloud:
    consul:
      host: hadoopnode3
      port: 8500
      discovery:
        serviceName: consul-service-a
        instance-id: ${spring.application.name}:${spring.cloud.client.ip-address}:${server.port} #实例ID
        health-check-path: /actuator/health                                                      #健康检查
        health-check-interval: 10s
        prefer-ip-address: true
        #ip-address: 10.0.0.63
        #register-health-check: true
        #health-check-critical-timeout: 2m
      token: ${SPRING_CLOUD_CONSUL_TOKEN:245d0a09-7139-bbea-aadc-ff170a0562b1}
      config:
        enabled: true #设置config是否启用,默认为true
        format: yaml   #设置配置的值的格式,可以yaml和properties        
        prefix: config     #目录,比如config
        profile-separator: ':'    #配置分隔符,默认为‘,’
        data-key: data  #为应用配置的key名字,值为整个应用配置的字符串
        
        #defaultContext 设置默认的配置,被所有的应用读取,本例子没用的

6. Zipkin Server

java -jar zipkin-server-2.12.9-exec.jar --STORAGE_TYPE=mysql --MYSQL_DB=zipkin --MYSQL_USER=root --MYSQL_PASS=mypass --MYSQL_HOST=10.0.0.8 --MYSQL_TCP_PORT=3306

https://zipkin.io/pages/architecture.html?from=singlemessage&isappinstalled=0

看到 每个call的时间及轨迹
image.png

7. Hystrix Dashboard

感受实时统计

https://github.com/kennedyoliveira/standalone-hystrix-dashboard

image.png
[root@hadoopnode4 sts]# java -jar standalone-hystrix-dashboard-1.5.6-all.jar
http://hadoopnode4:7979/hystrix-dashboard/

7. 结束语

https://github.com/dong099/spring-cloud-enterprise-consul

上一篇下一篇

猜你喜欢

热点阅读