序
主要有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/
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
http://192.168.99.100:9003/hystrix/monitor?stream=http%3A%2F%2F192.168.99.100%3A9001%2Fhystrix.stream
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
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/
参考
- 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