SpringCloud微服务实战

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

eureka

  • pom配置

        
            org.springframework.boot
            spring-boot-starter-web
        
        
            org.springframework.boot
            spring-boot-starter-actuator
        
        
            org.springframework.cloud
            spring-cloud-starter-eureka-server
        
        
            junit
            junit
            test
        
    
  • 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配置

        
            org.springframework.cloud
            spring-cloud-starter
        
        
            org.springframework.cloud
            spring-cloud-config-server
        
        
            org.springframework.cloud
            spring-cloud-starter-eureka
        
    
  • 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

        
            org.springframework.cloud
            spring-cloud-starter
        
        
            org.springframework.boot
            spring-boot-starter-web
        
        
            org.springframework.boot
            spring-boot-starter-actuator
        
        
            org.springframework.cloud
            spring-cloud-config-client
        
        
            org.springframework.cloud
            spring-cloud-starter-eureka
        
        
            com.codecraft
            common
            1.0-SNAPSHOT
        

        
        
            org.springframework.cloud
            spring-cloud-starter-ribbon
        
        
            org.springframework.cloud
            spring-cloud-starter-feign
        

        
        
            org.springframework.cloud
            spring-cloud-starter-hystrix
        
        
            org.springframework.cloud
            spring-cloud-starter-hystrix-dashboard
        

    
  • 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

        
            org.springframework.cloud
            spring-cloud-starter-zuul
        
        
            org.springframework.cloud
            spring-cloud-starter-eureka
        
        
            org.springframework.cloud
            spring-cloud-starter
        
        
            org.springframework.cloud
            spring-cloud-starter-config
        
        
            org.springframework.boot
            spring-boot-starter-web
        
        
            org.springframework.boot
            spring-boot-starter-actuator
        
    
  • 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

        
            org.springframework.boot
            spring-boot-starter-web
        
        
            org.springframework.cloud
            spring-cloud-starter
        
        
            org.springframework.cloud
            spring-cloud-starter-turbine
        
        
            org.springframework.boot
            spring-boot-starter-actuator
        
        
            org.springframework.cloud
            spring-cloud-config-client
        
        
            org.springframework.cloud
            spring-cloud-starter-eureka
        

        
        
            org.springframework.cloud
            spring-cloud-starter-hystrix
        
        
            org.springframework.cloud
            spring-cloud-starter-hystrix-dashboard
        

    
  • 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

graphite配置

  • pom

        
            org.springframework.boot
            spring-boot-starter-actuator
        
        
            org.springframework.boot
            spring-boot-starter-test
            test
        
        
        
            io.dropwizard.metrics
            metrics-core
            ${dropwizard-metrics.version}
        
        
            io.dropwizard.metrics
            metrics-graphite
            ${dropwizard-metrics.version}
        
        
            io.dropwizard.metrics
            metrics-annotation
            ${dropwizard-metrics.version}
        
        
            io.dropwizard.metrics
            metrics-jvm
            ${dropwizard-metrics.version}
        

        
            com.ryantenney.metrics
            metrics-spring
            3.1.0
            
                
                    spring-beans
                    org.springframework
                
                
                    spring-aop
                    org.springframework
                
            
        

    
  • 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微服务实战_第5张图片

参考

  • 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

你可能感兴趣的:(java,docker)