当前位置:   article > 正文

springcloud光速入门(一) 服务的注册与发现_springcloud:服务注册与发现,负载均衡,服务限流熔断,服务网关,服务配置

springcloud:服务注册与发现,负载均衡,服务限流熔断,服务网关,服务配置

springcloud光速入门

简单概述

springcloud看上去很难,很恐怖,但是我一遍学下来,感觉还是蛮容易的,面向配置编程,这一篇主要是讲配置,细节可能比较少。首先我们的微服务应该有以下部分:

  • 服务注册中心

简单说一下,服务注册中心就是我们的一个类,可以有很多方法,但是我们的方法只能被我们同一个项目中的其他类调用,或者说我电脑上写了一个类,有很多方法,但是我没办法让另一台电脑调用这个方法,解决方案就是将这个类注册进一个注册中心,然后其他的(电脑)通过网络连接从注册中心中就可以去访问我们的方法。

这么做的好处是我们的业务拆分了,我们把那些不同的业务直接拆分,如果需要调用别的业务方法,去注册中心去拿,而且我们可以每一个业务都准备好几份客户端,这样爆掉几也不会怎么样,高可用。而且我们还可以在项目运营的时候进行版本升级,什么意思呢?比如说我们开了100个支付服务,但是我们又要引入新的支付方式,原来的单体项目只能项目下线,然后重新部署。但这里我们可以先关闭10台机器,然后进行版本升级,再部署上线,然后慢慢的把这100台都更新到新版本,这个过程可以靠定时任务来做,这就是业务拆分的好处。

  • 服务发现

简单的说就是去服务注册中心去调用其他的服务,一般而言我们的springcloud中任何的组件都是一个服务,可以理解为是一个独立的项目。

  • 服务降级/熔断

我们的业务拆分了,除了可以每个业务部署多个做高可用以外,还可以做一些异常处理。平时单体项目如果出现异常是一件很恐怖的事情,因为我们可能是出现了BUG了,或者机房着火了,反正线上运营出现问题就很难受,导致我们的项目如果做的很大就会出现各种事故。
服务降级是指我们A服务调用B业务的方法,但是B服务很久没响应,报错了,机房着火了,服务器炸了之类的。我们A服务可以自己准备一个兜底的方法,比如访问一个资源找不到,如果把404交给客户,客户可能以为自己网断了,我们可以给用户一个友好的提示界面:机房着火,请稍后再试,这样客户就知道不是自己的问题了。

  • 服务网关

这个不好解释,简单的说就是我们的JavaEE不是有三大组件Filter,Servlet,Listener吗?我们的项目可以理解为Servlet,基本都是Spring框架架起整个业务。我们的网关是一种Filter,这么好理解吧。我们的网关就是看门的,可以做很多事情,负载均衡,限流,权限等等,这个和Nginx很像。

  • 服务配置中心

这个得看项目才能体现到,简单的说,我们的每一个服务就是一个项目,有配置文件和springboot主启动类这些东西,然后我们的服务都要连接数据库吧,但是我们一般都是把数据库连接的账号密码都写在这些配置文件,有2个问题:我们很多服务都是连接同一套数据库,账号密码都是一样的我们要改得大规模去改;这么做不安全,一般而言数据库的数据应该有人负责和管理,密码知道的人少一点比较好也好排查商业卧底。

服务配置中心大概是这样的:运维人员先把我们的一些公用的配置都放在git上,然后添加一个配置中心服务,去读取git上的配置,如果git进行更改,比如运维人员要换数据库密码了,这时候我们的配置中心可以动态的获取最新的数据。然后我们每一个普通的服务都去配置中心拿数据,并且在配置中心更新时,应该可以让各个服务都相应的更改配置

比如git上放一个yml文件,里面有如下内容:

jdbc:
	password: 123456
  • 1
  • 2

这时候运维人员密码改成123,然后配置中心刷新一手,然后告诉各个服务,哥们,我换密码了。卧槽,各个服务一一去读取新的密码。

  • 其他服务

其实微服务的东西很多,比如链路跟踪,日志跟踪,分布式锁,分布式事务很多的东西需要学,这一篇主要是讲一下springcloud-Netflix的各个组件,然后分享一个简单的小demo。

快速开始

简单介绍一下项目

image-20201102141423878

cloud-common:抽取公共的一些类,比如POJO类
cloud-config:配置中心
cloud-consumer:模拟一个消费者,会调用order的方法
cloud-order:模拟一个生产者,用于被别人调用,当然我们也可以直接调用
cloud-gateway:网关
cloud-eureka:注册中心
cloud-config-client:模拟一个普通的服务,其配置信息都是从配置中心拉取

Eureka注册中心

先写一个生产者,生产者提供了两个简单的方法,我写个主启动类,启动服务后直接去调用这两个方法,不会出问题。

image-20201102142334247

OrderController控制器

模拟一个很ok的业务方法,和一个用时比较久的方法,模拟一些超时的检测。

@RestController
public class OrderController {

    @GetMapping("ok")
    public ResultData ok(){
        return new ResultData(200,"理论上应该成功的正常方法_成功",null);
    }

    @GetMapping("timeout_success")
    public ResultData timeoutSuccess(){
        try {
            TimeUnit.SECONDS.sleep(3);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return new ResultData(200,"理论上应该成功的超时测试方法_成功",null);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

现在我们想把这个服务注册进注册中心,这样我们的其他服务就可以去访问,这里我们选用Eureka注册中心。我们的这些服务都可以理解为一个客户端,都要注册进注册中心,就像我们的小公司都是在某个大厦里面租了几层,我们在一楼大厅就可以在企业的花名册看到我们的公司名。所以我们需要导入一个jar包,表示>spring-cloud-starter-netflix-eureka-client表示这是一个客户端,然后我们进行一些客户端的配置。

<dependencies>
    <!--  eureka注册中心服务端  -->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
    </dependency>
    <!--  通用Api  -->
    <dependency>
        <groupId>com.kaikeba</groupId>
        <artifactId>cloud-common</artifactId>
        <version>1.0-SNAPSHOT</version>
    </dependency>
    <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>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
</dependencies>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42

application.yml

  • 我们的服务占用8001端口

  • 服务名是:cloud-order-service,服务名可以重复的,表示同一个服务

  • instance-id: order-8000这个则不能重复,用于区分。如果不写,eureka会把端口加上服务名作为我们的

  • register-with-eureka: truefetch-registry: true表示是否注册进注册中心,肯定啊。

  • defaultZone: http://eureka7001.com:7001/eureka 表示我们要连接的eureka服务器的地址,这里我们的eureka还没写好呢。

server:
  port: 8001

spring:
  application:
    name: cloud-order-service
    
eureka:
  instance:
    instance-id: order-8000
    prefer-ip-address: true
  client:
    register-with-eureka: true
    fetch-registry: true
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

同时我们导入了Eureka的配置,还需要再主启动类上去让他生效,使用@EnableEurekaClient

@SpringBootApplication
@EnableEurekaClient
public class OrderMainApplication {
    public static void main(String[] args) {
        SpringApplication.run(OrderMainApplication.class, args);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

Eureka服务端端

image-20201102143636412

和客户端的区别就是jar包后面跟着的是server,表示这个是一个Eureka的服务端。

    <dependencies>
        <!--  eureka注册中心服务端  -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
        </dependency>
        <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>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36

注意一下,hostname这个属性,表示服务器的名字,不能重复

register-with-eureka: false,fetch-registry: false表示我自己是注册中心,我自己是个服务,但是我们需要给别人看吗,我们这个服务根本没有任何业务逻辑,这里选择false,我们没必要吧自己也注册了吧。

server:
  port: 7001

spring:
  application:
    name: cloud-eureka-service

eureka:
  instance:
    hostname: eureka7001.com
  client:
    register-with-eureka: false
    fetch-registry: false
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

主启动类,@EnableEurekaServer表示开启eureka服务注册中心。

@EnableEurekaServer
@SpringBootApplication
public class EurekaMainApplication {
    public static void main(String[] args) {
        SpringApplication.run(EurekaMainApplication.class, args);
    }
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

当然还有一步,那就是改host文件,具体可以看一下网上的帖子。

windows:C:\Windows\System32\drivers\etc\hosts 这个文件,然后加如下内容,我们这里加一个7001就行了

#springcloud
127.0.0.1 eureka7001.com
  • 1
  • 2

然后cmd输入以下命令

ipconfig/flushdns
  • 1

出现一下内容表示我们刷新了我们的hosts文件的修改。image-20201102144038349

然后我们启动一下我们的服务,先启动注册中心再启动order。

image-20201102144155033

先1后2,不然报错说找不到Eureka配置中心,访问localhost:7001可以看到如下内容:

我们可以看到我们的CLOUD-ORDER-SERVICE服务已经进入了注册中心,右边order-8000是我们配置的instance-id名。1表示我们现在只有一个服务,以后可以搞集群。

image-20201102144314723

我们访问8001,可以成功访问的。

image-20201102144944081

OpenFeign注册发现

我们的Eureka是注册中心只是注册,我们要访问注册中心需要一个桥梁,我们要调用哪个服务的方法,怎么调用,要传递什么参数,这里我们需要添加一个组件,openFeign,这里我们不需要再去写一个发现中心,我们需要调用其他业务的方法时,只需要把我们这个服务添加一些注解支持,就可以去访问注册中心的内容

现在我们添加一个消费者,表示要调用别的服务。

image-20201102145059063

pom.xml

<!--  发现中心  -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<!--  eureka注册中心服务端  -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<!--  通用Api  -->
<dependency>
    <groupId>com.kaikeba</groupId>
    <artifactId>cloud-common</artifactId>
    <version>1.0-SNAPSHOT</version>
</dependency>
<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>
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <optional>true</optional>
</dependency>
<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45

application.xml

server:
  port: 81

spring:
  application:
    name: cloud-consumer-service


eureka:
  instance:
    instance-id: consumer-81
    prefer-ip-address: true
  client:
    register-with-eureka: true
    fetch-registry: true
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

这里我们要写一个接口,然后接口方法上加上RequestMapping的注解,然后我们的spring会为我们生成一个代理类,该类的方法的方法体就是我们order的方法体。简单的说,我们要调用一个服务,我们先写一个接口,当我们调用该接口方法时,会去注册中心找一个服务,然后把请求参数都交给他,最后这个服务会把结果返回给我们的的接口方法,我们只是一个调用者,没有属于自己的方法体。

@FeignClient(value = “CLOUD-ORDER-SERVICE”)表示我们该接口要调用哪个服务,然后该接口类的方法又是调用该服务的那些方法,最后使用@Component注解将接口交给spring,spring会为我们生产一个代理对象。

@Component
@FeignClient(value = "CLOUD-ORDER-SERVICE")
public interface ConsumerService {
    @GetMapping("ok")
    ResultData success();
    @GetMapping("timeout_success")
    ResultData timeoutSuccess();
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

Controller

这是我们的控制器,注入了consumerService,然后我们的自己写一套访问方式,这里的url请求可以自行修改。consumerService调用的是ok,这里我们调用success,没关系。

@RestController
public class ConsumerController {
    @Resource
    ConsumerService consumerService;

    @GetMapping("success")
    public ResultData ok(){
        return consumerService.success();
    }
    @GetMapping("timeout_success")
    public ResultData timeoutSuccess(){
        return consumerService.timeoutSuccess();
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

主启动类

消费者本身也是一个服务,也把它注册进注册中心。我们又加入了openFeign服务发现,所以要是用**@EnableDiscoveryClient** 和**@EnableFeignClients这两个注解,一个标识开启服务发现,另一个标识开启Feign客户端的支持,我们的服务发现中心有很多,@EnableDiscoveryClient**是必须的,另一个看你用什么发现中心就用哪个。

@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
@EnableEurekaClient
public class ConsumerMainApplication {
    public static void main(String[] args) {
        SpringApplication.run(ConsumerMainApplication.class, args);
    }
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

我们运行主启动类,这里我们还是要先把eureka的服务启动再启动consumer和order。

我们看到两个服务都注册进eureka,当然注册没什么技术含量,关键是调用是否生效。

image-20201102150514967

成功调用!其实我这里放了一个小彩蛋,那就是那个超时方法会报错,但是我们在8001去调用是却没什么问题,这里就是一些服务熔断的一些东西了,下一篇再讲哈。

image-20201102150604748

我们调用原来的提供者的方法,也是可以的。

image-20201102150620356

学会以上内容,我们的微服务就算入门了,我们现在可以进行一些简单的业务拆分,比如:

image-20201102150741929

这是我之前写的快递e栈的项目,但是我们的电脑端和微信端很多东西都重复了,调用同一套POJO类,同一套的Controller,这里我们可以写一个provider-server,表示我这个服务专门提供方法的,其他的服务你们尽管来掉就完事了!我的e_expres-order-pce_expres-order-wx都去注册中心去拿e_express-provider-server的方法,这就是简单的服务注册中心的应用了。我们以后的项目都是A调B,B调C,服务拆分不但好分工,而且BUG排查也非常的快。

注册中心是为了解决单体应用而生的技术,而网关,配置中心,服务熔断等都是为了解决微服务的问题而生的技术,所以学起来会觉得枯燥,这些内容放下一篇。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小桥流水78/article/detail/818553
推荐阅读
相关标签
  

闽ICP备14008679号