SpringCloud微服务实战

主要有eureka做服务发现、config做分布式配置、zuul做api-gateway、feign做客户端负载均衡、hystrix做断路器、turbine做聚合的monitor、graphite做指标监控。

eureka

  • pom配置

<dependencies>
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-webartifactId>
        dependency>
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-actuatorartifactId>
        dependency>
        <dependency>
            <groupId>org.springframework.cloudgroupId>
            <artifactId>spring-cloud-starter-eureka-serverartifactId>
        dependency>
        <dependency>
            <groupId>junitgroupId>
            <artifactId>junitartifactId>
            <scope>testscope>
        dependency>
    dependencies>
  • application.yml

server:
  port: 8761

eureka:
  instance:
    hostname: discovery
  client:
    registerWithEureka: false
    fetchRegistry: false
    serviceUrl:
      defaultZone: http://discovery:${server.port}/eureka/

spring.cloud.config.discovery.enabled: true
  • bootstrap.yml

spring:
  application:
    name: discovery
  • application

@SpringBootApplication
@EnableEurekaServer
public class EurekaApplication {
    public static void main( String[] args ) {
        SpringApplication.run(EurekaApplication.class, args);
    }
}
  • 访问
    http://192.168.99.100:8761/

SpringCloud微服务实战_第1张图片

config

  • pom配置

<dependencies>
        <dependency>
            <groupId>org.springframework.cloudgroupId>
            <artifactId>spring-cloud-starterartifactId>
        dependency>
        <dependency>
            <groupId>org.springframework.cloudgroupId>
            <artifactId>spring-cloud-config-serverartifactId>
        dependency>
        <dependency>
            <groupId>org.springframework.cloudgroupId>
            <artifactId>spring-cloud-starter-eurekaartifactId>
        dependency>
    dependencies>
  • application.yml

spring:
  cloud:
    config:
      server:
        native:
          search-locations: classpath:/config

server:
  port: 8888
  • bootstrap.yml

spring:
  application:
    name: config
  profiles:
    active: native
    
eureka:
  instance:
    preferIpAddress: true
  client:
    service-url:
      defaultZone: http://discovery:8761/eureka/
  • application

@SpringBootApplication
@EnableConfigServer
@EnableEurekaClient
public class ConfigApplication {
    public static void main( String[] args ) {
        SpringApplication.run(ConfigApplication.class,args);
    }
}
  • 访问
    http://192.168.99.100:8888/review/default/master

feign实例

  • pom

<dependencies>
        <dependency>
            <groupId>org.springframework.cloudgroupId>
            <artifactId>spring-cloud-starterartifactId>
        dependency>
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-webartifactId>
        dependency>
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-actuatorartifactId>
        dependency>
        <dependency>
            <groupId>org.springframework.cloudgroupId>
            <artifactId>spring-cloud-config-clientartifactId>
        dependency>
        <dependency>
            <groupId>org.springframework.cloudgroupId>
            <artifactId>spring-cloud-starter-eurekaartifactId>
        dependency>
        <dependency>
            <groupId>com.patterncatgroupId>
            <artifactId>commonartifactId>
            <version>1.0-SNAPSHOTversion>
        dependency>

        
        <dependency>
            <groupId>org.springframework.cloudgroupId>
            <artifactId>spring-cloud-starter-ribbonartifactId>
        dependency>
        <dependency>
            <groupId>org.springframework.cloudgroupId>
            <artifactId>spring-cloud-starter-feignartifactId>
        dependency>

        
        <dependency>
            <groupId>org.springframework.cloudgroupId>
            <artifactId>spring-cloud-starter-hystrixartifactId>
        dependency>
        <dependency>
            <groupId>org.springframework.cloudgroupId>
            <artifactId>spring-cloud-starter-hystrix-dashboardartifactId>
        dependency>

    dependencies>
  • application.yml

server:
  port: 9001

endpoints:
  restart:
    enabled: true
  shutdown:
    enabled: true
  health:
    sensitive: false

ribbon:
  eureka:
    enabled: true
  • bootstrap.yml

spring:
  application:
    name: product
  cloud:
    config:
      uri: http://config:8888
encrypt:
  failOnError: false

eureka:
  instance:
    preferIpAddress: true
  client:
    registerWithEureka: true
    fetchRegistry: true
    serviceUrl:
      defaultZone: http://discovery:8761/eureka/
  • FeignClient

@FeignClient("recommend")
public interface RemoteRecommendService {
    @RequestMapping(method = RequestMethod.GET,value = "/recommend")
    public List getRecommendations(
            @RequestParam(value = "productId",  required = true) int productId);
}
  • feign使用

@RestController
public class ProductController {

    private static final Logger LOG = LoggerFactory.getLogger(ProductController.class);

    @Autowired
    private SetProcTimeBean setProcTimeBean;

    @Autowired
    RemoteRecommendService remoteRecommendService;

    @RequestMapping("/product/recommends")
    @HystrixCommand(fallbackMethod = "callRecommendFallback", commandProperties = {
            @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "100")
    })
    public List remoteRecommends(@RequestParam(value = "productId",  required = true) int productId){
        return remoteRecommendService.getRecommendations(productId);
    }

    public List callRecommendFallback(int productId) {
        return Collections.emptyList();
    }

    @RequestMapping("/product/{productId}")
    public Product getProduct(@PathVariable int productId) {

        int pt = setProcTimeBean.calculateProcessingTime();
        LOG.info("/product called, processing time: {}", pt);

        sleep(pt);

        LOG.debug("/product return the found product");
        return new Product(productId, "name", 123);
    }
}
  • application

@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
@EnableCircuitBreaker
@EnableHystrix
@EnableHystrixDashboard
public class ProductApplication {
    private static final Logger LOG = LoggerFactory.getLogger(ProductApplication.class);

    public static void main(String[] args){
        SpringApplication.run(ProductApplication.class,args);
        LOG.info("Register ShutdownHook");
        Runtime.getRuntime().addShutdownHook(new Thread(){
            @Override
            public void run() {
                LOG.info("Shutting down product service, unregister from Eureka!");
                DiscoveryManager.getInstance().shutdownComponent();
            }
        });
    }
}

api-gateway

  • pom

<dependencies>
        <dependency>
            <groupId>org.springframework.cloudgroupId>
            <artifactId>spring-cloud-starter-zuulartifactId>
        dependency>
        <dependency>
            <groupId>org.springframework.cloudgroupId>
            <artifactId>spring-cloud-starter-eurekaartifactId>
        dependency>
        <dependency>
            <groupId>org.springframework.cloudgroupId>
            <artifactId>spring-cloud-starterartifactId>
        dependency>
        <dependency>
            <groupId>org.springframework.cloudgroupId>
            <artifactId>spring-cloud-starter-configartifactId>
        dependency>
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-webartifactId>
        dependency>
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-actuatorartifactId>
        dependency>
    dependencies>
  • application.yml

server:
  port: 10000

#sidecar:
  #port: 8000

endpoints:
  restart:
    enabled: true
  shutdown:
    enabled: true
  health:
    sensitive: false


zuul:
  ignored-services: "*"
  routes:
    product:
      path: /product/**
      url: http://product:9001/product
    recommend:
      path: /recommend/**
      url: http://recommend:9002/recommend
    review:
      path: /review/**
      url: http://review:9003/review
  • bootstrap.yml

spring:
  application:
    name: gateway
  cloud:
    config:
      uri: http://config:8888
encrypt:
  failOnError: false

eureka:
  instance:
    preferIpAddress: true
  client:
    registerWithEureka: true
    fetchRegistry: true
    serviceUrl:
      defaultZone: http://discovery:8761/eureka/
  • application

@SpringBootApplication
@EnableCircuitBreaker
@EnableDiscoveryClient
@EnableZuulProxy
public class ApiGatewayApplication {
    public static void main( String[] args ) {
        new SpringApplicationBuilder(ApiGatewayApplication.class).web(true).run(args);
    }
}
  • 访问
    http://192.168.99.100:10000/recommend?productId=1

转向
http://192.168.99.100:9002/recommend?productId=1

hystrix

http://192.168.99.100:9001/product/recommends?productId=1
http://192.168.99.100:9001/hystrix

SpringCloud微服务实战_第2张图片

http://192.168.99.100:9003/hystrix/monitor?stream=http%3A%2F%2F192.168.99.100%3A9001%2Fhystrix.stream

SpringCloud微服务实战_第3张图片

turbine

  • pom

<dependencies>
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-webartifactId>
        dependency>
        <dependency>
            <groupId>org.springframework.cloudgroupId>
            <artifactId>spring-cloud-starterartifactId>
        dependency>
        <dependency>
            <groupId>org.springframework.cloudgroupId>
            <artifactId>spring-cloud-starter-turbineartifactId>
        dependency>
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-actuatorartifactId>
        dependency>
        <dependency>
            <groupId>org.springframework.cloudgroupId>
            <artifactId>spring-cloud-config-clientartifactId>
        dependency>
        <dependency>
            <groupId>org.springframework.cloudgroupId>
            <artifactId>spring-cloud-starter-eurekaartifactId>
        dependency>

        
        <dependency>
            <groupId>org.springframework.cloudgroupId>
            <artifactId>spring-cloud-starter-hystrixartifactId>
        dependency>
        <dependency>
            <groupId>org.springframework.cloudgroupId>
            <artifactId>spring-cloud-starter-hystrix-dashboardartifactId>
        dependency>

    dependencies>
  • application.yml

server:
  port: 8889

eureka:
  instance:
    preferIpAddress: true
  client:
    registerWithEureka: true
    fetchRegistry: true
    serviceUrl:
      defaultZone: http://discovery:8761/eureka/

turbine:
  appConfig: product,review
  clusterNameExpression: new String("default")
  • bootstrap.yml

spring:
  application:
    name: turbine
  cloud:
    config:
      uri: http://config:8888
encrypt:
  failOnError: false
  • application

@SpringCloudApplication
@EnableTurbine
@EnableHystrixDashboard
public class TurbineApplication {
    public static void main(String[] args){
        SpringApplication.run(TurbineApplication.class,args);
    }
}
  • 访问

http://192.168.99.100:9001/hystrix

SpringCloud微服务实战_第4张图片

http://192.168.99.100:9001/product/recommends?productId=1
http://192.168.99.100:9003/review/product/100

SpringCloud微服务实战_第5张图片

graphite配置

  • pom

<dependencies>
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-actuatorartifactId>
        dependency>
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-testartifactId>
            <scope>testscope>
        dependency>
        
        <dependency>
            <groupId>io.dropwizard.metricsgroupId>
            <artifactId>metrics-coreartifactId>
            <version>${dropwizard-metrics.version}version>
        dependency>
        <dependency>
            <groupId>io.dropwizard.metricsgroupId>
            <artifactId>metrics-graphiteartifactId>
            <version>${dropwizard-metrics.version}version>
        dependency>
        <dependency>
            <groupId>io.dropwizard.metricsgroupId>
            <artifactId>metrics-annotationartifactId>
            <version>${dropwizard-metrics.version}version>
        dependency>
        <dependency>
            <groupId>io.dropwizard.metricsgroupId>
            <artifactId>metrics-jvmartifactId>
            <version>${dropwizard-metrics.version}version>
        dependency>

        <dependency>
            <groupId>com.ryantenney.metricsgroupId>
            <artifactId>metrics-springartifactId>
            <version>3.1.0version>
            <exclusions>
                <exclusion>
                    <artifactId>spring-beansartifactId>
                    <groupId>org.springframeworkgroupId>
                exclusion>
                <exclusion>
                    <artifactId>spring-aopartifactId>
                    <groupId>org.springframeworkgroupId>
                exclusion>
            exclusions>
        dependency>

    dependencies>
  • configuration

@Configuration
@AutoConfigureAfter(MetricRepositoryAutoConfiguration.class)
@ConditionalOnProperty(prefix = "graphite", name = "enabled", matchIfMissing = true)
@EnableConfigurationProperties(GraphiteProperties.class)
@EnableScheduling
@EnableMetrics
public class GraphiteAutoConfiguration {

    private static final Logger logger = LoggerFactory.getLogger(GraphiteAutoConfiguration.class);

    @Bean
    public MetricsConfigurerAdapter metricsConfigurerAdapter(final GraphiteProperties graphiteProperties) {
        return new GraphiteReportingManager(graphiteProperties);
    }

    /**
     * https://qbgbook.gitbooks.io/spring-boot-reference-guide-zh/content/IV.%20Spring%20Boot%20features/36.3.3.%20Property%20conditions.html
     * @param graphiteProperties
     * @param metricRegistry
     * @return
     */
    @Bean
    @ConditionalOnProperty(value = "graphite.host",matchIfMissing = true)
    public ConsoleReporter consoleReporter(GraphiteProperties graphiteProperties,MetricRegistry metricRegistry) {
        ConsoleReporter.Builder builder = ConsoleReporter.forRegistry(metricRegistry);
        ConsoleReporter reporter = builder.build();
        reporter.start(graphiteProperties.getReportInterval(), TimeUnit.MILLISECONDS);
        return reporter;
    }
}
  • report

public class GraphiteReportingManager extends MetricsConfigurerAdapter implements DisposableBean {

    private final Logger logger = LoggerFactory.getLogger(getClass());

    private GraphiteProperties props;


    public GraphiteReportingManager(GraphiteProperties props) {
        this.props = props;
    }

    @Override
    public void configureReporters(MetricRegistry metricRegistry) {
        //gc的metrics,目前看来每秒发送一次貌似太频繁,可以另起一个reporter进行
        metricRegistry.register("jvm.gc", new GarbageCollectorMetricSet());
        metricRegistry.register("jvm.mem", new MemoryUsageGaugeSet());
        metricRegistry.register("jvm.thread-states", new ThreadStatesGaugeSet());

        logger.info("graphite host:{},port:{}", props.getHost(), props.getPort());
        GraphiteReporter reporter = GraphiteReporter.forRegistry(metricRegistry)
                .prefixedWith(props.getPrefix())
//                        .convertRatesTo(TimeUnit.SECONDS)
                .convertDurationsTo(TimeUnit.MILLISECONDS)
                .filter(MetricFilter.ALL)
                .build(createSender(props));
        registerReporter(reporter);
        reporter.start(1L, TimeUnit.SECONDS);
    }

    @Override
    public void destroy() throws Exception {
        super.destroy();
    }

    private GraphiteSender createSender(GraphiteProperties props) {
        switch (props.getSenderType()) {
            case udp:
                return new GraphiteUDP(props.getHost(), props.getPort());
            case tcp:
                return new Graphite(props.getHost(), props.getPort());
            case pickled:
                return new PickledGraphite(props.getHost(), props.getPort());
            default:
                return new GraphiteUDP(props.getHost(), props.getPort());
        }
    }

}
  • 访问

http://192.168.99.100:8070/

SpringCloud微服务实战_第6张图片

参考

  • Blog Series - Building Microservices

  • git.blog-microservices

  • exposing-jvm-metrics-in-spring-boot

  • git.spring-boot-jvm-monitoring-demo

  • exporting-to-graphite-with-the-prometheus-java-client

 

https://segmentfault.com/a/1190000005142460

你可能感兴趣的:(架构,微服务,java,git,runtime)