SpringCloud -服务注册中心

服务注册中心

概念

在服务注册与发现中,有一个注册中心。当服务器启动的时候,会把当前自己服务器的信息,比如服务地址通讯地址等以别名方式注册到注册中心上。另一方(消费者|服务提供者)以该别名的方式去注册中心上获取到实际的服务通讯地址,然后再实现RPC本地调用RPC远程服务,框架核心设计思想:在于注册中心,因为使用注册中心管理每个服务与服务之间的一个依赖关系(服务治理概念)

Eureka

两个组件

在这里插入图片描述

集群说明

在这里插入图片描述

Eureka搭建(单机版及集群版)

1. Eureka注册中心

  1. pom.xml
<!--eureka-server-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
  1. yml
server:
  port: 7001

eureka:
  instance:
    hostname: eureka7001.com #eureka服务端的实例名称,本地需要在hosts文件改
  client:
    register-with-eureka: false     #false表示不向注册中心注册自己。
    fetch-registry: false     #false表示自己端就是注册中心,我的职责就是维护服务实例,并不需要去检索服务
    service-url:
#      集群指向其它eureka
      defaultZone: http://eureka7002.com:7002/eureka/
  1. 主启动类
@SpringBootApplication
@EnableEurekaServer //作为Eureka服务端
public class EurekaMain7001 {
    public static void main(String[] args) {
        SpringApplication.run(EurekaMain7001.class,args);
    }
}

2. 服务提供者

  1. pom.xml
<!--eureka-client-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
  1. yml
spring:
  application:
    name: cloud-payment-service # 该服务的名称,相同的服务名字相同,ip+端口不同

eureka:
  client:
    # 表示是否将自己注册进EurekaServer 默认为true
    register-with-eureka: true
    # 是否从eurekaServer抓取已有的注册信息,默认为true。单节点无所谓,集群必须设置为true才能配合ribbon使用负载均衡
    fetch-registry: true
    service-url:
      # 单机版
#      defaultZone: http://localhost:7001/eureka
      # 集群版
      defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka
  1. 主启动类
@SpringBootApplication
@EnableEurekaClient //作为Eureka客户端
public class PaymentMain8001 {
    public static void main(String[] args) {
        SpringApplication.run(PaymentMain8001.class,args);
    }
}
  1. controller类
public class PaymentController {

    @Resource
    private PaymentService paymentService;

//import org.springframework.beans.factory.annotation.Value; 获得配置文件属性
    @Value("${server.port}") 
    private String serverPort;

    @ResponseBody
    @PostMapping(value = "/payment/create")
    public CommonResult create(@RequestBody Payment payment){
        int i = paymentService.create(payment);
        log.info("****插入结果:"+i);
        if(i>0){
            return new CommonResult(200,"插入数据成功"+serverPort,i);
        }else {
            return new CommonResult(444,"插入数据失败",null);
        }
    }
    

    @RequestMapping(value = "/payment/get/{id}")
    @ResponseBody
    public CommonResult<Payment> getPaymentById(@PathVariable("id") Long id)
    {
        Payment payment = paymentService.getPaymentById(id);
        log.info("数据:{}",payment);

        if(payment != null)
        {
            return new CommonResult(200,"查询成功,serverPort:"+serverPort,payment);
        }else{
            return new CommonResult(444,"没有对应记录,查询ID: "+id,null);
        }
    }
}

3. 服务消费者

  1. pom.xml
<!--eureka-client-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
  1. yml
eureka:
  client:
    # 表示是否将自己注册进EurekaServer 默认为true
    register-with-eureka: true
    # 是否从eurekaServer抓取已有的注册信息,默认为true。单节点无所谓,集群必须设置为true才能配合ribbon使用负载均衡
    fetch-registry: true
    service-url:
      # 单机版
#      defaultZone: http://localhost:7001/eureka
      # 集群版
      defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka
  1. 主启动类
@SpringBootApplication
@EnableEurekaClient
public class OrderMain80 {
    public static void main(String[] args) {
        SpringApplication.run(OrderMain80.class,args);
    }
}
  1. 配置RestTemplate
@Configuration
public class ApplicationContextConfig {

    @Bean
    @LoadBalanced //赋予负载均衡能力
    public RestTemplate getRestTemplate(){
        return new RestTemplate();
    }
}
  1. controller
@RestController
@Slf4j
public class OrderController {
//    private static final String PAYMENT_URL = "http://localhost:8001";
    private static final String PAYMENT_URL = "http://CLOUD-PAYMENT-SERVICE"; //提供者对外开放的服务名

    @Resource
    private RestTemplate restTemplate;

    @GetMapping("/consumer/payment/create")
    public CommonResult create(Payment payment){
        return restTemplate.postForObject(PAYMENT_URL+"/payment/create",payment,CommonResult.class);
    }

    @GetMapping("/consumer/payment/get/{id}")
    public CommonResult getPayment(@PathVariable long id){
        return restTemplate.getForObject(PAYMENT_URL+"/payment/get/"+id,CommonResult.class);
    }
}

4.附录

  1. CommonResult
@Data
@AllArgsConstructor
@NoArgsConstructor
public class CommonResult<T> {
    //404 Not Found

    private Integer code;
    private String message;
    private T data;

    public CommonResult(Integer code, String message) {
        this(code,message,null);
    }
}

服务发现DisCovery(服务提供者暴露)

  1. yml
instance:
  # 修改status处名称,修改命名规范
  instance-id: payment8001
  # 访问历经可以显示IP地址
  prefer-ip-address: true
  1. Controller(主要)
@Resource
private DiscoveryClient discoveryClient;

@GetMapping("/payment/discovery")
public Object discovery(){

    //获得服务清单,仅名字
    List<String> services = discoveryClient.getServices();
    for (String elements : services) {
        log.info("*********element: +{}",elements);
    }

    //第二种获得方式,可获得属性
    List<ServiceInstance> instances = discoveryClient.getInstances("cloud-payment-service");
    for (ServiceInstance instance : instances) {
        log.info(instance.getServiceId()+"\t"+instance.getHost()+"\t"+instance.getPort()+"\t"+instance.getUri());
    }
    return this.discoveryClient;
}
  1. 主启动类
@SpringBootApplication
@EnableEurekaClient
@EnableDiscoveryClient
public class PaymentMain8001 {
    public static void main(String[] args) {
        SpringApplication.run(PaymentMain8001.class,args);
    }
}

Eureka自我保护

  1. 导致原因

某一时刻某一个微服务不可用了,Eureka不会立刻清除,依旧会对改为服务的信息进行保存
属于CAP里面的AP分支

  1. 自我保护模式
  1. 默认情况下,如果EurekaServer在一定时间内没有收到某个微服务实例的心跳,Eureka将会注销该实例(默认90s)
  2. 因网络故障可能短时间内丢失很多微服务,这些微服务本不应该被注销,此时Eureka开启自我保护模式
  3. 在自我保护模式中,Eureka Server会保护服务注册表中的信息,不再注销任何服务实例
  1. Eureka服务端配置
eureka:
  server:
    #关闭自我保护机制,保证不可用服务被及时踢除
    enable-self-preservation: false
    # 2ms没有心跳就删除
    eviction-interval-timer-in-ms: 2000
  1. 可在客户端设置心跳发送时间
eureka:
 instance:
  # Eureka客户端向服务端发送心跳的时间间隔,单位是秒(默认30s)
  lease-renewal-interval-in-seconds: 1
  # Eureka服务端在收到最后一次心跳后等待时间上限,单位是秒(默认90s)
  lease-expiration-duration-in-seconds: 2

Zookeeper

服务提供者配置

  1. pom.xml (注意这里需要些许操作)
<!-- SpringBoot整合zookeeper客户端 -->
<!-- 注意如果报zookeeper-xxx-beta.jar 错误,就是Jar包不匹配,需以下操作 -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-zookeeper-discovery</artifactId>
    <!--先排除自带的zookeeper3.5.3-->
    <exclusions>
        <exclusion>
            <groupId>org.apache.zookeeper</groupId>
            <artifactId>zookeeper</artifactId>
        </exclusion>
    </exclusions>
</dependency>
<!--添加zookeeper3.4.9版本-->
<dependency>
    <groupId>org.apache.zookeeper</groupId>
    <artifactId>zookeeper</artifactId>
    <version>3.4.9</version>
</dependency>
  1. yml
#8004表示注册到zookeeper服务器的支付服务提供者端口号
server:
  port: 8004


#服务别名----注册zookeeper到注册中心名称
spring:
  application:
    name: cloud-provider-payment
  cloud:
    zookeeper:
      connect-string: 39.108.176.185:2181
  1. 主启动类
@SpringBootApplication
@EnableDiscoveryClient //该注解用于向使用consul或者zookeeper作为注册中心时注册服务
public class PaymentMain8004 {
    public static void main(String[] args) {
        SpringApplication.run(PaymentMain8004.class,args);
    }
}
  1. controller
@RestController
public class PaymentController {
    @Value("${server.port}")
    private String serverPort;

    @RequestMapping(value = "/payment/zk")
    public String paymentzk()
    {
        return "springcloud with zookeeper: "+serverPort+"\t"+ UUID.randomUUID().toString();
    }
}

服务消费者配置

  1. pom同上
  2. yml
#8004表示注册到zookeeper服务器的支付服务提供者端口号
server:
  port: 80


#服务别名----注册zookeeper到注册中心名称
spring:
  application:
    name: cloud-consumer-order
  cloud:
    zookeeper:
      connect-string: 39.108.176.185:2181
  1. 主启动类
@SpringBootApplication
@EnableDiscoveryClient
public class OrderZKMain80 {
    public static void main(String[] args) {
        SpringApplication.run(OrderZKMain80.class,args);
    }
}
  1. 配置类
@Configuration
public class RestTemplateConfig {

    @Bean
    @LoadBalanced //赋予负载均衡能力
    public RestTemplate restTemplate(){
        return  new RestTemplate();
    }
}
  1. controller
@RestController
@Slf4j
public class OrderZKController {
    public static final String INVOKE = "http://cloud-provider-payment";

    @Resource
    private RestTemplate restTemplate;

    @RequestMapping(value = "/consumer/payment/zk",method = RequestMethod.GET)
    public String paymentInfo(){
        return restTemplate.getForObject(INVOKE + "/payment/zk", String.class);
    }

}

基本

  1. zookeeper创建的是临时节点
  2. 集群配置同zookeeper

ConSul

官网
安装

基本

  1. 基本同zookeeper,即服务提供者+消费者
  2. 访问地址为:host:8500
  3. 不确定:consul与客户端之间要相互可以ping通,否则service check不通过,服务无法上线

服务提供者

  1. pom
<!--SpringCloud consul-server -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-consul-discovery</artifactId>
</dependency>
  1. yml
server:
  port: 8006

spring:
  application:
    name: consul-provider-payment

  cloud:
    consul:
      host: 192.168.199.132
      port: 8500
      discovery:
        service-name: ${spring.application.name}
        prefer-ip-address: true
  1. 主启动类
@SpringBootApplication
@EnableDiscoveryClient
public class PaymentMain8006 {
    public static void main(String[] args) {
        SpringApplication.run(PaymentMain8006.class,args);
    }
}
  1. controller
@RestController
@Slf4j
public class PaymentController {

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

    @RequestMapping(value = "/payment/consul")
    public String paymentConsul()
    {
        return "springcloud with consul: "+serverPort+"\t"+ UUID.randomUUID().toString();
    }
}

服务消费者

  1. pom同上
  2. yml
server:
  port: 80

spring:
  application:
    name: cloud-consumer-order

  cloud:
    consul:
      host: 192.168.199.132
      port: 8500
      discovery:
        service-name: ${spring.application.name}
  1. 配置类
@Configuration
public class RestTemplateConfig {

    @Bean
    @LoadBalanced //赋予负载均衡能力
    public RestTemplate restTemplate(){
        return  new RestTemplate();
    }
}
  1. 启动类
@SpringBootApplication
@EnableDiscoveryClient
public class OrderConsulMain80 {
    public static void main(String[] args) {
        SpringApplication.run(OrderConsulMain80.class,args);
    }
}
  1. controller
@RestController
public class OrderConsulController {
    public static final String INVOKE = "http://consul-provider-payment";
    
    @Resource
    private RestTemplate restTemplate;
    
    @RequestMapping(value = "/consumer/payment/consul",method = RequestMethod.GET)
    public String paymentInfo(){
        return restTemplate.getForObject(INVOKE + "/payment/consul", String.class);
    }
}

三者异同点

组件名语言CAP服务健康检查对外暴露接口spring Cloud集成
EurekaJavaAP可配支持HTTP已集成
ConsulGoCP支持HTTP/DNS已集成
ZookeeperJavaCP支持客户端已集成

CAP

概念

C:Consistency(强一致性,数据一定要一样)
A:Availability(可用性,不宕机)
P:Partition tolerance(分区容错性)
CAP理论关注粒度是数据,而不是整体系统设计的策略

经典CAP图

在这里插入图片描述

特点

  1. 理论核心

最多只能同时较好的满足两个
CAP的理论和形式:一个分布式系统不可能同时很好的满足一致性,可用性和分区容错性这三个需求

  1. 三大类
  • CA:单点集群,满足一致性,可用性的系统,通常在可扩展性上不太强大
  • CP:满足一致性,分区容忍性的系统,通常性能不是特别高
  • AP:满足可用性,分区容忍性的系统,通常对一致性要求低一些

A

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值