基础概念

  • Register 服务注册: Client 向 Server 注册,提供自身的元数据,比如IP地址、端口,运行状况指示符URL,主页等。
  • Renew 服务续约:Client 默认 30秒发送一次心跳来续约。告知 Server 该 Client仍然存在。正常情况下,如果 Server 在90秒没有收到 Client 的续约,会将该 Client 从其注册表中剔除。
  • Fetch Registeries:
    • Client 从 Server 获取注册表信息,并将其缓存在本地。
    • Client 会使用该信息查找其他服务,从而进行远程调用。
    • 该注册列表信息定期(每30秒)更新一次。
    • Server 注册列表信息可能与 Client 的缓存信息不同, 以 Server 端为准,覆盖本地。
  • Cancel 服务下线:Client 在程序关闭时向 Server发送取消请求。
  • Eviction 服务剔除: Server 在90秒(3个续约周期)没有收到 Client 的续约,会将该 Client 从其注册表中剔除。

    Eureka Server

    maven ```xml org.springframework.cloud spring-cloud-starter-netflix-eureka-server
  1. application.yml
  2. ```java
  3. spring:
  4. application:
  5. name: eureka-server
  6. server:
  7. # http://localhost:20000/
  8. port: 20000
  9. eureka:
  10. instance:
  11. hostname: localhost
  12. client:
  13. # 不发起服务注册,因为该示例本身就是注册中心
  14. register-with-eureka: false
  15. # 不拉取服务注册表
  16. fetch-registry: false

启动类

@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {
    public static void main(String[] args) {
        new SpringApplicationBuilder(EurekaServerApplication.class)
                .web(WebApplicationType.SERVLET)
                .run(args);
    }
}

监控页面属性
System Status:

  • Uptime 01:02 自启动到现在的时间,小时:分钟
  • Lease expiration enabled false 是否启用租约过期,和服务续约、服务剔除、服务自保 有关。租约过期剔除
  • Renews threshold 1 每分钟最少续约数,如果续订小于阈值,实例不会过期
  • Renews (last min) 0 上一分钟的续约数量(不包括当前分钟)

DS Replicas:
Instances currently registered with Eureka:

  • Application: 应用名称
  • AMIs
  • Availability Zones 机器数量
  • Status: UP(N)标识N个服务处于可用状态 DOWN(N)个服务挂掉

General Info:

  • total-avail-memory 388mb 总可用内存
  • environment test 环境
  • num-of-cpus 6 CPU 个数
  • current-memory-usage 204mb (52%) 当前使用内存
  • server-uptime 00:13 最近已启动时间
  • registered-replicas 相邻的集群复制节点
  • unavailable-replicas 集群中不可用的节点
  • available-replicas 集群中可用节点

Instance Info(注册中心信息):
ipAddr IP
status UP/DOWN

右上角 LAST 1000 SINE STARTUP:
Last 1000 cancelled leases 最近1000个取消租约的实例
Last 1000 newly registered leases 最近1000个注册实例

Eureka Provider

maven

<dependencies>
  <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>

application.yml

spring:
  application:
    name: eureka-provider
server:
  port: 30000

eureka:
  client:
    service-url:
      defaultZone: http://localhost:20000/eureka

启动类

@SpringBootApplication
@EnableDiscoveryClient
public class EurekaProviderApplication {

    public static void main(String[] args) {
        new SpringApplicationBuilder(EurekaProviderApplication.class)
                .web(WebApplicationType.SERVLET)
                .run(args);
    }
}

接口示例

@RestController
@Slf4j
public class HelloController {

    @Value("${server.port}")
    private String port;

    @GetMapping("/sayHi")
    public String sayHai() {
        return "This is " + port;
    }

    @PostMapping("/sayHi")
    public Friend sayHiPort(@RequestBody Friend friend) {
        log.info("You are" + friend.getName());
        friend.setPort(port);
        return friend;
    }
}

Eureka Consumer

与 provider 类似 对于 server 来说都是 client。对于业务流程,这里是消费者,也就是服务调用者。
调用者可以使用客户端的负载均衡来决定调用哪个生产者服务。
application.yml 示例

spring:
  application:
    name: eureka-consumer
server:
  port: 31000

eureka:
  client:
    service-url:
      defaultZone: http://localhost:20000/eureka

接口示例

@RestController
@Slf4j
public class Controller {

    @Autowired
    private LoadBalancerClient client;
    //  RestTemplate 要注册下 Bean
    @Autowired
    private RestTemplate restTemplate;

    @GetMapping("/hello")
    public String hello() {
        ServiceInstance instance = client.choose("eureka-provider");
        if (instance == null) {
            return "No available instance";
        }

        String target = String.format("http://%s:%s/sayHi", instance.getHost(), instance.getPort());
        log.info("url is {}", target);

        return restTemplate.getForObject(target, String.class);
    }

    @PostMapping("/hello")
    public Friend helloPost() {
        ServiceInstance instance = client.choose("eureka-provider");
        if (instance == null) {
            return null;
        }

        String target = String.format("http://%s:%s/sayHi", instance.getHost(), instance.getPort());
        log.info("url is {}", target);
        Friend friend = new Friend();
        friend.setName("Eureka Consumer");
        return restTemplate.postForObject(target, friend, Friend.class);
    }
}

测试启动

最好 先启动 server,再启动 client,最后 consumer。
否则可能出现服务不可用,要等一会才能重新发现服务

配置中心 Server 高可用

启动两台 Server,A 的 defaultZone 设置为 A,B 的 defaultZone 设置为 B

Client 的 defaultZone 设置为 A, B
例如

defaultZone: https://xxx.cn/eureka,https://yyy.cn/eureka

Server 之间同步注册表
Client 轮询 Server

https://juejin.cn/post/6844904007975043079
image.png
https://juejin.cn/post/6929572197333893133
image.png