Eureka注册中心

Eureka是一个Netflix开元的服务发现组件,本身是一个基于REST的服务。它包含Server和Client两部分。

  1. 服务注册 每个微服务应用在启动时都会向注册中心登记自己的信息(名称、地址、端口等);
  2. 服务发现 Eureka注册中心中的每个应用都会在本地缓存一份Eureka中所有微服务的信息,客户端调用时,可以通过应用名称找到具体的应用地址进行调用;

引入依赖

	<!--actuator 依赖(健康检查、审计、统计和监控)-->
	<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>
	<!--Eureka 注册中心服务端依赖-->
	<dependency>
		<groupId>org.springframework.cloud</groupId>
		<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
	</dependency>

定义配置文件

	#应用名称
	spring.application.name=octopus-eureka-server
	#端口号
	server.port=8761
	#配置启用所有的监控端点
	management.endpoints.web.exposure.include=*
	#注册中心地址(可配置为集群)
	eureka.client.service-url.default-zone=http://localhos:${server.port}/eureka/
	#false 表示不向注册中心注册自己
	eureka.client.register-with-eureka=false
	#false 表示不从注册中心获取注册信息
	eureka.client.fetch-registry=false

定义启动引导类

	/**
	 * code is far away from bug with the animal protecting
	 * @date 2018/12/4 14:17
	 * @description : 注册中心启动引导类 {@link SpringBootApplication}
	 **/
	@EnableEurekaServer
	@SpringBootApplication
	public class OctopusEurekaServerApplication {
	    public static void main(String[] args) {
	        SpringApplication.run(OctopusEurekaServerApplication.class, args);
	    }
	}

运行启动类

打开应用地址:http://localhost:8761/
Eureka注册中心

Config配置中心

Config用来为分布式系统中的基础设施和微服务应用提供集中化的外部配置支持, 它分为服务端与客户端两个部分。。
服务端也称为分布式配置中心, 它是一个独立的微服务应用, 用来连接配置仓库并为客户端提供获取配置信息、加密/解密信息等访问接口;
客户端则是微服务架构中的各个微服务应用或基础设施, 它们通过指定的配置中心来管理应用资源与业务相关的配置内容,并在启动的时候从配置中心获取和加载配置信息。

引入依赖

	<!--actuator 依赖(健康检查、审计、统计和监控)-->
	<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>
	<!--Config 配置中心服务端依赖-->
	<dependency>
		<groupId>org.springframework.cloud</groupId>
		<artifactId>spring-cloud-config-server</artifactId>
	</dependency>
	<!--Eureka 注册中心客户端依赖-->
	<dependency>
		<groupId>org.springframework.cloud</groupId>
		<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
	</dependency>

定义配置文件

	#端口号
	server.port=8060
	#应用名
	spring.application.name=octopus-config-server
	#配置启用所有的监控端点
	management.endpoints.web.exposure.include=*
	#git仓库配置
	spring.cloud.config.server.git.uri=http://192.168.0.113/sunxiaojun/octopus.cloud.config.profile.git
	spring.cloud.config.server.git.username=sunxiaojun
	spring.cloud.config.server.git.password=XIAOjun901008
	#注册中心地址(可配置多个)
	eureka.client.service-url.default-zone=http://localhost:8761/eureka/

定义启动引导类

/**
 * code is far away from bug with the animal protecting
 * @date 2018/12/4 14:17
 * @description : 配置中心启动引导类 {@link SpringBootApplication}
 **/
	@EnableConfigServer
	@SpringBootApplication
	public class OctopusConfigServerApplication {
	    public static void main(String[] args) {
	        SpringApplication.run(OctopusConfigServerApplication.class, args);
	    }
	}

自定义json格式数据配置文件解析

config配置中心会在应用启动的时候,将远程服务器(Git,Svn等)上的配置文件缓存到本地,生成一个List<PropertySource<?>> 对象。配置文件解析实现了PropertySourceLoader接口。解析配置文件时,根据文件后缀选择相应的Bean进行解析。

创建JsonPropertiesSourceLoader.java

	/**
	 * code is far away from bug with the animal protecting
	 * @date 2018/12/4 14:17
	 * @description :  {@link PropertySourceLoader}
	 *  自定义JSON格式配置文件加载
	 *  启动时,通过自动加载(AutoConfiguration)对Bean进行注册
	 *  在读取配置时,根据配置文件的后缀选用不同的配置文件读取方案
	 **/
	public class JsonPropertiesSourceLoader implements PropertySourceLoader {
	    @Override
	    public String[] getFileExtensions() {
	        return new String[]{"json"};
	    }
	
	    private ObjectMapper objectMapper = new ObjectMapper();
	
	    @Override
	    public List<PropertySource<?>> load(String name, Resource resource) throws IOException {
	        Map<String, ?> properties = loadJsonProperties(resource);
	        if (properties.isEmpty()) {
	            return Collections.emptyList();
	        }
	        return Collections
	                .singletonList(new OriginTrackedMapPropertySource(name, properties));
	    }
	
	    /**
	     * 读取JSON格式配置文件
	     * @param resource
	     * @return
	     */
	    private Map<String, ?> loadJsonProperties(Resource resource) {
	        FileInputStream is = null;
	        try {
	            File file = resource.getFile();
	            is = new FileInputStream(file);
	            JsonNode jsonNode = objectMapper.readTree(is);
	            Map<String, Object> result = objectMapper.convertValue(jsonNode, Map.class);
	            is.close();
	            return result;
	        } catch (FileNotFoundException e) {
	            e.printStackTrace();
	        } catch (IOException e) {
	            e.printStackTrace();
	        } finally {
	            try {
	                is.close();
	            } catch (IOException e) {
	                e.printStackTrace();
	            }
	        }
	        return null;
	    }
	}

配置自动加载

在resources目录下建一个META-INF/spring.factories配置文件,这个配置文件是Spring实现自动加载定义的文件

	# PropertySource Loaders
	org.springframework.boot.env.PropertySourceLoader=\
	com.octopus.cloud.configserver.env.JsonPropertiesSourceLoader

启动后,即可解析.json格式的配置文件。

服务提供者

引入依赖

	<!--actuator 依赖(健康检查、审计、统计和监控)-->
	<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>
	<!--注册中心依赖-->
	<dependency>
		<groupId>org.springframework.cloud</groupId>
		<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
	</dependency>
	<!--服务配置依赖-->
	<dependency>
		<groupId>org.springframework.cloud</groupId>
		<artifactId>spring-cloud-config-client</artifactId>
	</dependency>
	<!--BUS依赖-->
	<dependency>
		<groupId>org.springframework.cloud</groupId>
		<artifactId>spring-cloud-bus</artifactId>
	</dependency>
	<!--RabbitMq Stream 依赖-->
	<dependency>
		<groupId>org.springframework.cloud</groupId>
		<artifactId>spring-cloud-stream-binder-rabbit</artifactId>
	</dependency>
	<!--Web依赖-->
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-web</artifactId>
	</dependency>
	<!--服务跟踪依赖Sleuth-->
	<!--<dependency>-->
		<!--<groupId>org.springframework.cloud</groupId>-->
		<!--<artifactId>spring-cloud-starter-sleuth</artifactId>-->
	<!--</dependency>-->
	<!--Zipkin 服务跟踪 -->
	<dependency>
		<groupId>org.springframework.cloud</groupId>
		<artifactId>spring-cloud-starter-zipkin</artifactId>
	</dependency>

定义配置文件

bootstrap.properties

	#修改日志权限
	logging.level.root=INFO
	logging.level.org.springframework.web.servlet.DispatcherServlet=DEBUG
	#端口号
	server.port=1000
	#应用名称
	spring.application.name=octopus-provider
	#配置启用所有的监控端点
	management.endpoints.web.exposure.include=*
	#注册中心地址
	eureka.client.service-url.default-zone=http://localhost:8761/eureka/
	#微服务配置
	spring.cloud.config.profile=dev 
	spring.cloud.config.label=master
	#开启通过微服务发现组件访问Config Server功能
	spring.cloud.config.discovery.enabled=true
	#跟踪总线事件
	spring.cloud.bus.trace.enabled=true
	#指定Config Server在服务发现组件中的ServiceId
	spring.cloud.config.discovery.service-id=octopus-config-server
	#RabbitMQ配置
	spring.rabbitmq.host=localhost
	spring.rabbitmq.port=5672
	spring.rabbitmq.username=guest
	spring.rabbitmq.password=guest

application.properties

本地的application.proerties可以配置为空,下面的配置为远程配置中心文件

	#端口号
	server.port=1000
	eureka.instance.prefer-ip-address=true
	eureka.instance.metadata-map.my-metadata:我自定义的元数据
	#配置日志
	#logging.level.root=INFO
	#logging.level.org.hibernate=INFO
	#logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE
	#logging.level.org.hibernate.type.descriptor.sql.BasicExtractor=TRACE
	#修改日志权限
	logging.level.root=INFO
	logging.level.org.springframework.web.servlet.DispatcherServlet=DEBUG
	#配置采样比例
	spring.sleuth.sampler.probability=1.0

定义启动引导类

	/**
	 * code is far away from bug with the animal protecting
	 * @date 2018/12/4 14:17
	 * @description : 服务提供者启动引导类 {@link SpringBootApplication}
	 **/
	@EnableDiscoveryClient
	@SpringBootApplication
	public class OctopusProviderApplication {
	    public static void main(String[] args) {
	        SpringApplication.run(OctopusProviderApplication.class, args);
	    }
	}

定义Controller

	@RestController
	public class ProviderController {
	    @GetMapping("/{id}")
	    public Optional<String> findById(@PathVariable Long id) {
	        return Optional.ofNullable(UUID.randomUUID().toString().toUpperCase());
	    }
	}

服务消费者

引入依赖

	<!--actuator 依赖(健康检查、审计、统计和监控)-->
	<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>
	<!--注册中心客户端依赖-->
	<dependency>
		<groupId>org.springframework.cloud</groupId>
		<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
	</dependency>
	<!--配置中心客户端依赖-->
	<dependency>
		<groupId>org.springframework.cloud</groupId>
		<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
	</dependency>
	<!--服务配置依赖-->
	<dependency>
		<groupId>org.springframework.cloud</groupId>
		<artifactId>spring-cloud-config-client</artifactId>
	</dependency>
	<!--BUS依赖-->
	<dependency>
		<groupId>org.springframework.cloud</groupId>
		<artifactId>spring-cloud-bus</artifactId>
	</dependency>
	<!--RabbitMQ-->
	<dependency>
		<groupId>org.springframework.cloud</groupId>
		<artifactId>spring-cloud-stream-binder-rabbit</artifactId>
	</dependency>
	<!--Web依赖-->
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-web</artifactId>
	</dependency>
	<!--服务跟踪依赖-->
	<dependency>
		<groupId>org.springframework.cloud</groupId>
		<artifactId>spring-cloud-starter-zipkin</artifactId>
	</dependency>
	<!-- 熔断依赖-->
	<dependency>
		<groupId>org.springframework.cloud</groupId>
		<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
	</dependency>
	<dependency>
		<groupId>org.springframework.cloud</groupId>
		<artifactId>spring-cloud-netflix-hystrix-stream</artifactId>
	</dependency>

定义配置文件

bootstrap.properties

	#修改日志权限
	logging.level.root=INFO
	logging.level.org.springframework.web.servlet.DispatcherServlet=DEBUG
	#应用名称
	spring.application.name=octopus-consumer
	#配置启用所有的监控端点
	management.endpoints.web.exposure.include=*
	#注册中心地址
	eureka.client.service-url.default-zone=http://localhost:8761/eureka/
	eureka.instance.prefer-ip-address=true
	#微服务配置
	spring.cloud.config.profile=dev 
	spring.cloud.config.label=master
	#开启通过微服务发现组件访问Config Server功能
	spring.cloud.config.discovery.enabled=true
	#跟踪总线事件
	spring.cloud.bus.trace.enabled=true
	#指定Config Server在服务发现组件中的ServiceId
	spring.cloud.config.discovery.service-id=octopus-config-server
	#RabbitMQ配置
	spring.rabbitmq.host=localhost
	spring.rabbitmq.port=5672
	spring.rabbitmq.username=guest
	spring.rabbitmq.password=guest

application.properties

本地的application.proerties可以配置为空,下面的配置为远程配置中心文件

	#端口号
	server.port=2000
	eureka.instance.prefer-ip-address=true
	eureka.instance.metadata-map.my-metadata:我自定义的元数据
	#配置日志
	#logging.level.root=INFO
	#logging.level.org.hibernate=INFO
	#logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE
	#logging.level.org.hibernate.type.descriptor.sql.BasicExtractor=TRACE
	#配置采样比例
	spring.sleuth.sampler.probability=1.0

定义启动引导类

	/**
	 * code is far away from bug with the animal protecting
	 * @date 2018/12/4 14:17
	 * @description : 服务消费者启动引导类 {@link SpringBootApplication}
	 **/
	@EnableDiscoveryClient
	@SpringBootApplication
	@EnableCircuitBreaker
	public class OctopusComsumerApplication {
	    @Bean
	    @LoadBalanced
	    public RestTemplate restTemplate(){
	        return new RestTemplate();
	    }
	    /**
	     * 因2.X后的版本不在开放hystrix.stream端点,需要自定义配置
	     * @return
	     */
	    @Bean
	    public ServletRegistrationBean getServlet(){
	        HystrixMetricsStreamServlet streamServlet = new HystrixMetricsStreamServlet();
	        ServletRegistrationBean registrationBean = new ServletRegistrationBean(streamServlet);
	        registrationBean.setLoadOnStartup(1);
	        registrationBean.addUrlMappings("/hystrix.stream");
	        registrationBean.setName("HystrixMetricsStreamServlet");
	        return registrationBean;
	    }
	    public static void main(String[] args) {
	        SpringApplication.run(OctopusComsumerApplication.class, args);
	    }
	}

定义Controller

	@RestController
	public class ConsumerController {
	    @Autowired
	    private RestTemplate restTemplate;
	    @Autowired
	    private DiscoveryClient discoveryClient;
	    @GetMapping("/user/{id}")
	    @HystrixCommand(fallbackMethod = "findByIdFallback")
	    public String findById(@PathVariable Long id) {
	        return this.restTemplate.getForObject("http://OCTOPUS-PROVIDER/" + id, String.class);
	    }
	    public String findByIdFallback(Long id){
	        return "默认用户";
	    }
	}

Hystrix监控面板

引入依赖

	<!--actuator 依赖(健康检查、审计、统计和监控)-->
	<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>
	<!--Hystrix监控面板依赖-->
	<dependency>
		<groupId>org.springframework.cloud</groupId>
		<artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
	</dependency>
	<!--注册中心客户端依赖-->
	<dependency>
		<groupId>org.springframework.cloud</groupId>
		<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
	</dependency>

定义配置文件

	#端口号
	server.port=8090
	#应用名称
	spring.application.name=octopus-hystrix-dashboard
	#配置启用所有的监控端点
	management.endpoints.web.exposure.include=*
	#注册中心地址
	eureka.client.service-url.default-zone=http://localhost:8761/eureka/

定义启动引导类

	/**
	 * code is far away from bug with the animal protecting
	 * @date 2018/12/4 14:17
	 * @description : Hystrix监控平台启动引导类 {@link SpringBootApplication}
	 **/
	@EnableDiscoveryClient
	@SpringBootApplication
	@EnableHystrixDashboard
	public class OctopusHystrixDashboardApplication {
	    public static void main(String[] args) {
	        SpringApplication.run(OctopusHystrixDashboardApplication.class, args);
	    }
	}

Turbine聚合监控

引入依赖

	<!--actuator 依赖(健康检查、审计、统计和监控)-->
	<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>
	<!--注册中心依赖-->
	<dependency>
		<groupId>org.springframework.cloud</groupId>
		<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
	</dependency>
	<!-- 熔断 stream 依赖 -->
	<dependency>
		<groupId>org.springframework.cloud</groupId>
		<artifactId>spring-cloud-netflix-hystrix-stream</artifactId>
	</dependency>
	<!--RabbitMQ 依赖-->
	<dependency>
		<groupId>org.springframework.cloud</groupId>
		<artifactId>spring-cloud-stream-binder-rabbit</artifactId>
	</dependency>
	<!--聚合监控 stream 依赖-->
	<dependency>
		<groupId>org.springframework.cloud</groupId>
		<artifactId>spring-cloud-starter-netflix-turbine-stream</artifactId>
	</dependency>

定义配置文件

	#端口号
	server.port=8031
	#项目名称
	spring.application.name=octopus-hystrix-turbine
	#配置启用所有的监控端点
	management.endpoints.web.exposure.include=*
	#注册中心地址
	eureka.client.service-url.default-zone=http://com.octopus.cloud:8761/eureka/
	eureka.instance.prefer-ip-address=true
	#turbine聚合
	# 指定聚合哪些集群,多个使用","分割,默认为default。可使用http://.../turbine.stream?cluster={clusterConfig之一}访问
	#turbine.aggregator.cluster-config=default
	#turbine.cluster-name-expression="default"
	#turbine.app-config=octopus-consumer
	#turbine.combine-host-port=true
	#这里和被监控启动类里的 registrationBean.addUrlMappings("/hystrix.stream")一致
	#turbine.instanceUrlSuffix=/hystrix.stream
	#RabbitMQ配置
	spring.rabbitmq.host=localhost
	spring.rabbitmq.port=5672
	spring.rabbitmq.username=guest
	spring.rabbitmq.password=guest

定义启动引导类

	/**
	 * code is far away from bug with the animal protecting
	 * @date 2018/12/4 14:17
	 * @description : Hystrix监控平台启动引导类 {@link SpringBootApplication}
	 **/
	@EnableDiscoveryClient
	@SpringBootApplication
	@EnableTurbineStream
	public class OctopusHystrixTurbineApplication {
	    public static void main(String[] args) {
	        SpringApplication.run(OctopusHystrixTurbineApplication.class, args);
	    }
	}

使用RabbitMQ使用数据时,目前发现服务消费者发送到的熔断信息的数据为能进入聚合监控,跟踪源码得知,在消费者应用和聚合监控的医用启动时,RabbitMQ中的Exchange:hystrixStreamOutput与turbineStreamInput未进行绑定,导致写入hystrixStreamOutput的数据未能传入turbineStreamInput中,这边需要手动建立一个绑定关系:
在这里插入图片描述

Zipkin微服务跟踪与数据

2.X之后,SpringCloud不在集成Zipkin,可以使用开源的Zipkin进行二次开发或使用打包好的zipkin.jar,因zipkin.jar是SpringBoot项目,可以直接使用java -jar zipkin.jar 启动,默认端口为 9411,使用rabbitmq作为进行数据收集。

curl -sSL https://zipkin.io/quickstart.sh | bash -s
java -jar zipkin.jar --zipkin.collector.rabbitmq.addresses=localhost

应用启动

依次启动

  1. 注册中心: OctopusEurekaServerApplication
  2. 配置中心: OctopusConfigServerApplication
  3. 服务消费者: OctopusComsumerApplication
  4. 服务提供者: OctopusProviderApplication
  5. Hystrix监控面板: OctopusHystrixDashboardApplication
  6. Turbine聚合监控: OctopusHystrixTurbineApplication
  7. Zipkin链路跟踪: zipkin.jar
    打开注册中心
    在这里插入图片描述
    调用客户端接口生成请求信息
    打开Zipkin链路跟踪服务地址:http://localhost:9411/,可看到如下信息:
    在这里插入图片描述
    打开Hystrix监控平台 http://localhost:8090/hystrix, 输入聚合监控的地址:http://localhost:8031/trubine.stream可看到如下信息:
    在这里插入图片描述

至此,基于SpringBoot2.X的微服务架构,整合Eureka注册中心、Config配置中心、Bus消息总线、Hystrix熔断、Turbine聚合监控、Zipkin服务跟踪搭建完成。

总结

1、聚合监控 Turbine 需要手动对RabbitMQ中的Exchange 进行绑定;
2、Zipkin在SpringBoot2.X之后已不在集成,可通过源码进行编译或使用打包好的jar包;
源码地址

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐