SpringCloud(一)使用Eureka实现服务注册与发现
Eureka服务端
SpringCloud项目基于SpringBoot,所以pom文件需要引入SpringCloud和SpringBoot的依赖。
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.13.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- spring-boot-starter-actuator 管理工具/web 查看堆栈,动态刷新配置 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!-- cloud eureka组件 注册中心 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka-server</artifactId>
</dependency>
</dependencies>
启动类:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
/**
* Created by chenxyz on 2018/5/20.
*/
@SpringBootApplication
@EnableEurekaServer
public class EurekaApplicationStarter {
public static void main(String[] args) {
SpringApplication.run(EurekaApplicationStarter.class, args);
}
}
application.yml文件
info:
name: Eureka Server
spring:
profiles:
active: dev
---
spring:
profiles: dev
server:
port: 8761
eureka:
client:
#是否注册到EurekaServer
register-with-eureka: true
#是否拉取信息
fetch-registry: false
#eureka server地址
service-url:
default-zone: http://127.0.0.1:8761/eureka/
server:
wait-time-in-ms-when-sync-empty: 0
#关闭自我保护,不管如何都要剔除心跳检测异常的服务
enable-self-preservation: true
peer-eureka-nodes-update-interval-ms: 1800000
instance:
hostname: eureka
bootstrap.yml这里的spring.application.name
会作为显示名称出现在Eureka的控制台页面。
spring:
application:
name: eureka-server
Eureka启动成功后,使用http://127.0.0.1:8761打开它的控制台页面。
在Eureka的注册服务
eureka的客户端都需要引入spring-cloud-starter-eureka
依赖。
生产者——短信服务(springCloudDemoSms)
pom文件
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.13.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- spring-boot-starter-actuator 管理工具/web 查看堆栈,动态刷新配置 -->
<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>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-rest</artifactId>
</dependency>
<dependency>
<groupId>org.hsqldb</groupId>
<artifactId>hsqldb</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
Eureka的客户端都需要使用@EnableEurekaClient
注解,表明这是一个Eureka客户端,并且在配置文件中需要指定注册中心的地址。
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
/**
* Created by chenxyz on 2018/5/20.
*/
@SpringBootApplication
@EnableEurekaClient
public class SMSApplicationStarter {
public static void main(String[] args) {
SpringApplication.run(SMSApplicationStarter.class, args);
}
}
bootstrap.yml
spring:
application:
name: sms-service
application.yml
info:
name: SMS service
server:
port: 8001
#eureka配置
eureka:
client:
register-with-eureka: true
fetch-registry: true
service-url:
default-zone: http://127.0.0.1:8761/eureka/
instance:
#心跳间隔
lease-renewal-interval-in-seconds: 30
使用data-jpa
和data-rest
快速实现一个Rest服务。
import com.chenxyz.springCloudDemo.sms.entity.SMSEntity;
import org.springframework.data.repository.PagingAndSortingRepository;
import org.springframework.data.rest.core.annotation.RepositoryRestResource;
/**
* Created by chenxyz on 2018/5/20.
*/
@RepositoryRestResource(collectionResourceRel = "sms", path = "sms")
public interface SMSSerivce extends PagingAndSortingRepository<SMSEntity, Long> {
}
相关的实体类SMSEntity.java
import javax.persistence.*;
import java.io.Serializable;
/**
* Created by chenxyz on 2018/5/20.
*/
@Entity
@Table(name = "sms")
public class SMSEntity implements Serializable {
private static final long serialVersionUID = -2323230989374343L;
@Id
@GeneratedValue
private long id;
@Column
private String phoneNo;
@Column
private String message;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getPhoneNo() {
return phoneNo;
}
public void setPhoneNo(String phoneNo) {
this.phoneNo = phoneNo;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
启动短信服务,并在Eureka控制台页面可以看到短信服务已被注册。
发送一个post请求(http://localhost:8001/sms),新增一条短消息,成功后会返回资源的路径(http://localhost:8001/sms/1)。
消费者——一个WebApp(springCloudDemoWeb)
WebApp项目只需要引入spring-boot-starter-web
,spring-cloud-starter-eureka
的依赖即可。其它配置文件与短信服务类似,端口使用8101。我们在此基础上实现一个调用短信服务的Controller。
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.client.RestTemplate;
import java.util.List;
/**
* Created by chenxyz on 2018/5/20.
*/
@Controller
@RequestMapping("/sms")
public class SMSController {
@Autowired
DiscoveryClient discoveryClient;
@Autowired
RestTemplate restTemplate;
public static final String SMS_INSTANCE = "sms-service";
public static final String SMS_PATH = "/sms";
@RequestMapping("getSMSById")
@ResponseBody
public String getSMSById(String id) {
List<ServiceInstance> instances = discoveryClient.getInstances(SMS_INSTANCE);
ServiceInstance instance = instances.get(0);
String url = "http://"+instance.getHost()+":"+instance.getPort()+SMS_PATH+"/"+id;
return restTemplate.getForObject(url, String.class);
}
}
discoveryClient.getInstances(SMS_INSTANCE)
会根据指定的应用名称在Eureka中找到服务部署的多个实例。
我们可以使用一个实例发起HTTP请求。
直接调用WebApp的接口http://localhost:8101/sms/getSMSById?id=1,成功获取到短信信息。
Eureka的高可用
实际环境中Eureka作为注册中心需要实现高可用。此处我们为了模拟这种场景,在本地的hosts文件中增加一行。
127.0.0.1 eureka1 eureka2 eureka3
修改Eureka的服务端application.yml
配置文件,使用不同的环境配置属性。
info:
name: Eureka Server
spring:
profiles:
active: dev
---
spring:
profiles: dev
server:
port: 8761
eureka:
client:
#是否注册到EurekaServer
register-with-eureka: true
#是否拉取信息
fetch-registry: false
#eureka server地址
service-url:
default-zone: http://127.0.0.1:8761/eureka/
server:
wait-time-in-ms-when-sync-empty: 0
#关闭自我保护,不管如何都要剔除心跳检测异常的服务
enable-self-preservation: true
peer-eureka-nodes-update-interval-ms: 1800000
instance:
hostname: eureka
---
spring:
profiles: eureka1
server:
port: 8761
eureka:
client:
registerWithEureka: true
fetchRegistry: true
serviceUrl:
defaultZone: http://eureka1:8761/eureka/,http://eureka2:8762/eureka/,http://eureka3:8763/eureka/
#defaultZone: http://127.0.0.1:8761/eureka/,http://127.0.0.1:8762/eureka/,http://127.0.0.1:8763/eureka/
server:
waitTimeInMsWhenSyncEmpty: 0
instance:
hostname: eureka1
#hostname: 127.0.0.1:8761
metadataMap:
instanceId: ${spring.application.name}:${vcap.application.instance_id:${spring.application.instance_id:${random.value}}}
---
spring:
profiles: eureka2
server:
port: 8762
eureka:
client:
registerWithEureka: true
fetchRegistry: true
serviceUrl:
defaultZone: http://eureka1:8761/eureka/,http://eureka2:8762/eureka/,http://eureka3:8763/eureka/
#defaultZone: http://127.0.0.1:8761/eureka/,http://127.0.0.1:8762/eureka/,http://127.0.0.1:8763/eureka/
server:
waitTimeInMsWhenSyncEmpty: 0
instance:
hostname: eureka2
#hostname: 127.0.0.1:8762
metadataMap:
instanceId: ${spring.application.name}:${vcap.application.instance_id:${spring.application.instance_id:${random.value}}}
---
spring:
profiles: eureka3
server:
port: 8763
eureka:
client:
registerWithEureka: true
fetchRegistry: true
serviceUrl:
defaultZone: http://eureka1:8761/eureka/,http://eureka2:8762/eureka/,http://eureka3:8763/eureka/
#defaultZone: http://127.0.0.1:8761/eureka/,http://127.0.0.1:8762/eureka/,http://127.0.0.1:8763/eureka/
server:
waitTimeInMsWhenSyncEmpty: 0
instance:
hostname: eureka3
#hostname: 127.0.0.1:8763
metadataMap:
instanceId: ${spring.application.name}:${vcap.application.instance_id:${spring.application.instance_id:${random.value}}}
将服务端代码打jar包,并且启动三个服务端,每个服务端加载不同的配置。
java -jar springCloudDemo-eureka.jar --spring.profiles.active=eureka1
java -jar springCloudDemo-eureka.jar --spring.profiles.active=eureka2
java -jar springCloudDemo-eureka.jar --spring.profiles.active=eureka3
服务启动成功后,打开三个控制端(端口分别为8761,8762,8763),可以观察到三个服务端已相互注册。使用短信服务或者WebApp应用向某一Eureka注册成功后,其它Eureka也会自动注册相应的应用。