Spring Cloud Eureka主要负责完成微服务架构中的服务治理功能。Spring Cloud通过为Eureka添加了Spring Boot风格的自动化配置,我们只需要通过简单引入依赖和注解配置就能让Spring Boot构件的微服务应用轻松的与Eureka服务治理体系进行整合。
服务治理可以说是微服务架构中最为核心和基础的模块,它主要用来实现各个微服务实例的自动化注册和发现。
服务注册:在服务治理框架中,通常都会构件一个注册中心,每个服务单元向注册中心登记自己提供的服务,将主机与端口号、版本号、通信协议等一些附加信息告诉注册中心,注册中心按服务名分类组织服务清单。当这些进程启动,并向注册中心注册了自己的服务之后,注册服务中心就会维护一个类似下表的服务清单。另外服务注册中心还需要以心跳的方式去监测清单中的服务是否可用,若不可用将从服务清单中剔除,以达到排除故障服务的效果。
服务发现:由于在服务治理框架下运作,服务间的调用不再通过指定具体的实例地址来实现,而是通过向服务名发起请求调用实现。所以服务调用方在调用服务提供方接口的时候,并不知道具体服务实例的位置。因此,调用方需要向服务注册中心咨询服务,并获取所有的服务实例清单,以实现对具体服务实例的调用。同时,由于每个服务可能都不止一个实例提供服务,客户端可以采用某种轮询的策略轮流调用,这就是客户端负载均衡的实现思路。
Spring Cloud Eureka是用来实现服务注册与发现的,它同时包含的服务端组件和客户端组件,并且服务端和客户端都采用Java语言编写,所以Eureka主要适用于通过Java实现的分布式系统。如果需要将其他语言实现的微服务纳入Eureka的服务治理体系中来,需要自己实现Eureka客户端程序。
Eureka服务端,也称为服务注册中心,下面实例尝试搭建一个简单的服务注册中心。
首先创建一个Spring Boot工程,命名为eureka-server,其pom.xml文件内容如下:
<?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>cn.badtom</groupId> <artifactId>eureka-server</artifactId> <version>1.0-SNAPSHOT</version> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.2.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka-server</artifactId> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Dalston.SR1</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
package cn.badtom.server; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer; @EnableEurekaServer @SpringBootApplication public class Application { public static void main(String[] args) { new SpringApplicationBuilder(Application.class).web(true).run(args); } }
在默认情况下,该服务注册中心也会将自己作为客户端来尝试注册它自己,所以我们禁用它的客户端注册行为,在Spring Boot的配置文件application.properties中增加如下配置:
server.port=1111 eureka.instance.hostname=localhost eureka.client.register-with-eureka=false eureka.client.fetch-registry=false eureka.client.serviceUrl.defaultZone=http://${eureka.instance.hostname}:${server.port}/eureka/
然后启动应用,访问浏览器http://localhost:1111/,可以看到Eureka的信息面板,其中Instances currently registered with Eureka栏是空的,说明目前还没有任何服务注册进来。
Eureka客户端,主要处理服务的注册和发现,下面实例尝试搭建一个简单的服务提供者并将自己注册到服务中心。
首先新建一个Spring Boot应用,命名为springboot-test,添加依赖包spring-cloud-starter-eureka,其pom.xml文件的内容如下:
<?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>cn.badtom</groupId> <artifactId>springboot-test</artifactId> <version>1.0-SNAPSHOT</version> <packaging>jar</packaging> <name>springboot-first-application</name> <description>Demo project for Spring Boot</description> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.2.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka</artifactId> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Dalston.SR1</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
然后新建HelloController类,相比于普通的Spring Boot Controller,通过注入DiscoveryClient对象,在日志中打印出服务的相关内容;通过添加@EnableDiscoveryClient注解,激活Eureka中DiscoveryClient的实现。具体代码如下:
package cn.badtom.controller; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.cloud.client.ServiceInstance; import org.springframework.cloud.client.discovery.DiscoveryClient; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; import org.apache.log4j.Logger; @RestController @EnableAutoConfiguration @EnableDiscoveryClient public class HelloController { private final Logger logger = Logger.getLogger(getClass()); @Autowired private DiscoveryClient client; @RequestMapping(value = "/hello", method = RequestMethod.GET) public String index() { ServiceInstance instance = client.getLocalServiceInstance(); logger.info("/hello,host:" + instance.getHost() + ",service_id:" + instance.getServiceId()); return "Greetings from Spring Boot!"; } public static void main(String[] args) { SpringApplication.run(HelloController.class, args); } }
最后,我们需要在application.properties配置文件中添加如下配置:
spring.application.name=hello-service eureka.client.serviceUrl.defaultZone=http://peer1:1111/eureka
下面启动该应用,可以在Eureka的服务控制面板页面中看到该服务已经被注册进去了:
与此同时,访问浏览器http://localhost:8080/hello,可以看到控制台的如下输出,说明我们刚刚定义的服务已经被成功的调用了:
到这里我们完成了Eureka服务治理模块的搭建,但这是单点的注册中心,后面一篇将讲解高可用注册中心的搭建。