1.简介
1.1 概述
Service Discovery is one of the key tenets of a microservice-based architecture. Trying to hand-configure each client or some form of convention can be difficult to do and can be brittle. Eureka is the Netflix Service Discovery Server and Client. The server can be configured and deployed to be highly available, with each server replicating state about the registered services to the others.
服务发现是基于微服务的体系结构的主要宗旨之一。尝试手动配置每个客户端或某种形式的约定可能很困难并且很脆弱。 Eureka是Netflix Service Discovery服务器和客户端。可以将服务器配置和部署为高度可用,每个服务器将有关已注册服务的状态复制到其他服务器。
1.2 特点
The Eureka server does not have a back end store, but the service instances in the registry all have to send heartbeats to keep their registrations up to date (so this can be done in memory). Clients also have an in-memory cache of Eureka registrations (so they do not have to go to the registry for every request to a service).
By default, every Eureka server is also a Eureka client and requires (at least one) service URL to locate a peer. If you do not provide it, the service runs and works, but it fills your logs with a lot of noise about not being able to register with the peer.
Eureka服务器没有后端存储,但是注册表中的所有服务实例都必须发送心跳信号以使其注册保持最新(这样可以在内存中完成)。客户端还具有Eureka注册的内存缓存(因此,不用每个请求都转发到注册中心)。
默认情况下,每个Eureka服务器也是Eureka客户端,并且需要(至少一个)服务URL来定位对等方。如果您不提供该服务,则该服务将运行并工作,但是它将使您的日志充满无法注册到对等方的噪音。
2.演示环境
- JDK 1.8.0_201
- Spring Boot 2.2.0.RELEASE、Spring Cloud Hoxton.RELEASE
- 构建工具(apache maven 3.6.3)
- 开发工具(IntelliJ IDEA )
3.演示代码
- nfx-eureka-client: eureka 客户端,注册到 eureka 服务端:
- user-api: 公共api,定义实体和接口;
- user-service-provider: 服务提供方,注册到 eureka server
- user-service-consumer: 服务调用方,注册到 eureka server
- nfx-eureka-server: eureka 服务端,负责提供服务注册及发现功能。
3.1 nfx-eureka-server
3.1.1 代码说明
eureka 服务端,供客户端进行注册,同时提供服务发现功能。
3.1.2 maven 依赖
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
</dependencies>
3.1.3 配置文件
spring.application.name=nfx-eureka-server
# 端口号
server.port=9090
# 服务注册中心主机名
eureka.instance.hostname=localhost
# 是否注册自己
eureka.client.register-with-eureka=false
# 是否检索服务
eureka.client.fetch-registry=false
# eureka server 地址
eureka.client.service-url.defaultZone=http://${eureka.instance.hostname}:${server.port}/eureka/
3.1.4 java代码
NetflixEurekaServerApplication.java
// 通过 @EnableEurekaServer 声明为 eureka 服务端
@EnableEurekaServer
@SpringBootApplication
public class NetflixEurekaServerApplication {
public static void main(String[] args) {
SpringApplication.run(NetflixEurekaServerApplication.class, args);
}
}
3.2 nfx-eureka-client
3.2.1 user-api
3.2.1.1 代码说明
公共模型和接口定义
3.2.1.2 java代码
UserModel.java
public class UserModel {
private Long id;
private String name;
private Integer age;
private String birthday;
private String address;
private String phone;
public UserModel() {
}
public UserModel(Long id, String name, Integer age, String birthday, String address, String phone) {
this.id = id;
this.name = name;
this.age = age;
this.birthday = birthday;
this.address = address;
this.phone = phone;
}
// get&set&toString
}
UserService.java
public interface UserService {
List<UserModel> findAll();
UserModel findById(Long id);
UserModel add(UserModel userModel);
UserModel update(UserModel userModel);
UserModel deleteById(Long id);
}
3.2.2 user-service-provider
3.2.1 代码说明
服务提供者,依赖 user-api,实现其中的接口;注册到 eureka server
3.2.2 maven 依赖
<dependencies>
<dependency>
<groupId>com.soulballad.usage</groupId>
<artifactId>user-api</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
3.2.3 配置文件
spring.application.name=eureka-client-provider
server.port=8090
eureka.server.host=localhost
eureka.server.port=9090
eureka.client.service-url.defaultZone=http://${eureka.server.host}:${eureka.server.port}/eureka/
3.2.4 java代码
UserRepository.java
@Repository
public class UserRepository {
// 预置两条数据,所以起始值从2开始
private static final AtomicLong ID_GENERATOR = new AtomicLong(2);
// 模拟数据库操作
private static final Map<Long, UserModel> USER_MAP = new HashMap<>();
@PostConstruct
public void init() {
UserModel user1 = new UserModel(1L, "zhangsan", 20, "2000-01-02", "beijing", "13666666666");
UserModel user2 = new UserModel(2L, "lisi", 30, "1990-03-23", "shanghai", "13888888888");
USER_MAP.put(user1.getId(), user1);
USER_MAP.put(user2.getId(), user2);
}
public List<UserModel> findAll() {
return new ArrayList<>(USER_MAP.values());
}
public UserModel findById(Long id) {
return USER_MAP.containsKey(id) ? USER_MAP.get(id) : new UserModel();
}
public UserModel add(UserModel userModel) {
long id = ID_GENERATOR.incrementAndGet();
userModel.setId(id);
USER_MAP.put(id, userModel);
return userModel;
}
public UserModel update(UserModel userModel) {
USER_MAP.put(userModel.getId(), userModel);
return USER_MAP.get(userModel.getId());
}
public UserModel deleteById(Long id) {
UserModel userModel = USER_MAP.get(id);
USER_MAP.remove(id);
return userModel;
}
}
UserServiceImpl.java
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserRepository userRepository;
@Override
public List<UserModel> findAll() {
return userRepository.findAll();
}
@Override
public UserModel findById(Long id) {
return userRepository.findById(id);
}
@Override
public UserModel add(UserModel userModel) {
return userRepository.add(userModel);
}
@Override
public UserModel update(UserModel userModel) {
return userRepository.update(userModel);
}
@Override
public UserModel deleteById(Long id) {
return userRepository.deleteById(id);
}
}
UserProviderController.java
@RestController
@RequestMapping(value = "/provider/user")
public class UserProviderController {
@Autowired
private UserService userService;
@GetMapping(value = "/list")
public List<UserModel> list() {
return userService.findAll();
}
@GetMapping(value = "/query/{id}")
public UserModel query(@PathVariable Long id) {
return userService.findById(id);
}