一个简单的 springCloud 入门实例(一)

为什么要使用SpringCloud?

讲到这个肯定要提到微服务。
那么,什么叫做微服务:

微服务是一种用于构建应用的架构方案。微服务架构有别于更为传统的单体式方案,可将应用拆分成多个核心功能。每个功能都被称为一项服务,可以单独构建和部署,这意味着各项服务在工作(和出现故障)时不会相互影响。

简而言之:就是把一个复杂的项目拆分为多个核心功能,每个功能称之为一项服务。
其实,微服务当中的介绍也顺便说明了为什么需要使用微服务:无论是传统的 Servlet + JSP,还是 SSM,还是现在的 SpringBoot,它们都是单体应用,单体应用的优点很明显,就是简单,快捷,在一些小项目上面很方便。但是当项目大了以后,单体项目的劣势就越来越明显,比如改动影响大、风险高、部署成本高(全部重新部署)、无法快速扩容。
因此,微服务就这样出现了。讲完了微服务,我们再来看下SpringCloud给我们带来的是什么,也就是为什么要使用SpringCloud

Spring Cloud是一个集成了众多开源的框架,利用Spring Boot的开发便利性实现了服务治理、服务注册与发现、负载均衡、数据监控,REST API发布方式等,基本囊括了分布式框架所需要的所有功能。是一套易开放、易部署、易维护的分布式开发工具包。

这里面是一套解决方案:包括了注册中心、服务治理、负载均衡等等一系列的解决方案。
ps:下载地址在文末。

读完这篇文章,我们可以学到什么

  1. SpringCloud和SpringCloudAlibaba的区别。
    算是相辅相成,一起使用,SpringCloudAlibaba实际上对我们的SpringCloud2.x和1.x实现拓展组件功能。
    比如SringCloud中的有些解决方案(Eureka )停止开源了,那么alibaba中的nacos正好可以替代。
  2. SpringCloud和SpringBoot以及SpringCloudAlibaba的版本对应关系。
    github版本区别
  3. nacos注册中心简单实用(配置中心、yml文件的默认规则)。
  4. fegin服务调用。
  5. 如何更加优雅的实现服务间的调用。

使用的版本

springboot springCloud spring Cloud Alibaba
2.3.2.RELEASE Spring Cloud Hoxton.SR8 2.2.5.RELEASE

搭建maven父工程

1. 新建一个maven项目:

一个简单的 springCloud 入门实例(一)_第1张图片

2. 输入项目Group、PackAge

一个简单的 springCloud 入门实例(一)_第2张图片

3. 删除对应的无用文件

一个简单的 springCloud 入门实例(一)_第3张图片

4. 然后在pom文件中添加对应的springCloud、springCloudAlibaba依赖,如下图所示:

	注意:一定要注意这边的几个版本信息(springboot、springCloud、springCloud Alibaba)。

这里采用的是管理包。哪个服务中需要使用,哪个服务就引入对应的依赖。这里只是声明,不做导入。


<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0modelVersion>
    <parent>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-parentartifactId>
        <version>2.3.2.RELEASEversion>
        <relativePath/> 
    parent>
    <groupId>com.cjgroupId>
    <artifactId>cloudartifactId>
    <version>0.0.1-SNAPSHOTversion>
    <name>cloudname>
    <description>Demo project for Spring Bootdescription>
    <properties>
        <java.version>1.8java.version>
        <spring-cloud.version>Hoxton.SR8spring-cloud.version>
        <spring-cloud-alibaba.version>2.2.5.RELEASEspring-cloud-alibaba.version>
    properties>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloudgroupId>
                <artifactId>spring-cloud-dependenciesartifactId>
                <version>${spring-cloud.version}version>
                <type>pomtype>
                <scope>importscope>
            dependency>
            <dependency>
                <groupId>com.alibaba.cloudgroupId>
                <artifactId>spring-cloud-alibaba-dependenciesartifactId>
                <version>${spring-cloud-alibaba.version}version>
                <type>pomtype>
                <scope>importscope>
            dependency>

        dependencies>
    dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.bootgroupId>
                <artifactId>spring-boot-maven-pluginartifactId>
            plugin>
        plugins>
    build>
project>

新建微服务工程

下面我们还缺少2个服务,这里我就拿用户和订单的关系模型进行说明。
新建一个user子工程:

1. 项目右键->new Module,和之前一样的逻辑。这里我就不贴图了。

2. 去除无用的文件夹

一个简单的 springCloud 入门实例(一)_第4张图片

3. 加入依赖关系

到现在为止,这边的cloud-user只是单独的项目,和父项目并不存在依赖关系,所以这里我们需要将两者改成有依赖关系
cloud-user的pom文件修改如下:
标签内容改为如下所示:

    <parent>
        <groupId>com.cjgroupId>
        <artifactId>cloudartifactId>
        <version>0.0.1-SNAPSHOTversion>
    parent>

总的pom文件中增加标签:

   <modules>
        <module>cloud-usermodule>  
    modules>

把CloudUserApplication类修改如下:

/**
 * @author cj
 */
@RestController
@SpringBootApplication
public class CloudUserApplication {

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

    @GetMapping("/helloNacos")
    public String helloNacos() {
        System.out.println("当前实例------> A");
        return "你好,nacos!";
    }
}

到这里,其实没有结束,但是我们可以先把cloud-user这个工程启动起来看看效果。可能会有如下的报错,没关系,可以忽略,我们还没有配置对应的nacos注册中心(因为我们pom文件中引入了对应的依赖):
一个简单的 springCloud 入门实例(一)_第5张图片
出现如下:

一个简单的 springCloud 入门实例(一)_第6张图片

4. 新建user-order工程

步骤重复一下。

Nacos安装

1.下载Nacos

nacos
我这里是下载的1.3.1版本

2.安装Nacos

下载之后进入到bin文件目录,启动项目:
一个简单的 springCloud 入门实例(一)_第7张图片
如下图所示启动成功
一个简单的 springCloud 入门实例(一)_第8张图片
至此,nacos已经启动成功,我们可以访问地址:http://127.0.0.1:8848/nacos访问nacos的页面。
一个简单的 springCloud 入门实例(一)_第9张图片
这边需要关注2个地方:一个是服务管理,也就是服务的注册和发现;一个是配置管理(每个服务的配置中心)

服务注册和发现

回到工程中,如何将工程配置成一个服务,并且注册到nacos,让其他服务能用使用?

1.启动类增加注解@EnableDiscoveryClient

@RestController
@SpringBootApplication
@EnableDiscoveryClient
public class CloudUserApplication {

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

    @GetMapping("/helloNacos")
    public String helloNacos() {
        System.out.println("当前实例------> A");
        return "你好,nacos!";
    }
}

2.yml配置中指定注册中心的地址

这边需要注意的是:
创建配置文件名为bootstrap.yml,注意是bootstrap,而不是application
原因如下(详情请查看:配置文件application.yml和bootstrap.yml的配置的不同)

Nacos同springcloud-config一样,在项目初始化时,要保证先从配置中心进行配置拉取,拉取配置之后,才能保证项目的正常启动。springboot中配置文件的加载是存在优先级顺序的,bootstrap优先级高于application

pom文件内容:

spring:
  application:
    name: cloud-user
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848
      config:
        file-extension: yml
        server-addr: 127.0.0.1:8848
  profiles:
    active: dev

3.查看服务列表

我们可以在nacos中查看注册的服务:
一个简单的 springCloud 入门实例(一)_第10张图片

服务的配置中心

3.nacos新建配置文件

一个简单的 springCloud 入门实例(一)_第11张图片
新建配置中心如图所示:
一个简单的 springCloud 入门实例(一)_第12张图片
解释一下:
Data ID它的定义规则是:
${prefix}-${spring.profiles.active}.${file-extension}

  • prefix 默认为 spring.application.name 的值,也可以通过配置项spring.cloud.nacos.config.prefix 来配置。

  • spring.profile.active 即为当前环境对应的 profile,可以通过配置项 spring.profile.active 来配置。

  • file-exetension 为配置内容的数据格式,可以通过配置项 spring.cloud.nacos.config.file-extension 来配置。目前只支持 properties 和 yaml 类型。
    注意:当 spring.profile.active 为空时,对应的连接符 - 也将不存在
    dataId 的拼接格式变成${prefix}.${file-extension}
    然后对应下之前的yml配置,我们可以看出来,配置的文件名是:cloud-user-dev.yml
    如下所示:
    一个简单的 springCloud 入门实例(一)_第13张图片
    这里配置里面增加一个key-value,用来验证工程是否真的读到了配置。

4.测试配置

到这里,nacos的配置基本完成,下面,我们就把之前cloud-user代码稍微改下,读取heheda的值:

/**
 * @author cj
 */
@RestController
@SpringBootApplication
@EnableDiscoveryClient
public class CloudUserApplication {

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

    @Value("${heheda}")
    private String config;

    @GetMapping("/helloNacos")
    public String helloNacos() {
        System.out.println("当前实例------> A" + config);
        return "你好,nacos!";
    }
}

log输出:
一个简单的 springCloud 入门实例(一)_第14张图片
至此,nacos的注册、发现以及配置中心现在都可以使用了。
需要了解的知识点:

  1. DataId的命名规则。
  2. 注解@EnableDiscoveryClient的使用。
  3. pom文件的几个配置值的含义。

微服务之间的调用

按照之前的服务注册和发现还有服务配置中心的说明,我们把cloud-order工程也按照上面步骤写一下。
我们现在想实现一下用户下单的功能。那么首先在cloud-order中新建一个controller,写一个makeOrder的方法:

/**
 * 描述:
 *
 * @author caojing
 * @create 2021-02-05-14:15
 */
@RestController
public class OrderController {

    @GetMapping("/makeOrder")
    public String makeOrder(@RequestParam("name") String userName) {
            return userName + "下单成功";
    }
}
  1. 把cloud-order标记为fegin客户端。
  2. cloud-user中调用order服务。

1.cloud-order启动类添加@EnableFeignClients

/**
 * @author cj
 */
@EnableDiscoveryClient
@EnableFeignClients
@SpringBootApplication
public class CloudOrderApplication {

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

}

2.cloud-user调用服务

  1. 定义OrderRemoteClient,接口@FeignClient注解指定服务名来绑定服务,然后再使用Spring MVC的注解来绑定具体该服务提供的REST接口。
/**
 * 描述:
 *
 * @author caojing
 * @create 2021-02-05-14:20
 */
@FeignClient(name = "cloud-order")
public interface OrderRemoteClient1 {

    @GetMapping("/makeOrder")
    String makeOrder(@RequestParam("name") String userName);

}

注意:这里服务名不区分大小写 cloud-order=CLOUD-ORDER

  1. 直接@Autowired注入
    @Autowired
    private OrderRemoteClient1 orderRemoteClient1;


    @GetMapping("/helloNacos")
    public String helloNacos() {
        System.out.println("当前实例------> A" + orderRemoteClient1.makeOrder("caojinger"));
        return "你好,nacos!";
    }

访问该地址,出现如下所示,则表明访问成功:
一个简单的 springCloud 入门实例(一)_第15张图片

3. fegin的熔断机制(hystrix):

熔断机制:

一般在微服架构中,有一个组件角色叫熔断器。顾名思义,熔断器起的作用就是在特定的场景下关掉当前的通路,从而起到保护整个系统的效果。

在微服务架构中,一般我们的独立服务是比较多的,每个独立服务之间划分责任边界,并通过约定协议接口来进行通信。当我们的调用链路复杂依赖多时,很可能会发生雪崩效应。

假设有这么一个场景,有A, B, C, D四个独立服务,A会依赖B,C,D;当D发生负载过高或网络异常等导致响应过慢或超时时,很可能A会因此堆积过多的等待链接,从而导致A的状态也转为异常,后面依赖到A的其他服务跟着发生链式反应,这将会导致大面积的服务不可用。
新建TestFallBack类:

@Component
public class TestFallBack implements OrderRemoteClient1 {
    @Override
    public String makeOrder(String userName) {
        return "出错了";
    }
}

OrderRemoteClient1修改如下:

@FeignClient(name = "cloud-order",fallback = TestFallBack.class)
public interface OrderRemoteClient1 {

    @GetMapping("/makeOrder")
    String makeOrder(@RequestParam("name") String userName);

}

这样一个简单的熔断处理就完成了,为了模拟熔断机制,我们可以把order中的controller抛出异常 :

    @GetMapping("/makeOrder")
    public String makeOrder(@RequestParam("name") String userName) {
        throw new RuntimeException("服务端测试异常!");
//        return userName + "下单成功";
    }

重新访问地址,这边可以看到 cloud-order模块中抛出了异常,但是在cloud-user中是正常返回,只不过返回的信息是TestFallBack类中返回的信息,这样我们就可以阻止雪崩效应啦。

可能出现的问题

  • 报错了,没走熔断机制,直接抛出异常?
    答:这种问题应该是spring Cloud 没有开启熔断机制,那么该如何开启熔断机制呢?在配置中心加上如下配置:
feign:
  hystrix:
    enabled: true

总结

至此一个简单的springcloud项目已经搭建完成,但这样的项目远远没有达到开发的步骤,但万事开头难嘛,只要后续慢慢的完善,不断改进,总能达到开发的水平。

思考

微服务之间的调用真的是这样的么?
楼主这种方式:是调用方来写feignClient还是服务方来写?你觉得应该谁来写?怎么写?
感兴趣的同学可以看下这篇文章:
Fegin在spring Cloud中的实际应用

对应的demo下载:
demo

你可能感兴趣的:(Spring,Cloud,Alibaba,spring,cloud,spring,cloud,alibaba,spring,boot,feign)