Eureka学习例子
Eureka学习
Spring Cloud下有很多工程:
- Spring Cloud Config:依靠git仓库实现的中心化配置管理。配置资源可以映射到Spring的不同开发环境中,但是也可以使用在非Spring应用中。
- Spring Cloud Netflix:不同的Netflix OSS组件的集合:Eureka、Hystrix、Zuul、Archaius等。
- Spring Cloud Bus:事件总线,利用分布式消息将多个服务连接起来。非常适合在集群中传播状态的改变事件(例如:配置变更事件)
- Spring Cloud Consul:服务发现和配置管理,由Hashicorp团队开发。我决定先从Spring Cloud Netflix看起,它提供了如下的功能特性:
- 服务发现:Eureka-server实例作为服务提供者,可以注册到服务注册中心,Eureka客户端可以通过Spring管理的bean发现实例;
- 服务发现:嵌套式的Eureka服务可以通过声明式的Java配置文件创建;
- 断路器:利用注解,可以创建一个简单的Hystrix客户端;
- 断路器:通过Java配置文件可以创建内嵌的Hystrix控制面板;
- 声明式REST客户端:使用Feign可以创建声明式、模板化的HTTP客户端;
- 客户端负载均衡器:Ribbon
- 路由器和过滤器:Zuul可以在微服务架构中提供路由功能、身份验证、服务迁移、金丝雀发布等功能。
1. 服务注册中心
在IDEA中创建一个Spring Cloud工程,引入Eureka-Server包,pom文件整体如下:
<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>com.sl</groupId>
<artifactId>RegistryCenter</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>RegistryCenter</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.3.5.RELEASE</version>
<relativePath/>
</parent>
<dependencies>
<!– 用于注册中心访问账号认证 –>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</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-eureka-server</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Brixton.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<!– spring boot的maven打包插件 –>
<build>
<defaultGoal>compile</defaultGoal>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven–plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
创建APP类,并用@EnableEurekaServer和@SpringBootApplication两个注解修饰,后者是Spring Boot应用都需要用的,这里不作过多解释;@EnableEurekaServer注解的作用是触发Spring Boot的自动配置机制,由于我们之前在pom文件中导入了eureka-server,spring boot会在容器中创建对应的bean。Eureka的代码如下:
package com.sl.RegistryCenter;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
/**
* Hello world!
*
*/
@EnableEurekaServer
@SpringBootApplication
public class App {
public static void main(String[] args) {
new SpringApplicationBuilder(App.class).web(true).run(args);
}
}
添加配置文件application.properties,并且添加如下参数,才能创建一个真正可以使用的服务注册中心。
######eureka服务端######
spring.application.name=eureka-server
#驱逐下线的服务,间隔,5秒,默认是60,建议开发和测试环境配置
eureka.server.evictionIntervalTimerInMs=10000
server.port=8761
#是否需要注册到注册中心,因为该项目本身作为服务注册中心,所以为false
eureka.client.register-with-eureka=false
#是否需要从注册中心获取服务列表,原因同上,为false
eureka.client.fetch-registry=false
security.basic.enabled=true
security.user.name=admin
security.user.password=123
#注册服务器的地址:服务提供者和服务消费者都要依赖这个地址
eureka.client.serviceUrl.defaultZone=http://admin:123@localhost:8761/eureka
###Eureka自我保护机制,为true表示开,false表示关,默认为开####
eureka.server.enable-self-preservation=true
启动注册服务,并访问:http://localhost:8761,就可以看到如下界面。
2. 服务提供者
创建一个Spring Boot工程,代表服务提供者,该服务提供者会暴露一个当前请求产生的时间字符串。
工程的pom文件内容如下:
<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>com.sl</groupId>
<artifactId>TestMicroService</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>TestMicroService</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.3.5.RELEASE</version>
<relativePath /> <!– lookup parent from repository –>
</parent>
<dependencies>
<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-eureka</artifactId>
</dependency>
<!– 用于注册中心访问账号认证 –>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Brixton.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<defaultGoal>compile</defaultGoal>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven–plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
其中的关键在于spring-cloud-starter-eureka这个Jar包,其中包含了eureka的客户端实现。
在src/main/java/com.sl.TestMicroService下创建工程的主类App,使用@EnableDiscoveryClient注解修饰,该注解在服务启动的时候,可以触发服务注册的过程,向配置文件中指定的服务注册中心(Eureka-Server)的地址注册自己提供的服务。App的源码如下:
package com.sl.TestMicroService;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
/**
* Hello world!
*
*/
@EnableDiscoveryClient
@SpringBootApplication
public class
App {
public static void main(String[] args) {
new
SpringApplicationBuilder(App.class).web(true).run(args);
}
}
配置文件的内容如下:
server.port=8111
#设置应用的名称
spring.application.name=microservice-provider-user
#服务注册的Eureka Server地址
eureka.client.serviceUrl.defaultZone=http://admin:123@localhost:8761/eureka
#设置注册ip
eureka.instance.prefer-ip-address=true
#自定义应用实例id
#健康检查
eureka.client.healthcheck.enabled=true
服务提供者的基本框架搭好后,需要实现服务的具体内容,在ComputeController类中实现,它的具体代码如下:
package com.sl.TestMicroService;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.apache.log4j.Logger;
import
org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import
org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.web.bind.annotation.RequestMapping;
import
org.springframework.web.bind.annotation.RequestMethod;
import
org.springframework.web.bind.annotation.RestController;
@RestController
public class ComputeController {
private
final Logger logger = Logger.getLogger(getClass());
@Autowired
private
DiscoveryClient client;
private
SimpleDateFormat df = new SimpleDateFormat(“yyyy-MM-dd HH:mm:ss”);
@RequestMapping(value
= “/test”, method = RequestMethod.GET)
public
String test() {
ServiceInstance
instance = client.getLocalServiceInstance();
String
temp = “当前时间【” + df.format(new Date()) +
“】/add, host:” + instance.getHost() + “,
service_id:”
+
instance.getServiceId();
logger.info(temp);
return
temp;
}
}
先启动服务注册中心的工程,然后再启动服务提供者,在访问:localhost:8761,如下图所示,服务提供者已经注册到服务注册中心啦,下图可以查看
在Spring Cloud Netflix中,使用Ribbon实现客户端负载均衡,使用Feign实现声明式HTTP客户端调用——即写得像本地函数调用一样。
3. 服务消费者-Feign
pom配置如下:
<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>com.sl</groupId>
<artifactId>ServiceConsumer</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>ServiceConsumer</name>
<url>http://maven.apache.org</url>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.3.5.RELEASE</version>
<relativePath /> <!– lookup parent from repository –>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<build>
<defaultGoal>compile</defaultGoal>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven–plugin</artifactId>
</plugin>
</plugins>
</build>
<dependencies>
<!– Feign实现声明式HTTP客户端 –>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-feign</artifactId>
</dependency>
<!– eureka客户端 –>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<!– spring boot实现Java Web服务–>
<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>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Brixton.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
</project>
首先创建应用程序启动类:ConsumerApp,代码如下:
package com.sl.ServiceConsumer;
import org.springframework.boot.SpringApplication;
import
org.springframework.boot.autoconfigure.SpringBootApplication;
import
org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import
org.springframework.cloud.netflix.feign.EnableFeignClients;
/**
* Hello world!
*
*/
@EnableDiscoveryClient // 用于启动服务发现功能
@EnableFeignClients // 用于启动Fegin功能
@SpringBootApplication
public class ConsumerApp {
/**
* main函数入口
*
* @param args
*/
public
static void main(String[] args) {
SpringApplication.run(ConsumerApp.class);
}
}
然后创建ComputeClient接口,使用@FeignClient(“microservice-provider-user”)注解修饰,microservice-provider-user就是服务提供者的名称,然后定义要使用的服务,代码如下:
package com.sl.ServiceConsumer;
import
org.springframework.cloud.netflix.feign.FeignClient;
import
org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@FeignClient(“microservice-provider-user”)
public interface ConsumerClient {
//
@RequestMapping(method = RequestMethod.GET, value = “/add”)
// Integer
add(@RequestParam(value = “a”) Integer a, @RequestParam(value =
//
“b”) Integer b);
@RequestMapping(method
= RequestMethod.GET, value = “/test”)
String
test();
}
在ConsumerController中,像引入普通的spring
bean一样引入ComputeClient对象,其他的和Ribbon的类似。
package com.sl.ServiceConsumer;
import
org.springframework.beans.factory.annotation.Autowired;
import
org.springframework.web.bind.annotation.RequestMapping;
import
org.springframework.web.bind.annotation.RequestMethod;
import
org.springframework.web.bind.annotation.RestController;
@RestController
public class ConsumerController {
@Autowired
private
ConsumerClient computeClient;
@RequestMapping(value
= “/test”, method = RequestMethod.GET)
public
String test() {
return
computeClient.test();
}
}
application.properties的内容如下:
#应用名称
spring.application.name=fegin-consumer
#端口号
server.port=9000
#注册中心的地址
eureka.client.serviceUrl.defaultZone=http://localhost:8761/eureka/
启动fegin消费者,访问localhost:9000/add,也可以看到服务提供者已经收到了消费者发来的请求。
可以看到两个服务轮流被调用
注意事项
1.关于版本对应问题
- Angel版本对应Spring Boot 1.2.x
- Brixton版本对应Spring Boot 1.3.x
- Camden版本对应Spring Boot 1.4.x
2.直接打包
打包时记得引用下面的包
<build>
<defaultGoal>compile</defaultGoal>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven–plugin</artifactId>
</plugin>
</plugins>
</build>