SpringCloud(1)-服务注册与发现

SpringCloud

什么是微服务?

将单一的应用程序分成一组小的服务,服务间可以相互协调,配合(轻量级,)

什么是springcloud?

微服务架构的一站式解决方案

技术栈

服务注册与发现

EUREKA(停更),Zookeeper,Consul,Nocos

服务调用

RIBBON(NETFLIX网飞), LoadBalancer, FELGN(停更) , OpenFeign

服务熔断降级

HYSTRIX (不推荐) ,resilience4j (国外推荐) ,sentienl (国内推荐)

服务网关

ZUUL (不推荐) , gateWay

服务分布配置

SpringCloud Config (不推荐) , Nocos

服务总线

Bus (不推荐) , Nocos

服务开发

SpringBoot


Eureka

服务治理?

管理服务于服务间的依赖关系,实现:负载均衡,容错,服务调用

服务注册?

Service Provider 去 Eureka Server注册服务

Eureka Server

提供注册服务,存储可以的服务节点

Eureka Client

通过注册中心进行访问,也就是Service Provider,内置Ribbon负载均衡器(轮询),心跳周期(30s)

Service Consumer如何调用服务?

先去Eureka Server中找有没有该服务,再去调用Service Provider

单点故障

Eureka


服务注册

单机Eureka构建

EurekaServer

pom.xml
<!--        图形监控-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <!--eureka-server-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
        </dependency>
application.yml
server:
  port: 7001
spring:
  application:
    name: cloud-eureka-service

eureka:
  server:
    enable-self-preservation: false #出产默认,自我保护机制是开启的
  instance:
    # eureka服务端的实例名称
    hostname: localhost
  client:
    # false表示不向注册中心注册自己
    register-with-eureka: false
    # false表示自己端就是注册中心,我的职责就是维护服务实例,并不需要检索服务
    fetch-registry: false
    service-url:
      # 设置与Eureka Server交互的地址查询服务和注册服务都需要依赖这个地址
      defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
主启动类
@EnableEurekaServer
@SpringBootApplication
public class EurekaMain7001 {
    public static void main(String[] args) {
        SpringApplication.run(EurekaMain7001.class);
    }
}

在这里插入图片描述

EurekaClient

pom.xml
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
application.yml
server:
  port: 8001
  tomcat:
    uri-encoding: UTF-8

spring:
  application:
    name: cloud-payment-service
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/db2020?useUnicode=true&amp;characterEncoding=UTF8
    username: root
    password: 123456

mybatis:
  mapper-locations: classpath:mapper/*.xml
  type-aliases-package: com.wu.icloud.entities

eureka:
  client:
    fetch-registry: true
    register-with-eureka: true
    service-url:
            defaultZone: http://localhost:7001/eureka/
#      defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka  # 集群版
  instance:
    instance-id: payment8001
    prefer-ip-address: true #可以显示ip
主启动类

@EnableEurekaClient

@EnableEurekaClient
@SpringBootApplication
public class PaymentMain8001 {
    public static void main(String[] args) {
        SpringApplication.run(PaymentMain8001.class);

    }
}

在这里插入图片描述

Eureka集群构建

原则:互相注册,相互守望,每一个Eureka服务都要有其他Eureka服务的相关信息

eurekaServer7001

application.yml
server:
  port: 7001
spring:
  application:
    name: cloud-eureka-service

eureka:
  server:
    enable-self-preservation: false #出产默认,自我保护机制是开启的
  instance:
    # eureka服务端的实例名称
    hostname: eureka7001.com
  client:
    # false表示不向注册中心注册自己
    register-with-eureka: false
    # false表示自己端就是注册中心,我的职责就是维护服务实例,并不需要检索服务
    fetch-registry: false
    service-url:
      # 设置与Eureka Server交互的地址查询服务和注册服务都需要依赖这个地址
      defaultZone: http://eureka7002.com:7002/eureka/  #集群

在这里插入图片描述

eurekaServer7002

application.yml
server:
  port: 7002
spring:
  application:
    name: cloud-eureka-service2
eureka:
  instance:
    hostname: eureka7002.com
  client:
    register-with-eureka: false
    fetch-registry: false
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka/

在这里插入图片描述

简单的支付微服务集群

payment8001

application.yml
server:
  port: 8001
  tomcat:
    uri-encoding: UTF-8

spring:
  application:
    name: cloud-payment-service
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/db2020?useUnicode=true&amp;characterEncoding=UTF8
    username: root
    password: 123456

mybatis:
  mapper-locations: classpath:mapper/*.xml
  type-aliases-package: com.wu.icloud.entities

eureka:
  client:
    fetch-registry: true
    register-with-eureka: true
    service-url:
#            defaultZone: http://localhost:7001/eureka/
      defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka  # 集群版
  instance:
    instance-id: payment8001
    prefer-ip-address: true #可以显示ip
PaymentController
@RestController
public class PaymentController {

    @Resource
    private PaymentService paymentService;

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

    @Resource
    private DiscoveryClient discoveryClient;

    @PostMapping(value = "/payment/create")
    public CommonResult create(@RequestBody Payment payment) {
        int result = paymentService.create(payment);
        if (result > 0) {
            return new CommonResult(200, "插入数据成功!serverPort:" + serverPort, result);
        } else {
            return new CommonResult(400, "插入数据失败!");
        }
    }

    @GetMapping(value = "/payment/get/{id}")
    public CommonResult getPaymentById(@PathVariable("id") Long id) {
        Payment paymentById = paymentService.getPaymentById(id);
        if (paymentById != null) {
            return new CommonResult(200, "查询成功!serverPort:" + serverPort, paymentById);
        } else {
            return new CommonResult(400, "查询失败!");
        }
    }

    @GetMapping("/payment/discovery")
    public Object discovery() {
        //    通过服务发现来获得该服务的信息
        List<String> services = discoveryClient.getServices();
        for (String element : services) {
            System.out.println("----element:"+element);
        }
        //一个微服务下的全部实例
        List<ServiceInstance> instances = discoveryClient.getInstances("CLOUD-PAYMENT-SERVICE");
        for (ServiceInstance is:instances){
            System.out.println("----:"+is.getScheme()+"-"+is.getServiceId()+"-"+is.getHost()+"-"+is.getUri());
        }
        return this.discoveryClient;
    }

}

payment8002

application.yml
server:
  port: 8002
  tomcat:
    uri-encoding: UTF-8

spring:
  application:
    name: cloud-payment-service
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/db2020?useUnicode=true&amp;characterEncoding=UTF8
    username: root
    password: 123456

mybatis:
  mapper-locations: classpath:mapper/*.xml
  type-aliases-package: com.wu.icloud.entities

eureka:
  client:
    fetch-registry: true
    register-with-eureka: true
    service-url:
      #      defaultZone: http://localhost:7001/eureka/
      defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka  # 集群版
  instance:
#    主机名称:服务名称修改
    instance-id: payment8002
    prefer-ip-address: true #可以显示ip

ServiceConsumer80

消费者

application.yml
server:
  port: 80
spring:
  application:
     name: cloud-order-service
eureka:
  client:
    #表示是否将自己注册进EurekaServer默认为true。
    register-with-eureka: true
    #是否从EurekaServer抓取已有的注册信息,默认为true。单节点无所谓,集群必须设置为true才能配合ribbon使用负载均衡
    fetchRegistry: true
    service-url:
      #单机
#      defaultZone: http://localhost:7001/eureka
#      # 集群
      defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka  # 集群版
OrderController
@RestController
public class OrderController {
    //单机版
//    public static final String URL_PATH = "http://localhost:8001";
    //集群 --eureka中查找
    public static final String URL_PATH = "http://CLOUD-PAYMENT-SERVICE";  //CLOUD-PAYMENT-SERVICE服务名称,他会自动调度
    @Resource
    private RestTemplate restTemplate;

    @PostMapping(value = "/consumer/payment/create")
    public CommonResult create(Payment payment) {
        CommonResult commonResult = restTemplate.postForObject(URL_PATH + "/payment/create", payment, CommonResult.class);
        return commonResult;
    }

    @GetMapping(value = "/consumer/payment/get/{id}")
    public CommonResult getPaymentById(@PathVariable("id") Long id) {
        return restTemplate.getForObject(URL_PATH + "/payment/get/" + id,CommonResult.class);
    }
}
ApplicationConfiguration
@Configuration
public class ApplicationConfiguration {

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

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
可以看出serverPort会轮询的发生变化


服务发现

获取注册进Eureka的服务信息

/**
 * @program: iSpringCloud
 * @author: Mr-Jies
 * @create: 2020-04-14 17:45
 **/
@RestController
public class PaymentController {

    @Resource
    private DiscoveryClient discoveryClient;

    @GetMapping("/payment/discovery")
    public Object discovery() {
        //    通过服务发现来获得该服务的信息
        List<String> services = discoveryClient.getServices();
        for (String element : services) {
            System.out.println("----element:"+element);
        }
        //一个微服务下的全部实例
        List<ServiceInstance> instances = discoveryClient.getInstances("CLOUD-PAYMENT-SERVICE");
        for (ServiceInstance is:instances){
            System.out.println("----:"+is.getScheme()+"-"+is.getServiceId()+"-"+is.getHost()+"-"+is.getUri());
        }
        return this.discoveryClient;
    }

}

在这里插入图片描述
在这里插入图片描述

Eureka的自我保护

在这里插入图片描述

如果一个微服务不可用了,Eureka不会立刻清理.依旧会对该服务的信息进行保存

CAP

CAP原则又称CAP定理,指的是在一个分布式系统中, Consistency(一致性)、 Availability(可用性)、Partition tolerance(分区容错性),这三个要素最多只能同时实现两点,不可能三者兼顾。

  • 一致性(C):在分布式系统中的所有数据备份,在同一时刻是否同样的值。(等同于所有节点访问同一份最新的数据副本)
  • 可用性(A):在集群中一部分节点故障后,集群整体是否还能响应客户端的读写请求。(对数据更新具备高可用性)
  • 分区容错性(P):以实际效果而言,分区相当于对通信的时限要求。系统如果不能在时限内达成数据一致性,就意味着发生了分区的情况,

如何解除自卫保护??
实例:

  • eurekaServer7001
eureka:
  server:
    enable-self-preservation: false #出产默认,自我保护机制是开启的
    eviction-interval-timer-in-ms: 2000 #主动失效检测间隔
  • payment8001
  instance:
    instance-id: payment8001
    prefer-ip-address: true #可以显示ip
    lease-renewal-interval-in-seconds: 5 #发送心跳的间隔时间
    lease-expiration-duration-in-seconds: 5 #eureka服务端收到最后一次心跳后等待的是时间上限;; 默认为90秒

Zookeeper

支付服务注册进Zookeeper

pom.xml
    <dependencies>
        <!--web启动器-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--监控-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>

        <!--热部署-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <!--lombok-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <!--SpringBoot测试-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!--引入自己的API通用包,可以使用Payment支付Entity-->
        <dependency>
            <groupId>com.wu.sc</groupId>
            <artifactId>cloud-api-commons</artifactId>
            <version>${project.version}</version>
        </dependency>
        <!--zookeeper客户端-->
        <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>
        <dependency>
            <groupId>org.apache.zookeeper</groupId>
            <artifactId>zookeeper</artifactId>
            <version>3.4.9</version>
        </dependency>
    </dependencies>
application.yml
server:
  port: 8004
spring:
  application:
    name: cloud-payment-service
  cloud:
    zookeeper:
      connect-string: *****:2181
PaymentController
@RestController
@Slf4j
public class PaymentController {

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

    @RequestMapping(value = "payment/zk")
    public String paymentZk(){
        return "SpringCloud with zookeeper ,server port:"+port+"\t"+ UUID.randomUUID().toString();
    }
}
PaymentMain8004
@SpringBootApplication
@EnableDiscoveryClient
public class PaymentMain8004 {
    public static void main(String[] args) {
        SpringApplication.run(PaymentMain8004.class,args);
    }
}
测试

1->
在这里插入图片描述
2->

root@----:~# docker exec -it 48354534acbe /bin/bash 
root@48354534acbe:/apache-zookeeper-3.6.0-bin# cd bin/
root@48354534acbe:/apache-zookeeper-3.6.0-bin/bin# zkCli.sh -server 127.0.0.1:2181
[zk: 127.0.0.1:2181(CONNECTED) 1] ls /
[dubbo, services, zookeeper]
[zk: 127.0.0.1:2181(CONNECTED) 2] ls /services
[cloud-payment-service]  <-<-----------与   spring:application:name: 一样
[zk: 127.0.0.1:2181(CONNECTED) 3] ls /services/cloud-payment-service
[84e3db6a-5554-415a-81f5-fc3465e247df]
[zk: 127.0.0.1:2181(CONNECTED) 4] ls /services/cloud-payment-service/84e3db6a-5554-415a-81f5-fc3465e247df
[]     
[zk: 127.0.0.1:2181(CONNECTED) 5] get /services/cloud-payment-service/84e3db6a-5554-415a-81f5-fc3465e247df
{"name":"cloud-payment-service","id":"84e3db6a-5554-415a-81f5-fc3465e247df","address":"localhost","port":8004,"sslPort":null,"payload":{"@class":"org.springframework.cloud.zookeeper.discovery.ZookeeperInstance","id":"application-1","name":"cloud-payment-service","metadata":{}},"registrationTimeUTC":1589523333353,"serviceType":"DYNAMIC","uriSpec":{"parts":[{"value":"scheme","variable":true},{"value":"://","variable":false},{"value":"address","variable":true},{"value":":","variable":false},{"value":"port","variable":true}]}}

值得注意的服务节点是Zookeeper是临时节点,服务干掉了话,一段时间后Zookeeper会在注册表中删除掉服务的相关信息

Consul

服务提供者注册到Consul

pom.xml
<dependencies>
        <!--consul-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-consul-discovery</artifactId>
        </dependency>
        <!--web启动器-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--监控-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <!--热部署-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <!--lombok-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <!--SpringBoot测试-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!--引入自己的API通用包,可以使用Payment支付Entity-->
        <dependency>
            <groupId>com.wu.sc</groupId>
            <artifactId>cloud-api-commons</artifactId>
            <version>${project.version}</version>
        </dependency>
    </dependencies>
application.yml
server:
  port: 8006
spring:
  application:
    name: cloud-payment-service
  cloud:
    consul:
      host: 127.0.0.1
      port: 8500
      discovery:
        hostname: 127.0.0.1
        service-name: ${spring.application.name}
PaymentController
@RestController
@Slf4j
public class PaymentController {

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

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

消费者注册到Consul

pom.xml与主启动,yml配置文件,ApplicationConfiguration都一样

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值