当前位置:   article > 正文

SpringCloudAlibaba_shared-configs指定命名空间

shared-configs指定命名空间

Nacos

一、下载安装

1、下载

linuxhttps://github.com/alibaba/nacos/releases/download/2.0.4/nacos-server-2.0.4.tar.gz

  1. 执行下载命令
  2. wget https://github.com/alibaba/nacos/releases/download/2.0.4/nacos-server-2.0.4.tar.gz
  3. 解压安装包
  4. tar -zxxvf nacos-server-2.0.4.tar.gz nacos/

2、linux部署

(1)创建数据库nacos,执行conf目录下的nacos-mysql.sql脚本,初始化数据库

(2)进入conf目录编辑application.properties

(4)在bin目录下启动

./startup.sh -m standalone   //standalone代表着单机模式运行,非集群模式

看到最后一行的successfully启动成功 

(5)将nacos配置为系统服务

①添加文件nacos.service    vim /lib/systemd/system/nacos.service     并且增加如下信息 (nacos路径替换成自己的路径即可)

  1. [Unit]
  2. Description=nacos
  3. After=network.target
  4. [Service]
  5. Type=forking
  6. ExecStart=/usr/nacos-server-1.1.3/nacos/bin/startup.sh -m standalone
  7. ExecReload=/usr/nacos-server-1.1.3/nacos/bin/shutdown.sh
  8. ExecStop=/usr/nacos-server-1.1.3/nacos/bin/shutdown.sh
  9. PrivateTmp=true
  10. [Install]
  11. WantedBy=multi-user.target

②编辑nacos/bin目录下的startup.sh, 修改JAVA_HOME的路径,注释其他三项

③执行以下命令

  1. 1. 重新加载所有service服务
  2. systemctl daemon-reload
  3. 2. 开机启动nacos.service
  4. systemctl enable nacos.service
  5. 3. 查看该service是否开机启用
  6. systemctl is-enabled nacos.service
  7. 4. 启动该服务
  8. systemctl start nacos.service
  9. 可能报错: Job for nacos.service failed because the control process exited with error code. See "systemctl status nacos.service" and "journalctl -xe" for details.
  10. 5. 查看该服务状态
  11. systemctl status nacos.service

3、访问nacos:http://localhost:8848/nacos

初始账号密码:nacos/nacos.

二、nacos注册中心

1、依赖导入

  1. <dependency>
  2. <groupId>com.alibaba.cloud</groupId>
  3. <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
  4. </dependency>

2、服务注册 

  1. spring: 
  2. application: 
  3. name: sca-provider #服务注册的服务名 ,注意服务名的横线
  4. cloud: 
  5. nacos: 
  6. discovery: 
  7. server-addr: localhost:8848 #向nacos控制台注册

3、启动该工程查看是否注册成功

客户端定时(5秒)向nacos发送请求(心跳包),中断15秒,nacos客户端显示不健康,30秒认为中断死亡

 

三、服务远端调用

1、restTemplate远端调用

什么是restTemplate:传统情况下在java代码里访问restful服务,一般使用Apache的HttpClient。不过此种方法使用起来太过繁琐。spring提供了一种简单便捷的模板类来进行操作,这就是RestTemplate。

在SpringCloud的项目中,我们使用了自动配置的OAuth2RestTemplate,RestTemplate,但是在使用这些restTemplate的时候,url必须是服务的名称,如果要调用真实的域名或者ip的url,会有错误

  1. @Bean 
  2. public RestTemplate restTemplate(){ //基于此对象实现远端服务调用 
  3. return new RestTemplate(); 
  4. }
  5. restTemplate实现远端调用,此方法是将该类交给spring管理
  1. @Autowired
  2. private RestTemplate restTemplate;  // 实现远端调用服务
  3. restTemplate.getForObject(url, String.class);//参数一调用远端的url,参数二为该方法返回值类型的class对象

2、loadBalancerClient远端调用负载均衡客户端

LoadBalancerClient: 是 SpringCloud 提供的一种负载均衡客户端,Ribbon 负载均衡组件内部也是集成了 LoadBalancerClient 来实现负载均衡。

  1. @Autowired
  2. private LoadBalancerClient loadBalancerClient; //此对象负责从nacos服务中发现和获取服务实例
  3.          //  /ˈbælənsə(r)/ /ˈklaɪənt/
  4. @GetMapping("/controller/doRestEcho02")
  5. public String doRestEcho02() {
  6.     ServiceInstance serviceInstance = loadBalancerClient.choose("sca-provider");
  7.     String url = String.format("http://%s:%s/provider/echo/%s",
  8. serviceInstance.getHost(),
  9. serviceInstance.getPort(), appName); 
  10. //从nacos获取provider服务注册信息
  11.     System.out.println("url  :" + url);
  12.     return restTemplate.getForObject(url, String.class);
  13. }

3、loadBalancer注解简化服务获取过程

在restTemplate交给spring管理的方法上加上@loadBalancer在该步骤请求发送时,底层对该请求拦截,然后底层执行choose等一系列方法,获取host和port进行请求拼接

  1. @Autowired
  2. private RestTemplate loadBalancedRestTemplate;
  3. @GetMapping("/controller/doRestEcho03")
  4. public String oRestEcho03() {
  5.     String serviceId = "sca-provider";
  6.     String url = String.format("http://%s/provider/echo/%s", serviceId, appName);
  7.     return loadBalancedRestTemplate.getForObject(url, String.class);//在该步骤请求发送时,底层对该请求拦截,
  8. // 然后执行方法二的choose等一系列方法,获取host和port进行请求拼接
  9. }

4、OpenFeign实现远程服务调用,实现代码结构的优化

什么是OpenFeign

OpenFeign是一种声明式、模板化的HTTP客户端(仅在Application Client中使用)(称OpenFeign作用:声明式服务调用)。声明式调用是指,就像调用本地方法一样调用远程方法,无需感知操作远程http请求。学习完OpenFeign后可以不使用RestTemplate进行调用。

  • OpenFeign是Spring Cloud的子项目,而Feign是Netflix公司研发的;
  • Feign不支持SpringMVC的注解,另外Feign已不再维护,OpenFeign正常维护;

(1)添加依赖

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

(2)在启动类上添加@EnableFeignClients,作用类似于@MapperScan

(3)service层创建接口

  1. @Autowired
  2. private RemoteProviderService remoteProviderService;
  3. @GetMapping("/controller/doFeignEcho/{msg}")
  4. public String doFeignEcho(@PathVariable String msg) {
  5.     return remoteProviderService.echoMassage(msg);
  6. }

5、Ribbon负载均衡策略

  • Ribbon是Netflix开源的负载均衡组件,可以用来做客户端负载均衡,调用注册中心的服务;
  • OpenFeign与Feign都内置了Ribbon,用于实现负载均衡;

Nacos中的负载均衡底层是通过Ribbon实现,Ribbon中定义了一些负载均衡算法,然后基于这些算法从服务实例中获取一个实例为消费方法提供服务

随机策略  轮询策略  重试策略  最低并发策略  可用过滤策略  响应时间加权重策略  区域权重策略

四、Nacos服务配置中心

配置中心的作用动态管理发布配置,无需重启服务配置经常变化的配置信息,例如连接池,日志、线程池、限流熔断规则等。

(1)添加服务配置依赖

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

(2)将项目application.yml的名字修改为bootstrap.yml(启动优先级最高),并添加配置中心配置

  1. cloud:
  2.      nacos:
  3.        discovery:    #配置服务注册中心地址
  4.           server-addr: 127.0.0.1:8848  
  5.        config:       #配置服务配置中心地址
  6.          server-addr: 127.0.0.1:8848
  7.          file-extension: yml

五、Nacos配置管理模型

1、Namespace:命名空间

Nacos中的命名空间一般用于配置隔离,这种命名空间的定义一般会按照环 境(开发,生 产等环境)进行设计和实现.我们默认创建的配置都存储到了 public命名空间

更换命名空间:

在xml文件config下新增namespace: 命名空间的id

2、Group:分组

当我们在指定命名空间下,按环境或服务做好了配置以后,有时还需要基于 服务做分组配置, 例如,一个服务在不同时间节点(节假日,活动等)切换 不同的配置

更换分组:

在xml文件config下新增group: 分组名称

3、Service/DataId:共享配置

在xml文件config下新增    

  1.  shared-configs[0]:    #该命名空间下共享配置的引用,共享配置不止一个,使用下标依次引用。
  2.    data-id: app-public.yml  #该命名空间下共享配置的 Data id的值
  3.    refresh: true   #支持配置中心共享配置改变,动态刷新该共享配置。 默认fales
  4.   #group: DEFAULT_GROUP  #该命名空间下分组名称。#DEFAULT_GROUP,作为共享配置,创建时默认分组
  5. 名。                    

4、具体配置

 六、实时nacos中的配置参数

写一个Controller试试看,这里代码中需要加上 @RefreshScope 注解,注解作用就是当nacos中的配置文件更新的时候,同步更新到代码中! 

  1. @RestController
  2. @RequestMapping("/TestController")
  3. @RefreshScope
  4. public class TestController {
  5. @Value("${pattern.envSharedValue}")
  6. private String myName;
  7. @GetMapping("/test1")
  8. public String test1() {
  9. return myName;
  10. }
  11. }

Sentinel

作用:分布式系统的流量防卫兵

下载网址:https://github.com/alibaba/Sentinel/releases

知识补充:限流算法

计数器、令牌桶、漏斗算法,滑动窗口算法

Sentinel 默认的限流算法是滑动窗口算法

一、Sentinel环境搭建

 (1)添加依赖

  1. <dependency> 
  2. <groupId>com.alibaba.cloud</groupId>
  3. <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId> 
  4. </dependency>

(2)配置bootstrap.yml

  1. spring:
  2. cloud:
  3. sentinel:
  4. transport:
  5. dashboard: localhost:8180 # 指定sentinel控制台地址。

(3)找到目录执行运行命令

java-Dserver.port=8180-Dcsp.sentinel.dashboard.server=localhost:8180-Dproject.name=sentinel-dashboard -jar sentinel-dashboard-1.8.1.jar

idea启动Sentinel

  1. -Dserver.port=8180
  2. -Dcsp.sentinel.dashboard.server=localhost:8180
  3. -Dproject.name=sentinel-dashboard
  4. -jar
  5. D:\javaXM\sentinel-1.8.1\sentinel-dashboard-1.8.1.jar

二、Sentinel限流

QPS(代表每秒请求次数)单机阈值设置请求次数为1,代表每秒请求不超1次,超过做限流处理,处理方式直接调用失败。

流控模式:

直接,关联和链路

Sentinel的限流效果快速失败,预热,排队等待

链路模式实例:

  1.   /**
  2. @SentinelResource使用此注解描述的方法,在此方法被访问时,会sentinel的簇点链路中显示,此注解中指定的
  3. 名字就是资源名。此注解中的blockHandlerClass用于指定,出现限流异常时的异常处理类,blockHandler属性
  4. 用于指定异常处理类中的方法(此方法的返回类型,参数要与 @SentinelResource注解描述的方法参数一致,可
  5. 以BlockException异常类型参数,而且方法必须是静态.)fallbackClass 用于指定业务异常处理类,fallback
  6. 用于指向业务处理类中的异常处理方法(此方法的返回类型,参数要与@SentinelResource注解描述的方法参
  7. 数一致,可以加Throwable异常类型参数)
  8.    */
  9. @SentinelResource(value="doGetResource",
  10. blockHandlerClass = ResourceBlockHandler.class,
  11. blockHandler = "call",
  12.                   fallback = "call",
  13.                   fallbackClass = ResourceFallbackHandler.class)
  14.     public String doGetResource(){
  15.         return "do get resource";
  16.     }

说明:流控模式为链路模式时,Sentinel Web过滤器默认聚合所有URL的入口为sentinel_spring_web_context,在application.yml添加如下语句来关闭URL PATH聚合,入口名就不为默认

  1. sentinel:
  2.      web-context-unify: false

三、Sentinel熔断降级

作用:对调用链路中不稳定的资源进行熔断降级

熔断策略:

慢调用比例:请求数超过3时,平均响应时间超过200毫秒的有30%,则对请求进行熔断,熔断时长为10秒钟,10秒以后恢复正常。

②异常比例   

③异常数

四、Sentinel 异常处理

系统提供了默认的异常处理机制,如默认处理机制不满足我们需求,我们可以自己进行定义

实现方式:定义方式上可以直接或间接实现BlockExceptionHandler接口,并将对象交给spring管理。

  1. @Slf4j
  2. @Component
  3. public class ServiceBlockExceptionHandler implements BlockExceptionHandler {
  4.     @Override
  5.     public void handle(HttpServletRequest request,
  6.                        HttpServletResponse response,
  7.                        BlockException e) throws Exception {
  8.         //设置响应数据编码
  9.         response.setCharacterEncoding("utf-8");
  10.         //告诉客户端响应数据的类型,以及客户端显示内容的编码
  11.         response.setContentType("text/html;charset=utf-8");
  12.         //向客户端响应一个json格式的字符串
  13.         //String str="{\"status\":429,\"message\":\"访问太频繁了\"}";
  14.         Map<String,Object> map=new HashMap<>();
  15.         map.put("status", 429);
  16.         map.put("message","访问太频繁了");
  17. //将map集合变为json格式的字符串
  18.         String jsonStr=new ObjectMapper().writeValueAsString(map);
  19.         PrintWriter out = response.getWriter();
  20.         out.print(jsonStr);
  21.         out.flush();
  22.         out.close();
  23.     }
  24. }

 五、Sentinel 热点规则 

作用:对经常使用的数据做配置

①写方法

  1. @GetMapping("/sentinel/findById")
  2.         @SentinelResource("resource")
  3.         public String doFindById(@RequestParam("id") Integer id){
  4.             return "resource id is "+id;
  5.         }

②设置限流的热点

资源名:@SentinelResource注解的值

参数索引@SentinelResource注解的方法参数下标,0代表第一个参数,1代表第二个参数。

单机阈值以及统计窗口时长表示在此窗口时间超过阈值就限流。

参数例外项:表示参数为5时阈值为100,其它参数值阈值为1.

六、Sentinel 系统规则

作用:监控服务器的状态,保证服务器正常的运行

Sentinel的常用系统规则

RT,QPS,CPU,线程,Load-linux,unix

七、Sentinel授权规则

作用:根据黑白名单规则,限制请求是否通过,只有请求来源位于不在黑名单或则在白名单内时才可通过;若配置黑名单则请求来源位于黑名单时不通过

基于参数授权规则的实现

定义请求解析器

        用于对请求进行解析(RequestOriginParser接口的实现类),并返回解析结果,sentinel底层在

        拦截到用户请求以后,会对请求数据基于此对象进行解析,判定是否符合黑白名单规则

  1. @Component
  2. public class DefaultRequestOriginParser implements RequestOriginParser {
  3.     @Override
  4.     public String parseOrigin(HttpServletRequest request) {
  5.         String origin = request.getParameter("origin");//这里的参数名会与请求中的参数名一致
  6.         return origin;
  7.     }
  8. }

定义流控规则

资源名:即限流规则的作用对象

流控应用:对应的黑名单/白名单中设置的规则值,多个值用逗号隔开.

执行资源访问

基于请求ip等方式进行黑白名单的规则设计

定义请求解析器

  1. @Component
  2. public class DefaultRequestOriginParser  implements RequestOriginParser {
  3.     //解析请求源数据
  4.     @Override
  5.     public String parseOrigin(HttpServletRequest request) {
  6.         //获取访问请求中的ip地址,基于ip地址进行黑白名单设计(例如在流控应用栏写ip地址)
  7.         String ip= request.getRemoteAddr();
  8.         System.out.println("ip="+ip);
  9.         return ip;
  10.     }//授权规则中的黑白名单的值,来自此方法的返回值
  11. }

定义流控规则

Gateway网关

作用:一个各种服务访问的入口在项目中简化前端的调用逻辑,同时也简化内部服务之间互相调用的复杂度

特点:

(1)性能强劲:是第一代网关Zuul的1.6倍。

(2)依赖Netty与WebFlux(Spring5.0),不是传统的Servlet编程模型 (Spring MVC就是基于此模型实现),学习成本高。

(3)需要Spring Boot 2.0及以上的版本,才支持

一、配置流程

(1)导入依赖:

  1. <dependency>
  2.      <groupId>org.springframework.cloud</groupId>
  3.      <artifactId>spring-cloud-starter-gateway</artifactI
  4. </dependency>

(2)application.yml(假如已有则无须创建)添加相关配置设定uri实现负载均衡

  1. gateway:  #和nacos同一级
  2.     routes: #配置网关路由规则
  3.       - id: route01  #路由id,自己指定一个唯一值即可
  4.            uri: lb://sca-provider
  5. #uri: http://localhost:8082/ #网关帮我们转发的url(url是uri  的子集,uri是统一资源标
  6. 识符)
  7.          predicates: #断言(谓此):匹配请求规则
  8.             - Path=/nacos/provider/echo/** 
  9. - Before=2021-01-30T00:00:00.000+08:00 
  10. - Method=GET
  11. #请求路径定义,此路径对应uri中的资源,**代表传入的参数
  12.         filters: #网关过滤器,用于对谓词中的内容进行判断分析以及处理
  13.            - StripPrefix=1 #转发之前去掉path中第一层路径

Predicate(断言)又称谓词,用于条件判断,只有断言结果都为真,才会真正的执行路由

二、断言的类型

(1)基于Datetime类型的断言工厂,此类型的断言根据时间做判断,主要有三个:

AfterRoutePredicateFactory:判断请求日期是否晚于指定日 期

BeforeRoutePredicateFactory:判断请求日期是否早于指定 日期

BetweenRoutePredicateFactory:判断请求日期是否在指定 时间段内

例:-After=2020-12-31T23:59:59.789+08:00[Asia/Shanghai]:判断请求日期是否晚于指定日期

(2)基于header的断言工厂HeaderRoutePredicateFactory,判断请求Header是否具有给定名称且值与正则表达式匹配

例:-Header=X-Request-Id, \d+

(3)基于Method请求方法的断言工厂,MethodRoutePredicateFactory

接收一个参数,判断请求类型是否跟指定的类型匹配

例:-Method=GET

(4)基于Query请求参数的断言工厂,QueryRoutePredicateFactory 

接收两个参数,请求param和正则表达式, 判断请求参数是否具 有给定名称且值与正则表达式匹配.

例:-Query=pageSize,\d+

三、网关限流

(1)添加依赖

  1. <dependency>
  2.    <groupId>com.alibaba.cloud</groupId>
  3.    <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
  4. </dependency>
  5. <dependency>
  6.    <groupId>com.alibaba.cloud</groupId>
  7. <artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId>
  8. </dependency>

(2)添加Sentinel 控制台地址

  1. sentinel: 
  2. transport: 
  3. dashboard: localhost:8180 #Sentinel 控制台地址 
  4. eager: true #取消Sentinel控制台懒加载,即项目启动即连接

(3)添加sentinel的jvm参数,通过此菜单可以让网关服务在sentinel控制台显示不一样的菜单,代码如下:-Dcsp.sentinel.app.type=1

四、特殊菜单中自定义API维度限流

作用:自定义API分组,是一种更细粒度的限流规则定义,它允许我们利用sentinel提供的API,将请求路径进行分组,然后在组上设置限流规则

第一步:新建API分组

第二步:新建分组流控规则

第三步:定制流控网关返回值

  1. @Configuration
  2. public class GatewayConfig {
  3.     public GatewayConfig(){
  4.         GatewayCallbackManager.setBlockHandler( new BlockRequestHandler() {
  5.             @Override
  6.             public Mono<ServerResponse> handleRequest(
  7. ServerWebExchangeserverWebExchange,
  8. Throwable throwable) {
  9.                 Map<String,Object> map=new HashMap<>();
  10.                 map.put("state",429);
  11.                 map.put("message","two many request");
  12.                 String jsonStr=JSON.toJSONString(map);
  13.                 return ServerResponse.ok().body(Mono.just(jsonStr),String.class);
  14.             }
  15.         });
  16.     }
  17. }

五、定制流控网关返回值

  1. 1、设置拦截条件,返回true放行,返回false表示拦截
  2. /*MVC中的拦截器对象*/
  3. @Slf4j
  4. public class TimeAccessInterceptor implements HandlerInterceptor {
  5. /*此方法在执行目标controller方法之前执行,返回值为true表示放行该请求*/
  6. @Override
  7. public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
  8. LocalTime now= LocalTime.now();//JDK8中的时间对象(推荐使用)
  9. int hour=now.getHour();//获取当前时间对应小时
  10. //System.out.println("hour="+hour);
  11. log.info("hour {}",hour);
  12. /*在规定时间范围内(6点到22点)允许访问,将请求放行*/
  13. if(hour<=6||hour>=22)
  14. throw new RuntimeException("请在6~10点进行访问");
  15. return true;
  16. }
  17. }
  1. 被限流时定制返回错误信息
  2. @Configuration
  3. public class GatewayConfig {
  4.   public GatewayConfig(){
  5.     GatewayCallbackManager.setBlockHandler( new BlockRequestHandler(){
  6.         @Override
  7.        public Mono<ServerResponse> handleRequest(ServerWebExchange serverWebExchange, Throwable throwable) {
  8.                 Map<String,Object> map=new HashMap<>();
  9.                 map.put("state",429);
  10.                 map.put("message","two many request");
  11.                 String jsonStr=JSON.toJSONString(map);
  12.    return ServerResponse.ok().body(Mono.just(jsonStr),String.class);
  13.             }
  14.         });
  15.     }
  16. }

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

闽ICP备14008679号