软件开发定制Spring Cloud Alibaba 第一篇(Nacos组件)

一、Spring Cloud Alibaba

1.1.简介

Spring Cloud Alibaba 软件开发定制致力于提供开发的一站软件开发定制式解决方案。软件开发定制此项目包含开发分布式软件开发定制应用微服务的必需组件,软件开发定制方便开发者通过 Spring Cloud 软件开发定制编程模型轻松使用这些软件开发定制组件来开发分布式应用服务。

依托 Spring Cloud Alibaba,软件开发定制您只需要添加一些注解软件开发定制和少量配置,就可以将 Spring Cloud 软件开发定制应用接入阿里微服务解决方案,软件开发定制通过阿里中间件来迅速软件开发定制搭建分布式应用系统。

Spring Cloud :软件开发定制是一种微服务开发规范,软件开发定制是一套标准接口。软件开发定制所有器实现的框架都 软件开发定制必须要符合 该标准

实现框架:

Spring Cloud Netflix 软件开发定制第一点版本 软件开发定制在去年已经停止更新

Spring Cloud Alibaba 软件开发定制第二代版本,软件开发定制非常的便于介入阿里云软件开发定制各种云服务

1.2. 主要功能

  • 软件开发定制服务限流降级:默认支持WebServlet、WebFlux、OpenFeign、RestTemplate、Spring Cloud Gateway、Zuul、Dubbo 和 RocketMQ软件开发定制限流降级功能的接入,软件开发定制可以在运行时通过控制软件开发定制台实时修改限流降级规则,软件开发定制还支持查看限流降级Metrics监控。
  • 软件开发定制服务注册与发现:适配Spring Cloud 软件开发定制服务注册与发现标准,软件开发定制默认集成了Ribbon的支持。 软件开发定制提供注册中心相关功能(nacos,eureka,zk)
  • 软件开发定制分布式配置管理:软件开发定制支持分布式系统中的外部化配置,软件开发定制配置更改时自动刷新。                 软件开发定制我们可以让很多实例 去共享 软件开发定制同一个远程的 application.proerties
  • 软件开发定制消息驱动能力:基于 Spring Cloud Stream 软件开发定制为微服务应用构建消息驱动能力。              软件开发定制消息推送功能,通知
  • 软件开发定制分布式事务:使用 @GlobalTransactional 注解, 高效并且对业务零侵入地解决分布式事务问题。。                                                                                                                   解决跨应用之间的 事务 一致性

  • 阿里云对象存储:阿里云提供的海量、安全、低成本、高可靠的云存储服务。支持在任何应用、任何时间、任何地点存储和访问任意类型的数据。                                            可以将文件直接存储 阿里云对象存储

  • 分布式任务调度:提供秒级、精准、高可靠、高可用的定时(基于 Cron 表达式)任务调度服务。同时提供分布式的任务执行模型,如网格任务。网格任务支持海量子任务均匀分配到所有 Worker(schedulerx-client)上执行。                                                 Redis + Quartz或者Elastic-Job来解决。

  • 阿里云短信服务:覆盖全球的短信服务,友好、高效、智能的互联化通讯能力,帮助企业迅速搭建客户触达通道。

1.3. 组件

:把流量作为切入点,从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性。

:一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。

:一款开源的分布式消息系统,基于高可用分布式集群技术,提供低延时的、高可靠的消息发布与订阅服务。

:Apache Dubbo™ 是一款高性能 Java RPC 框架。

:阿里巴巴开源产品,一个易于使用的高性能微服务分布式事务解决方案。

: 阿里云对象存储服务(Object Storage Service,简称 OSS),是阿里云提供的海量、安全、低成本、高可靠的云存储服务。您可以在任何应用、任何时间、任何地点存储和访问任意类型的数据。

: 阿里中间件团队开发的一款分布式任务调度产品,提供秒级、精准、高可靠、高可用的定时(基于 Cron 表达式)任务调度服务。

: 覆盖全球的短信服务,友好、高效、智能的互联化通讯能力,帮助企业迅速搭建客户触达通道。

1.4.为什么要用Spring Cloud Alibaba?

1.我们需要知道Spring Cloud Alibaba在Spring Cloud家族中的地位,它是一个套件,与Netflix OSS一样,涵盖了非常多的实用组件,其中也有不少内容存在重叠。

2.我们需要知道Netflix OSS下的诸多重要组件先后宣布停止新功能开发的大背景,而Spring Cloud Alibaba是一个新生项目,正处于高速迭代中。对于未来,相信谁都会选。

3.对于中国用户来说,Spring Cloud Alibaba还有一个非常特殊的意义:它将曾经红极一时的Dubbo,以及阿里巴巴的强力消息中间件RocketMQ融入Spring Cloud体系。还在纠结于如何让这些共存的团队,你们所面临过的各种困难与问题,马上就会迎刃而解。不用再烦恼是不是要扩展Dubbo的注册中心,还是自己为RocketMQ实现一套的Spring Cloud Stream的Binder等等问题。

4.对于Spring Cloud Alibaba的上手学习成本如何呢?

如果您已经是Spring Cloud的用户,那么恭喜您,在Spring Cloud Common的抽象和Spring Cloud Alibaba团队的努力下,你会非常容易、甚至不需要改变多少编码模式,就能适应它。如果您第一次接触Spring Cloud,那么也恭喜您,因为这是有史以来,中文文档最全的一个Spring Cloud组件了,相信机制的您一定也能很快的上手使用它

如何引入依赖

  1. <packaging>pom</packaging>
  2. <properties>
  3. <!-- Environment Settings -->
  4. <java.version>1.8</java.version>
  5. <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  6. <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
  7. <!-- Spring Settings -->
  8. <spring-cloud.version>Hoxton.SR1</spring-cloud.version>
  9. <spring-cloud-alibaba.version>2.2.0.RELEASE</spring-cloud-alibaba.version>
  10. </properties>
  11. <dependencyManagement>
  12. <dependencies>
  13. <dependency>
  14. <groupId>org.springframework.cloud</groupId>
  15. <artifactId>spring-cloud-dependencies</artifactId>
  16. <version>${spring-cloud.version}</version>
  17. <type>pom</type>
  18. <scope>import</scope>
  19. </dependency>
  20. <dependency>
  21. <groupId>com.alibaba.cloud</groupId>
  22. <artifactId>spring-cloud-alibaba-dependencies</artifactId>
  23. <version>${spring-cloud-alibaba.version}</version>
  24. <type>pom</type>
  25. <scope>import</scope>
  26. </dependency>
  27. </dependencies>
  28. </dependencyManagement>

二、Nacos组件

致力于帮助您发现、配置和管理微服务。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据及流量管理。

Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。 Nacos 是构建以“服务”为中心的现代应用架构 (例如微服务范式、云原生范式) 的服务基础设施。

2.1 特性

  • 服务发现和服务健康监测

Nacos 支持基于 DNS 和基于 RPC 的服务发现。服务提供者使用 、、或一个注册 Service 后,服务消费者可以使用 或查找和发现服务。

相当于dubbo的zookeeper和springcloud的eureka

 实现:nacos ,eureka,zookeeper

  • 动态配置服务

动态配置服务可以让您以中心化、外部化和动态化的方式管理所有环境的应用配置和服务配置。

动态配置消除了配置变更时重新部署应用和服务的需要,让配置管理变得更加高效和敏捷。

配置中心化管理让实现无状态服务变得更简单,让服务按需弹性扩展变得更容易。

相当于动态配置的zookeeper和springcloude-nacos-config

  • 动态 DNS 服务

动态 DNS 服务支持权重路由,让您更容易地实现中间层负载均衡、更灵活的路由策略、流量控制以及数据中心内网的简单DNS解析服务。动态DNS服务还能让您更容易地实现以 DNS 协议为基础的服务发现,以帮助您消除耦合到厂商私有服务发现 API 上的风险。

  • 服务及其元数据管理

Nacos 能让您从微服务平台建设的视角管理数据中心的所有服务及元数据,包括管理服务的描述、生命周期、服务的静态依赖分析、服务的健康状态、服务的流量管理、路由及安全策略、服务的 SLA 以及最首要的 metrics 统计数据。

我们可以通过 nacos 完成对注册到nacos 中的所有的实例进行健康检测,包保存其元数据

2.2 作用

  • 注册中心:帮助发现其他服务对应的实例

  • 配置中心:全局的配置文件

  • 健康监控管理中心:监控实例的健康状态

2.3 安装

环境要求

  1. 64 bit OS,支持 Linux/Unix/Mac/Windows,推荐选用 Linux/Unix/Mac。

  2. 64 bit JDK 1.8+; & 。

  3. Maven 3.2.x+; & 。

2.3.1.下载安装包

nacos-server-1.2.0-beta.0.zip

注意下载[nacos-server-1.2.0 以上版本会报错

2.3.2 解压

2.3.3 启动

 进入到bin目录

 

2.3.4.访问 路径

三、springcloud alibaba 实例

1.创建一个服务的生产者 提供服务 springcloud-alibaba-provider

2.创建一个服务的消费者 消费提供的服务springcloud-alibaba-consume

3.1.创建父工程springcloudalibaba

在父工程的pom.xml文件引入以下依赖

  1. <!-- 标记该工程 为父工程-->
  2. <packaging>pom</packaging>
  3. <!--
  4. spring cloud 必须 基于spring boot 实现
  5. -->
  6. <parent>
  7. <groupId>org.springframework.boot</groupId>
  8. <artifactId>spring-boot-starter-parent</artifactId>
  9. <version>2.2.4.RELEASE</version>
  10. </parent>
  11. <properties>
  12. <!-- Environment Settings -->
  13. <java.version>1.8</java.version>
  14. <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  15. <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
  16. <!-- Spring Settings
  17. spirng cloud 版本是 以伦敦地铁站 命名 Hoxton.SR1
  18. -->
  19. <spring-cloud.version>Hoxton.SR1</spring-cloud.version>
  20. <!--
  21. spring-cloud-alibaba 版本
  22. -->
  23. <spring-cloud-alibaba.version>2.2.0.RELEASE</spring-cloud-alibaba.version>
  24. </properties>
  25. <!-- 管理子工程 的依赖 ,保证子工程依赖的 jar 和 父工程 保持一致
  26. 在子工程中 不需要加版本号
  27. -->
  28. <dependencyManagement>
  29. <dependencies>
  30. <dependency>
  31. <groupId>org.springframework.cloud</groupId>
  32. <artifactId>spring-cloud-dependencies</artifactId>
  33. <version>${spring-cloud.version}</version>
  34. <type>pom</type>
  35. <scope>import</scope>
  36. </dependency>
  37. <dependency>
  38. <groupId>com.alibaba.cloud</groupId>
  39. <artifactId>spring-cloud-alibaba-dependencies</artifactId>
  40. <version>${spring-cloud-alibaba.version}</version>
  41. <type>pom</type>
  42. <scope>import</scope>
  43. </dependency>
  44. </dependencies>
  45. </dependencyManagement>

3.2 创建服务提供者springcloud-alibaba-provider

创建子工程springcloud-alibaba-providerr,引入以下依赖,下面是我的pom.xml文件

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  5. <parent>
  6. <artifactId>springcloudalibaba</artifactId>
  7. <groupId>com.qf</groupId>
  8. <version>1.0-SNAPSHOT</version>
  9. </parent>
  10. <modelVersion>4.0.0</modelVersion>
  11. <artifactId>springcloud-alibaba-provider</artifactId>
  12. <dependencies>
  13. <!--springBoot 相关 -->
  14. <dependency>
  15. <groupId>org.springframework.boot</groupId>
  16. <artifactId>spring-boot-starter-web</artifactId>
  17. </dependency>
  18. <dependency>
  19. <groupId>org.springframework.boot</groupId>
  20. <artifactId>spring-boot-starter-actuator</artifactId>
  21. </dependency>
  22. <dependency>
  23. <groupId>org.springframework.boot</groupId>
  24. <artifactId>spring-boot-starter-test</artifactId>
  25. <scope>test</scope>
  26. </dependency>
  27. <!-- alibaba.cloud 相关-->
  28. <dependency>
  29. <groupId>com.alibaba.cloud</groupId>
  30. <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
  31. </dependency>
  32. <dependency>
  33. <groupId>com.alibaba.cloud</groupId>
  34. <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
  35. </dependency>
  36. </dependencies>
  37. </project>

创建配置文件,application.properties

  1. # 应用名 模块名 注意应用名 不可以使用_
  2. spring.application.name=springcloud-alibaba-provider
  3. #配置nacos 服务器地址
  4. spring.cloud.nacos.server-addr=localhost:8848
  5. #配置tomcat端口号
  6. server.port=8083
  7. #暴露所有应用断点,便于监控
  8. management.endpoints.web.exposure.include=*

创建启动类

  1. package com.qf;
  2. import org.springframework.boot.SpringApplication;
  3. import org.springframework.boot.autoconfigure.SpringBootApplication;
  4. import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
  5. @EnableDiscoveryClient //激活nacos相关功能
  6. @SpringBootApplication
  7. public class ProviderApplication {
  8. public static void main(String[] args) {
  9. SpringApplication.run(ProviderApplication.class,args);
  10. }
  11. }

创建测试类

  1. package com.qf.controller;
  2. import com.qf.entity.Student;
  3. import org.springframework.beans.factory.annotation.Value;
  4. import org.springframework.web.bind.annotation.*;
  5. @RestController //Controller + ResponseBody 该注解下面的方法返回的都是Json数据
  6. public class HelloController {
  7. @Value("${server.port}")
  8. private Integer port;
  9. @RequestMapping("/getMessage/{msg}") //restFul风格
  10. public String getMessage(@PathVariable("msg") String msg){
  11. return "msg:"+msg + "--from-port:" + port;
  12. }
  13. @RequestMapping("/say")
  14. public String say(@RequestParam("msg") String msg){
  15. return "msg:"+msg + "--from-port:" + port;
  16. }
  17. }

测试启动provider

访问nacos管理界面,可以看到

访问  和 

 3.3 创建服务消费者 springcloud-alibaba-consumer

消费者通过nacos调用服务提供者的接口使用LoadBalanceClient 和 RestTemplate来完成

1.创建springcloud-alibaba-consumer

引入以下pom和provider 一致

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  5. <parent>
  6. <artifactId>springcloudalibaba</artifactId>
  7. <groupId>com.qf</groupId>
  8. <version>1.0-SNAPSHOT</version>
  9. </parent>
  10. <modelVersion>4.0.0</modelVersion>
  11. <artifactId>springcloud-alibaba-consumer</artifactId>
  12. <dependencies>
  13. <!--springBoot 相关 -->
  14. <dependency>
  15. <groupId>org.springframework.boot</groupId>
  16. <artifactId>spring-boot-starter-web</artifactId>
  17. </dependency>
  18. <dependency>
  19. <groupId>org.springframework.boot</groupId>
  20. <artifactId>spring-boot-starter-actuator</artifactId>
  21. </dependency>
  22. <dependency>
  23. <groupId>org.springframework.boot</groupId>
  24. <artifactId>spring-boot-starter-test</artifactId>
  25. <scope>test</scope>
  26. </dependency>
  27. <!-- alibaba.cloud 相关-->
  28. <dependency>
  29. <groupId>com.alibaba.cloud</groupId>
  30. <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
  31. </dependency>
  32. <dependency>
  33. <groupId>com.alibaba.cloud</groupId>
  34. <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
  35. </dependency>
  36. </dependencies>
  37. </project>

2.创建配置文件

  1. #应用名 模块名 注意应用名 不可以使用_
  2. spring.application.name=springcloud-alibaba-consumer
  3. #配置nacos 服务器地址
  4. spring.cloud.nacos.server-addr=localhost:8848
  5. #配置tomcat端口号
  6. server.port=8085
  7. #暴露所有应用断点,便于监控
  8. management.endpoints.web.exposure.include=*

3.创建启动类

  1. package com.qf;
  2. import org.springframework.boot.SpringApplication;
  3. import org.springframework.boot.autoconfigure.SpringBootApplication;
  4. import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
  5. @EnableDiscoveryClient //激活nacos相关功能
  6. @SpringBootApplication
  7. public class ConsumerApplication {
  8. public static void main(String[] args) {
  9. SpringApplication.run(ConsumerApplication.class,args);
  10. }
  11. }

5.创建配置类

  1. package com.qf.config;
  2. import org.springframework.context.annotation.Bean;
  3. import org.springframework.context.annotation.Configuration;
  4. import org.springframework.web.client.RestTemplate;
  5. @Configuration //标记当前类是配置类,相当于spring中的bean.xml
  6. public class NacosConfig {
  7. /**
  8. * RestTemplate 就是一个帮助我们发起远程http请求的客户端(类似于postman,浏览器)
  9. * */
  10. @Bean //向容器中加入一个RestTemplate
  11. public RestTemplate getRestTemplate(){
  12. return new RestTemplate();
  13. }
  14. }

6.创建测试类

  1. package com.qf.controller;
  2. import org.springframework.beans.factory.annotation.Autowired;
  3. import org.springframework.cloud.client.ServiceInstance;
  4. import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
  5. import org.springframework.web.bind.annotation.RequestMapping;
  6. import org.springframework.web.bind.annotation.RestController;
  7. import org.springframework.web.client.RestTemplate;
  8. import java.util.HashMap;
  9. import java.util.Map;
  10. /**
  11. * 主要用于consumer向provider发起远程请求
  12. * */
  13. @RestController
  14. public class NacosConsumerController {
  15. /**
  16. * loadBalancerClient负载均衡的客户端,用来根据服务名从nacos中获取对应的ip
  17. * */
  18. @Autowired
  19. private LoadBalancerClient loadBalancerClient;
  20. /**
  21. * RestTemplate 就是一个帮助我们发起远程http请求的客户端(类似于postman,浏览器)
  22. * */
  23. @Autowired
  24. private RestTemplate restTemplate;
  25. @RequestMapping("/test1")
  26. public String test1(){
  27. // 调用远程 provider 中的 @RequestMapping("/getMessage/{msg}")
  28. // 现在是 写死 地址,也可以使用 nacos 找到 springcloud-alibaba-provider 对应的ip 端口
  29. // String url = "http://localhost:8083/getMessage/hello";
  30. // serviceInstance 就是远程 provider 实例的 ip 和 端口 的封装
  31. ServiceInstance serviceInstance = loadBalancerClient.choose("springcloud-alibaba-provider");
  32. // 得到远程服务实例的ip
  33. //serviceInstance.getHost();
  34. // 得到端口
  35. // serviceInstance.getPort();
  36. //%s 就是需要替换的参数
  37. String url = String.format("http://%s:%s/getMessage/%s",serviceInstance.getHost(),serviceInstance.getPort(),"hello");
  38. // 使用restTemplate 发起网络请求
  39. return restTemplate.getForObject(url,String.class);
  40. }
  41. @RequestMapping("/test2")
  42. public String test2(){
  43. // 远程调用 @RequestMapping("/say")
  44. // public String say(@RequestParam("msg") String msg)
  45. ServiceInstance serviceInstance= loadBalancerClient.choose("springcloud-alibaba-provider");
  46. String url = String.format("http://%s:%s/say?msg={msg}",serviceInstance.getHost(),serviceInstance.getPort());
  47. //msg值的初始化
  48. Map map = new HashMap();
  49. map.put("msg","hello java2109");
  50. // 使用restTemplate 发起网络请求
  51. return restTemplate.getForObject(url,String.class,map);
  52. }
  53. }

启动服务提供者和服务消费者进行测试,

查看nacos管理界面可以看到:http://localhost:8848/nacos

 浏览器访问:

RestTemplate:帮助我们发起远程请求的 客户端

使用的都是模板设计模式

LoadBalancerClient:loadBalancerClient 负载均衡的客户端 ,用来 根据服务名 从nacos 中获取对应的ip

 四、Ribbon

如果provider 提供的服务有多个,那么consumer 调用provider时,就需要更多不同的负载均衡算法 选择不同的实例发起请求

4.1 Ribbon概述

是一个客户端的负载均衡器,它提供对大量的HTTP和TCP客户端的访问控制
可以实现服务的远程调用和服务的负载均衡协调

4.2 Ribbon的负载均衡

 4.3 示例

1. 在springcloud-alibaba-consumer中引入负载均衡依赖

  1. <!-- 引入负载均衡-->
  2. <dependency>
  3. <groupId>org.springframework.cloud</groupId>
  4. <artifactId>spring-cloud-starter-netflix-ribbon
  5. </artifactId>
  6. </dependency>

2.在配置文件中配置负载均衡器(将原来的myConfig类屏蔽)

  1. import com.netflix.loadbalancer.IRule;
  2. import com.netflix.loadbalancer.RandomRule;
  3. import org.springframework.cloud.client.loadbalancer.LoadBalanced;
  4. import org.springframework.context.annotation.Bean;
  5. import org.springframework.context.annotation.Configuration;
  6. import org.springframework.web.client.RestTemplate;
  7. @Configuration
  8. public class RibbonConfig {
  9. @LoadBalanced // 对RestTemplate 的发起网络请求 进行拦截,
  10. // 运用负载均衡策略(就是按照策略选择对应的ip)
  11. @Bean //向容器中加入一个 RestTemplate
  12. public RestTemplate restTemplate(){
  13. return new RestTemplate();
  14. }
  15. @Bean // 将随机的 策略加入到容器中
  16. public IRule iRule(){
  17. // 创建一个随机的负载均衡策略
  18. IRule rule = new RandomRule();
  19. //2.权重响应时间分配规则 代替ResponseTimeRule 响应时间加权策略
  20. // WeightedResponseTimeRule responseTimeRule=new WeightedResponseTimeRule();
  21. // //3.最低并发策略 分配的时候选择目前并发量最小的
  22. // BestAvailableRule bestAvailableRule=new BestAvailableRule();
  23. // //4.轮训策略
  24. // RoundRobinRule roundRobinRule=new RoundRobinRule();
  25. // //5.重试策略 如果在配置时间内,无法选择服务,尝试选择一个服务 重试机制
  26. // RetryRule retryRule=new RetryRule();
  27. // //6.区域感知策略 就近访问
  28. // ZoneAvoidanceRule zoneAvoidanceRule=new ZoneAvoidanceRule();
  29. 7.可用过滤策略 可用根据阈值进行服务过滤
  30. // AvailabilityFilteringRule filteringRule=new AvailabilityFilteringRule();
  31. return rule;
  32. }
  33. }

3.创建RibbonTestController 测试(屏蔽原来 TestController)

  1. package com.qf.controller;
  2. import org.springframework.beans.factory.annotation.Autowired;
  3. import org.springframework.web.bind.annotation.RequestMapping;
  4. import org.springframework.web.bind.annotation.RestController;
  5. import org.springframework.web.client.RestTemplate;
  6. import java.util.HashMap;
  7. import java.util.Map;
  8. @RestController
  9. public class RibbonTestController {
  10. /**
  11. * RestTemplate 就是一个帮助我们发起远程http请求的客户端(类似于postman,浏览器)
  12. * */
  13. @Autowired
  14. private RestTemplate restTemplate;
  15. @RequestMapping("/test1")
  16. public String test1(){
  17. // 调用远程 provider 中的 @RequestMapping("/getMessage/{msg}")
  18. // http://springcloud-alibaba-provider/getMessage/%s
  19. //restTemplate 向 http://springcloud-alibaba-provider服务发起请求,但是会被ribbon 进行拦截,
  20. // 会根据负载均衡策略选择其中一台 provider实例,并替换 springcloud-alibaba-provider为 ip:端口
  21. // %s 就是需要替换的参数
  22. String url = String.format("http://springcloud-alibaba-provider/getMessage/%s","hello");
  23. // 使用restTemplate 发起网络请求
  24. return restTemplate.getForObject(url,String.class);
  25. }
  26. @RequestMapping("/test2")
  27. public String test2(){
  28. // 远程调用 @RequestMapping("/say")
  29. // public String say(@RequestParam("msg") String msg)
  30. String url = String.format("http://springcloud-alibaba-provider/say?msg={msg}");
  31. //msg值的初始化
  32. Map map = new HashMap();
  33. map.put("msg","hello java2109");
  34. // 使用restTemplate 发起网络请求
  35. return restTemplate.getForObject(url,String.class,map);
  36. }
  37. }

4.启动 两个provider (端口一定不同),在启动一个consumer进行测试

 然后修改端口号为8084,再次启动

 然后启动consumer

 然后访问:http://localhost:8848/nacos/ 

打开新的页面,输入:

Ribbon:是一个负载均衡的客户端,他可以拦截RestTemplate 发起的请求,并且将请求路径中的服务名,根据负载均衡策略替换为ip:端口,并发起网络请求

底层原理:使用aop ,动态代理实现

五、Feign

Feign:就是伪装,feign 就是可以将远程的访问调用,伪装成本地的接口调用。

Feign = RestTemplate + Ribbon

5.1 什么是Feign?

Feign 的英文表意为“假装,伪装,变形”, 是一个http请求调用的轻量级框架,可以Java接口注解的方式调用Http请求,而不用像Java中通过封装HTTP请求报文的方式直接调用。Feign通过处理注解,将请求模板化,当实际调用的时候,传入参数,根据参数再应用到请求上,进而转化成真正的请求,这种请求相对而言比较直观。 Feign被广泛应用在Spring Cloud 的解决方案中,是学习基于Spring Cloud 微服务架构不可或缺的重要组件。

5.2 实例1

1.创建一个springcloud-feign-cosumer工程,导入依赖

  1. <dependencies>
  2. <!--springBoot 相关 -->
  3. <dependency>
  4. <groupId>org.springframework.boot</groupId>
  5. <artifactId>spring-boot-starter-web</artifactId>
  6. </dependency>
  7. <dependency>
  8. <groupId>org.springframework.boot</groupId>
  9. <artifactId>spring-boot-starter-actuator</artifactId>
  10. </dependency>
  11. <dependency>
  12. <groupId>org.springframework.boot</groupId>
  13. <artifactId>spring-boot-starter-test</artifactId>
  14. <scope>test</scope>
  15. </dependency>
  16. <!-- alibaba.cloud nacos 相关-->
  17. <dependency>
  18. <groupId>com.alibaba.cloud</groupId>
  19. <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
  20. </dependency>
  21. <dependency>
  22. <groupId>com.alibaba.cloud</groupId>
  23. <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
  24. </dependency>
  25. <!-- opengin -->
  26. <dependency>
  27. <groupId>org.springframework.cloud</groupId>
  28. <artifactId>spring-cloud-starter-openfeign</artifactId>
  29. </dependency>
  30. </dependencies>

2.创建配置文件application.properties

  1. # 应用名 模块名 注意应用名 不可以使用_ springcloud-alibaba-feign-consumer
  2. spring.application.name=springcloud-alibaba-feign-consumer
  3. #配置nacos 服务地址
  4. spring.cloud.nacos.server-addr=localhost:8848
  5. server.port=8086
  6. #暴露所有应用断点,便于监控
  7. management.endpoints.web.exposure.include=*

3.创建启动类

  1. package com.qf;
  2. import org.springframework.boot.SpringApplication;
  3. import org.springframework.boot.autoconfigure.SpringBootApplication;
  4. import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
  5. import org.springframework.cloud.openfeign.EnableFeignClients;
  6. @EnableFeignClients //激活feign 相关功能
  7. @EnableDiscoveryClient //激活nacos功能
  8. @SpringBootApplication
  9. public class FeignApplication {
  10. public static void main(String[] args) {
  11. SpringApplication.run(FeignApplication.class,args);
  12. }
  13. }

4.创建Feign伪装接口

  1. package com.qf.service;
  2. import com.qf.entity.Student;
  3. import org.springframework.cloud.openfeign.FeignClient;
  4. import org.springframework.web.bind.annotation.*;
  5. /**
  6. * 伪装 接口
  7. *
  8. * 我们需要向那个一个 服务发起远程调用,就需要将远程的处理器 方法拷贝过来,只剩方法名,没有方法体
  9. * 1.拷贝 provider 中的 处理器方法
  10. * 2.删除方法体
  11. *
  12. * @FeignClient(value = "springcloud-alibaba-provider")
  13. * //标记当前接口 是一个feign伪装接口,feign 更具接口配置的方法,生成对应的实现类
  14. * 向远程服务发起请求 ----》 将改接口实现 完成 RestTemplate 请求
  15. *
  16. */
  17. @FeignClient(value = "springcloud-alibaba-provider")
  18. public interface FeignService {
  19. @RequestMapping("/getMessage/{msg}") //restFul风格
  20. public String getMessage(@PathVariable("msg") String msg);
  21. @RequestMapping("/say")
  22. public String say(@RequestParam("msg") String msg);
  23. /**
  24. * 更新学生
  25. * @param Student
  26. * @return
  27. */
  28. @RequestMapping("/updateStudent")
  29. public Student updateStudent(@RequestBody Student student);
  30. }

5.创建FeignTestController使用伪装接口进行测试

  1. package com.qf.controller;
  2. import com.qf.entity.Student;
  3. import com.qf.service.FeignService;
  4. import org.springframework.beans.factory.annotation.Autowired;
  5. import org.springframework.web.bind.annotation.RequestMapping;
  6. import org.springframework.web.bind.annotation.RestController;
  7. @RestController
  8. public class FeignTestController {
  9. @Autowired
  10. private FeignService feignService;
  11. @RequestMapping("/test1")
  12. public String test1(){
  13. // 调用远程 provider 中的 @RequestMapping("/getMessage/{msg}")
  14. return feignService.getMessage("hello BeiJing");
  15. }
  16. @RequestMapping("/test2")
  17. public String test2(){
  18. // 远程调用 @RequestMapping("/say")
  19. // public String say(@RequestParam("msg") String msg)
  20. return feignService.say("hello - java2109");
  21. }
  22. }

启动 两个provider (端口一定不同),再启动Fegin-consumer进行测试

 5.3 实例二(使用feign 远程调用传递对象)

1.创建common工程

 2.创建实体类Student

  1. import java.io.Serializable;
  2. /**
  3. * 创建一个实体类
  4. * 1.get set 方法
  5. * 2.toString()
  6. * 3.实现序列化 序列化作用:1.便于保存对象存入磁盘 2.便于网络间传输
  7. *
  8. * 4.如果创建了 有参构造 ,必须创建无参构造 必须注意
  9. */
  10. public class Student implements Serializable {
  11. private int id;
  12. private String name;
  13. private int age;
  14. private String sex;
  15. private float height;
  16. public Student() {
  17. }
  18. public Student(int id, String name, int age, String sex, float height) {
  19. this.id = id;
  20. this.name = name;
  21. this.age = age;
  22. this.sex = sex;
  23. this.height = height;
  24. }
  25. public int getId() {
  26. return id;
  27. }
  28. public void setId(int id) {
  29. this.id = id;
  30. }
  31. public String getName() {
  32. return name;
  33. }
  34. public void setName(String name) {
  35. this.name = name;
  36. }
  37. public int getAge() {
  38. return age;
  39. }
  40. public void setAge(int age) {
  41. this.age = age;
  42. }
  43. public String getSex() {
  44. return sex;
  45. }
  46. public void setSex(String sex) {
  47. this.sex = sex;
  48. }
  49. public float getHeight() {
  50. return height;
  51. }
  52. public void setHeight(float height) {
  53. this.height = height;
  54. }
  55. @Override
  56. public String toString() {
  57. return "Student{" +
  58. "id=" + id +
  59. ", name='" + name + '\'' +
  60. ", age=" + age +
  61. ", sex='" + sex + '\'' +
  62. ", height=" + height +
  63. '}';
  64. }
  65. }

打成jar包,并存入到本地仓库

 4.在provider中引入依赖

  1. <!-- 引入 公共的依赖 -->
  2. <dependency>
  3. <groupId>com.qfedu</groupId>
  4. <artifactId>springcloud-alibaba-common</artifactId>
  5. <version>1.0-SNAPSHOT</version>
  6. </dependency>

5.在provider 创建接受方法 一定要加 @RequestBody

  1. /**
  2. * 更新学生
  3. * // 普通 的键值对 转对象 updateStudent(Student student),不可以被接受,只能接受json 转对象
  4. *
  5. * Student updateStudent(@RequestBody Student student)
  6. *
  7. * @param Student
  8. * @return
  9. */
  10. @RequestMapping("/updateStudent")
  11. public Student updateStudent(@RequestBody Student student){
  12. // 修改名字
  13. student.setName(student.getName() +" --port:"+port);
  14. System.out.println("服务提供者 更新student = " + student);
  15. return student;
  16. }

6.在feign-consumer 中引入 common

  1. <!-- 引入 公共的依赖 -->
  2. <dependency>
  3. <groupId>com.qfedu</groupId>
  4. <artifactId>springcloud-alibaba-common</artifactId>
  5. <version>1.0-SNAPSHOT</version>
  6. </dependency>

7.在feign-consumer 的 FeignService 中添加

  1. /**
  2. * 更新学生
  3. * @param Student
  4. * @return
  5. */
  6. @RequestMapping("/updateStudent")
  7. public Student updateStudent(@RequestBody Student student);

8.在FeignTestController添加方法

  1. @RequestMapping("/test3")
  2. public Student test3() {
  3. Student student = new Student(100,"xiaoming", 13,"F",170);
  4. return feignService.updateStudent(student);
  5. }

9.测试

先重新启动 provider ,feign-consumer

然后观察 nacos ,再测试

5.4 Feign的容错机制

容错:consumer 调用provider,如果Provider 有异常,消费者也会报错,容错机制就是保证,Provider 有异常,消费依然可以正常的返回兜底数据,客户感觉不到 provider有异常

1.在配置文件中开启容错

  1. #开启 feign 容错机制
  2. feign.hystrix.enabled=true

2.实现容错类

  1. package com.qf.service.impl;
  2. import com.qf.entity.Student;
  3. import com.qf.service.FeignService;
  4. import org.springframework.stereotype.Component;
  5. /**
  6. * Feign 伪装接口的容错实现类
  7. * */
  8. @Component //加入到容器中
  9. public class FeignServiceFallBackImpl implements FeignService {
  10. @Override
  11. public String getMessage(String msg) {
  12. return "feign 触发容错 getMessage 返回数据" + msg;
  13. }
  14. @Override
  15. public String say(String msg) {
  16. return "feign 触发容错 say 返回数据" + msg;
  17. }
  18. @Override
  19. public Student updateStudent(Student student) {
  20. student.setName(student.getName()+"----容错返回");
  21. return student;
  22. }
  23. }

3.在FeignService伪装类接口中配置容错策略

  1. package com.qf.service;
  2. import com.qf.entity.Student;
  3. import com.qf.service.impl.FeignServiceFallBackImpl;
  4. import org.springframework.cloud.openfeign.FeignClient;
  5. import org.springframework.web.bind.annotation.PathVariable;
  6. import org.springframework.web.bind.annotation.RequestBody;
  7. import org.springframework.web.bind.annotation.RequestMapping;
  8. import org.springframework.web.bind.annotation.RequestParam;
  9. /**
  10. * 伪装 接口
  11. *
  12. * 我们需要向那个一个 服务发起远程调用,就需要将远程的处理器 方法拷贝过来,只剩方法名,没有方法体
  13. * 1.拷贝 provider 中的 处理器方法
  14. * 2.删除方法体
  15. *
  16. * @FeignClient(value = "springcloud-alibaba-provider")
  17. * //标记当前接口 是一个feign伪装接口,feign 更具接口配置的方法,生成对应的实现类
  18. * 向远程服务发起请求 ----》 将改接口实现 完成 RestTemplate 请求
  19. *
  20. * fallback=FeignServiceFallBackImpl.class 配置容错实现类
  21. */
  22. @FeignClient(value = "springcloud-alibaba-provider",fallback= FeignServiceFallBackImpl.class)
  23. public interface FeignService {
  24. @RequestMapping("/getMessage/{msg}") //restFul风格
  25. public String getMessage(@PathVariable("msg") String msg);
  26. @RequestMapping("/say")
  27. public String say(@RequestParam("msg") String msg);
  28. /**
  29. * 更新学生
  30. * @param Student
  31. * @return
  32. */
  33. @RequestMapping("/updateStudent")
  34. public Student updateStudent(@RequestBody Student student);
  35. }

4.进行测试

1.重新启动 feign-consumer 正常返回数据

2.停止provider ,则feign-consumer 返回容错数据

 正常访问,此时的provider是正常状态

 将provider关掉,继续访问:

 六、Nacos Config(分布式配置中心)

在分布式系统中,由于服务数量巨多,为了方便服务配置文件统一管理,实时更新,所以需要分布式配置中心组件。

Nacos 提供用于存储配置和其他元数据的 key/value 存储,为分布式系统中的外部化配置提供服务器端和客户端支持。使用 Spring Cloud Alibaba Nacos Config,您可以在 Nacos Server 集中管理你 Spring Cloud 应用的外部属性配置。

Spring Cloud Alibaba Nacos Config 是 Spring Cloud Config Server 和 Client 的替代方案,客户端和服务器上的概念与 Spring Environment 和 PropertySource 有着一致的抽象,在特殊的 bootstrap 阶段,配置被加载到 Spring 环境中。当应用程序通过部署管道从开发到测试再到生产时,您可以管理这些环境之间的配置,并确保应用程序具有迁移时需要运行的所有内容。

1.创建springcloud-alibaba-nacos-fonfig 应用,并引入依赖

  1. <dependencies>
  2. <!--springBoot 相关 -->
  3. <dependency>
  4. <groupId>org.springframework.boot</groupId>
  5. <artifactId>spring-boot-starter-web</artifactId>
  6. </dependency>
  7. <!-- spring 的监控模块-->
  8. <dependency>
  9. <groupId>org.springframework.boot</groupId>
  10. <artifactId>spring-boot-starter-actuator</artifactId>
  11. </dependency>
  12. <dependency>
  13. <groupId>org.springframework.boot</groupId>
  14. <artifactId>spring-boot-starter-test</artifactId>
  15. <scope>test</scope>
  16. </dependency>
  17. <!-- alibaba.cloud 相关-->
  18. <dependency>
  19. <groupId>com.alibaba.cloud</groupId>
  20. <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
  21. </dependency>
  22. <dependency>
  23. <groupId>com.alibaba.cloud</groupId>
  24. <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
  25. </dependency>
  26. </dependencies>

2.nacos 配置文件

springboot 读取配置文件的顺序

bootstrap.properties ---->bootstrap.yaml ------>application.proerties---->application.yaml

bootstrap.properties

  1. #应用springboot 启动前 先去读取bootstrap.properties ,然后去配置中心拉取对应的配置文件
  2. # 应用名 模块名 注意应用名 不可以使用_ springcloud_alibaba_provider
  3. spring.application.name=springcloud-alibaba-nacos-provider
  4. #配置nacos 服务地址
  5. spring.cloud.nacos.server-addr=localhost:8848
  6. server.port=8086
  7. #暴露所有应用断点,便于监控
  8. management.endpoints.web.exposure.include=*
  9. student.name=xiaoming

3.在nacos 配置中创建 对应配置文件

服务名.properties

 

 4.配置启动类

  1. import org.springframework.boot.SpringApplication;
  2. import org.springframework.boot.autoconfigure.SpringBootApplication;
  3. import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
  4. @EnableDiscoveryClient
  5. @SpringBootApplication
  6. public class ConfigApplication {
  7. public static void main(String[] args) {
  8. SpringApplication.run(ConfigApplication.class,args);
  9. }
  10. }

 5.读取配置文件内容测试

  1. import org.springframework.beans.factory.annotation.Autowired;
  2. import org.springframework.beans.factory.annotation.Value;
  3. import org.springframework.cloud.netflix.archaius.ConfigurableEnvironmentConfiguration;
  4. import org.springframework.web.bind.annotation.RequestMapping;
  5. import org.springframework.web.bind.annotation.RestController;
  6. @RestController
  7. public class ConfigController {
  8. // 在启动时 获取配置文件一次数据,中间不改变
  9. @Value("${student.name}")
  10. private String studentName;
  11. @Autowired
  12. // ConfigurableEnvironmentConfiguration 实时得到配置中中对应配置文件的数据
  13. private ConfigurableEnvironmentConfiguration configuration;
  14. @RequestMapping("/getStudent")
  15. public String getStudent(){
  16. return "配置文件---studentName:"+studentName +"---与配置中心保持一致的数据:"+configuration.getString("student.name");
  17. }
  18. }

测试

 修改文件内容,得到立即的推送

可以在配置文件加入spring.cloud.nacos.config.refresh.enabled=false禁止自动刷新

七、Nacos Config 多环境的配置

bootstrap.properties  application.properties 默认配置都是任何时候都生效的

我们还可以配置自定义环境,便于开发,但是前提必须是要先激活

自定义的环境有:

        ①开发环境:bootstrap-dev.properties

        ②测试环境:bootstrap-test.properties

多环境的配置有两种:

第一种是在bootstrap.properties中配置,下面是我的bootstrap.properties文件的内容

  1. #应用SpringBoot 启动前,先去读取bootstrap.properties,然后去配置中心拉去对应的配置文件
  2. #应用名 模块名 主要应用名不可以使用_
  3. spring.application.name=springcloud-alibaba-nacos-config
  4. #配置nacos服务地址
  5. spring.cloud.nacos.server-addr=localhost:8848
  6. #配置tomcat端口号
  7. server.port=8087
  8. #暴露所有应用端点,便于监控
  9. management.endpoints.web.exposure.include=*
  10. # 将该文件中配置的student.name注释掉
  11. #student.name=xiaoming
  12. #激活dev环境 让bootstrap-dev.properties生效
  13. spring.cloud.nacos.config.file-extension=properties
  14. spring.profiles.active=dev

创建bootstrap-dev.properties文件

  1. #应用springboot 启动前 先去读取bootstrap.properties,然后去配置中心拉取对应的配置文件
  2. #配置student.name
  3. student.name=xiaoming-dev

先启动nacos,再启动项目,先访问:http://localhost:8848/nacos 查看服务注册上没

然后访问服务:

在配置中心创建配置文件springcloud-alibaba-nacos-config-dev.properties

 

 刷新页面:

修改配置文件的内容,再次发布,再次刷新页面: 

可以看到内容实时在更新

 

第二种方式:懒得测了,感兴趣的可以测测

 

网站建设定制开发 软件系统开发定制 定制软件开发 软件开发定制 定制app开发 app开发定制 app开发定制公司 电商商城定制开发 定制小程序开发 定制开发小程序 客户管理系统开发定制 定制网站 定制开发 crm开发定制 开发公司 小程序开发定制 定制软件 收款定制开发 企业网站定制开发 定制化开发 android系统定制开发 定制小程序开发费用 定制设计 专注app软件定制开发 软件开发定制定制 知名网站建设定制 软件定制开发供应商 应用系统定制开发 软件系统定制开发 企业管理系统定制开发 系统定制开发