侧边栏壁纸
博主头像
soulballad博主等级

技术文章记录及总结

  • 累计撰写 169 篇文章
  • 累计创建 26 个标签
  • 累计收到 4 条评论

目 录CONTENT

文章目录

【Spring Cloud学习】-2.Spring Cloud Eureka 服务注册中心

soulballad
2020-08-11 / 0 评论 / 0 点赞 / 56 阅读 / 11,770 字
温馨提示:
本文最后更新于 2022-04-19,若内容或图片失效,请留言反馈。部分素材来自网络,若不小心影响到您的利益,请联系我们删除。

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.演示环境

  1. JDK 1.8.0_201
  2. Spring Boot 2.2.0.RELEASE、Spring Cloud Hoxton.RELEASE
  3. 构建工具(apache maven 3.6.3)
  4. 开发工具(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);
    }

    @PostMapping(value = "/add")
    public UserModel add(@RequestBody UserModel userModel) {
        return userService.add(userModel);
    }

    @PutMapping(value = "/update")
    public UserModel update(@RequestBody UserModel userModel) {
        return userService.update(userModel);
    }

    @DeleteMapping(value = "/delete/{id}")
    public UserModel deleteById(@PathVariable Long id) {
        return userService.deleteById(id);
    }
}

3.2.3 user-service-consumer

3.2.3.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-consumer
server.port=8080
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代码

UserServiceProxy.java

@Service
public class UserServiceProxy implements UserService {

    // user-service-provider 的 application.properties 中 spring.application.name + prefix
    private static final String USER_PROVIDER_PREFIX = "http://eureka-client-provider" + "/provider/user";

    // 在 UserServiceConsumerApplication 进行声明
    @Autowired
    private RestTemplate restTemplate;

    @Override
    public List<UserModel> findAll() {
        UserModel[] userArray = restTemplate.getForObject(USER_PROVIDER_PREFIX + "/list", UserModel[].class);
        return Arrays.asList(userArray != null ? userArray : new UserModel[0]);
    }

    @Override
    public UserModel findById(Long id) {
        return restTemplate.getForObject(USER_PROVIDER_PREFIX + "/query/{id}", UserModel.class, id);
    }

    @Override
    public UserModel add(UserModel userModel) {
        return restTemplate.postForObject(USER_PROVIDER_PREFIX + "/add", userModel, UserModel.class);
    }

    @Override
    public UserModel update(UserModel userModel) {
        restTemplate.put(USER_PROVIDER_PREFIX + "/update", userModel);
        return findById(userModel.getId());
    }

    @Override
    public UserModel deleteById(Long id) {
        UserModel userModel = findById(id);
        restTemplate.delete(USER_PROVIDER_PREFIX + "/delete/{id}", id);
        return userModel;
    }
}

UserConsumerController.java

@RestController
@RequestMapping(value = "/consumer/user")
public class UserConsumerController {

    @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);
    }

    @PostMapping(value = "/add")
    public UserModel add(@RequestBody UserModel userModel) {
        return userService.add(userModel);
    }

    @PutMapping(value = "/update")
    public UserModel update(@RequestBody UserModel userModel) {
        return userService.update(userModel);
    }

    @DeleteMapping(value = "/delete/{id}")
    public UserModel deleteById(@PathVariable Long id) {
        return userService.deleteById(id);
    }
}

UserServiceConsumerApplication.java

@EnableDiscoveryClient
@SpringBootApplication
public class UserServiceConsumerApplication {

    public static void main(String[] args) {
        SpringApplication.run(UserServiceConsumerApplication.class, args);
    }

    // 负载均衡
    @Bean
    @LoadBalanced
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
}

3.3 git 地址

spring-cloud-nfx-02-eureka: Spring Cloud 整合 Eureka 实现的分布式注册中心方案

4.效果展示

4.1 nfx-eureka-server

启动 eureka 服务端 nfx-eureka-server,访问 http://localhost:9090, 可以看到如下页面

没有任何服务注册到 nfx-eureka-server 上面来。

4.2 user-service-provider

然后再启动 user-service-provider,再次访问 http://localhost:9090,可以看到服务提供者已经注册上来了

在 netflix-eureka-client-provider 访问下列地址,观察输出信息是否符合预期。

查询用户列表

###  GET /provider/user/list
GET http://localhost:8090/provider/user/list
Accept: application/json

根据id查询用户

###  GET /provider/user/query/{id}
GET http://localhost:8090/provider/user/query/1
Accept: application/json

新增用户

###  POST /provider/user/add
POST http://localhost:8090/provider/user/add
Accept: application/json
Content-Type: application/json

{
  "name": "wangwu",
  "age": 20,
  "birthday": "2000-01-01",
  "address": "wuhan",
  "phone": "15999999999"
}

更新用户

###  PUT /provider/user/update
PUT http://localhost:8090/provider/user/update
Accept: application/json
Content-Type: application/json

{
  "id": 2,
  "name": "lisi",
  "age": 40,
  "birthday": "1980-01-01",
  "address": "guangzhou",
  "phone": "13888888888"
}

根据id删除用户

###  DELETE /provider/user/delete/{id}
DELETE http://localhost:8090/provider/user/delete/3
Accept: application/json

可以看到 user-service-provider 提供的接口都可以正常运行

4.3 user-service-consumer

然后再启动 user-service-consumer,再次访问 http://localhost:9090,可以看到服务提供者已经注册上来了

在 netflix-eureka-client-consumer 访问下列地址,观察输出信息是否符合预期。

查询用户列表

###  GET /consumer/user/list
GET http://localhost:8080/consumer/user/list
Accept: application/json

根据id查询用户

###  GET /consumer/user/query/{id}
GET http://localhost:8080/consumer/user/query/1
Accept: application/json

新增用户

###  POST /consumer/user/add
POST http://localhost:8080/consumer/user/add
Accept: application/json
Content-Type: application/json

{
  "name": "wangwu",
  "age": 20,
  "birthday": "2000-01-01",
  "address": "wuhan",
  "phone": "15999999999"
}

更新用户

###  PUT /consumer/user/update
PUT http://localhost:8080/consumer/user/update
Accept: application/json
Content-Type: application/json

{
  "id": 2,
  "name": "lisi",
  "age": 40,
  "birthday": "1980-01-01",
  "address": "shanghang-pudong",
  "phone": "13888888888"
}

根据id删除用户

###  DELETE /consumer/user/delete/{id}
DELETE http://localhost:8080/consumer/user/delete/4
Accept: application/json

5.参考

  1. 官方文档-Spring Cloud Netflix/Eureka
0

评论区