zoukankan      html  css  js  c++  java
  • springcloud配置

    一、概述

    1.微服务与单体架构区别

     

    2. 什么是Spring Cloud

    Spring Cloud是一系列框架的集合。它利用Spring Boot的开发便利性简化了分布式系统基础设施的开发,如服务发现、服务注册、配置中心、消息总线、负载均衡、 熔断器、数据监控等,都可以用Spring Boot的开发风格做到一键启动和部署。Spring并没有重复制造轮子,它只是将目前各家公司开发的比较成熟、经得起实际考验的服务框架组合起来,通过SpringBoot风格进行再封装屏蔽掉了复杂的配置和实现原理,最终给开发者留出了一套简单易懂、易部署和易维护的分布式系统开发工具包

    3.Spring Cloud和Spring Boot是什么关系

    • Spring Boot Spring 的一套快速配置脚手架,可以基于Spring Boot 快速开发单个微服务,Spring Cloud是一个基于Spring Boot实现的开发工具;
    • Spring Boot专注于快速、方便集成的单个微服务个体,Spring Cloud关注全局的服务治理框架;
    • Spring Boot使用了默认大于配置的理念,很多集成方案已经帮你选择好了,能不配置就不配置,Spring Cloud很大的一部分是基于Spring Boot来实现,必须基于Spring Boot开发。
    • 可以单独使用Spring Boot开发项目,但是Spring Cloud离不开 Spring Boot

    4.Spring Cloud相关基础服务组件

     二、Nacos

    1.概述

    1.常见的注册中心

     2.Nacos主要提供以下四大功能

     3. 结构

     2. 安装与配置

    1.下载 nacos

    下载地址:https://github.com/alibaba/nacos/releases

    2.启动nacos服务

    • - Linux/Unix/Mac
      • 启动命令(standalone代表着单机模式运行,非集群模式)
      • 启动命令:sh startup.sh -m standalone
    • - Windows
      • 启动命令:cmd startup.cmd 或者双击startup.cmd运行文件。
      • 访问:http://localhost:8848/nacos
    • 用户名密码:nacos/nacos

    3.步骤

    1. 引入依赖

     1         <dependency>
     2             <groupId>org.springframework.cloud</groupId>
     3             <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
     4         </dependency>
     5         <!-- hystrix熔断器依赖,主要是用 @HystrixCommand -->
     6         <dependency>
     7             <groupId>org.springframework.cloud</groupId>
     8             <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
     9         </dependency>
    10         <!--服务注册-->
    11         <dependency>
    12             <groupId>org.springframework.cloud</groupId>
    13             <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
    14          </dependency>
    15         <!--服务调用-->
    16         <dependency>
    17             <groupId>org.springframework.cloud</groupId>
    18             <artifactId>spring-cloud-starter-openfeign</artifactId>
    19         </dependency>

    2. 添加配置信息

    1 # application.properties
    2 # nacos服务地址
    3 spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848

    3. 添加Nacos客户端注解

    1 @EnableDiscoveryClient

    4. 在服务端的启动类添加注解

    1 @EnableFeignClients

    5. 在服务端创建包和接口 (客户端)

    创建client

    • @FeignClient注解用于指定从哪个服务中调用功能 ,名称与被调用的服务名保持一致。
    • @DeleteMapping注解用于对被调用的微服务进行地址映射。
    • @PathVariable注解一定要指定参数名称,否则出错
    • @Component注解防止,在其他位置注入CodClientidea报错
    1 @FeignClient("service-vod")
    2 @Component
    3 public interface VodClient {
    4     @DeleteMapping(value = "/eduvod/vod/video/{videoId}") // 该处写全路径名
    5     public R removeVideo(@PathVariable("videoId") String videoId); //该处一点要加别名"videoId"
    6 }

    6. 调用微服务

    1 @Autowire
    2 private VodClient vodClient;

    三、Hystrix基本概念

    1. Spring Cloud调用接口过程

    • (1)接口化请求调用当调用被@FeignClient注解修饰的接口时,在框架内部,将请求转换成Feign的请求实例feign.Request,交由Feign框架处理。
    • (2Feign :转化请求Feign是一个http请求调用的轻量级框架,可以以Java接口注解的方式调用Http请求,封装了Http调用流程。
    • 3Hystrix:熔断处理机制 Feign的调用关系,会被Hystrix代理拦截,对每一个Feign调用请求,Hystrix都会将其包装成HystrixCommand参与Hystrix的流控和熔断规则。如果请求判断需要熔断,则Hystrix直接熔断,抛出异常或者使用FallbackFactory返回熔断Fallback结果;如果通过,则将调用请求传递给Ribbon组件。
    • 4Ribbon:服务地址选择 当请求传递到Ribbon之后,Ribbon会根据自身维护的服务列表,根据服务的服务质量,如平均响应时间,Load等,结合特定的规则,从列表中挑选合适的服务实例,选择好机器之后,然后将机器实例的信息请求传递给Http Client客户端,HttpClient客户端来执行真正的Http接口调用;
    • 5HttpClient Http客户端,真正执行Http调用根据上层Ribbon传递过来的请求,已经指定了服务地址,则HttpClient开始执行真正的Http请求

    2. 步骤

    1.导入依赖

    2.在配置文件中添加hystrix配置

    1 #开启熔断机制
    2 feign.hystrix.enabled=true
    3 # 设置hystrix超时时间,默认1000ms
    4 hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=6000

    3.创建熔断器的实现类 (即实现VodClient)

    注意:开启熔断器后必要要有实现类

     1 @Component
     2 public class VodFileDegradeFeignClient implements VodClient {
     3     @Override
     4      public R removeVideo(String videoId) {
     5         return R.error().message("time out");
     6     }
     7     @Override
     8     public R removeVideoList(List videoIdList) {
     9         return R.error().message("time out");
    10     }
    11 }        

    4.修改VodClient接口的注解

    1 @FeignClient(name = "service-vod", fallback = VodFileDegradeFeignClient.class)
    2 @Component
    3 public interface VodClient {
    4     @DeleteMapping(value = "/eduvod/vod/{videoId}")
    5     public R removeVideo(@PathVariable("videoId") String videoId);
    6 
    7     @DeleteMapping(value = "/eduvod/vod/delete-batch")
    8     public R removeVideoList(@RequestParam("videoIdList") List videoIdList);
    9 }

    四、网关

    1. 问题

    • (1)客户端会多次请求不同的微服务,增加了客户端的复杂性。
    • (2)存在跨域请求,在一定场景下处理相对复杂。
    • (3)认证复杂,每个服务都需要独立认证。
    • (4)难以重构,随着项目的迭代,可能需要重新划分微服务。例如,可能将多个服务合并成一个或者将一个服务拆分成多个。如果客户端直接与微服务通信,那么重构将会很难实施。
    • (5)某些微服务可能使用了防火墙 / 浏览器不友好的协议,直接访问会有一定的困难。以上这些问题可以借助 API 网关解决。API 网关是介于客户端和服务器端之间的中间层,所有的外部请求都会先经过 API 网关这一层。也就是说,API 的实现方面更多的考虑业务逻辑,而安全、性能、监控可以交由 API 网关来做,这样既提高业务灵活性又不缺安全性

    2. 网关作用

     (1)路由。路由是网关最基础的部分,路由信息有一个ID、一个目的URL、一组断言和一组Filter组成。如果断言路由为真,则说明请求的URL和配置匹配
     (2)断言。Java8中的断言函数。Spring Cloud Gateway中的断言函数输入类型是Spring5.0框架中的ServerWebExchange。Spring Cloud Gateway中的断言函数允许开发者去定义匹配来自于httprequest中的任何信息,比如请求头和参数等。

     (3)过滤器。一个标准的Spring webFilter。Spring cloud gateway中的filter分为两种类型的Filter,分别是Gateway Filter和Global Filter。过滤器Filter将会对请求和响应进行修改处理

    3. 步骤

    1.导入依赖

     1     <dependencies>
     2         <dependency>
     3             <groupId>com.atguigu</groupId>
     4             <artifactId>common-util</artifactId>
     5             <version>0.0.1-SNAPSHOT</version>
     6         </dependency>
     7         <dependency>
     8             <groupId>org.springframework.cloud</groupId>
     9             <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
    10         </dependency>
    11         <dependency>
    12             <groupId>org.springframework.cloud</groupId>
    13             <artifactId>spring-cloud-starter-gateway</artifactId>
    14         </dependency>
    15         <!--gson-->
    16         <dependency>
    17             <groupId>com.google.code.gson</groupId>
    18             <artifactId>gson</artifactId>
    19         </dependency>
    20         <!--服务调用-->
    21         <dependency>
    22             <groupId>org.springframework.cloud</groupId>
    23             <artifactId>spring-cloud-starter-openfeign</artifactId>
    24         </dependency>
    25     </dependencies>

    2. 配置文件

     1 # 服务端口
     2 server.port=9001
     3 # 服务名
     4 spring.application.name=gateway
     5 # nacos服务地址
     6 spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848
     7 #使用服务发现路由
     8 spring.cloud.gateway.discovery.locator.enabled=true
     9 #服务路由名小写
    10 #spring.cloud.gateway.discovery.locator.lower-case-service-id=true
    11 #设置路由id
    12 spring.cloud.gateway.routes[0].id=service-acl
    13 #设置路由的uri
    14 spring.cloud.gateway.routes[0].uri=lb://service-acl
    15 #设置路由断言,代理servicerId为auth-service的/auth/路径
    16 spring.cloud.gateway.routes[0].predicates= Path=/*/acl/**
    17 #配置service-edu服务
    18 spring.cloud.gateway.routes[1].id=service-edu
    19 spring.cloud.gateway.routes[1].uri=lb://service-edu
    20 spring.cloud.gateway.routes[1].predicates= Path=/eduservice/**
    21 #配置service-ucenter服务
    22 spring.cloud.gateway.routes[2].id=service-ucenter
    23 spring.cloud.gateway.routes[2].uri=lb://service-ucenter
    24 spring.cloud.gateway.routes[2].predicates= Path=/ucenterservice/**
    25 #配置service-ucenter服务
    26 spring.cloud.gateway.routes[3].id=service-cms
    27 spring.cloud.gateway.routes[3].uri=lb://service-cms
    28 spring.cloud.gateway.routes[3].predicates= Path=/cmsservice/**
    29 spring.cloud.gateway.routes[4].id=service-msm
    30 spring.cloud.gateway.routes[4].uri=lb://service-msm
    31 spring.cloud.gateway.routes[4].predicates= Path=/edumsm/**
    32 spring.cloud.gateway.routes[5].id=service-order
    33 spring.cloud.gateway.routes[5].uri=lb://service-order
    34 spring.cloud.gateway.routes[5].predicates= Path=/orderservice/**
    35 spring.cloud.gateway.routes[6].id=service-order
    36 spring.cloud.gateway.routes[6].uri=lb://service-order
    37 spring.cloud.gateway.routes[6].predicates= Path=/orderservice/**
    38 spring.cloud.gateway.routes[7].id=service-oss
    39 spring.cloud.gateway.routes[7].uri=lb://service-oss
    40 spring.cloud.gateway.routes[7].predicates= Path=/eduoss/**
    41 spring.cloud.gateway.routes[8].id=service-statistic
    42 spring.cloud.gateway.routes[8].uri=lb://service-statistic
    43 spring.cloud.gateway.routes[8].predicates= Path=/staservice/**
    44 spring.cloud.gateway.routes[9].id=service-vod
    45 spring.cloud.gateway.routes[9].uri=lb://service-vod
    46 spring.cloud.gateway.routes[9].predicates= Path=/eduvod/**
    47 spring.cloud.gateway.routes[10].id=service-edu
    48 spring.cloud.gateway.routes[10].uri=lb://service-edu
    49 spring.cloud.gateway.routes[10].predicates= Path=/eduuser/**
    网关配置

    3. 配置

     1 import org.springframework.context.annotation.Bean;
     2 import org.springframework.context.annotation.Configuration;
     3 import org.springframework.web.cors.CorsConfiguration;
     4 import org.springframework.web.cors.reactive.CorsWebFilter;
     5 import org.springframework.web.cors.reactive.UrlBasedCorsConfigurationSource;
     6 import org.springframework.web.util.pattern.PathPatternParser;
     7 
     8 
     9 @Configuration
    10 public class CorsConfig {
    11     @Bean
    12     public CorsWebFilter corsFilter() {
    13         CorsConfiguration config = new CorsConfiguration();
    14         config.addAllowedMethod("*");
    15         config.addAllowedOrigin("*");
    16         config.addAllowedHeader("*");
    17 
    18         UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(new PathPatternParser());
    19         source.registerCorsConfiguration("/**", config);
    20 
    21         return new CorsWebFilter(source);
    22     }
    23 }
    CorsConfig
     1 import com.google.gson.JsonObject;
     2 import org.springframework.cloud.gateway.filter.GatewayFilterChain;
     3 import org.springframework.cloud.gateway.filter.GlobalFilter;
     4 import org.springframework.core.Ordered;
     5 import org.springframework.core.io.buffer.DataBuffer;
     6 import org.springframework.http.server.reactive.ServerHttpRequest;
     7 import org.springframework.http.server.reactive.ServerHttpResponse;
     8 import org.springframework.stereotype.Component;
     9 import org.springframework.util.AntPathMatcher;
    10 import org.springframework.web.server.ServerWebExchange;
    11 import reactor.core.publisher.Mono;
    12 
    13 import java.nio.charset.StandardCharsets;
    14 import java.util.List;
    15 
    16 /**
    17  * <p>
    18  * 全局Filter,统一处理会员登录与外部不允许访问的服务
    19  * </p>
    20  *
    21  */
    22 @Component
    23 public class AuthGlobalFilter implements GlobalFilter, Ordered {
    24 
    25     private AntPathMatcher antPathMatcher = new AntPathMatcher();
    26 
    27     @Override
    28     public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
    29         ServerHttpRequest request = exchange.getRequest();
    30         String path = request.getURI().getPath();
    31         //谷粒学院api接口,校验用户必须登录
    32         if(antPathMatcher.match("/api/**/auth/**", path)) {
    33             List<String> tokenList = request.getHeaders().get("token");
    34             if(null == tokenList) {
    35                 ServerHttpResponse response = exchange.getResponse();
    36                 return out(response);
    37             } else {
    38 //                Boolean isCheck = JwtUtils.checkToken(tokenList.get(0));
    39 //                if(!isCheck) {
    40                     ServerHttpResponse response = exchange.getResponse();
    41                     return out(response);
    42 //                }
    43             }
    44         }
    45         //内部服务接口,不允许外部访问
    46         if(antPathMatcher.match("/**/inner/**", path)) {
    47             ServerHttpResponse response = exchange.getResponse();
    48             return out(response);
    49         }
    50         return chain.filter(exchange);
    51     }
    52 
    53     @Override
    54     public int getOrder() {
    55         return 0;
    56     }
    57 
    58     private Mono<Void> out(ServerHttpResponse response) {
    59         JsonObject message = new JsonObject();
    60         message.addProperty("success", false);
    61         message.addProperty("code", 28004);
    62         message.addProperty("data", "鉴权失败");
    63         byte[] bits = message.toString().getBytes(StandardCharsets.UTF_8);
    64         DataBuffer buffer = response.bufferFactory().wrap(bits);
    65         //response.setStatusCode(HttpStatus.UNAUTHORIZED);
    66         //指定编码,否则在浏览器中会中文乱码
    67         response.getHeaders().add("Content-Type", "application/json;charset=UTF-8");
    68         return response.writeWith(Mono.just(buffer));
    69     }
    70 }
    AuthGlobalFilter
     1 import org.springframework.beans.factory.ObjectProvider;
     2 import org.springframework.boot.autoconfigure.web.ResourceProperties;
     3 import org.springframework.boot.autoconfigure.web.ServerProperties;
     4 import org.springframework.boot.context.properties.EnableConfigurationProperties;
     5 import org.springframework.boot.web.reactive.error.ErrorAttributes;
     6 import org.springframework.boot.web.reactive.error.ErrorWebExceptionHandler;
     7 import org.springframework.context.ApplicationContext;
     8 import org.springframework.context.annotation.Bean;
     9 import org.springframework.context.annotation.Configuration;
    10 import org.springframework.core.Ordered;
    11 import org.springframework.core.annotation.Order;
    12 import org.springframework.http.codec.ServerCodecConfigurer;
    13 import org.springframework.web.reactive.result.view.ViewResolver;
    14 
    15 import java.util.Collections;
    16 import java.util.List;
    17 
    18 /**
    19  * 覆盖默认的异常处理
    20  *
    21  *
    22  */
    23 @Configuration
    24 @EnableConfigurationProperties({ServerProperties.class, ResourceProperties.class})
    25 public class ErrorHandlerConfig {
    26 
    27     private final ServerProperties serverProperties;
    28 
    29     private final ApplicationContext applicationContext;
    30 
    31     private final ResourceProperties resourceProperties;
    32 
    33     private final List<ViewResolver> viewResolvers;
    34 
    35     private final ServerCodecConfigurer serverCodecConfigurer;
    36 
    37     public ErrorHandlerConfig(ServerProperties serverProperties,
    38                                      ResourceProperties resourceProperties,
    39                                      ObjectProvider<List<ViewResolver>> viewResolversProvider,
    40                                         ServerCodecConfigurer serverCodecConfigurer,
    41                                      ApplicationContext applicationContext) {
    42         this.serverProperties = serverProperties;
    43         this.applicationContext = applicationContext;
    44         this.resourceProperties = resourceProperties;
    45         this.viewResolvers = viewResolversProvider.getIfAvailable(Collections::emptyList);
    46         this.serverCodecConfigurer = serverCodecConfigurer;
    47     }
    48 
    49     @Bean
    50     @Order(Ordered.HIGHEST_PRECEDENCE)
    51     public ErrorWebExceptionHandler errorWebExceptionHandler(ErrorAttributes errorAttributes) {
    52         JsonExceptionHandler exceptionHandler = new JsonExceptionHandler(
    53                 errorAttributes,
    54                 this.resourceProperties,
    55                 this.serverProperties.getError(),
    56                 this.applicationContext);
    57         exceptionHandler.setViewResolvers(this.viewResolvers);
    58         exceptionHandler.setMessageWriters(this.serverCodecConfigurer.getWriters());
    59         exceptionHandler.setMessageReaders(this.serverCodecConfigurer.getReaders());
    60         return exceptionHandler;
    61     }
    62 }
    ErrorHandlerConfig
     1 import org.springframework.boot.autoconfigure.web.ErrorProperties;
     2 import org.springframework.boot.autoconfigure.web.ResourceProperties;
     3 import org.springframework.boot.autoconfigure.web.reactive.error.DefaultErrorWebExceptionHandler;
     4 import org.springframework.boot.web.reactive.error.ErrorAttributes;
     5 import org.springframework.context.ApplicationContext;
     6 import org.springframework.http.HttpStatus;
     7 import org.springframework.web.reactive.function.server.*;
     8 
     9 import java.util.HashMap;
    10 import java.util.Map;
    11 
    12 /**
    13  * 自定义异常处理
    14  *
    15  * <p>异常时用JSON代替HTML异常信息<p>
    16  *
    17  *
    18  */
    19 public class JsonExceptionHandler extends DefaultErrorWebExceptionHandler {
    20 
    21     public JsonExceptionHandler(ErrorAttributes errorAttributes, ResourceProperties resourceProperties,
    22                                 ErrorProperties errorProperties, ApplicationContext applicationContext) {
    23         super(errorAttributes, resourceProperties, errorProperties, applicationContext);
    24     }
    25 
    26     /**
    27      * 获取异常属性
    28      */
    29     @Override
    30     protected Map<String, Object> getErrorAttributes(ServerRequest request, boolean includeStackTrace) {
    31         Map<String, Object> map = new HashMap<>();
    32         map.put("success", false);
    33         map.put("code", 20005);
    34         map.put("message", "网关失败");
    35         map.put("data", null);
    36         return map;
    37     }
    38 
    39     /**
    40      * 指定响应处理方法为JSON处理的方法
    41      * @param errorAttributes
    42      */
    43     @Override
    44     protected RouterFunction<ServerResponse> getRoutingFunction(ErrorAttributes errorAttributes) {
    45         return RouterFunctions.route(RequestPredicates.all(), this::renderErrorResponse);
    46     }
    47 
    48     /**
    49      * 根据code获取对应的HttpStatus
    50      * @param errorAttributes
    51      */
    52     @Override
    53     protected int getHttpStatus(Map<String, Object> errorAttributes) {
    54         return 200;
    55     }
    56 }
    JsonExceptionHandler
     1 import org.springframework.boot.SpringApplication;
     2 import org.springframework.boot.autoconfigure.SpringBootApplication;
     3 import org.springframework.context.annotation.ComponentScan;
     4 
     5 
     6 @SpringBootApplication
     7 @ComponentScan("com.atguigu")
     8 public class GatewayApplication {
     9     public static void main(String[] args) {
    10         SpringApplication.run(GatewayApplication.class,args);
    11     }
    12 }
    GatewayApplication

    五、配置中心 nacos

    应用场景:
    在系统开发过程中,开发者通常会将一些需要变更的参数、变量等从代码中分离出来独立管理,以独立的配置文件的形式存在。目的是让静态的系统工件或者交付物(如 WARJAR 包等)更好地和实际的物理运行环境进行适配。配置管理一般包含在系统部署的过程中,由系统管理员或者运维人员完成。配置变更是调整系统运行时的行为的有效手段。


    如果微服务架构中没有使用统一配置中心时,所存在的问题:

    • - 配置文件分散在各个项目里,不方便维护
    • - 配置内容安全与权限
    • - 更新配置后,项目需要重启
    • nacos配置中心:系统配置的集中管理(编辑、存储、分发)、动态更新不重启、回滚配置(变更管理、历史版本管理、变更审计)等所有与配置相关的活动。

    1. 读取Nacos配置中心的配置文件

    1.导入依赖

    1 <dependency>
    2   <groupId>org.springframework.cloud</groupId>
    3   <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
    4 </dependency>

    2.创建bootstrap.properties配置文件

    #配置中心地址
    spring.cloud.nacos.config.server-addr=127.0.0.1:8848
    #spring.profiles.active=dev
    # 该配置影响统一配置中心中的dataId
    spring.application.name=service-statistics

     

     a)Data ID 的完整规则格式如下${prefix}-${spring.profile.active}.${file-extension}

    • - prefix 默认为所属工程配置spring.application.name 的值(即:nacos-provider),也可以通过配置项 spring.cloud.nacos.config.prefix来配置。
    • - spring.profiles.active=dev 即为当前环境对应的 profile注意:当spring.profiles.active 为空时,对应的连接符 - 也将不存在,dataId 的拼接格式变成${prefix}.${file-extension}
    • - file-exetension 为配置内容的数据格式,可以通过配置项spring.cloud.nacos.config.file-extension 来配置。目前只支持 properties yaml 类型。

    2.名称空间切换环境

    在实际开发中,通常有多套不同的环境(默认只有public),那么这个时候可以根据指定的环境来创建不同的 namespce,例如,开发、测试和生产三个不同的环境,那么使用一套 nacos 集群可以分别建以下三个不同的 namespace。以此来实现多环境的隔离

     

     

     

     

     

    3.多配置文件加载

     在一些情况下需要加载多个配置文件。假如现在dev名称空间下有三个配置文件:service-statistics.propertiesredis.propertiesjdbc.properties

     

     

     

     

     

     

     

     

     

     

    作者:zhangshuai
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须在文章页面给出原文连接,否则保留追究法律责任的权利。
  • 相关阅读:
    subprocess 子进程模块
    3.5 魔法方法
    ThinkPHP中,display和assign用法详解
    linux常用指令
    退出当前Mysql使用的db_name 的方式
    PHP中GD库是做什么用的? PHP GD库介绍11111111
    include跟include_once 以及跟require的区别
    全局变量跟局部变量
    关于define
    创建、删除索引---高级部分
  • 原文地址:https://www.cnblogs.com/zhangshaui/p/15062899.html
Copyright © 2011-2022 走看看