第31课时 微服务概述、Nacos、Ribbon及Feign

一、微服务架构概述

1、单体应用概述

第31课时 微服务概述、Nacos、Ribbon及Feign_第1张图片
单体应用:一个归档包(例如war格式)包含所有功能的应用程序
优点:比较容易部署、测试
缺点:
复杂性高:一个应用百万行级别,修改代码容易牵一发而动全身
技术债务:已使用的系统设计或代码难以被修改
部署频率低:构建和部署的时间长→部署频率低→两次发布之间有大量功能变更与缺陷修复,出错概率比较高
可靠性差:某个应用bug,可能会导致整个应用的崩溃
扩展能力受限:单体应用智能作为一个整体进行扩展,无法根据业务模块的需要进行伸缩
阻碍技术创新:引入新框架或新技术平台的成本非常高
如何解决单体应用架构存在的问题
微服务就是这样的一种架构模式。

2、什么是微服务

第31课时 微服务概述、Nacos、Ribbon及Feign_第2张图片
微服务架构应具备以下特性:
每个微服务可独立运行在自己的进程里
一系列独立运行的微服务共同构建起整个系统
每个服务为独立的业务开发,一个微服务只关注某个特定的功能,例如订单管理、用户管理等
微服务之间通过一些轻量的通信机制进行通信,例如通过RESTful API进行调用
可以使用不同的语言与数据存储技术
全自动的部署机制

3、微服务架构的优点与挑战

3.1微服务架构的优点

易于开发和维护:一个微服务只会关注一个特定的业务功能,所以它业务清晰、代码量比较少。开发和维护单个微服务相对简单。而整个应用是由若干个微服务构建而成的,所以整个应用也会被维持在一个可控状态。
单个微服务启动较快:单个微服务代码量较少,所以启动会比较快。
局部修改容易部署:单体应用只要有修改,就得重新部署整个应用,微服务解决了这样的问题。一般来说,对某个微服务进行修改,只需要重新部署这个服务即可。
技术栈不受限:在微服务架构中,可以结合项目业务及团队的特点,合理地选择技术栈。例如某些服务可使用关系型数据库MySQL;某些微服务有图形计算的需求,可以使用Neo4j;甚至可根据需要,部分微服务使用Java开发,部分微服务使用Node.js开发。
按需伸缩:可根据需求,实现细粒度的扩展。例如,系统中的某个微服务遇到了瓶颈,可以结合这个微服务的业务特点,增加内存、升级CPU或者是增加节点。

3.2微服务架构面临的挑战

运维要求较高:更多的服务意味着更多的运维投入。
分布式固有的复杂性:使用微服务构建的是分布式系统。对于系统容错、网络延迟、分布式事务等都会带来巨大的挑战
接口调整成本高:微服务之间通过接口进行通信。如果修改某一个微服务的API,可能所有使用了该接口的微服务都需要做调整。
重复劳动:很多服务可能都会使用到相同的功能,而这个功能并没有达到分解为一个微服务的程度,这个时候,可能各个服务都会开发这个功能,从而导致代码重复。尽管可以使用共享库来解决这个问题(例如可以将这个功能封装成公共组件,需要该功能的微服务引用该组件),但共享库在多语言环境下不一定行得通了。

3.3微服务设计原则

单一职责原则:一个单元(类、方法或者服务等)只应关注整个系统功能中单独、有界限的一部分。单一职责原则可以帮助我萌更优雅地开发、更敏捷地交付。单一职责原则是SOLID原则之一。
服务自治原则:每个微服务应具备独立的业务能力、依赖于运行环境。在微服务架构中,服务是独立的业务单元,应该与其他服务高度解耦。每个微服务从开发、测试、构建、部署,都应当可以独立运行,而不应该依赖其他的服务。
轻量级通信机制:微服务之间应该通过轻量级的通信机制进行交互。轻量级的通信机制应具备两点:首先是它的体量较轻;其次是它应该是跨语言、跨平台的。例如我们所熟悉的REST协议,就是一个典型的“轻量级通信机制”。
微服务架构中,常用的协议有REST、AMQP、STOMP、MQTT等。
微服务粒度:微服务的粒度是难点,也常常是争论的焦点。应当使用合理的粒度划分微服务,而不是一味地把服务做小。代码量的多少不能作为微服务划分的依据,因为不同的微服务本身的业务复杂性不同,代码量也不同。
在微服务的设计阶段,就应该确定其边界。微服务之间应该相对独立并保持松耦合。
领域驱动设计(Domain Driven Design,简称DDD)中的“界限上下文”可作为划分微服务边界、确定微服务粒度的重要依据。同时,在划分微服务的过程中,还应综合考虑团队的现状。

4、如何实现微服务架构

4.1技术选型

相对单体应用的交付,微服务应用的交付要复杂很多,不仅需要开发框架的支持,还需要一些自动化的部署工具,以及IaaS、PaaS或CaaS的支持。
下面从开发和运行平台两个维度考虑挑选技术选型。

开发框架的选择
可使用Spring Cloud作为微服务开发框架。
首先,Spring Cloud具备开箱即用的生产特性,可大大提升开发效率;再者,SpringCloud的文档丰富、社区活跃,遇到问题比较容易获得支持;更为可贵的是,SpringCloud为微服务架构提供了完整的解决方案。
当然,也可使用其他的开发框架或者解决方案来实现微服务,例如Dubbo、Dropwizard、Armada等。

运行平台
微服务并不绑定运行平台,将微服务部署在PC Server,或者阿里云、AWS等云计算平台都是可以的。

4.2架构图及常用组件

第31课时 微服务概述、Nacos、Ribbon及Feign_第3张图片
服务注册中心(服务发现):微服务模块统一到注册中心注册,生成注册表,进行统一管理各服务所在的机器和端口号(例如订单服务想要调用库存服务,通过注册中心就可以知道库存服务在哪台机器及端口)
配置管理中心:集中管理各项配置
负载均衡:会帮你在每次请求时选择一台机器,均匀的把请求分发到各个机器上
网关:请求从客服端发到服务器,网关会进行一系列验证和过滤,也具有路由功能,避免了客户端直接和服务模块进行交互(客户端不用存各种微服务的名字,网关根据请求路径分发至相应的微服务)。
限流、熔断和降级:限流就是对客户端的请求数进行控制;熔断相当于电路中的保险丝,(举例如果做秒杀的时候,大量的订单服务线程卡在积分服务这里,然后订单服务也挂了,完犊子,雪崩,整个服务炸了。如果第一次请求积分服务的时候发现它挂了,就不在管他,各服务都做它该做的事。)降级就是指服务不可用时提供的一种兜底方案。
链路追踪:一次请求往往需要涉及到多个服务,需要对一次请求涉及的多个服务链路进行日志记录,性能监控即链路追踪

5、微服务开发框架

5.1 SpringCloud简介

尽管SpringCloud带有Cloud字样,但它并不是云计算解决方案,而是在SpringBoot基础上构建的,用于快速构建分布式系统的通用模式的工具集。spring cloud 是一系列框架的集合。它利用 spring boot 的开发便利性巧妙地简化了分布式系统基础设施的开发,如服务发现注册、配置中心、消息总线、负载均衡、断路器、数据监控等,都可以用 spring boot 的开发风格做到一键启动和部署。spring cloud 并没有重复制造轮子,它只是将目前各家公司开发的比较成熟、经得起实际考验的服务框架组合起来,通过 spring boot 风格进行再封装屏蔽掉了复杂的配置和实现原理,最终给开发者留出了一套简单易懂、易部署和易维护的分布式系统开发工具包。

5.2 spring cloud 技术组成

第31课时 微服务概述、Nacos、Ribbon及Feign_第4张图片

5.3 SpringCloud Alibaba介绍

Spring Cloud Alibaba 致力于提供微服务开发的一站式解决方案。此项目包含开发分布式应用微服务的必需组件,方便开发者通过 Spring Cloud 编程模型轻松使用这些组件来开发分布式应用服务。
依托 Spring Cloud Alibaba,您只需要添加一些注解和少量配置,就可以将 Spring Cloud 应用接入阿里微服务解决方案,通过阿里中间件来迅速搭建分布式应用系统。

5.3.1 主要功能

1.服务限流降级:默认支持 WebServlet、WebFlux, OpenFeign、RestTemplate、Spring Cloud Gateway, Zuul, Dubbo 和 RocketMQ 限流降级功能的接入,可以在运行时通过控制台实时修改限流降级规则,还支持查看限流降级 Metrics 监控。
2.服务注册与发现:适配 Spring Cloud 服务注册与发现标准,默认集成了 Ribbon 的支持。
3.分布式配置管理:支持分布式系统中的外部化配置,配置更改时自动刷新。
4.消息驱动能力:基于 Spring Cloud Stream 为微服务应用构建消息驱动能力。
5.分布式事务:使用 @GlobalTransactional 注解, 高效并且对业务零侵入地解决分布式事务问题。阿里云对象存储:阿里云提供的海量、安全、低成本、高可靠的云存储服务。支持在任何应用、任 何时间、任何地点存储和访问任意类型的数据。
6.分布式任务调度:提供秒级、精准、高可靠、高可用的定时(基于 Cron 表达式)任务调度服务。同时提供分布式的任务执行模型,如网格任务。网格任务支持海量子任务均匀分配到所有Worker(schedulerx-client)上执行。
7.阿里云短信服务:覆盖全球的短信服务,友好、高效、智能的互联化通讯能力,帮助企业迅速搭建 客户触达通道。

5.3.2 组件

  1. Nacos:一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。
  2. RocketMQ:一款开源的分布式消息系统,基于高可用分布式集群技术,提供低延时的、高可靠 的消息发布与订阅服务。
  3. Sentinel:把流量作为切入点,从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳 定性。
  4. Seata:阿里巴巴开源产品,一个易于使用的高性能微服务分布式事务解决方案。
  5. Dubbo:Apache Dubbo™ 是一款高性能 Java RPC 框架。
  6. Sleuth:链路追踪
  7. Alibaba Cloud ACM:一款在分布式架构环境中对应用配置进行集中管理和推送的应用配置中心产品。
  8. Alibaba Cloud OSS: 阿里云对象存储服务(Object Storage Service,简称 OSS),是阿里云提 供的海量、安全、低成本、高可靠的云存储服务。您可以在任何应用、任何时间、任何地点存储和 访问任意类型的数据。
  9. Alibaba Cloud SchedulerX: 阿里中间件团队开发的一款分布式任务调度产品,提供秒级、精准、高可靠、高可用的定时(基于 Cron 表达式)任务调度服务。
  10. Alibaba Cloud SMS: 覆盖全球的短信服务,友好、高效、智能的互联化通讯能力,帮助企业迅速搭建客户触达通道。

6、微服务之间的通信协议

6.1常见的远程调用方式

常见的远程调用方式有以下2种:

  1. RPC:Remote Produce Call远程过程调用,类似的还有RMI。自定义数据格式,基于原生TCP通信,速度快,效率高。早期的webservice,现在热门的dubbo,都是RPC的典型代表。

  2. Http:http其实是一种网络传输协议,基于TCP,规定了数据传输的格式。现在客户端浏览器与服务端通信基本都是采用Http协议,也可以用来进行远程服务调用。缺点是消息封装臃肿,优势是对服务的提供和调用方没有任何技术限定,自由灵活,更符合微服务理念。

现在热门的Rest风格,就可以通过http协议来实现。

6.2.Http客户端工具

既然微服务选择了Http,那么我们就需要考虑自己来实现对请求和响应的处理。不过开源世界已经有很多的http客户端工具,能够帮助我们做这些事情,例如:

  1. HttpClient
  2. OKHttp
  3. URLConnection
    接下来,不过这些不同的客户端,API各不相同

6.3.Spring的RestTemplate
Spring提供了一个RestTemplate模板工具类,对基于Http的客户端进行了封装,并且实现了对象与json的序列化和反序列化,非常方便。RestTemplate并没有限定Http的客户端类型,而是进行了抽象,目前常用的3种都有支持:

  1. HttpClient
  2. OkHttp
  3. JDK原生的URLConnection(默认的)

首先在项目中注册一个RestTemplate对象,可以在启动类位置注册:

@SpringBootApplication
public class HttpDemoApplication {

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

    @Bean
    public RestTemplate restTemplate() {
   
        return new RestTemplate();
    }
}基于http调用, Rest API

在测试类中直接@Autowired注入:

@RunWith(SpringRunner.class)
@SpringBootTest(classes = HttpDemoApplication.class)
public class HttpDemoApplicationTests {

    @Autowired
    private RestTemplate restTemplate;

    @Test
    public void httpGet() {
        // 调用springboot案例中的rest接口
        User user = this.restTemplate.getForObject("http://localhost/user/1", User.class);
        System.out.println(user);
    }
}

7、Nacos Discover—服务发现

7.1搭建nacos环境

1、下载
下载地址:https://github.com/alibaba/nacos/releases
也可以用附件中的
在这里插入图片描述
解压到自定义目录

2、运行
双击解压后文件夹bin目录下的startup.cmd
第31课时 微服务概述、Nacos、Ribbon及Feign_第5张图片
第3步: 访问nacos
打开浏览器输入http://localhost:8848/nacos,即可访问服务, 默认密码是nacos/nacos
第31课时 微服务概述、Nacos、Ribbon及Feign_第6张图片

7.2服务注册到nacos

在微服务架构中,最常见的场景就是微服务之间的相互调用。我们以电商系统中常见的用户下单为例来演示微服务的调用:客户向订单微服务发起一个下单的请求,在进行保存订单之前需要调用商品微服务查询商品的信息。
第31课时 微服务概述、Nacos、Ribbon及Feign_第7张图片
创建模块
SpringCloudAlibabaDemo 父工程
api-common 公共模块【实体类】
order-8001 订单微服务 【端口: 8001】
payment-9001 商品微服务 【端口:9001】
父工程pom

<?xml version="1.0" encoding="UTF-8"?>
<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.0</modelVersion>

    <groupId>cn.yiliedu</groupId>
    <artifactId>springcloudalibabademo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <modules>
        <module>order-8001</module>
        <module>api-commons</module>
        <module>payment9001</module>
    </modules>
    <packaging>pom</packaging>
    <name>springcloudalibabademo</name>
    <description>Demo project for Spring Boot</description>

    <!-- 统一管理jar包版本 -->
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
        <junit.version>4.12</junit.version>
        <log4j.version>1.2.17</log4j.version>
        <lombok.version>1.16.18</lombok.version>
        <mysql.version>8.0.15</mysql.version>
        <druid.version>1.1.16</druid.version>
        <mybatis.spring.boot.version>1.3.0</mybatis.spring.boot.version>
    </properties>

    <dependencyManagement>
        <dependencies>
            <!--spring boot 2.2.2-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>2.2.2.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <!--spring cloud Hoxton.SR1-->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Hoxton.SR1</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <!--spring cloud alibaba 2.1.1.RELEASE-->
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>2.1.1.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>${mysql.version}</version>
            </dependency>
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>druid</artifactId>
                <version>${druid.version}</version>
            </dependency>
            <dependency>
                <groupId>org.mybatis.spring.boot</groupId>
                <artifactId>mybatis-spring-boot-starter</artifactId>
                <version>${mybatis.spring.boot.version}</version>
            </dependency>
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>${junit.version}</version>
            </dependency>
            <dependency>
                <groupId>log4j</groupId>
                <artifactId>log4j</artifactId>
                <version>${log4j.version}</version>
            </dependency>
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <version>${lombok.version}</version>
                <optional>true</optional>
            </dependency>
        </dependencies>
    </dependencyManagement>


    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

订单模块pom

<?xml version="1.0" encoding="UTF-8"?>
<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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <groupId>cn.yiliedu.springcloud</groupId>
        <artifactId>SpringCloudAlibabaDemo</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>order8001</artifactId>



    <dependencies>
        <!--SpringCloud openfeign -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
        <!--SpringCloud ailibaba nacos -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <!--SpringCloud ailibaba sentinel -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
        </dependency>
        <!-- 引入自己定义的api通用包,可以使用Payment支付Entity -->
        <dependency>
            <groupId>cn.yiliedu.springcloud</groupId>
            <artifactId>api-commons</artifactId>
            <version>${project.version}</version>
        </dependency>
        <!-- SpringBoot整合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>
        <!--日常通用jar包配置-->
       <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
</project>

商品模块pom

<?xml version="1.0" encoding="UTF-8"?>
<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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>cloud2020</artifactId>
        <groupId>com.atguigu.springcloud</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>payment9001</artifactId>



    <dependencies>
        <!--SpringCloud ailibaba nacos -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <!-- SpringBoot整合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>
        <!--日常通用jar包配置-->
         <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
</project>

商品模块和订单模块,主启动类上需要加上@EnableDiscoveryClient

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

订单工程application.properties如下

server.port=8001
spring.application.name=nacos-order-consumer
#nacos服务中心地址
spring.cloud.nacos.discovery.server-addr=localhost:8848

商品工程application.properties如下

server.port=9001
spring.application.name=nacos-payment-provider
spring.cloud.nacos.discovery.server-addr=localhost:8848
#暴露全部监控端点
management.endpoints.web.exposure.include=*

商品工程新建一个Controller

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

@GetMapping(value = "/payment/nacos/{id}")
public String getPayment(@PathVariable("id") Integer id)
{
    return "nacos registry, serverPort: "+ serverPort+"\t id"+id;
}

订单工程新建一个Controller

@RestController
@Slf4j
public class OrderNacosController
{
    @Resource
    private RestTemplate restTemplate;

    @Value("${service-url.nacos-user-service}")
    private String serverURL;

    @GetMapping(value = "/consumer/payment/nacos/{id}")
    public String paymentInfo(@PathVariable("id") Long id)
    {
        return restTemplate.getForObject(serverURL+"/payment/nacos/"+id,String.class);
    }

}

订单工程新建一个配置类

@Configuration
public class MyConfig {
      @Bean
      @LoadBalanced
      public RestTemplate getRestTemplate()
      {
          return new RestTemplate();
      }

}

7.3 实现服务调用的负载均衡

1、 什么是负载均衡

通俗的讲, 负载均衡就是将负载(工作任务,访问请求)进行分摊到多个操作单元(服务器,组件)上进行执行。
根据负载均衡发生位置的不同,一般分为服务端负载均衡和客户端负载均衡。
服务端负载均衡指的是发生在服务提供者一方,比如常见的nginx负载均衡
而客户端负载均衡指的是发生在服务请求的一方,也就是在发送请求之前已经选好了由哪个实例处理请求。
第31课时 微服务概述、Nacos、Ribbon及Feign_第8张图片
我们在微服务调用关系中一般会选择客户端负载均衡,也就是在服务调用的一方来决定服务由哪个提供者执行。

2、自定义实现负载均衡策略
a)再启动一个商品微服务,设置其端口为8002
b)通过nacos查看微服务的启动情况
c)修改订单微服务 的代码,实现负载均衡

List<ServiceInstance> instances = discoveryClient.getInstances("service- product");

int index = new Random().nextInt(instances.size());

ServiceInstance serviceInstance = instances.get(index);

String url = serviceInstance.getHost() + ":" +

        serviceInstance.getPort();

log.info(">>从nacos中获取到的微服务地址为:" + url);

7.4开启Ribbon负载均衡

Ribbon是Spring Cloud的一个组件, 它可以让我们使用一个注解就能轻松的搞定负载均衡

@Bean
@LoadBalanced
public RestTemplate getRestTemplate()
{
    return new RestTemplate();
}

Ribbon支持的负载均衡策略
Ribbon内置了多种负载均衡策略,内部负载均衡的顶级接口为com.netflix.loadbalancer.IRule , 具体的负载策略如下图所示:
第31课时 微服务概述、Nacos、Ribbon及Feign_第9张图片
我们可以通过修改配置来调整Ribbon的负载均衡策略,具体代码如下:
调用的提供者的名称.ribbon.NFLoadBalancerRuleClassName=com.netflix.loadbalancer.RandomRule

7.5整合Feign

RestTemplate进行互相访问,但是这种方式对参数传递和使用都不是很方便,所以弃用此方式,采用feign进行声明式服务之间的调用,可以简化调用流程;Feign整合了Ribbon,默认负载均衡策略也是轮询
添加依赖

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
@FeignClient(value = "nacos-payment-provider",fallback = PaymentFallbackService.class)
public interface PaymentService
{
    @GetMapping(value = "/paymentSQL/{id}")
    public CommonResult<Payment> paymentSQL(@PathVariable("id") Long id);
}

主启动类上增加@EnableFeignClients
Feign调用的超时控制(默认1秒)

#请求处理的超时时间
ribbon.ReadTimeout=1000
#请求连接的超时时间
ribbon.ConnectTimeout: 500

8、Nacos Config—配置管理中心

8.1 为什么要有服务配置中心

首先我们来看一下,微服务架构下关于配置文件的一些问题:
1.配置文件相对分散。在一个微服务架构下,配置文件会随着微服务的增多变的越来越多,而且分散在各个微服务中,不好统一配置和管理。
2.配置文件无法区分环境。微服务项目可能会有多个环境,例如:测试环境、预发布环境、生产环境。每一个环境所使用的配置理论上都是不同的,一旦需要修改,就需要我们去各个微服务下手动维护,这比较困难。
3.配置文件无法实时更新。我们修改了配置文件之后,必须重新启动微服务才能使配置生效,这对一个正在运行的项目来说是非常不友好的。
基于上面这些问题,我们就需要配置中心的加入来解决这些问题。

配置中心的思路是:
1.首先把项目中各种配置全部都放到一个集中的地方进行统一管理,并提供一套标准的接口。
2.当各个服务需要获取配置的时候,就来配置中心的接口拉取自己的配置。
3.当配置中心中的各种参数有更新的时候,也能通知到各个服务实时的过来同步最新的信息,使之动态更新。
当加入了服务配置中心之后,我们的系统架构图会变成下面这样
第31课时 微服务概述、Nacos、Ribbon及Feign_第10张图片
在业界常见的服务配置中心,有下面这些:
Apollo
Apollo是由携程开源的分布式配置中心。特点有很多,比如:配置更新之后可以实时生效,支持灰度发布功能,并且能对所有的配置进行版本管理、操作审计等功能,提供开放平台API。并且资料也写的很详细。
Disconf
Disconf是由百度开源的分布式配置中心。它是基于Zookeeper来实现配置变更后实时通知和生效的。
SpringCloud Config
这是Spring Cloud中带的配置中心组件。它和Spring是无缝集成,使用起来非常方便,并且它的配置存储支持Git。不过它没有可视化的操作界面,配置的生效也不是实时的,需要重启或去刷新。
Nacos
这是SpingCloud alibaba技术栈中的一个组件,前面我们已经使用它做过服务注册中心。其实它也集成了服务配置的功能,我们可以直接使用它作为服务配置中心。

8.2 nacos config的几个概念

命名空间(Namespace)
命名空间可用于进行不同环境的配置隔离。一般一个环境划分到一个命名空间

配置分组(Group)
配置分组用于将不同的服务可以归类到同一分组。一般将一个项目的配置分到一组

配置集(Data ID)
在系统中,一个配置文件通常就是一个配置集。一般微服务的配置就是一个配置集
第31课时 微服务概述、Nacos、Ribbon及Feign_第11张图片
在nacos中添加配置
点击配置列表,点击右边+号,新建配置。在新建配置过程中,要注意下面的细节:
1)Data ID不能随便写,要跟配置文件中的对应,对应关系如图所示
2)配置文件格式要跟配置文件的格式对应
3)配置内容按照上面选定的格式书写

第31课时 微服务概述、Nacos、Ribbon及Feign_第12张图片
注释本地的application.properties中的内容, 启动程序进行测试

8.3 代码示例

在微服务中引入nacos的依赖

<dependency> 
<groupId>com.alibaba.cloud</groupId> 
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency> 

在微服务中添加nacos config的配置

注意:不能使用原来的application. properties作为配置文件,而是新建一个bootstrap.properties作为配置文件

server.port=7001
spring.application.name=nacos-config-client
#Nacos服务注册中心地址
spring.cloud.nacos.discovery.server-addr=localhost:8848
#Nacos作为配置中心地址
spring.cloud.nacos.config.server-addr=localhost:8848
#指定配置文件格式
spring.cloud.nacos.config.file-extension=properties
spring.cloud.nacos.config.group=shop
spring.cloud.nacos.config.namespace=7d8f0f5a-6a53-4785-9686-dd460158e5d4
# dev 表示开发环境 test 表示测试环境 
spring.profiles.active=dev 

配置文件优先级(由高到低):
bootstrap.properties -> bootstrap.yml -> application.properties -> application.yml
新建一个controller

@RestController
@RefreshScope //支持Nacos的动态刷新功能。
public class ConfigClientController
{
    @Value("${payment.info}")
    private String configInfo;

    @GetMapping("/payment/info")
    public String getConfigInfo() {
        return configInfo;
    }
}

8.4 配置持久化

nacos默认的是嵌入式的数据库derby,所以当我们在nacos进行相关配置之后,其数据会保存在该数据库中,但是当重启nacos时,客户端的数据还是消失,因此我们可以把nacos中嵌入的数据库derby换成我们本地的mysql数据库来实现数据的持久化。

1、初始化数据库
Nacos的数据库脚本文件在我们下载Nacos-server时的压缩包中就有
进入nacos-server-1.2.1\nacos\conf目录,初始化文件:nacos-mysql.sql
此处我创建一个名为 mynacos 的数据库,然后执行初始化脚本,成功后会生成 11 张表

2、修改配置文件
这里是需要修改Nacos-server的配置文件
Nacos-server其实就是一个Java工程或者说是一个Springboot项目,他的配置文件在nacos-server-1.2.1\nacos\conf目录下,名为 application.properties,在文件底部添加数据源配置:

spring.datasource.platform=mysql

db.num=1
db.url.0=jdbc:mysql://127.0.0.1:3306/mynacos?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true& serverTimezone=UTC
db.user=root
db.password=123456

3、启动Nacos-server和Nacos-config
需要添加mysql8的驱动jar包至nacos\plugins\mysql下面(需新建文件夹)
在这里插入图片描述
先启动Nacos-server,启动方式不变,直接双击执行nacos-server-1.2.1\nacos\bin下的startup.cmd文件
启动成功后进入Nacos控制台,此时的Nacos控制台中焕然一新,之前的数据都不见了
因为加入了新的数据源,Nacos从mysql中读取所有的配置文件,而我们刚刚初始化的数据库是干干净净的,自然不会有什么数据和信息显示。

4、验证是否持久化到数据库
在公共空间(public)中新建一个配置文件DataID: nacos-config.properties, 配置内容如下:
Server.port=9989
nacos.config=配置文件已持久化到数据库中。。。
观察数据库mynacos中的数据库表 config_info , 如下
在这里插入图片描述

你可能感兴趣的:(Java开发第二阶段)