• [技术干货] 【SpringCloud Alibaba】Nacos服务管理与Feign负载均衡-转载
     一、微服务搭建 1.1 服务提供者与服务消费者 服务提供者    服务的被调用方(即:为其他微服务提供接口的微服务) 服务消费者    服务的调用方(即:调用其他微服务接口的微服务)   就以图(仅供娱乐,无不良影响)为例搭建一个简单的微服务项目,可以看到一下项目结构:  cloud (父级项目,这样为了更好管理项目资源):  basketball (生产者)  common (公共资源) ikun (消费者)  1.2 依赖关系 1、Cloud顶级模块pom文件 (完整) :  <?xml version="1.0" encoding="UTF-8"?> <project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"          xmlns="http://maven.apache.org/POM/4.0.0"          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">       <modelVersion>4.0.0</modelVersion>     <groupId>org.example</groupId>     <artifactId>cloud</artifactId>     <version>1.0-SNAPSHOT</version>     <packaging>pom</packaging>       <!--定义子模块-->     <modules>         <module>ikun</module>         <module>basketball</module>         <module>common</module>     </modules>       <!--依赖版本-->     <properties>         <spring-boot.version>2.4.2</spring-boot.version>         <spring-cloud.version>2020.0.1</spring-cloud.version>         <spring-cloud-alibaba.version>2021.1</spring-cloud-alibaba.version>     </properties>       <dependencies>         <!--nacos服务注册-->         <dependency>             <groupId>com.alibaba.cloud</groupId>             <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>         </dependency>         <!--Orika是java Bean映射框架,可以实现从一个对象递归拷贝数据至另一个对象。-->         <dependency>             <groupId>ma.glasnost.orika</groupId>             <artifactId>orika-core</artifactId>             <version>1.4.6</version>         </dependency>         <!--提供负载均衡的支持-->         <dependency>             <groupId>org.springframework.cloud</groupId>             <artifactId>spring-cloud-loadbalancer</artifactId>         </dependency>         <!--简化 Java 代码的工具库-->         <dependency>             <groupId>org.projectlombok</groupId>             <artifactId>lombok</artifactId>         </dependency>         <!--开启负载均衡-->         <dependency>             <groupId>org.springframework.cloud</groupId>             <artifactId>spring-cloud-starter-openfeign</artifactId>         </dependency>     </dependencies>       <!--声明的依赖版本号可以被子模块引用,但不会自动引入这些依赖-->     <dependencyManagement>         <dependencies>             <dependency>                 <groupId>org.springframework.boot</groupId>                 <artifactId>spring-boot-dependencies</artifactId>                 <version>${spring-boot.version}</version>                 <type>pom</type>                 <scope>import</scope>             </dependency>             <dependency>                 <groupId>org.springframework.cloud</groupId>                 <artifactId>spring-cloud-dependencies</artifactId>                 <version>${spring-cloud.version}</version>                 <type>pom</type>                 <scope>import</scope>             </dependency>             <dependency>                 <groupId>com.alibaba.cloud</groupId>                 <artifactId>spring-cloud-alibaba-dependencies</artifactId>                 <version>${spring-cloud-alibaba.version}</version>                 <type>pom</type>                 <scope>import</scope>             </dependency>         </dependencies>     </dependencyManagement>   </project>          在父级中指定了子模块,子模块需要引用父级模块就能同步使用父级依赖,这样就可以把所有子模块共同依赖同意管理。  2、ikun子模块pom: (basketball如同)  <?xml version="1.0" encoding="UTF-8"?> <project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"          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>com.example</groupId>     <artifactId>ikun</artifactId>     <version>0.0.1-SNAPSHOT</version>       <!--引用父模块依赖-->     <parent>         <groupId>org.example</groupId>         <artifactId>cloud</artifactId>         <version>1.0-SNAPSHOT</version>     </parent>       <dependencies>         <dependency>             <groupId>org.springframework.boot</groupId>             <artifactId>spring-boot-starter-web</artifactId>         </dependency>         <!--引入公共模块-->         <dependency>             <groupId>org.example</groupId>             <artifactId>common</artifactId>             <version>1.0-SNAPSHOT</version>         </dependency>     </dependencies>       <build>         <plugins>             <plugin>                 <groupId>org.apache.maven.plugins</groupId>                 <artifactId>maven-compiler-plugin</artifactId>                 <version>3.8.1</version>                 <configuration>                     <source>1.8</source>                     <target>1.8</target>                     <encoding>UTF-8</encoding>                 </configuration>             </plugin>             <plugin>                 <groupId>org.springframework.boot</groupId>                 <artifactId>spring-boot-maven-plugin</artifactId>                 <version>${spring-boot.version}</version>                 <configuration>                     <mainClass>com.example.ikun.IkunApplication</mainClass>                 </configuration>                 <executions>                     <execution>                         <id>repackage</id>                         <goals>                             <goal>repackage</goal>                         </goals>                     </execution>                 </executions>             </plugin>         </plugins>     </build>   </project>            二、服务注册与负载均衡使用      以上的操作只是建造了一个空壳,我们需要通过一些组件来继续完善微服务体系结构。  2.1 Nacos 实现服务的注册与发现 Nacos下载:Releases · alibaba/nacos · GitHub  1、添加依赖          <dependency>             <groupId>com.alibaba.cloud</groupId>             <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>         </dependency> 2、配置服务提供者,从而服务提供者可以通过 Nacos 的服务注册发现功能将其服务注册到 Nacos server 上。  basketball(服务提供者)配置Nacos server 的地址:  server:   port: 8080 spring:   cloud:     nacos:       server-addr: localhost:8848   application:     name: basketball  通过 Spring Cloud 原生注解 @EnableDiscoveryClient 开启服务注册发现功能:  package com.example.basketball;   import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; import org.springframework.cloud.openfeign.EnableFeignClients;   @SpringBootApplication @EnableDiscoveryClient @EnableFeignClients public class BasketballApplication {       public static void main(String[] args) {         SpringApplication.run(BasketballApplication.class, args);     }   }  3、配置服务消费者,从而服务消费者可以通过 Nacos 的服务注册发现功能从 Nacos server 上获取到它要调用的服务。  ikun(服务消费者)中配置 Nacos server 的地址:  server:   port: 8081 spring:   cloud:     nacos:       server-addr: localhost:8848   application:     name: ikun 通上在启动类上添加 Spring Cloud 原生注解 @EnableDiscoveryClient 开启服务注册发现功能。  2.2 Loadbalancer负载均衡、Feign声明式服务调用 因为两个子模块都需要此组件,所以直接在父模块cloud添加负载均衡依赖:          <!--提供负载均衡的支持-->         <dependency>             <groupId>org.springframework.cloud</groupId>             <artifactId>spring-cloud-loadbalancer</artifactId>         </dependency>           <!--远程服务通信-->         <dependency>             <groupId>org.springframework.cloud</groupId>             <artifactId>spring-cloud-starter-openfeign</artifactId>         </dependency> 在两个子模块启动类添加注释开启服务通信  @EnableFeignClients 2.3 示例综合实现 那么所有配置都已搭建好,接下来编写api接口来实现服务通信与负载均衡:  1、准备一个实体与dto类,因为本次示例并没有连接数据库,仅仅编写一个类用于实例化数据。这里我准备了一个公共模块(common)用来放置公共所需的类  package pojo.dto;   import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor;   /**  * @author 云村小威  * @create 2024-01-06 15:52  */ @Data @NoArgsConstructor @AllArgsConstructor public class IkunDto {       private Long id;     private String account;     private String password;     private Integer age;     private String hobby;   }  消费者 远程调用 生产者 : 需要网络传输,使用DTO同一封装对象 原理与SpringBoot启动类相同  将DTO对象封装到公共DTO模块 为需要的项目引入公共DTO模块         <!--引入公共模块-->         <dependency>             <groupId>org.example</groupId>             <artifactId>common</artifactId>             <version>1.0-SNAPSHOT</version>         </dependency> 注意点:  不需要继承父模块(重复引用问题) 打包方式为jar 不需要添加启动类的编译   VO(View Object):视图对象,用于展示层,它的作用是把某个指定页面(或组件)的所有数据 封装起来。  DTO(Data Transfer Object):数据传输对象,这个概念来源于J2EE的设计模式,原来的目的是 为了EJB的分布式应用提供粗粒度的数据实体,以减少分布式调用的次数,从而提高分布式调用的 性能和降低网络负载,但在这里,我泛指用于展示层与服务层之间的数据传输对象。  DO(Domain Object):领域对象,就是从现实世界中抽象出来的有形或无形的业务实体。 PO(Persistent Object):持久化对象,它跟持久层(通常是关系型数据库)的数据结构形成一 一对应的映射关系,如果持久层是关系型数据库,那么,数据表中的每个字段(或若干个)就对应 PO的一个(或若干个)属性。  2、服务提供者(basketball)  提供接口方法和返回结果  package com.example.basketball.controller;   import pojo.dto.IkunDto; import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.*;   import java.util.Map;   @Slf4j @RestController @RequestMapping("/kun") public class CXKController {         @RequestMapping("/{account}")     public String getByPath(@PathVariable String account) {         log.info("account:" + account);         return "kun : 唱";     }       @RequestMapping("/param")     public String getByParam(@RequestParam("account") String account,                              @RequestParam("password") String password) {         log.info("param:" + account + "\t" + password);         return "kun : 跳";     }       @RequestMapping("/pojo")     public String getByPojo(@RequestBody IkunDto ikunDto) {         log.info("dto:" + ikunDto);         return "kun : rep";     }       @RequestMapping("/more")     public String getByMore(@RequestBody Map<String, Object> map) {         log.info("more:" + map);         return "🏀";     }   }  3、服务消费者(ikun)   I. 创建Server,并使用Feign表示其需要远程对接的服务名称,并使用@RequestMapping表示其映射的 路径   package com.example.ikun.serice;   import pojo.dto.IkunDto; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam;   import java.util.Map;   /**  * 连接生产者 Controller  *  * @author 云村小威  * @create 2024-01-06 15:40  */ @FeignClient("basketball") //连接服务器名称(服务提供者yml设置) @RequestMapping("/kun") public interface FeginKunService {       @RequestMapping("/{account}")     public String getByPath(@PathVariable(value = "account") String account);       @RequestMapping("/param")     public String getByParam(@RequestParam("account") String account,                              @RequestParam("password") String password);       @RequestMapping("/pojo")     public String getByPojo(@RequestBody IkunDto ikunDto);       @RequestMapping("/more")     public String getByMore(@RequestBody Map<String, Object> map);   }   II. 消费者行为接口测试  package com.example.ikun.controller;   import com.example.ikun.serice.FeginKunService; import pojo.dto.IkunDto; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController;   import java.util.HashMap; import java.util.Map;   @RestController public class TestController {       @Autowired     private FeginKunService kunService;       @RequestMapping("/play01")     public String play() {         return kunService.getByPath("姬霓太美");     }       @RequestMapping("/play02")     public String play02() {         return kunService.getByParam("小黑子", "123");     }       @RequestMapping("/play03")     public String play03() {         return kunService.getByPojo(new IkunDto(1L, "纯路人", "123", 5 / 2, "music"));     }       @RequestMapping("/play04")     public String play04() {         Map<String, Object> paramMap = new HashMap<>();         paramMap.put("真爱粉", new IkunDto(2L, "梅丽猫", "321", 5 / 2, "唱、跳、rep、篮球"));         return kunService.getByMore(paramMap);     }   }  III. 先启动Nacos服务、在启动项目  这里注意Nacos默认为集群模式,本次示例并没有连接数据库,所以要修改为单机模式启动  windows指令 : startup.cmd -m standalone     接着输入nacos地址进行登录,账号与密码默认为:nacos    接着就可以看到已注册的服务   最后接口测试:  2.3.1 服务注册与发现测试  Nacos服务注册与发现的流程:  1、服务注册:  在微服务启动时,它会向 Nacos 服务注册自己的信息,包括 IP 地址、端口号、服务名称等。 通过 Nacos 的客户端 SDK 或与之集成的框架(如 Spring Cloud)来完成服务注册。 2、服务发现:  当一个服务需要调用另一个服务时,它会向 Nacos 发送一个服务发现请求,请求特定服务名称的所有可用实例。 Nacos 会返回该服务名称对应的所有服务实例信息,包括 IP 地址和端口号。 调用方可以根据负载均衡策略选择一个实例进行调用,从而实现服务间的通信。 2.3.2 负载均衡测试  为了更好体现负载均衡的作用,这里将basketball与ikun两个模块进行打包运行测试   Tip:  请看上面这张动图:首先我启用了两个生产者(basketball)和一个消费者(ikun),在ikun调用basketball方法时,它是实现了负载均衡的(各自权重都为1)。而我把一个basketball关掉之后,它并立刻没有把服务下线。原因是服务它会时刻会向Nacos发送心跳证明我还活着,如果关掉某个服务,Nacos会给服务10秒的等待时间,10秒内服务没有向Nacos发送心跳就会把他下线不在使用此服务。  ————————————————                              版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。                          原文链接:https://blog.csdn.net/Justw320/article/details/135430167 
  • [技术干货] 如何解决Spring Cloud Gateway微服务网关Body只能读取一次的问题?
    在构建微服务架构时,Spring Cloud Gateway作为一个重要的微服务网关,经常需要在过滤器(Filter)中对POST请求的Body内容进行操作,如日志记录、签名验证和权限验证等。然而,由于Request的Body只能读取一次,如果直接在过滤器中读取而不进行封装,可能导致后续服务无法获取数据。网上搜这个问题的解决方案,大多数文章都是告诉你写一个Filter将Request的Body缓存起来。这种方法确实可以,只不过需要对代码经过充分压力测试,否则很有可能出现如下所示的堆外内存溢出问题。// 堆代码 duidaima.comreactor.netty.ReactorNetty$InternalNettyException: io.netty.util.internal.OutOfDirectMemoryError:failed to allocate实际上,Spring Cloud Gateway已经内置了AdaptCachedBodyGlobalFilter过滤器,它在Exchange中巧妙地缓存了Request的Body,避免了直接读取导致的一系列问题。这种方式更为稳妥,避免了潜在的内存溢出风险。在需要获取Body的地方,我们只需要通过以下方法即可:DataBuffer body = exchange.getAttributeOrDefault("cachedRequestBody", null);String bodyStr = body.toString(StandardCharsets.UTF_8);只不过通过源码可以看出,缓存RequestBody需要路由被标记为需要缓存,也就是this.routesToCache.containsKey(rouceId)方法必须返回true。AdaptCachedBodyGlobalFilter会监听EnableBodyCachingEvent事件,当发布该事件时就将RouteId放入routesToCache中。为了方便使用,我们可以编写一个配置类,在初始化时发布EnableBodyCachingEvent事件,将所有路由都启用缓存功能。@Configuration(proxyBeanMethods = false)@Slf4jpublic class EnableCachedBodyConfiguration { // 堆代码 duidaima.com @Resource private ApplicationEventPublisher publisher; @Resource private GatewayProperties gatewayProperties; @PostConstruct public void init() { gatewayProperties.getRoutes().forEach(routeDefinition -> { // 对 spring cloud gateway 路由配置中的每个路由都启用 AdaptCachedBodyGlobalFilter EnableBodyCachingEvent enableBodyCachingEvent = new EnableBodyCachingEvent(new Object(), routeDefinition.getId()); publisher.publishEvent(enableBodyCachingEvent); }); }}通过这种方式,我们可以更加方便地处理POST请求的Body内容,避免了一些常见的问题。在实际应用中,考虑到稳定性和性能,这种解决方案提供了一种更为可靠的选择。转载自https://www.duidaima.com/Group/Topic/JAVA/18125
  • [技术干货] Nacos有几种负载均衡策略?
    Nacos 作为目前主流的微服务中间件,包含了两个顶级的微服务功能:配置中心和注册中心。1.配置中心扫盲配置中心是一种集中化管理配置的服务,通俗易懂的说就是将本地配置文件“云端化”。这样做的好处有以下几个:集中管理配置信息:配置中心将不同服务的配置信息集中放在一起进行管理,实现了配置信息的集中存储。动态更新配置:配置中心中的配置信息可以通过操作界面或 API 进行动态更新,无需重启服务就可以应用最新的配置信息。配置信息共享:将配置集中在配置中心中,不同的服务实例可以共享同一套配置信息。配置信息安全:配置中心可以对配置信息提供安全管理、权限控制等管理功能。信息追溯:支持配置版本管理、历史记录等管理功能。当然,配置中心不可能有负载均衡的功能,所以略过,咱们直接来看注册中心。2.注册中心扫盲注册中心(Registry)是分布式系统中的一个组件,用于实现服务的注册与发现。注册中心用于管理服务实例的元数据信息,并提供服务发现和路由的功能。在微服务架构中,服务之间经常需要互相调用和通信。注册中心的作用是为服务提供一个集中管理和协调的中心,默认情况下,服务将自己的信息注册到注册中心,其他服务可以通过查询注册中心的信息来发现和调用目标服务。注册中心的核心功能包括以下几个:服务注册:服务提供者在启动时将自己的信息(比如 IP 地址、端口号、服务名称等)注册到注册中心。注册中心维护着一张服务实例的清单。服务发现:服务消费者通过向注册中心查询服务信息,获取可用的服务实例列表。通过注册中心,服务消费者能够找到并连接到目标服务。健康检查:注册中心可以定时检查服务实例的健康状态,并根据服务的状态更新服务实例的可用性。负载均衡:注册中心可以根据负载均衡策略,将请求分发给不同的服务实例,以实现负载均衡和服务高可用。服务路由:在一些高级注册中心中,还可以定义服务路由规则,将请求路由到不同的服务实例,实现更灵活的流量控制和管理。3.注册中心与负载均衡负载均衡严格的来说,并不算是传统注册中心的功能。⼀般来说服务发现的完整流程应该是先从注册中心获取到服务的实例列表,然后再根据自身的需求,来选择其中的部分实例或者按照⼀定的流量分配机制来访问不同的服务提供者,因此注册中心本身⼀般不限定服务消费者的访问策略。例如 Eureka、Zookeeper 包括 Consul,本身都没有去实现可配置及可扩展的负载均衡机制,Eureka 的负载均衡是由 Ribbon 来完成的,而 Consul 则是由 Fabio 做负载均衡。也就是说注册中心和负载均衡,其实完全属于两个不同的东西,注册中心主要提供服务的注册,以及将服务注册的列表交给消费者,至于消费者要使用哪种负载均衡策略?完全可以由自己决定。此时消费者可以通过客户端负载均衡器来实现服务的选择和调用,例如客户端负载均衡器 Ribbon 或 Spring Cloud LoadBalancer。4.客户端与服务端负载均衡客户端负载均衡器通常位于服务的消费者端,主要负责将请求合理地分发给不同的服务提供者。工作原理是客户端在发起请求前,通过负载均衡算法选择一个合适的服务实例进行请求。客户端根据服务实例的健康度、负载状况等指标来决定选择哪个服务实例。常见的客户端负载均衡器有 Ribbon、Feign 等。服务端负载均衡器通常被称为反向代理服务器或负载均衡器,它位于服务的提供者端,接收客户端的请求,并根据一定的负载均衡策略将请求分发给后端的多个服务实例。工作原理是将客户端的请求集中到负载均衡器,由负载均衡器将请求分发给多台服务提供者。常见的服务器端负载均衡器有 Nginx、HAProxy 等。客户端负载均衡 VS 服务端负载均衡客户端负载均衡器的优点是可以实现本地的负载均衡算法,避免了对注册中心的频繁调用,降低了网络开销。它的缺点是每个客户端都需要集成负载均衡器,导致代码冗余和维护复杂性。服务器负载均衡器的优点是可以集中管理请求流量,提供一致的负载均衡策略和配置,对客户端透明。它的缺点是服务器端负载均衡器通常需要独立部署和配置,增加了系统的复杂性和维护成本。并且它很可能成为整个系统的瓶颈(因为客户端需要频繁的调用),所以此时需要考虑其性能和可靠性等问题。5.Nacos和负载均衡然而 Nacos 的注册中心和传统的注册中心不太一样,例如 Eureka、Zookeeper、Consul 等。因为 Nacos 在 0.7.0 之后(包含此版本),它内置了以下两种负载均衡策略:基于权重的负载均衡策略,这个在 Nacos 服务编辑的时候也可以看到其设置:基于第三方 CMDB(地域就近访问)标签的负载均衡策略,这个可以参考官方说明文档:cid:link_0小结注册中心和负载均衡器严格意义上来说是两个东西,但 Nacos 注册中心中,内置了两种负载均衡策略:基于权重和基于 CMDB(低于就近访问)的负载均衡策略。转载自https://www.cnblogs.com/vipstone/p/17800652.html
  • [技术干货] 若依cloud-plus框架使用心得(狮子大佬写的那个)附centos7.9下minio安装教程
    最近一直想更深入的去学习使用springcloud,在网上搜了下很多大佬写的框架,然后就各种搜,看那个适合自己。虽然明知道贪多嚼不烂,但是还是想找一个技术栈比较新,比较全的框架来学习 。然后就先遇到了若依。讲真,虽然项目里面可能有些用不到。但是是真的全面。结果用了几天无意就发现了plus版本也就是狮子大佬写的那个,那个好像看大佬的对比,支持的更多,更灵活。先说说几点感受吧 。1.之前自己使用的是fastdfs,测试 生产环境部署的时候都是非常痛苦的,步骤非常之多,ruoyi-cloud-plus使用的是minio,好不好用我先不说,因为我只是自己在测试环境学习,体会不到性能的差距,但是单纯就安装部署方面来讲,2个字完爆。。。其次文档方面更是没得比 。起码我在华为云服务器上安装minio一次成功。下面插播一下安装过程 哈哈 。参考网上的链接,但是也有些链接是不能一次成功的,(别问我怎么知道的,我朋友发的链接就是让我安装出问题了)其实也不是一次出问题了,这个暂时不表,放在后面说。一、下载安装文件1、在home目录下创建minio文件夹mkdir /home/minio2、进入/home/minio 文件夹cd /home/minio3、下载文件wget 链接二、创建数据文件夹mkdir /home/minio/data三、创建日志文件touch /home/minio/log/minio.log四、启动# 赋予权限chmod 777 minio# 前台启动命令./minio server /home/minio/data# 后台启动命令nohup ./minio server --address :9000 --console-address :9010 /opt/soft/minio/data > /opt/soft/minio/log/minio.log 2>&1 &注意:按照如上启动命令启动时,访问控制台地址为ip+9010端口,且注意开放防火墙,文件服务器地址就还是9000端口上面这个地方也是真的在第一篇链接中没仔细看, 然后再加上官方文档也说的端口是9000 ,然后 我的minio也正常启动了 但是就是不能进入控制台,防火墙,服务,什么的都检查了都没办法进入,在我后来看到的教程里才看到这里是分为2个端口的,9010才是控制台端口,所以去安全策略里面添加9010端口就可以访问了。如果想要修改超管账户名和密码1、打开 /etc/profile 文件vi /etc/profile2、在文件的最末尾加上以下信息(启动的时候看提示,新版本需要用MINIO_ROOT_USER和MINIO_ROOT_PASSWORD,旧版需要用MINIO_ACCESS_KEY和MINIO_SECRET_KEY)。按 i 键后,在文档末尾输入(1)新版:export MINIO_ROOT_USER=minioadminexport MINIO_ROOT_PASSWORD=admin@111(2)旧版export MINIO_ACCESS_KEY=minioadminexport MINIO_SECRET_KEY=admin@111重点就在这里啊 , 别人发的链接只有新版的,然后我就直接使用了 但是发现并不行,后来发现用的是旧版才可以 3、保存退出(1)编辑完成后,按ctrl+c键结束编辑(2)输入:wq保存退出4、然后 刷新,重载环境变量source /etc/profile安装告一段落。继续说使用感受2.对于代码生成器的感受。可能是我一直没关注,我用了他这个代码生成器,(也不知道是若依大佬,还是狮子大佬,反正都是大佬)大佬写的代码生成器我只有2个字全面。先放图基本上对于简单业务来说是可以不用写代码的,简单的调整下样式就可以,真的是非常全面。3.nacos作为配置中心,真的感觉还是挺方便。当然刚开始也是各种踩坑项目里面改了 不知道怎么就没生效,后来才知道需要再nacos里面改,而且这个里面配置太多了 ,还是在学习中。对于配置统一管理也挺好的 。至于其他技术还是在摸索中,后续有心得了继续分享。
  • [技术干货] Nacos Auth权限
    Nacos Auth是Nacos提供的身份验证和授权模块。Nacos是一个开源的解决方案,用于动态服务发现、配置管理和服务管理。Nacos Auth可以通过启用身份验证和授权机制,确保对Nacos控制台和API的访问安全。它提供了细粒度的访问控制,以保护Nacos资源免受未经授权的访问。借助Nacos Auth,您可以配置不同的身份验证方法,例如用户名和密码认证或基于令牌的身份验证,用于对访问Nacos控制台或API的用户进行身份验证。它还支持基于角色的访问控制(RBAC),您可以将角色分配给用户,并为不同的资源定义权限。通过实施Nacos Auth,您可以确保只有经过身份验证和授权的用户可以访问您的Nacos基础架构。这有助于提高Nacos部署的安全性,并保护敏感配置数据和服务信息的安全。Nacos Auth提供以下参数来配置身份验证和授权:auth.enabled:启用或禁用Nacos Auth功能。设置为true启用,设置为false禁用。auth.identification:用于身份认证的方法。可以是password(用户名和密码认证)或token(令牌认证)。auth.password.encrypt:设置是否对密码进行加密。设置为true进行加密,设置为false不进行加密。默认为true。auth.token.ttl:令牌的过期时间(毫秒)。可以根据需要设置合适的值,默认为60000毫秒(1分钟)。auth.token.secretKey:用于生成和验证令牌的密钥。可以是任意字符串,用于加密和解密令牌。auth.token.ignoreUrls:需要忽略令牌验证的URL列表。可以配置某些URL不受令牌验证的限制。auth.rbac.enabled:启用或禁用基于角色的访问控制。设置为true启用,设置为false禁用。auth.rbac.rolePerms:定义角色和权限的映射。可以为每个角色指定一组权限。这些参数可以根据您的需求进行配置,以实现适合您的身份验证和授权策略。
  • [技术干货] Nacos Gateway参数详解
    Nacos Gateway 是基于 Nacos 服务发现和配置中心的一种开源服务网关解决方案。它提供了一种简单而强大的方式来管理和路由服务间的请求流量,同时支持动态的路由配置和鉴权,具有高度的可扩展性和灵活性。在 Nacos Gateway 中,有一些常用的参数可用于配置和定制网关的行为。下面是一些常见的参数及其详细说明:routeRules:参数类型:字符串(JSON 格式)参数说明:用于配置路由规则,指定请求的转发目标。可以配置多个路由规则。示例:[ { "predicate": { "path": "/api", "method": "GET" }, "filters": [ { "name": "StripPrefix", "args": { "parts": 1 } } ], "uri": "http://backend-service" }, { "predicate": { "path": "/api", "method": "POST" }, "filters": [ { "name": "AddRequestHeader", "args": { "name": "Content-Type", "value": "application/json" } } ], "uri": "http://backend-service" } ]说明:上述示例中设置了两个路由规则。第一个规则是将 GET 方式请求 /api 路径的请求转发到名为 http://backend-service 的服务,并剥离路径中的前缀。第二个规则是将 POST 方式请求 /api 路径的请求转发到同样的服务,并在转发请求时添加头部信息。redirectRules:参数类型:字符串(JSON 格式)参数说明:用于配置重定向规则,指定请求的重定向路径。可以配置多个重定向规则。示例:[ { "predicate": { "path": "/old", "method": "GET" }, "status": 302, "uri": "/new" } ]说明:上述示例中设置了一个重定向规则,将 GET 方式请求 /old 路径的请求重定向到 /new 路径,并返回状态码 302。globalFilters:参数类型:字符串(JSON 格式)参数说明:用于配置全局过滤器,对所有请求都生效的过滤器。可以配置多个全局过滤器。示例:[ { "name": "RateLimiter", "args": { "burstCapacity": 10, "replenishRate": 5 } } ]说明:上述示例中设置了一个全局过滤器,使用令牌桶算法进行限流。每秒钟允许发出 5 个请求,令牌桶最大容量为 10 个。consumerCluster:参数类型:字符串参数说明:用于指定服务消费者的集群名称,可以接收多个集群名称,多个集群名称之间用逗号分隔。示例:consumerCluster: cluster1,cluster2以上是一些常见的 Nacos Gateway 参数的详细说明,不同网关实现可能会有更多的参数选项和配置方式。具体可以根据实际场景和需求进行配置和定制。
  • [技术干货] @Fegin用法介绍 示例
    Feign是一个声明式的、基于接口的HTTP客户端,方便了开发者使用RESTful Web Services。它可以将Java接口转换为Web服务客户端,并自动与Spring Cloud服务注册中心集成,从而使得客户端可以通过服务名访问对应的远程服务。下面是@Feign用法的示例:添加Feign相关依赖包 xml复制代码<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency> 创建一个接口定义服务 java复制代码@FeignClient(name = "service-provider") public interface UserFeignClient { @GetMapping("/user/{id}") User getUserById(@PathVariable("id") Long id); @PostMapping("/user") User addUser(@RequestBody User user); } 其中,@FeignClient注解用于指定服务提供方的服务名,而getUserById和addUser方法则定义了两个接口,分别用于获取用户和添加用户。通过@Autowired方式注入UserFeignClient接口 java复制代码@RestController public class UserController { @Autowired private UserFeignClient userFeignClient; @GetMapping("/user/{id}") public User getUserById(@PathVariable Long id) { return userFeignClient.getUserById(id); } @PostMapping("/user") public User addUser(@RequestBody User user) { return userFeignClient.addUser(user); } } 启动服务并测试API在启动服务之前,确保已经启动服务提供方("service-provider"),并且已经注册到了服务注册中心。然后,通过访问上述接口,即可实现通过服务名调用远程服务。总之,@Feign是一种声明式的、基于接口的HTTP客户端,可以方便地使用RESTful Web Services。在使用该注解时,需要定义一个接口并指定服务提供方的服务名,然后通过@Autowired方式将接口注入到其他类中,并实现对应的方法即可进行调用。
  • [技术干货] OpenFegin+hystrix实现远程HTTP服务调用、服务降级
     简介 OpenFeign 是 Spring Cloud 家族的一个成员, 它最核心的作用是为 HTTP 形式的 Rest API 提供了非常简洁高效的 RPC 调用方式。支持Hystrix 、Ribbon和SpringMVC 注解。  Feign和OpenFeign的区别? 1、Feign:  Feign是Netflix公司(第一代SpringCloud)研发的一个轻量级RESTful的伪HTTP服务客户端。  Feign内置了Ribbon逻辑,通过负载均衡算法可以从注册中心中寻找服务。  2、OpenFeign:  OpenFeign是SpringCloud自己研发的,在Feign的基础上做了增强。  OpenFeign除了原有Ribbon逻辑外,还支持了Hystrix和Spring MVC注解。  一、服务端Provider 注意: 当前是springboot整合OpenFegin 服务端没有配置注册中心, 如分布式 微服务请自行配置  服务端Controller层 @CrossOrigin @RestController @RequestMapping("/customer/information") public class CrmCustomersController {         @Autowired     private CrmCustomersService crmCustomersService;       /**      * 服务数据      */     @RequestMapping(value = "customerlist", method = {RequestMethod.GET,RequestMethod.POST})     public PmpResult  queryCustomerList (@RequestParam(value="pageNum",defaultValue="1") int pageNum, @RequestParam(value="pageSize",defaultValue="10") int pageSize,String customersno, String customersname,String daogouid){         try {               PageInfo<CustomerInformationVo> pageInfo = crmCustomersService.queryCustomerList(pageNum,pageSize,customersno,customersname,daogouid);               logger.info("查询成功");             return PmpResult.success(pageInfo);         }catch (Exception e) {             logger.error(e.getMessage(), e);             String errorMessage = "查询异常";             if (isDev){                 errorMessage = e.getMessage();             }             return PmpResult.paramError(errorMessage);         }       }    }  二、消费端Consumer 消费端~例图  Pom.xml <!-- openFeing --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency>  Api @FeignClient注解  @FeignClient参数:  name: 指定FeignClient的(服务)名称,在Eureka/Nacos/其他注册中心 中对应的服务名称。  url: 指定远程调用地址。  configuration: 指定配置类,可以自定义FeignClient的配置。  fallback: 指定降级类,在服务调用失败时返回降级类中的内容。  fallbackFactory: 指定降级工厂类,在服务调用失败时返回降级工厂类中的内容。  decode404: 指定404响应是否解码,默认为true。  path: 指定服务请求的基础路径。  contextId: 当一个服务有多个接口时,我们又不想把所有接口都写到一个类中是时候就用到了 contextId为当前类设置一个唯一ID。不然就回报如下错误 。  [扩展]@FeignClient注解 通过属性 contextId 解决名称重复无法启动的问题 错误如下:  Description: The bean 'optimization-user.FeignClientSpecification', defined in null, could not be registered. A bean with that name has already been defined in null and overriding is disabled. Action: Consider renaming one of the beans or enabling overriding by setting spring.main.allow-bean-definition-overriding=true 导致 名称重复问题 复现:  /* *Consumer1 */ @FeignClient(name = "xj-user") public interface UserRemoteConsumer1 {     @GetMapping("/user1/get")     public User getUser(@RequestParam("id") int id); }   /* *Consumer2 */ @FeignClient(name = "xj-user") public interface UserRemoteConsumer2 {     @GetMapping("/user2/get")     public User getUser(@RequestParam("id") int id); }  这种情况下启动就会报错了,因Bean的名称冲突。  原因:由于name重复,而又不允许BeanDefinition重复,所以导致在进行注册时报错。  解决方案一:  增加下面的配置,作用允许出现beanName一样的BeanDefinition。   spring.main.allow-bean-definition-overriding=true 解释:  spring.main.allow-bean-definition-overriding=true应用程序的一个配置属性,它允许在应用程序上下文中覆盖bean定义。如果设置为true,则可以在应用程序上下文中定义多个具有相同名称的bean,后定义的bean将覆盖先前定义的bean。但是,这可能会导致不可预测的行为和错误,因此应该谨慎使用。  解决方案二(推荐):  每个FeignClient手动指定不同的contextId,这样就不会冲突了。  @FeignClient添加contextId属性  /* *Consumer1 */ @FeignClient(name = "xj-user" contextId = UserRemoteConsumer1) public interface UserRemoteConsumer1 {     @GetMapping("/user1/get")     public User getUser(@RequestParam("id") int id); }   /* *Consumer2 */ @FeignClient(name = "xj-user" contextId = UserRemoteConsumer2) public interface UserRemoteConsumer2 {     @GetMapping("/user2/get")     public User getUser(@RequestParam("id") int id); }  总结:想创建多个具有相同名称或url的外部客户端,以便它们指向同一台服务器,但每个服务器都有不同的自定义配置,那么可以使用@FeignClient的contextId属性,以避免这些配置bean的名称冲突。  @RequestMapping(value = "/customer/information/customerlist", method = RequestMethod.GET)是要调的接口名  openFegin调用如下:  import com.alibaba.fastjson.JSONObject; import com.lt.crm.service.fallback.TransactionFallBackFactory; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.stereotype.Repository; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam;     @Repository @FeignClient(name = "service-client", url = "http://10.1.8.22:9001", contextId = "ConsumerService", fallbackFactory = TransactionFallBackFactory.class) public interface ConsumerService {       @RequestMapping(value = "/customer/information/customerlist", method = RequestMethod.GET)     JSONObject queryCustomerList(@RequestParam(value = "pageNum") final int pageNum, @RequestParam(value = "pageSize") final int pageSize);     }  Hystrix 服务降级处理 说明:  Hystrix配合OpenFeign进行降级,可以对应接口中定义的远程调用单独进行降级操作。  直白的说: 远程调用失败,我们添加一个替代方案,我们知道OpenFegin是以接口的形式来声明远程调用,只要是远程调用失效超时,就执行替代方案。创建一个实现类,对原有的接口方法进行替代方案实现。  使用@Component注解 交给String管理 注入IOC容器  对Api接口进行进行实现、重写调用的Api 远程接口 代码如下:  @Component 注解是 Spring 框架中的注解,用于将一个类标记为 Spring 容器中的一个组件,让 Spring 自动扫描并管理这个组件的生命周期和依赖注入。  实现implements FallbackFactory原因:用于在使用 Feign 进行服务调用时,定义一个 FallbackFactory<> 来处理服务调用失败的情况的<ConsumerService>。[ import feign.hystrix.FallbackFactory; ]  以下码为例:服务降级内容我只是返回一段话,根据自己业务定性, 可判断参数是否为空等 返回具体错误信息。  import com.alibaba.fastjson.JSONObject; import com.lt.crm.service.api.ConsumerService; import feign.hystrix.FallbackFactory; import org.apache.commons.lang.exception.ExceptionUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component;     @Component public class TransactionFallBackFactory implements FallbackFactory<ConsumerService>  {       private Logger logger = LoggerFactory.getLogger(getClass());     @Override     public ConsumerService create(Throwable throwable) {           return new ConsumerService() {             @Override             public JSONObject queryCustomerList(int pageNum, int pageSize) {                 logger.error("TransactionMsgWaitingConfirm Error : {}" , ExceptionUtils.getFullStackTrace(throwable));                 String  fallbackMessage = "被Hystrix熔断,已作降级处理!";                 JSONObject jsonObject = new JSONObject();                 jsonObject.put("fallbackMessage",fallbackMessage);                 return jsonObject;             }         };     }       }  消费端Controller层 @Autowired  private ConsumerService consumerService;  在消费端Controller注入Api调用 ConsumerService    import com.alibaba.fastjson.JSONObject; import com.lt.crm.common.PmpResult; import com.lt.crm.service.api.ConsumerService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseBody;     @Controller @RequestMapping("/customer/information") @Api(tags = "跨服务调用数据") public class ConsumerController {     /**      * 日志      */     private final static Logger logger = (Logger) LoggerFactory.getLogger(ConsumerController.class);       @Autowired     private ConsumerService consumerService;       @ResponseBody     @ApiOperation(value = "公共开放的端口")     @RequestMapping(value = "customerlist", method = RequestMethod.GET)     public PmpResult queryCustomerList(@RequestParam(value = "pageNum", defaultValue = "1") int pageNum, @RequestParam(value = "pageSize", defaultValue = "10") int pageSize) {           try {              // String类型 转换成json 接收             JSONObject GetJsonObject = consumerService.queryCustomerList(pageNum, pageSize);                if (null != GetJsonObject) {                 logger.info("调用数据成功");                 return PmpResult.success("数据服务", GetJsonObject);             }           } catch (Exception e) {             e.printStackTrace();             return PmpResult.serviceError("服务异常");         }         return null;     }     }  application.properties配置超时时间 说明: OpenFegin 默认1ms 未响应会抛出异常 , 往往在调用远程接口的时候 、业务逻辑复杂、 没等业务处理完毕就抛出异常 、我们可以针对这类问题 可以配置延长时长。  配置 Feign 超时问题  配置hystrix 超时时间  ######################################openFegin###################################### # 默认开启 feign.httpclient.enabled=true # 默认关闭 feign.okhttp.enabled=false # 默认关闭 feign.hystrix.enabled=true # 默认关闭 feign.sentinel.enabled=false   # default context 连接超时时间 5000ms = 5秒 feign.client.config.default.connectTimeout = 5000 # default context 读超时时间 feign.client.config.default.readTimeout = 5000   ######################################Hystrix Config###################################### #开启hystrix超时管理 hystrix.command.default.execution.timeout.enabled=true #hystrix超时时间 hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=60000   #开启ribbon超时管理 ribbon.http.client.enabled=false #请求超时时间 ribbon.ReadTimeout=20000 #连接超时时间 ribbon.ConnectTimeout=20000 ribbon.MaxAutoRetries=0 ribbon.MaxAutoRetriesNextServer=1 ribbon.OkToRetryOnAllOperations=false  启动类: 启动类上使用注解 @EnableFeignClients 开启 openFeign 功能。  /**  * 微服务应用服务启动类  * 1、(@EnableDiscoveryClient)注解为链接微服务注册中心用,如实际环境中使用注册中心,请取消注释部分,  *     与配置文件中相关注册中心配置信息结合使用。  * @author xj  *  */ @EnableDiscoveryClient @EnableFeignClients(clients= {ConsumerService.class} )//加入@EnableFeignClients注解 开启Feign远程服务调用,使Feign的bean可以被注入 @ServletComponentScan @SpringBootApplication(scanBasePackages = {"com.lt.crm"}) @EnableCaching public class OpenFeignApplication {     public static void main(String[] args) {         SpringApplication.run(OpenFeignApplication.class, args);} }  测试 熔断降级 启动消费端Consumer,并没有启动服务端Provider ,过了超时时间,此时执行了服务降级,这样做避免了在微服务中服务雪崩的灾难。  后台也捕获了error :  连接被拒绝:连接执行GET: Connection refused: connect executing GET http://10.1.8.22:9001/customer/information/customerlist?pageNum=1&pageSize=10  2023-03-17 16:56:52.399 ERROR 20928 --- [ervice-client-1] c.l.c.s.f.TransactionFallBackFactory     : TransactionMsgWaitingConfirm Error : feign.RetryableException: Connection refused: connect executing GET http://10.1.8.22:9001/customer/information/customerlist?pageNum=1&pageSize=10     at feign.FeignException.errorExecuting(FeignException.java:84)     at feign.SynchronousMethodHandler.executeAndDecode(SynchronousMethodHandler.java:113)     at feign.SynchronousMethodHandler.invoke(SynchronousMethodHandler.java:78)     at feign.hystrix.HystrixInvocationHandler$1.run(HystrixInvocationHandler.java:106)     at com.netflix.hystrix.HystrixCommand$2.call(HystrixCommand.java:302)     at com.netflix.hystrix.HystrixCommand$2.call(HystrixCommand.java:298)     at rx.internal.operators.OnSubscribeDefer.call(OnSubscribeDefer.java:46)     at rx.internal.operators.OnSubscribeDefer.call(OnSubscribeDefer.java:35)     at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:48)     at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:30)     at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:48)     at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:30)     at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:48)     at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:30)     at rx.Observable.unsafeSubscribe(Observable.java:10327)     at rx.internal.operators.OnSubscribeDefer.call(OnSubscribeDefer.java:51)     at rx.internal.operators.OnSubscribeDefer.call(OnSubscribeDefer.java:35)     at rx.Observable.unsafeSubscribe(Observable.java:10327)     at rx.internal.operators.OnSubscribeDoOnEach.call(OnSubscribeDoOnEach.java:41)     at rx.internal.operators.OnSubscribeDoOnEach.call(OnSubscribeDoOnEach.java:30)     at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:48)     at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:30)     at rx.Observable.unsafeSubscribe(Observable.java:10327)     at rx.internal.operators.OperatorSubscribeOn$SubscribeOnSubscriber.call(OperatorSubscribeOn.java:100)     at com.netflix.hystrix.strategy.concurrency.HystrixContexSchedulerAction$1.call(HystrixContexSchedulerAction.java:56)     at com.netflix.hystrix.strategy.concurrency.HystrixContexSchedulerAction$1.call(HystrixContexSchedulerAction.java:47)     at com.netflix.hystrix.strategy.concurrency.HystrixContexSchedulerAction.call(HystrixContexSchedulerAction.java:69)     at rx.internal.schedulers.ScheduledAction.run(ScheduledAction.java:55)     at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)     at java.util.concurrent.FutureTask.run(FutureTask.java:266)     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)     at java.lang.Thread.run(Thread.java:748)  现在启动服务端再次调用,已经通过消费者9004端口 拿到了服务端9001提供的数据。  三、openFeign传参方式 简介:   在接口当中传参的方式有很多,但是在 openFeig中的 传参是 有一定规则的,详细如下。  传递JSON数据 服务端Provider接口中JSON传参方法如下:  @RestController @RequestMapping("/openfeign/provider") public class OpenFeignProviderController {     @PostMapping("/order1")     public Order createOrder1(@RequestBody Order order){         return order;     } } 注意:在Spring Boot 中通过@RequestBody标识入参。  消费端Consumer在openFeign接口传参如下:  @FeignClient(value = "openFeign-provider")//服务名 public interface OpenFeignService {     /**      * 参数默认是@RequestBody标注的,这里的@RequestBody可以不填      * 方法名称任意      */     @RequestMapping("/openfeign/provider/order1", method = RequestMethod.GET)     Order createOrder1(@RequestBody Order Order); } 注意: 我用的是@RequestMapping注解 这是一个组合注解,里面包含@RequestBody 可以不填。  POJO表单传参 服务端Provider接口传参方法如下:  @RestController @RequestMapping("/openfeign/provider") public class OpenFeignProviderController {     @PostMapping("/order2")     public Order createOrder2(Order order){         return order;     } } 注意: 参数使用POJO对象接收。  消费端Consumer在openFeign接口传参如下:  @FeignClient(value = "openFeign-provider") public interface OpenFeignService {     /**      * 参数默认是@RequestBody标注的,如果通过POJO表单传参的,使用@SpringQueryMap标注      */     @RequestMapping("/customer/information/order2", method = RequestMethod.GET)     Order createOrder2(@SpringQueryMap Order order); } 注意: openFeign提供了一个注解@SpringQueryMap解决POJO表单传参,这也是官方文档明确给出了解决方案。  URL中携带参数 服务端Provider接口传参方法如下:  @RestController @RequestMapping("/openfeign/provider") public class OpenFeignProviderController {       @GetMapping("/test/{id}")     public String test(@PathVariable("id")Integer id){         return "accept one msg id="+id; } 注意: 此种方式针对restful方式中的GET请求方式。  消费端Consumer在openFeign接口传参如下:  @FeignClient(value = "openFeign-provider") public interface OpenFeignService {       @GetMapping("/openfeign/provider/test/{id}")     String get(@PathVariable("id")Integer id); } 注意: 使用注解@PathVariable接收url中的占位符。  四、开启日志增强 说明: openFeign 虽提供了日志增强功能,但默认是不显示任何日志的,开发者在调试阶段可以自己配置日志的级别。  级别如下:  NONE:默认的,不显示任何日志;  BASIC:仅记录请求方法、URL、响应状态码及执行时间;  HEADERS:除了BASIC中定义的信息之外,还有请求和响应的头信息;  FULL:除了HEADERS中定义的信息之外,还有请求和响应的正文及元数据。  配置日志级别 自定义一个配置类,在其中设置日志级别如下:    import feign.Logger; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration;   @Configuration public class OpenFeginConfig {     /**      * 日志级别定义      * @return      */     @Bean     Logger.Level OpenFeignLoggerLevel(){         return Logger.Level.FULL;     } }  注意细节:Logger导包是feign包。  YAML配置 logging:   level:     com.lt.crm.service.api: debug 注意:此处 com.lt.crm.service.api 是 openFeign 接口所在的包名,可以根据自己项目路径配置一个特定的openFeign接口。  注解@FeignClient中配置 configuration 说明:@FeignClient配置里 configuration = OpenFeginConfig.class  @Repository @FeignClient(name = "service-client", url = "http://10.1.8.22:9001", contextId = "ConsumerService", fallbackFactory = TransactionFallBackFactory.class, configuration = OpenFeginConfig.class) public interface ConsumerService {       @RequestMapping(value = "/customer/information/customerlist", method = RequestMethod.GET)     JSONObject queryCustomerList(@RequestParam(value = "pageNum") final int pageNum, @RequestParam(value = "pageSize") final int pageSize);     } 查看打印日志示意图  五、Gzip压缩数据(全局压缩~接口与浏览器响应压缩) 全局压缩相关配置 ######################################接口与浏览器响应压缩###################################### #全局压缩(接口与浏览器响应压缩) server:   compression:     #开启Gzip压缩     enabled: true     #配置min-response-size 压缩数据大小的最小阈值,默认2048     min-response-size: 1 #设置1kb以上开始压缩     #配置mime-types 压缩支持的MIME  TYPE     mime-types:     - image/png     - image/jpeg     - image/jpg     - text/html     - text/xml     - application/xml     - application/json  min-response-size 和 mime-types 含默认值,可以不手动指定,如有其他需要可按需指定  测试压缩 未开启压缩前 请求数据大小为526KB  开启压缩 请求数据大小为82KB  点击查看请求头信息  Gzip压缩算法 Gzip是一种数据格式,采用deflate算法压缩数据;当GZIP算法压缩到一个纯文本数据时,效果会非常显著。  数据经过压缩后实际上降低了网络传输的字节数,最明显的好处就是可以加快网页加载的速度。网页加载速度加快,除了节省流量,改善用户的浏览体验外。  Gzip压缩传输原理图如下:  1、客户端向服务器请求头中带有:Accept-Encoding:gzip,deflate 字段,向服务器表示,客户端支持的压缩格式(gzip或者deflate),如果不发送该消息头,服务器是不会压缩的。  2、服务端在收到请求之后,如果发现请求头中含有 Accept-Encoding 字段,并且支持该类型的压缩,就对响应报文压缩之后返回给客户端,并且携带 Content-Encoding:gzip 消息头,表示响应报文是根据该格式压缩过的。  3、客户端接收到响应之后,先判断是否有 Content-Encoding 消息头,如果有,按该格式解压报文。否则按正常报文处理。  六、OpenFeign开启Gzip压缩数据(局部压缩~微服务之间利用Feign请求及响应压缩) 全局压缩相关配置 ######################################openFegin Gzip###################################### #局部压缩(微服务之间利用feign请求及响应压缩) feign:   compression:     request:       enabled: true    # 开启压缩       min-request-size: 1  # 开启压缩的阈值,单位字节,默认2048,即是2k,此处为演示效果设置成1字节       mime-types: text/xml,application/xml,application/json     response:       enabled: true #响应压缩 注意:openFeign支持的Gzip仅仅是在openFeign接口的请求和响应,即openFeign消费者调用服务提供者的接口。  开启Gzip压缩后日志信息 查看Gzip压缩开启后的打印日志  日志中包含 content-encoding: gzip 表示压缩成功  开启Gzip压缩后日志信息 查看Gzip压缩关闭后的打印日志  日志中未出现 content-encoding: gzip 表示未被压缩 并且可以清楚看到时间为 1231ms  七、如何OpenFegin 替换默认的httpclient ? 前言:  1、OpenFeign在默认情况下使用的是JDK原生的URLConnection发送HTTP请求,没有连接池,但是对每个地址会保持一个长连接,即利用HTTP的persistence connection。  2、默认的http客户端是 javax.net.ssl.HttpsURLConnection,详细信息查看feign-core:feign.Client,该http客户端不支持添加拦截器和连接池。所以我们需要添加第三方http客户端。  在生产环境中,通常也不会使用默认的httpclient,两种选择如下:  使用ApacheHttpClient  使用OkHttp  声明: 我使用的是 OkHttp 如果使用 ApacheHttpClient 思路是基本一致 。  pom.xml依赖如下         <!-- 使用 Apache HttpClient 替换 Feign原生httpclient-->         <dependency>             <groupId>org.apache.httpcomponents</groupId>             <artifactId>httpclient</artifactId>         </dependency>         <!-- 使用 Okhttp 替换 Feign原生httpclient-->         <dependency>             <groupId>io.github.openfeign</groupId>             <artifactId>feign-okhttp</artifactId>             <version>10.1.0</version>         </dependency> application.properties 启用 OkHttp 配置 # 默认开启 feign.httpclient.enabled=false # 默认关闭 feign.okhttp.enabled=true 关闭默认的httpclient 开启okhttp  配置OkHttp响应拦截器 前言:  微服务之间使用OpenFeign,由于业务得需求有时候我们需要在请求或者响应的时候做一些额外的操作。比如请求的时候添加请求头,响应时候判断token是否过期等等。这时候拦截器就派上用场了! import lombok.extern.slf4j.Slf4j; import okhttp3.Interceptor; import okhttp3.MediaType; import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.Response; import okhttp3.ResponseBody; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import java.io.IOException;   @Slf4j @Configuration public class FeignOkHttpClientConfig {         @Bean     public OkHttpClient.Builder okHttpClientBuilder() {         return new OkHttpClient.Builder().addInterceptor(new FeignOkHttpClientResponseInterceptor());     }         /**      * okHttp响应拦截器      */     public static class FeignOkHttpClientResponseInterceptor implements Interceptor {             @Override         public Response intercept(Chain chain) throws IOException {               Request originalRequest = chain.request();             Response response = chain.proceed(originalRequest);               MediaType mediaType = response.body().contentType();             String content = response.body().string();                        //解析content,做你想做的事情!!!             System.out.print("拦截器"+content+"往哪跑?");               //生成新的response返回,网络请求的response如果取出之后,直接返回将会抛出异常             return response.newBuilder()                     .body(ResponseBody.create(mediaType, content))                     .build();         }     }       }  Feign使用okhttpclient时报错:java.lang.IllegalStateException: original request is required 问题复现:      2023-03-27 16:43:23.754 ERROR 21120 --- [ervice-client-1] c.l.c.s.f.TransactionFallBackFactory     : TransactionMsgWaitingConfirm Error : java.lang.IllegalStateException: original request is required     at feign.Util.checkState(Util.java:127)     at feign.Response.<init>(Response.java:48)     at feign.Response.<init>(Response.java:38)     at feign.Response$Builder.build(Response.java:133)     at feign.okhttp.OkHttpClient.toFeignResponse(OkHttpClient.java:99)     at feign.okhttp.OkHttpClient.execute(OkHttpClient.java:161) 具体描述:  可以看到状态200 请求成功 ,并且我设置的超时是5秒,而我查看后台日志请求只用了130ms说明没有超时,为什么一直走熔断? 为什么会一直报: java.lang.IllegalStateException: original request is required  解决方案:  最初我用的okhttp 版本是9.7.0 导致,feign-core 的版本和 feign-okhttp版本不一致问题引起,或者可以理解版本为不兼容导致,将 feign-okhttp版本换成 10.1.0 成方可解决。 
  • [其他] Spring Cloud 组件介绍和对比
    服务发现:Nacos、Eureka微服务架构里面的核心,负责微服务各个模块的服务注册和发现,各个微服务模块将自己的服务地址、端口号等元数据发送给注册中心,注册中心将此信息记录到服务列表中并通知发送给各个子模块中。 Nacos融合SpringCloud官方文档:cid:link_1Eurka Spring官方文档:cid:link_5远程服务调用(RPC):Dubbo、Feign协议Dubbo 支持多传输协议: Dubbo、Rmi、http,可灵活配置Feign 基于Http传输协议,短连接,性能比dubbo低与Spring Cloud 集成Dubbo 在早期Dubbo是与Spring Cloud 集成有一些脱落,但是在Spring Cloud Alibaba 出现后,spring-cloud-starter-dubbo 与Spring Cloud完美集成Feign Spring Cloud 最早支持的RPC框架,兼容性好文档Dubbo Apache文档:cid:link_7Dubbo融合Nacos教程:cid:link_2Feign:RestTemplate + Ribbon结合Eureka进行RPC调用。负载均衡:Ribbon、DubboDubboRibbonFeign自身是没有负载均衡能力的,之前默认使用Ribbon作为负载均衡的组件,但是Netfix 已经不在维护了 新版本的Spring Cloud已经将Ribbon替换成Spring Cloud Load Balancer,Ribbon是客户端级别的负载均衡,不像dubbo支持客户端和服务端双向配置网关:SpringCloud Gateway、Zuul、KongKong 网关:Kong 的性能非常好,非常适合做流量网关,但是对于复杂系统不建议业务网关用 Kong,主要是工程性方面的考虑。官网:cid:link_10Zuul1.x 网关:Zuul 1.0 的落地经验丰富,但是性能差、基于同步阻塞IO,适合中小架构,不适合并发流量高的场景,因为容易产生线程耗尽,导致请求被拒绝的情况gateway 网关:功能强大丰富,性能好,官方基准测试 RPS (每秒请求数)是Zuul的1.6倍,能与 SpringCloud 生态很好兼容,单从流式编程+支持异步上也足以让开发者选择它了。官网教程:cid:link_8Zuul 2.x:性能与 gateway 差不多,基于非阻塞的,支持长连接,但 SpringCloud 没有集成 zuul2 的计划,并且 Netflix 相关组件都宣布进入维护期,前景未知。教程:cid:link_4综上,gateway 网关更加适合 SpringCloud 项目,而从发展趋势上看,gateway 替代 zuul 也是必然的。配置中心:Consul、Nacos、ApolloConsul 官网:cid:link_9中文文档:cid:link_6Apollo 和 Nacos 提供了更多开箱即用的功能,更适合用来作为配置中心。 Nacos 使用起来比较简单,并且还可以直接用来做服务发现及管理。Apollo 只能用来做配置管理,使用相对复杂一些。 官网:cid:link_3Apollo 在配置管理方面做的更加全面,就比如说虽然 Nacos 在 1.1.0 版本开始支持灰度配置,但 Nacos 的灰度配置功能实现的比较简单,Apollo 实现的灰度配置功能就相对更完善一些。不过,Nacos 提供的配置中心功能已经可以满足绝大部分项目的需求了。官网:cid:link_0服务熔断:Hystrix、Sentinel什么是 Hystrix?在分布式环境中,不可避免地会遇到所依赖的服务挂掉的情况,Hystrix 可以通过增加 延迟容忍度 与 错误容忍度,来控制这些分布式系统的交互。Hystrix 在服务与服务之间建立了一个中间层,防止服务之间出现故障,并提供了失败时的 fallback 策略,来增加你系统的整体可靠性和弹性。Hystrix 做了那些事情?引入第三方的 client 类库,通过延迟与失败的检测,来保护服务与服务之间的调用(网络间调用最为典型)阻止复杂的分布式系统中出现级联故障快速失败与快速恢复机制提供兜底方案(fallback)并在适当的时机优雅降级提供实时监控、报警与操作控制Hystrix能干嘛?服务降级服务熔断服务限流接近实时的监控Sentinel 具有以下特征:丰富的应用场景: Sentinel 承接了阿里巴巴近 10 年的双十一大促流量的核心场景,例如秒杀(即突发流量控制在系统容量可以承受的范围)、消息削峰填谷、实时熔断下游不可用应用等。完备的实时监控: Sentinel 同时提供实时的监控功能。您可以在控制台中看到接入应用的单台机器秒级数据,甚至 500 台以下规模的集群的汇总运行情况。广泛的开源生态: Sentinel 提供开箱即用的与其它开源框架/库的整合模块,例如与 Spring Cloud、Dubbo、gRPC 的整合。您只需要引入相应的依赖并进行简单的配置即可快速地接入 Sentinel。完善的 SPI 扩展点: Sentinel 提供简单易用、完善的 SPI 扩展点。您可以通过实现扩展点,快速的定制逻辑。例如定制规则管理、适配数据源等。链路追踪:Spring Cloud Sleuth + zipkin微服务架构是一个分布式架构,它按业务划分服务单元,一个分布式系统往往有很多个服务单元。由于服务单元数量众多,业务的复杂性,如果出现了错误和异常,很难去定位。主要体现在,一个请求可能需要调用很多个服务,而内部服务的调用复杂性,决定了问题难以定位。所以微服务架构中,必须实现分布式链路追踪,去跟进一个请求到底有哪些服务参与,参与的顺序又是怎样的,从而达到每个请求的步骤清晰可见,出了问题,很快定位。 举几个例子:在微服务系统中,一个来自用户的请求,请求先达到前端A(如前端界面),然后通过远程调用,达到系统的中间件B、C(如负载均衡、网关等),最后达到后端服务D、E,后端经过一系列的业务逻辑计算最后将数据返回给用户。对于这样一个请求,经历了这么多个服务,怎么样将它的请求过程的数据记录下来呢?这就需要用到服务链路追踪。分析微服务系统在大压力下的可用性和性能。 Zipkin可以结合压力测试工具一起使用,分析系统在大压力下的可用性和性能。Spring Cloud Sleuth 主要功能就是在分布式系统中提供追踪解决方案,并且兼容支持了 zipkin,你只需要在pom文件中引入相应的依赖即可。Sleuth与Zipkin关系spring cloud提供了spring-cloud-sleuth-zipkin来方便集成zipkin实现(指的是Zipkin Client,而不是Zipkin服务器),该jar包可以通过spring-cloud-starter-zipkin依赖来引入。ZipkinZipkin是什么 Zipkin分布式跟踪系统;它可以帮助收集时间数据,解决在microservice架构下的延迟问题;它管理这些数据的收集和查找;Zipkin的设计是基于谷歌的Google Dapper论文。 每个应用程序向Zipkin报告定时数据,Zipkin UI呈现了一个依赖图表来展示多少跟踪请求经过了每个应用程序;如果想解决延迟问题,可以过滤或者排序所有的跟踪请求,并且可以查看每个跟踪请求占总跟踪时间的百分比。为什么使用Zipkin 随着业务越来越复杂,系统也随之进行各种拆分,特别是随着微服务架构和容器技术的兴起,看似简单的一个应用,后台可能有几十个甚至几百个服务在支撑;一个前端的请求可能需要多次的服务调用最后才能完成;当请求变慢或者不可用时,我们无法得知是哪个后台服务引起的,这时就需要解决如何快速定位服务故障点,Zipkin分布式跟踪系统就能很好的解决这样的问题。Zipkin原理 针对服务化应用全链路追踪的问题,Google发表了Dapper论文,介绍了他们如何进行服务追踪分析。其基本思路是在服务调用的请求和响应中加入ID,标明上下游请求的关系。利用这些信息,可以可视化地分析服务调用链路和服务间的依赖关系。 对应Dpper的开源实现是Zipkin,支持多种语言包括JavaScript,Python,Java, Scala, Ruby, C#, Go等。其中Java由多种不同的库来支持 Spring Cloud Sleuth是对Zipkin的一个封装,对于Span、Trace等信息的生成、接入HTTP Request,以及向Zipkin Server发送采集信息等全部自动完成。Spring Cloud Sleuth的概念图见上图。
  • [技术干货] springcloud alibaba项目搭建踩坑记
    随着现在微服务架构的流行,学习微服务成为了大势所趋 。最新流行的应该就是springcloud Alibaba这一套技术栈了 。所以在网上搜索了资料进行了 整合学习 。下面分享一下 在项目搭建中遇到的一些坑 。背景:刚开始肯定是要参考大佬们的案例的 。于是在网上搜索了 大名鼎鼎的ry框架,cloud版本的。当然第一步就是先fork到自己的仓库 然后把代码下载下来了 。按照官方的指导,先在虚拟机上面安装了数据库,redis,nacos,之类相关的中间件。其中也遇到了很多坑,不过那些都不是重点,重点是当我启动完项目开始搭建自己的项目的时候坑来了 。1.版本间匹配关系。按照人家先有的springcloud springboot springcloud alibaba的版本 感觉好像什么都没问题一样 。然后我就开始都按照官网最新的版本来选。spring.io 进去搜索。结果项目导入进去各种报错,最基本的启动不起来,搜索后得知是有版本对应关系的。Spring Cloud Alibaba Version 2021.0.4.0*Spring Cloud Version Spring Cloud 2021.0.4Spring Boot Version 2.6.11Sentinel Version  1.8.5Nacos Version  2.0.4RocketMQ Version  4.9.4Seata Version 1.5.2这个是在官方的说明里面找到的版本对应说明。2.子父模块之间的maven依赖问题这个问题遇到的坑比较多,因为没自己搭建过,没能很好的梳理好子父间关系 。遇到如下问题Maven ‘parent.relativePath‘ of POM 发现是在《parent》 标签里面没有写<relativePath /> Non-resolvable parent POM for  遇到这个问题 是因为修改了父, 子项目之后没有重新构建父项目 导致包不对。最坑的就是这个问题了 SpringBoot工程启动不起来,报错Unable to start ServletWebServerApplicationContext due to missing ServletWebServerFactory bean.什么都没有动项目就没起来,问题在哪,我最后找了一圈发现由于pom文件对应的pom文件内置tomcat的写法上  问题出现前是这样的  <dependency>             <groupId>org.springframework.boot</groupId>             <artifactId>spring-boot-starter-tomcat</artifactId>             <scope>provided</scope>         </dependency>  <dependency> https://bbs.huaweicloud.com/forum/thread-0221112501396435024-1-1.html  具体可以看我这篇帖子。暂时就遇到这么些问题,还没有搭建成功 还要继续努力。
  • [技术干货] 记微服务架构下服务互相调用踩的坑。
    最近单位的搞了个新的项目,项目架构从单体变成了微服务,之前对于微服务的一些知识都知识停留在纸面上,以及自己的一些demo上,没有真正的实操过 。这不,这下就踩了坑 。刚开始还不是很熟练,技术方面用到了 springcloud,nacos,feign,gateway。然后就在feign上踩坑了 。先简单的说下feign相关的注解@RequestLine//定义请求方式,请求路径,还有请求参数String value();// 是否编码/符号,默认是会编码的,也就是转义的意思boolean decodeSlash() default true;// 默认支持URL传多值,是通过key来传输的。形如:key=value1&key=value2&key=value3// CollectionFormat不同的取值对应不同的分隔符,一般不建议改CollectionFormat collectionFormat() default CollectionFormat.EXPLODED;@FeignClient标签的常用属性如下:name:指定FeignClient的名称,如果项目使用了Ribbon,name属性会作为微服务的名称,用于服务发现url: url一般用于调试,可以手动指定@FeignClient调用的地址decode404:当发生http 404错误时,如果该字段位true,会调用decoder进行解码,否则抛出FeignExceptionconfiguration: Feign配置类,可以自定义Feign的Encoder、Decoder、LogLevel、Contractfallback: 定义容错的处理类,当调用远程接口失败或超时时,会调用对应接口的容错逻辑,fallback指定的类必须实现@FeignClient标记的接口fallbackFactory: 工厂类,用于生成fallback类示例,通过这个属性我们可以实现每个接口通用的容错逻辑,减少重复的代码path: 定义当前FeignClient的统一前缀,当我们项目中配置了server.context-path,server.servlet-path时使用 。一般情况下在启动类里面,加入注解声明开启远程调用然后就可以了。我的需求是微服务中 服务A调用服务B,服务B里又调用服务C 。贴上我的代码 。然后这个时候看着只有2行代码但是就是调用不了,但是又不好意思问,因为只有2行都搞定不了实在是 。。就只能去搜索恶补知识。以为是哪里的其他配置细节没做好。@FeignClient(name="custorm",fallback=Hysitx.class) public interface IRemoteCallService {     @RequestMapping(value="/custorm/getTest",method = RequestMethod.POST)     List<String> test(@RequestParam("names") String[] names); 搜到了 如上所示代码 ,这个时候我就更坚定写的没问题了么。。在多次尝试未果之后问了同事才搞定 。、原来是@EnableFeignClients跨服务调用的注解。@EnableDiscoveryClient将一个微服务注册到Eureka Server上面的@FeignClient 这个注解是不行的 。  搜到的代码 和我的需求是不一样的 。真的是新手入门 ,一个小坑记录提醒自己 。
  • [技术干货] Feign整合Sentinel 开启 feign.sentinel.enabled=true 启动报错
     Feign 整合 Sentinel 开启 feign.sentinel.enabled=true 启动报错 Requested bean is currently in creation: Is there an unresolvable circular reference? Spring Boot 版本为:2.3.9.RELEASE Spring Cloud 版本为:Hoxton.SR10 Spring Cloud Alibaba 版本为:2.2.5.RELEASE  报错信息:   修改 Spring Cloud 版本为 Hoxton.SR8 启动成功  熔断回调写法: @FeignClient(value = "user-service",fallbackFactory = UserClientFallbackFactory.class) public interface UserClient {     @GetMapping("/user/getUserInfoById/{id}")     User getUserInfoById(@PathVariable Integer id);  ​启动项配置  熔断生效:    ———————————————— 原文作者:zhaozhangxiao 转自链接:https://learnku.com/articles/67789 版权声明:著作权归作者所有。商业转载请联系作者获得授权,非商业转载请保留以上作者信息和原文链接。 
  • [技术干货] 应用服务版块问题解决汇总贴
    1.SpringCloud快速接入CSE启动报错:MicroserviceConfigLoader转String失败问题描述:在把springCloud快速接入CSE的时候,pom和配置修改完成,启动服务的时候报错,报错信息如下:org.springframework.core.convert.ConverterNotFoundException: No converter found capable of converting from type [org.apache.servicecomb.config.archaius.sources.MicroserviceConfigLoader] to type [java.lang.String]请问这个是什么导致的?怎么解决?帖子链接:https://bbs.huaweicloud.com/forum/thread-194622-1-1.html2.CSE可以管理本地启动的微服务吗?问题描述:CSE可以管理本地启动的微服务吗?本地的服务是不是只需要配置华为云CSE上的注册服务发现地址和配置中心地址就可以管理微服务了?还是说必须要把服务部署后才能用CSE管理呢?帖子链接:https://bbs.huaweicloud.com/forum/thread-192451-1-1.html3.项目基于spring-cloud,注册中心用nacos,服务之间调用用的dubbo,现在项目迁移CSE,dubbo这块怎么配置?问题描述:现在公司项目基于spring-cloud-alibaba,注册中心用的nacos,但服务调用没有用openfeign,用的dubbo调的(也是注册到nacos,没有用zookeeper),如图:现在要迁移到华为云,使用CSE的注册中心和配置中心,这一块倒没有问题,官方有文档,就是不知道迁移过去dubbo这一块的配置应该怎么搞,官网只有个基于纯dubbo项目迁移CSE的方案(https://support.huaweicloud.com/devg-cse/cse_devg_0011.html),按照文档说明引入对应maven依赖,就直接报错:帖子链接:https://bbs.huaweicloud.com/forum/thread-192450-1-1.html4.ServiceComb打开Tls开关,如何能支持常规非CSE服务间访问的HTTP请求问题描述:ServiceComb打开Tls开关,如何能支持普通非CSE服务间访问的HTTP请求?打开sslEnabled之后,CSE服务间访问确实是走tls,但是常规http请求也是需要https,可否配置部分url走http的策略?帖子链接:https://bbs.huaweicloud.com/forum/thread-185501-1-1.html5.微服务引擎CSE中配置中心请问下怎么用,翻遍了文档没找到问题描述:在s3服务器上搭建了cse环境,下载了下载本地轻量化微服务引擎,搭建了注册中心配置中心,同时下载了demo 的basic中的三个服务注册到注册中心去在30103操作页面配置yaml时就遇到了问题,第一个没理解配置管理怎么用第二个,配置了配置项,但是返回读取的信息还是工程里的yaml配置的信息,并不是从配置中心获取的怎么样才能像spring-cloud-config那样让服务从配置中心读取配置项数据呢?哪位大佬帮忙解决下帖子链接:https://bbs.huaweicloud.com/forum/thread-185292-1-1.html
  • [干货汇总] 零代码修改,教你Spring Cloud应用轻松接入CSE
    【摘要】 Sermant Agent是一种基于JavaAgent的无代理服务网格技术。它利用JavaAgent来检测主机应用程序,并具有增强的服务治理功能,以解决海量微服务架构中的服务治理问题。本文介绍了Sermant Agent的接入原理和如何使用Sermant Agent无修改接入CSE。本文分享自华为云社区《Spring Cloud应用零代码修改接入华为云微服务引擎CSE》,作者: 微服务小助手 。一、 Sermant Agent介绍Sermant Agent是一种基于JavaAgent的无代理服务网格技术。它利用JavaAgent来检测主机应用程序,并具有增强的服务治理功能,以解决海量微服务架构中的服务治理问题。Sermant Agent处于快速发展阶段,当前已支持多种服务治理能力,包含流量治理、注册、优雅上下线及动态配置能力。 二、 为何使用Sermant Agent接入代码零侵入,配置很简单相较于SDK方式接入,基于Sermant Agent的接入会更加快捷高效,配置简单,且应用无需做任何代码改造,仅需在服务启动时附带Sermant Agent即可动态接入到CSE。支持多种治理能力Sermant Agent默认集成流量治理能力,当前支持熔断、限流、隔离仓以及重试治理能力,该能力可基于CSE配置中心进行配置与发布。支持多种注册中心Sermant Agent目前支持业内主流的注册中心,已经支持了ServiceComb ServiceCenter、Naocs,Eureka、Zookeeper等正在开发中。支持应用不停机迁移Sermant Agent支持服务的双注册,可根据配置中心下发的服务订阅策略,动态修改当前服务的订阅策略,并基于该能力帮助线上应用在业务不中断的前提下完成服务迁移。不仅如此,Sermant Agent提供优雅上下线能力,在服务重启、上下线时提供保障,在保护服务的同时,规避服务下线时可能存在的流量丢失问题。三、 接入原理当然,在说明原理之前,我们首先需要了解什么是Java Agent。Java Agent是在JDK1.5之后引入的新特性,它支持JVM将字节码文件读入内存之后,JVM使用对应的字节流在Java堆中生成一个Class对象之前,用户可以对其字节码进行修改的能力,JVM使用修改之后的字节码进行Class对象的创建,从而实现Java应用的非代码侵入的业务逻辑修改和替换。Sermant Agent正是基于动态修改字节码的技术,在服务启动时,动态增强原服务的注册逻辑。那Sermant Agent是如何在不修改代码的前提下接入CSE呢?主要流程如下:Sermant Agent接入CSE的时序图包含以下6个步骤:首先服务携带Sermant Agent启动;服务启动时,针对服务执行字节码增强操作(基于Java Agent的字节码增强),主要针对注册与配置两块,在步骤3-5体现;通过字节码增强,动态识别原应用的注册中心;注入启动配置,动态关闭原应用的注册中心自动配置逻辑;随后通过Spring的SpringFactory机制注入基于Spring Cloud实现的注册CSE的自动配置类,由Spring接管;当应用发起注册时,会通过步骤5注入的注册逻辑向CSE发起注册,最终完成接入。四、 简单零代码修改,轻松接入CSE接入场景分为虚机接入和容器接入,大家可以根据自身需求选择合适的接入方式。虚机场景接入CSE虚机部署的应用可通过Sermant Agent接入到CSE,点击查看虚机接入CSE流程。接入流程基于ECS将应用接入CSE流程如下:容器场景接入CSE容器部署的应用可通过Sermant Injector自动挂载Sermant Agent,从而通过Sermant Agent接入到CSE,点击查看容器接入CSE流程。接入流程基于CCE将应用接入CSE流程如下:五、 更多支持版本当前Sermant已支持大部分业内主流版本,相关Spring及注册中心版本如下:开源方式接入除了上述接入方式,还可基于开源方式接入,您可在Sermant开源社区拉取最新代码,并自行打包,启动步骤可参考虚机接入流程。开源项目Sermant:https://github.com/huaweicloud/Sermant
  • [问题求助] SpringCloud快速接入CSE启动报错:MicroserviceConfigLoader转String失败
    各位大佬,我在把springCloud快速接入CSE的时候,pom和配置修改完成,启动服务的时候报错,报错信息如下:org.springframework.core.convert.ConverterNotFoundException: No converter found capable of converting from type [org.apache.servicecomb.config.archaius.sources.MicroserviceConfigLoader] to type [java.lang.String]请问这个是什么导致的?怎么解决?