服务器网站建设软件有哪些网站建设公司策划
2026/4/6 9:13:35 网站建设 项目流程
服务器网站建设软件有哪些,网站建设公司策划,asp网站密码,朝阳seo网站建设Feign声明式服务调用 1. 学习目标2. 什么是Feign ​ Feign是Spring Cloud Netflix组件中的一个轻量级Restful的HTTP客户端#xff0c;实现了负载均衡和Rest调用的开源框架#xff0c;封装了Ribbon和RestTemplate#xff0c;实现了WebService的面向接口编程#xff0c;进一…Feign声明式服务调用1. 学习目标2. 什么是Feign​ Feign是Spring Cloud Netflix组件中的一个轻量级Restful的HTTP客户端实现了负载均衡和Rest调用的开源框架封装了Ribbon和RestTemplate实现了WebService的面向接口编程进一步降低了项目的耦合度。​ Feign内置了Ribbon用来做客户端负载均衡调用服务注册中心的服务。​ Feigin本身不支持SpringMVC的注解它有一套自己的注解为了更方便的使用Spring Cloud孵化了OpenFeign。​ Feign是一种声明式、模板化的HTTP客户端仅在Consumer中使用。​ Feign支持的注解和用法请参考官方文档https://github.com/OpenFeign/feign 或 https://spring.io/​ Feign的使用方式是使用Feign的注解定义接口调用这个接口就可以调用服务注册中心的服务。3. Feign解决什么问题​ Feign旨在使编写JAVA HTTP客户端编的更加容易Feign简化了RestTemplate代码实现了Ribbon负载均衡使代码变得更加简洁也少了客户端调用的代码使用Feign实现负载均衡是首选方案。只需要你创建一个接口然后在上面添加注解即可。​ Feign是声明式服务调用组件其核心是像调用本地方法一样调用远程方法无感知远程HTTP请求。它解决了让开发者调用远程接口就跟调用本地方法一样的体验开发者完全感知不到这是远程方法更感知不到这是一个http请求无需关注与远程的交互细节更无需关注分布式环境开发。它像Dubbo一样Consumer直接调用Provider接口方法而不需要通过常规的Http Client构造请求再解析返回数据4. Feign vs OpenFeign​ OpenFeign是Spring Cloud在Feign的基础上支持了Spring MVC的注解如RequestMapping、PathVariable等待​ OpenFeign的FeignClient可以解析SpringMVC的RequestMapping注解下的接口并通过动态代理的方式产生实现类实现类中做负载均衡并调用服务。5. Feign入门案例​ Feign的使用主要分为以下几个步骤服务消费者添加Feign依赖创建业务层接口添加FeignClient注解声明需要调用的服务业务层抽象方法使用 SpringMVC注解配置服务地址及参数启动类添加**EnableFeignClients**注解激活Feign组件核心在于消费者5.1 创建项目ps: 服务消费者通过Eureka注册中心来获取服务或者Ribbon点对点直连模式都可以使用Feign来实现我们创建聚合项目并使用Eureka注册中心来讲解Feign首先创建一个pom工程。同eureka-demo一致先前项目的子模块复制进来即可创建父工程feigin-demo5.2 添加依赖!-- 集中定义依赖组件版本号但不引入 在子工程中用到生声明的依赖时可以不加依赖的版本号 这样就可以统一管理工程中用到的依赖版本 --propertiesmaven.compiler.source8/maven.compiler.sourcemaven.compiler.target8/maven.compiler.targetproject.build.sourceEncodingUTF-8/project.build.sourceEncoding!--Spring Cloud Hoxton. SR1 依赖--spring-cloud.versionHoxton.SR1/spring-cloud.version/properties!--项目依赖管理 父项目只是声明依赖 子项目写明需要的依赖可以省略版本信息--dependencyManagementdependencies!--spring cloud依赖--dependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-dependencies/artifactIdversion${spring-cloud.version}/versiontypepom/typescopeimport/scope/dependency/dependencies/dependencyManagement5.3 注册中心 eureka-server启动2个服务eureka-server01和eureka-server02 就是端口不同defaultZone互相注册其他都一直5.3.1 依赖文件dependencies!--eureka server--dependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-netflix-eureka-server/artifactId/dependency!--springboot web--dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-web/artifactId/dependency!--spring boot security--dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-security/artifactId/dependency!--springboot test--dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-test/artifactIdscopetest/scopeexclusionsexclusiongroupIdorg.junit.vintage/groupIdartifactIdjunit-vintage-engine/artifactId/exclusion/exclusions/dependency/dependencies5.3.2 启动类EnableEurekaServerSpringBootApplicationpublicclassEurekaServer01Application{publicstaticvoidmain(String[]args){SpringApplication.run(EurekaServer01Application.class);}}5.3.3 配置类EnableWebSecuritypublicclassWebSecurityConfigextendsWebSecurityConfigurerAdapter{Overrideprotectedvoidconfigure(HttpSecurityhttp)throwsException{super.configure(http);// 为了访问eureka控制台和 /actuator时能做安全控制http.csrf().ignoringAntMatchers(/eureka/**);// 忽略 /eureka/** 的所有请求}}5.3.4 配置文件server: port: 8761 # 端口 spring: application: name: eureka-server01 # 应用名称 # 安全认证 security: user: name: root password: 145263 # 配置Eureka Server 注册中心 eureka: server: enable-self-preservation: false # true 开启自我保护吗模式 false 关闭自我保护模式 eviction-interval-timer-in-ms: 60000 # 清理间隔 单位: 毫秒 默认是 60 * 10000 instance: hostname: eureka01 # 主机名 不配置的时候根据操作系统的主机名来获取 prefer-ip-address: true # 是否使用IP注册 instance-id: ${spring.cloud.client.ip-address}:${server.port} # ip:port client: # 设置服务注册中心地址 指向另一个注册中心 service-url: # 注册中心对外暴露的注册地址 # defaultZone: http://localhost:8762/eureka/ # 最开始没加认证之前的配置 defaultZone: http://root:145263localhost:8762/eureka/5.4 服务提供者 service-provider启动2个服务 service-provider和service-provider025.4.1 添加依赖dependencies!--eureka client--dependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-netflix-eureka-client/artifactId/dependency!--spring boot actuator--dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-actuator/artifactId/dependency!--springboot web--dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-web/artifactId/dependency!--lombook--dependencygroupIdorg.projectlombok/groupIdartifactIdlombok/artifactIdscopeprovided/scope/dependency!--springboot test--dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-test/artifactIdscopetest/scopeexclusionsexclusiongroupIdorg.junit.vintage/groupIdartifactIdjunit-vintage-engine/artifactId/exclusion/exclusions/dependency/dependencies5.4.2 配置文件server:port:7070spring:application:name:service-provider# 应用名称 集群下相同# 配置Eureka Server 注册中心eureka:instance:prefer-ip-address:true# 是否使用IP注册instance-id:${spring.cloud.client.ip-address}:${server.port}# ip:portclient:# 设置服务注册中心地址 指向另一个注册中心service-url:# 设置服务注册中心地址defaultZone:http://root:145263localhost:8761/eureka/,http://root:145263localhost:8762/eureka/# 度量指标监控与健康检查management:endpoints:web:exposure:exclude:shutdown# 开启shutdown端点访问endpoint:shutdown:enabled:true# 开启shutdown 实现优雅停服5.4.3 实体类DataAllArgsConstructorNoArgsConstructorpublicclassProductimplementsSerializable{privateIntegerid;privateStringproductName;privateIntegerproductNum;privateDoubleproductPrice;}5.4.4 编写服务ProduceService.javapublicinterfaceProduceService{/** * 查询商品列表 * return */ListProductselectProduceList();}实现类ServicepublicclassProduceServiceImplimplementsProduceService{OverridepublicListProductselectProduceList(){returnArrays.asList(newProduct(1,华为手机,newRandom().nextInt(3)1,588D),newProduct(2,联系电脑,newRandom().nextInt(10)2,221D),newProduct(3,小米平板,newRandom().nextInt(5)1,266D));}}5.4.5 控制层RestControllerRequestMapping(/product)publicclassProductController{AutowiredprivateProduceServiceproduceService;GetMapping(/list)publicListProductselectProductList(){returnproduceService.selectProduceList();}}5.4.6 启动类EnableEurekaClient// 如果配置了Eureka注册中心 默认会开启此注解 可不写SpringBootApplicationpublicclassServiceProviderApplication{publicstaticvoidmain(String[]args){SpringApplication.run(ServiceProviderApplication.class);}}5.4.7 访问当前效果图如下接口结果5.5 服务消费者 service-consumer5.5.1 创建项目​ 在刚才的父工程下创建一个service-consumer服务消费者项目5.5.2 添加依赖dependencies!--spring cloud openfeign依赖--dependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-openfeign/artifactId/dependency!--eureka client--dependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-netflix-eureka-client/artifactId/dependency!--spring boot actuator--dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-actuator/artifactId/dependency!--springboot web--dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-web/artifactId/dependency!--lombook--dependencygroupIdorg.projectlombok/groupIdartifactIdlombok/artifactIdscopeprovided/scope/dependency!--springboot test--dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-test/artifactIdscopetest/scopeexclusionsexclusiongroupIdorg.junit.vintage/groupIdartifactIdjunit-vintage-engine/artifactId/exclusion/exclusions/dependency/dependencies5.5.3 配置文件server:port:9090# 端口spring:application:name:service-consumer# 应用名称# 配置 Eureka Server 注册中心eureka:client:register-with-eureka:false# 是否将自己注册到注册中心 默认为trueregister-fetch-interval-seconds:10# 表示 Eureka Client 间隔多久去服务器拉取注册信息 默认 30秒service-url:defaultZone:http://root:145263localhost:8761/eureka/,http://root:145263localhost:8762/eureka/5.5.4 实体类Product.javaDataAllArgsConstructorNoArgsConstructorpublicclassProductimplementsSerializable{privateIntegerid;privateStringproductName;privateIntegerproductNum;privateDoubleproductPrice;}Order.javaDataAllArgsConstructorNoArgsConstructorpublicclassOrderimplementsSerializable{privateIntegerid;privateStringorderNo;privateStringorderAddress;privateDoubletotalPrice;privateListProductproductList;}5.5.5 消费服务OrderService.javapublicinterfaceOrderService{/** * 根据主键查询订单 * return */OrderselectOrderById(Integerid);}OrderServiceImpl.javaServicepublicclassOrderServiceImplimplementsOrderService{ResourceprivateProductServiceproductService;OverridepublicOrderselectOrderById(Integerid){returnnewOrder(id,order-007,中国,81156D,productService.selectProductList());}}ProductService.java// 声明需要调用的服务FeignClient(service-provider)publicinterfaceProductService{/** * 查询商品列表 */// 配置需要调用的服务地址及参数GetMapping(/product/list)ListProductselectProductList();}5.5.6 控制层OrderController.javaRestControllerRequestMapping(/order)publicclassOrderController{AutowiredprivateOrderServiceorderService;GetMapping(/{id})publicOrderselectOrderById(PathVariable(id)Integerid){returnorderService.selectOrderById(id);}}5.5.7 启动类SpringBootApplication// 开启EurekaClient注解 目前版本入股配置了 Eureka 注册中心 默认会开启该注解//EnableEurekaClient// 开启FeignClients注解EnableFeignClientspublicclassServiceConsumerApplication{publicstaticvoidmain(String[]args){SpringApplication.run(ServiceConsumerApplication.class,args);}}5.5.5 访问http://localhost:9090/order/1{id:1,orderNo:order-007,orderAddress:中国,totalPrice:81156,productList:[{id:1,productName:华为手机,productNum:2,productPrice:588},{id:2,productName:联系电脑,productNum:5,productPrice:221},{id:3,productName:小米平板,productNum:5,productPrice:266}]}6. Feign负载均衡​ Feign封装了Ribbon自然也就集成了负载均衡的功能默认采用轮询策略如何修改负载均衡策略呢与之前学习Ribbon时讲解的配置是一致的。6.1 全局​ 在启动类或配置类注入负载均衡策略对象所有服务请求均使用该策略。BeanpublicRandomRulerandomRule(){returnnewRandomRule();}修改先前的俩个provider内容做区分6.2 局部​ 修改配置文件指定服务的负载均衡策略。​ 格式服务应用名.ribbon.NFLoadBalancerRuleClassName# 负载均衡策略 service-provider 为调用的服务的名称service-provider:ribbon:NFLoadBalancerRuleClassName:com.netflix.loadbalancer.RandomRule7. Feign请求传参7.1 GET​ 使用PathVariable注解 或RequestParam注解接收请求参数7.1.1 服务提供者ProduceService.javapublicinterfaceProduceService{/** * 查询商品列表 * return */ListProductselectProduceList();/** * 根据主键查询商品 * param id * return */ProductselectProductById(Integerid);}ProduceServiceImpl.javaServicepublicclassProduceServiceImplimplementsProduceService{OverridepublicListProductselectProduceList(){returnArrays.asList(newProduct(1,华为手机-7071,newRandom().nextInt(3)1,588D),newProduct(2,联系电脑-02,newRandom().nextInt(10)2,221D),newProduct(3,小米平板,newRandom().nextInt(5)1,266D));}OverridepublicProductselectProductById(Integerid){returnnewProduct(id,冰箱-7071,1,5888D);}}ProductController.javaRestControllerRequestMapping(/product)publicclassProductController{AutowiredprivateProduceServiceproduceService;GetMapping(/list)publicListProductselectProductList(){returnproduceService.selectProduceList();}GetMapping(/{id})publicProductselectProductById(PathVariable(id)Integerid){returnproduceService.selectProductById(id);}}7.1.2 服务消费者FeignClient(service-provider) public interface ProductService { GetMapping(/product/{id}) Product selectProductById(PathVariable(id) Integer id); }OrderServiceImpl.javaServicepublicclassOrderServiceImplimplementsOrderService{ResourceprivateProductServiceproductService;OverridepublicOrderselectOrderById(Integerid){// return new Order(id,order-007,中国,81156D,productService.selectProductList());returnnewOrder(id,order-007,中国,81156D,Arrays.asList(productService.selectProductById(12)));}}7.1.3 访问http://localhost:9090/order/1222{id:1222,orderNo:order-007,orderAddress:中国,totalPrice:81156,productList:[{id:12,productName:冰箱-7070,productNum:1,productPrice:2666}]}7.2 POST​ 使用RequestBody注解接收请求参数。7.2.1 服务提供者ProduceService.java/** * 新增商品 * param product * return */MapObject,ObjectcreateProduct(Productproduct);ProduceServiceImpl.javaOverridepublicMapObject,ObjectcreateProduct(Productproduct){System.out.println(product product);returnnewHashMapObject,Object(){{put(code,200);put(message,新增成功);put(data,product);}};}ProductController.javaPostMapping(/single)publicProductsingle(RequestBodyIntegerid){returnproduceService.selectProductById(id);}PostMapping(/save)publicMapObject,ObjectcreateProduct(RequestBodyProductproduct){returnproduceService.createProduct(product);}7.2.2 服务消费者ProductService.java// 声明需要调用的服务 FeignClient(service-provider) public interface ProductService { /** * 查询商品列表 */ // 配置需要调用的服务地址及参数 GetMapping(/product/list) ListProduct selectProductList(); GetMapping(/product/{id}) Product selectProductById(PathVariable(id) Integer id); /** * 根据主键查询商品 * param id * return */ PostMapping(/product/single) Product queryProductById(Integer id); /** * 新增商品 * param product * return */ PostMapping(/product/save) MapObject,Object createProduct(Product product); }ProductController.javaRestControllerRequestMapping(/product)publicclassProductController{AutowiredprivateProductServiceproductService;/** * 根据主键查询商品 * param id * return */PostMapping(/info)publicProductqueryProductById(Integerid){returnproductService.queryProductById(id);}PostMapping(/save)publicMapObject,ObjectcreateProduct(RequestBodyProductproduct){returnproductService.createProduct(product);}}7.2.3 访问访问info接口访问save接口8. Feign性能优化8.1 Gzip压缩​ gzip介绍gzip是一种数据格式采用deflate算法压缩数据gzip是一种流行的文件压缩算法应用十分广泛尤其是在Linux平台。​ gzip能力当Gzip压缩一个纯文本文件时效果是非常明显的大约可以**减少70%**以上的文件大小。​ gzip作用网络数据经过压缩后实际上降低了网络传输的字节数最明显的好处就是可以加快网页加载的速度。网页加载速度加快的好处不言而喻除了节省流量改善用户的浏览体验外另一个潜在的好处是Gzip与搜索引擎的抓取工具有着更好的关系。例如Google就可以通过直接读取gzip文件来比普通手干抓取更快地检索网页。8.1.1 HTTP协议关于压缩传输的规定客户端向服务器请求中带有Accept-Encoding:gzipdeflate字段向服务器表示客户端支持的压缩格式gzip或者deflate如果不发生该消息头服务端默认是不会压缩的。服务端在收到请求之后如果发现请求头中含有Accept-Encoding字段并且支持该类型压缩就会对响应报文压缩之后返回客户端并且携带Content-Encoding:gzip消息头表示响应报文是根据该格式进行压缩的。客户端接收到请求之后先判断是否有Content-Encoding消息头如果有按该格式解压报文。否则按正常报文处理8.1.2 Gzip压缩案例8.1.2.1 局部​ 只配置Consumer 通过Feign到Provider的请求与相应的Gzip压缩​ 服务消费者 application.ymlfeign:compression:request:mime-types:text/xml,application/xml,application/json# 配置压缩支持的MIME TYPEmin-request-size:512# 配置压缩数据大小的最小阈值 默认 2048enabled:true# 请求是否开启gzip压缩response:enabled:true# 响应是否开启gzip压缩8.1.2.2 全局​ 对客户端浏览器的请求以及Consumer对Provider的请求与响应都实现Gzip压缩​ 服务消费者 application.ymlserver:port:9090compression:enabled:true# 是否开启压缩mime-types:text/xml,text/plain,application/xml,application/json#配置压缩支持的MIME TYPE8.1.2.3 测试访问http://localhost:9090/order/1222没开启之前的访问开启之后的访问效果8.2 HTTP连接池​ 为什么HTTP连接池能提升性能8.2.1 HTTP的背景原理两台服务器建立HTTP连接的过程是很复杂的一个过程涉及到多个数据包的交换很耗时间HTTP连接需要的3次握手和4次挥手开销很大这一开销对于大量的比较小的HTTP消息来说更大8.2.2 解决方案​ 采用HTTP连接池可以节约大量的3次握手和4次挥手这样能大大提升吞吐量​ Feign的HTTP客户端支持3种框架HttpURLConnection、HttpClient、Oktup默认是HttpURLConnection可以通过查看源码org.springframework.cloud.openfeign.ribbon.FeignRibbonClientAutoConfiguration.java得知传统的HttpURLConnection是JDK自带的并不支持连接池如果实现连接池的机制还需要自己来管理连接对象对于网络请求这种底层相对复杂的操作如果有可用的其他方案没有必要自己去管理连接对象HttpClient相比传统JDK自带的HttpURLConnection它封装了访问HTTP的请求头参数、内容体响应等等它不使客户端发送HTTP请求变得容易而且也方便了测试接口基于HTTP协议的既提高了开发的效率又提高了代码的健壮性另外高并发大量的亲戚网络的时候也是“连接池”提升吞吐量8.2.3 HttpClient​ 将Feign的Http客户端工具修改为HttpClient。8.2.3.1 添加依赖​ 修改Consumer项目添加两个依赖因为文本中使用的Spring Cloud版本已经默认集成了apache httpclient依赖所以只需要添加一个依赖即可。!--当前版本已经默认集成了 apache httpclient依赖--dependencygroupIdorg.apache.httpcomponents/groupIdartifactIdhttpclient/artifactIdversion4.5.11/version/dependency!-- 仅添加此依赖即可 --!--sfeign apache httpclient 依赖--dependencygroupIdio.github.openfeign/groupIdartifactIdfeign-httpclient/artifactIdversion10.7.4/version/dependency8.2.3.2 配置文件feign: httpclient: enabled: true # 开启httpclientPS如果使用HttpClient作为Feign的客户端工具那么在定义接口的注解是需要注意的如果传递的参数是一个自定义的对象对象会使用JSON格式来传递需要配置参数类型例如GetMapping(value /single/pojo, consumes MediaType.APPLICATION_JSON_VALUE)。本文中使用的Spring Cloud版本已无需手动配置并且使用了HttpClient客户端以后我们还可以通过GET请求传递对象参数。8.2.3.3 服务提供者​ 演示如何通过GET请求传递对象参数POST请求的方式代码无需任何变化ProduceService.javapublicinterfaceProduceService{/** * 接收商品对象参数 * param product * return */ProductselectProductByPojo(Productproduct);}ProduceServiceImpl.javaServicepublicclassProduceServiceImplimplementsProduceService{OverridepublicProductselectProductByPojo(Productproduct){System.out.println(product product);returnproduct;}}ProductController.javaRestControllerRequestMapping(/product)publicclassProductController{GetMapping(/pojo)publicProductselectUserByPojo(RequestBodyProductproduct){returnproduceService.selectProductByPojo(product);}}8.2.3.4 服务消费者ProductService.java 调用商品微服务// 声明需要调用的服务 FeignClient(service-provider) public interface ProductService { GetMapping(/product/pojo) Product selectProductByPojo(Product product); }ProductController.javaRestControllerRequestMapping(/product)publicclassProductController{AutowiredprivateProductServiceproductService;GetMapping(/pojo)publicProductselectUserByPojo(Productproduct){returnproductService.selectProductByPojo(product);}}8.2.3.5 测试访问 http://localhost:9090/product/pojo?id1productName二级productNum14productPrice399{ id: 1, productName: 二级, productNum: 14, productPrice: 399 }8.3 状态查看​ 浏览器发起的请求我们可以借助F12Devtools中的NetWrok来查看请求和响应信息对于微服务中每个接口我们又该如何查看URL状态码和耗时信息我们可以使用配置日志的方式进行查看。8.3.1 logback.xml​ Consumer 项目添加logback.xml 日志文件内容如下logback日志的输出级别需要时DEBUG级别?xml version1.0 encodingutf-8?!-- 日志级别从低到高分为TRACEDEBUGINFONARNERRORFATAL,如果设置为WARN,则低于WARN的信息都不会输出 --!-- scan:当此属性设置为true时配置文件如果发生改变将会被重新加载默认值为true--!-- scanPeriod:设置监测配置文件是否有修改的时间间隔如果没有给出时间单位认单位是毫秒。当scan为true时此属性生效。默认的时间间隔为1分钟。--!-- debug:当此属性设置为true时将打印出logback内部日志信息实时查看logback运行状态。默认值为false。--configurationscantruescanPeriod10 secondsdebugtrue!-- 日志上下文名称 --contextNamemy_logback/contextName!-- name的值是变的名称value的值是变里定义的值。通过定义的值会被插入到 logger上下文中。定义变里后可以使${}来使用变里。--propertynamelog.pathvalueS(catalina.base)/service-consumer/logs/!-- 彩色日志 --!-- 彩色日志依赖的渲染类 --conversionRuleconversionWordclrconverterClassorg.springframework.boot.logging.logback.ColorConverter/conversionRuleconversionWordwexconverterClassch.qos.logback.classic.spi.WhitespaceThrowableProxyConverter/conversionRuleconversionWordwExconverterClassorg.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter/!-- 彩色日志格式 --propertynameCONSOLE_LOG_PATTERNvalue${CONSOLE_LOG_PATTERN:-%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint}%clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}/!-- 文件日志输入格式 --propertynameFILE_LOG_PATTERNvalue%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n/!--输出到控制台--appendernameCONSOLEclassch.qos.logback.core.ConsoleAppender!-- 此日志appender是为开发使用 只配置最低级别 控制台输出的日志级别是大于或等于此级别的日志信息 --filterclassch.qos.logback.classic.filter.ThresholdFilterlevelDEBUG/level/filterencoderpattern${CONSOLE_LOG_PATTERN}/pattern!--设置字符集--charsetUTF-8/charset/encoder/appender!-- 输出到文件 --!-- 时间滚动输出level为DEBUG的日志 --appendernameDEBUG_FILEclassch.qos.logback.core.rolling.RollingFileAppender!-- 正在记录的日志文件的路径及文件名 --file${log.path}/log_debug.log/file!-- 日志文件输出格式 --encoderpattern${FILE_LOG_PATTERN}/patterncharsetUTF-8/charset/encoder!-- 日志记录器的滚动策略 按日志 按大小记录 --rollingPolicyclassch.qos.logback.core.rolling.TimeBasedRollingPolicy!-- 日志归档 --fileNamePattern${log.path}/debug/log-debug-%d{yyyy-MM-dd}.%i.log/fileNamePatterntimeBasedFileNamingAndTriggeringPolicyclassch.qos.logback.core.rolling.SizeAndTimeBasedFNATPmaxFileSize100MB/maxFileSize/timeBasedFileNamingAndTriggeringPolicy!-- 日志文件保留天数 --maxHistory15/maxHistory/rollingPolicy!-- 此日志只记录DEBUG级别的 --filterclassch.qos.logback.classic.filter.LevelFilterlevelDEBUG/levelonMatchACCEPT/onMatchonMismatchDENY/onMismatch/filter/appender!--时间滚动输出 level 为INFO日志--appendernameINFO_FILEclassch.qos.logback.core.rolling.RollingFileAppender!--正在记录的日志文件的路径及文件名--file${log.path}/log_info.log/file!-- 日志文件输出格式 --encoderpattern${FILE_LOG_PATTERN}/patterncharsetUTF-8/charset/encoder!-- 日志记录器的滚动策略 按日志 按大小记录 --rollingPolicyclassch.qos.logback.core.rolling.TimeBasedRollingPolicy!-- 日志归档 --fileNamePattern${log.path}/info/log-info-%d{yyyy-MM-dd}.%i.log/fileNamePatterntimeBasedFileNamingAndTriggeringPolicyclassch.qos.logback.core.rolling.SizeAndTimeBasedFNATPmaxFileSize100MB/maxFileSize/timeBasedFileNamingAndTriggeringPolicy!-- 日志文件保留天数 --maxHistory15/maxHistory/rollingPolicy!--此日志只记录info级别的--filterclassch.qos.logback.classic.filter.LevelFilterlevelINFO/levelonMatchACCEPT/onMatchonMismatchDENY/onMismatch/filter/appender!--时间滚动输出 level 为 WARN 日志--appendernameWARN_FILEclassch.qos.logback.core.rolling.RollingFileAppender!--正在记录的日志文件的路径及文件名--file${log.path}/log_warn.log/file!-- 日志文件输出格式 --encoderpattern${FILE_LOG_PATTERN}/patterncharsetUTF-8/charset/encoder!-- 日志记录器的滚动策略 按日志 按大小记录 --rollingPolicyclassch.qos.logback.core.rolling.TimeBasedRollingPolicy!-- 日志归档 --fileNamePattern${log.path}/info/log-warn-%d{yyyy-MM-dd}.%i.log/fileNamePatterntimeBasedFileNamingAndTriggeringPolicyclassch.qos.logback.core.rolling.SizeAndTimeBasedFNATPmaxFileSize100MB/maxFileSize/timeBasedFileNamingAndTriggeringPolicy!-- 日志文件保留天数 --maxHistory15/maxHistory/rollingPolicy!--此日志只记录warn级别的--filterclassch.qos.logback.classic.filter.LevelFilterlevelWARN/levelonMatchACCEPT/onMatchonMismatchDENY/onMismatch/filter/appender!--时间滚动输出 level 为 ERROR 日志--appendernameERROR_FILEclassch.qos.logback.core.rolling.RollingFileAppender!--正在记录的日志文件的路径及文件名--file${log.path}/log_error.log/file!-- 日志文件输出格式 --encoderpattern${FILE_LOG_PATTERN}/patterncharsetUTF-8/charset/encoder!-- 日志记录器的滚动策略 按日志 按大小记录 --rollingPolicyclassch.qos.logback.core.rolling.TimeBasedRollingPolicyfileNamePattern${log.path}/info/log-error-%d{yyyy-MM-dd}.%i.log/fileNamePatterntimeBasedFileNamingAndTriggeringPolicyclassch.qos.logback.core.rolling.SizeAndTimeBasedFNATPmaxFileSize100MB/maxFileSize/timeBasedFileNamingAndTriggeringPolicy!-- 日志文件保留天数 --maxHistory15/maxHistory!--日志量最大10GB--totalSizeCap10GB/totalSizeCap/rollingPolicy!--此日志只记录error级别的--filterclassch.qos.logback.classic.filter.LevelFilterlevelERROR/levelonMatchACCEPT/onMatchonMismatchDENY/onMismatch/filter/appender!-- 对于类路径以com.example.logback开头的Logger 输出级别设置为warn 并且只输出到控制台 --!-- 这个logger没有指定appender 它会继承root节点中定义的那些appender --!-- logger namecom.example.logback levelwarn / --!-- 通过LoggerFactory.getLogger(myLog) 可以获取到这个logger --!-- 对于这个logger自动继承了root的appender root中已经有了stdout的appender了 自己这边又引入了stdout的appender --!-- 如果没有设置 additivityfalse 就会导致一条日志在控制台输出俩次的情况 --!-- additivity 表示不要使用rootLogger配置的appender进行输出--loggernamemyLoglevelINFOadditivityfalseappender-refrefCONSOLE//logger!--日志输出级别及方式--rootlevelDEBUGappender-refrefCONSOLE/appender-refrefDEBUG_FILE/appender-refrefINFO_FILE/appender-refrefWARN_FILE/appender-refrefERROR_FILE//root/configuration8.3.2 全局​ Consumer项目启动类中注入Feign的Logger对象/** * NONE 不记录任何信息 默认值 * BASIC 记录清河区方法、请求URL、状态码和用时 * HEADERS 在BASIC基础上再记录一些常用信息 * FULL 记录请求和相应的所有信息 */BeanpublicLogger.LevelgetLog(){returnLogger.Level.FULL;}8.3.3 局部​ Consumer项目application.yml中指定服务开启状态查看feign: client: config: service-provider: # 需要调用的服务名称 logger-level: FULL8.3.4 测试访问http://localhost:9090/order/2核心日志如下2025-12-1321:59:12.222 DEBUG2128---[nio-9090-exec-6]o.s.web.servlet.DispatcherServlet:GET/order/2,parameters{}2025-12-1321:59:12.222 DEBUG2128---[nio-9090-exec-6]s.w.s.m.m.a.RequestMappingHandlerMapping:Mapped to com.lgfdc.controller.OrderController#selectOrderById(Integer)2025-12-1321:59:12.223 DEBUG2128---[nio-9090-exec-6]com.lgfdc.service.ProductService:[ProductService#selectProductById] --- GET http://service-provider/product/12 HTTP/1.12025-12-1321:59:12.223 DEBUG2128---[nio-9090-exec-6]com.lgfdc.service.ProductService:[ProductService#selectProductById] --- END HTTP (0-byte body)2025-12-1321:59:12.223 DEBUG2128---[nio-9090-exec-6]c.n.loadbalancer.ZoneAwareLoadBalancer:Zone aware logic disabled or there is only one zone2025-12-1321:59:12.223 DEBUG2128---[nio-9090-exec-6]c.n.loadbalancer.LoadBalancerContext:service-provider using LB returned Server:192.168.126.1:7070forrequest http:///product/122025-12-1321:59:12.223 DEBUG2128---[nio-9090-exec-6]o.a.h.client.protocol.RequestAuthCache:Auth cache notsetinthe context2025-12-1321:59:12.223 DEBUG2128---[nio-9090-exec-6]h.i.c.PoolingHttpClientConnectionManager:Connection request:[route:{}-http://192.168.126.1:7070][total available:1;route allocated:1of50;total allocated:1of200]2025-12-1321:59:12.230 DEBUG2128---[nio-9090-exec-6]org.apache.http.wire:http-outgoing-0[read] I/O error: Read timed out[nio-9090-exec-6]h.i.c.PoolingHttpClientConnectionManager:Connection leased:[id:0][route:{}-http://192.168.126.1:7070][total available:0;route allocated:1of50;total allocated:1of200][nio-9090-exec-6]h.i.c.DefaultManagedHttpClientConnection:http-outgoing-0:setsockettimeoutto0[nio-9090-exec-6]h.i.c.DefaultManagedHttpClientConnection:http-outgoing-0:setsockettimeoutto1000[nio-9090-exec-6]o.a.http.impl.execchain.MainClientExec:Executing request GET /product/12 HTTP/1.1[nio-9090-exec-6]o.a.http.impl.execchain.MainClientExec:Target auth state: UNCHALLENGED[nio-9090-exec-6]o.a.http.impl.execchain.MainClientExec:Proxy auth state: UNCHALLENGED[nio-9090-exec-6]org.apache.http.headers:http-outgoing-0GET /product/12 HTTP/1.1[nio-9090-exec-6]org.apache.http.headers:http-outgoing-0Accept: */*[nio-9090-exec-6]org.apache.http.headers:http-outgoing-0Content-Length:0[nio-9090-exec-6]org.apache.http.headers:http-outgoing-0Host:192.168.126.1:7070[nio-9090-exec-6]org.apache.http.headers:http-outgoing-0Connection: Keep-Alive[nio-9090-exec-6]org.apache.http.headers:http-outgoing-0User-Agent: Apache-HttpClient/4.5.11(Java/1.8.0_161)[nio-9090-exec-6]org.apache.http.wire:http-outgoing-0GET /product/12 HTTP/1.1[\r][\n][nio-9090-exec-6]org.apache.http.wire:http-outgoing-0Accept: */*[\r][\n][nio-9090-exec-6]org.apache.http.wire:http-outgoing-0Content-Length: 0[\r][\n][nio-9090-exec-6]org.apache.http.wire:http-outgoing-0Host: 192.168.126.1:7070[\r][\n][nio-9090-exec-6]org.apache.http.wire:http-outgoing-0Connection: Keep-Alive[\r][\n][nio-9090-exec-6]org.apache.http.wire:http-outgoing-0User-Agent: Apache-HttpClient/4.5.11 (Java/1.8.0_161)[\r][\n][nio-9090-exec-6]org.apache.http.wire:http-outgoing-0[\r][\n][nio-9090-exec-6]org.apache.http.wire:http-outgoing-0HTTP/1.1 200 [\r][\n][nio-9090-exec-6]org.apache.http.wire:http-outgoing-0Content-Type: application/json[\r][\n][nio-9090-exec-6]org.apache.http.wire:http-outgoing-0Transfer-Encoding: chunked[\r][\n][nio-9090-exec-6]org.apache.http.wire:http-outgoing-0Date: Sat, 13 Dec 2025 13:59:12 GMT[\r][\n][nio-9090-exec-6]org.apache.http.wire:http-outgoing-0Keep-Alive: timeout60[\r][\n][nio-9090-exec-6]org.apache.http.wire:http-outgoing-0Connection: keep-alive[\r][\n][nio-9090-exec-6]org.apache.http.wire:http-outgoing-0[\r][\n][nio-9090-exec-6]org.apache.http.wire:http-outgoing-04a[\r][\n][nio-9090-exec-6]org.apache.http.wire:http-outgoing-0{id:12,productName:[0xe5][0x86][0xb0][0xe7][0xae][0xb1]-7070,productNum:1,productPrice:2666.0}[\r][\n][nio-9090-exec-6]org.apache.http.headers:http-outgoing-0HTTP/1.1200[nio-9090-exec-6]org.apache.http.headers:http-outgoing-0Content-Type: application/json[nio-9090-exec-6]org.apache.http.headers:http-outgoing-0Transfer-Encoding: chunked[nio-9090-exec-6]org.apache.http.headers:http-outgoing-0Date: Sat,13Dec202513:59:12 GMT[nio-9090-exec-6]org.apache.http.headers:http-outgoing-0Keep-Alive:timeout60[nio-9090-exec-6]org.apache.http.headers:http-outgoing-0Connection: keep-alive[nio-9090-exec-6]o.a.http.impl.execchain.MainClientExec:Connection can be kept alivefor60000MILLISECONDS[nio-9090-exec-6]com.lgfdc.service.ProductService:[ProductService#selectProductById] --- HTTP/1.1 200 (9ms)[nio-9090-exec-6]com.lgfdc.service.ProductService:[ProductService#selectProductById] connection: keep-alive[nio-9090-exec-6]com.lgfdc.service.ProductService:[ProductService#selectProductById] content-type: application/json[nio-9090-exec-6]com.lgfdc.service.ProductService:[ProductService#selectProductById] date: Sat, 13 Dec 2025 13:59:12 GMT[nio-9090-exec-6]com.lgfdc.service.ProductService:[ProductService#selectProductById] keep-alive: timeout60[nio-9090-exec-6]com.lgfdc.service.ProductService:[ProductService#selectProductById] transfer-encoding: chunked[nio-9090-exec-6]com.lgfdc.service.ProductService:[ProductService#selectProductById][nio-9090-exec-6]org.apache.http.wire:http-outgoing-00[\r][\n][nio-9090-exec-6]org.apache.http.wire:http-outgoing-0[\r][\n][nio-9090-exec-6]h.i.c.PoolingHttpClientConnectionManager:Connection[id:0][route:{}-http://192.168.126.1:7070]can be kept alivefor60.0seconds[nio-9090-exec-6]h.i.c.DefaultManagedHttpClientConnection:http-outgoing-0:setsockettimeoutto0[nio-9090-exec-6]h.i.c.PoolingHttpClientConnectionManager:Connection released:[id:0][route:{}-http://192.168.126.1:7070][total available:1;route allocated:1of50;total allocated:1of200][nio-9090-exec-6]com.lgfdc.service.ProductService:[ProductService#selectProductById] {id:12,productName:冰箱-7070,productNum:1,productPrice:2666.0}[nio-9090-exec-6]com.lgfdc.service.ProductService:[ProductService#selectProductById] --- END HTTP (74-byte body)[nio-9090-exec-6]o.s.w.c.HttpMessageConverterExtractor:Reading to[com.lgfdc.pojo.Product][nio-9090-exec-6]m.m.a.RequestResponseBodyMethodProcessor:Usingapplication/json;q0.8, given[text/html, application/xhtmlxml, image/avif, image/webp, image/apng, application/xml;q0.9, application/signed-exchange;vb3;q0.7, */*;q0.8]and supported[application/json, application/*json, application/json, application/*json][nio-9090-exec-6]m.m.a.RequestResponseBodyMethodProcessor:Writing[Order(id2,orderNoorder-007,orderAddress中国,totalPrice81156.0,productList[Product(id12, prod(truncated)...][nio-9090-exec-6]o.s.web.servlet.DispatcherServlet:Completed200OK[nio-9090-exec-7]o.s.web.servlet.DispatcherServlet:GET/.well-known/appspecific/com.chrome.devtools.json,parameters{}[nio-9090-exec-7]o.s.w.s.handler.SimpleUrlHandlerMapping:Mapped to ResourceHttpRequestHandler[classpath:/META-INF/resources/,classpath:/resources/,classpath:/static/,classpath:/public/,/][nio-9090-exec-7]o.s.w.s.r.ResourceHttpRequestHandler:Resource not found[nio-9090-exec-7]o.s.web.servlet.DispatcherServlet:Completed404NOT_FOUND[nio-9090-exec-7]o.s.web.servlet.DispatcherServlet:ERRORdispatchforGET/error,parameters{}[nio-9090-exec-7]s.w.s.m.m.a.RequestMappingHandlerMapping:Mapped to org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController#error(HttpServletRequest)[nio-9090-exec-7]o.s.w.s.m.m.a.HttpEntityMethodProcessor:Usingapplication/json, given[*/*]and supported[application/json, application/*json, application/json, application/*json][nio-9090-exec-7]o.s.w.s.m.m.a.HttpEntityMethodProcessor:Writing[{timestampSat Dec1321:59:12 CST2025,status404,errorNot Found,messageNo message available,(truncated)...][nio-9090-exec-7]o.s.web.servlet.DispatcherServlet:Exiting fromERRORdispatch, status404[ionManagerTimer]h.i.c.PoolingHttpClientConnectionManager:Closing expired connections8.4 请求超时​ Feign的负载均衡底层使用的就是Ribbon所以这里的请求超时配置其实就是配置Ribbon​ 分布式项目中服务压力比较大的情况下可能处理服务的过程需要花费一定的时间而默认情况下请求超时的配置是1s所有我们需要调整该配置延长请求超时时间。8.4.1 全局​ Consumer项目中配置请求超时的处理。ribbon: ConnectTimeout: 5000 # 请求连接的超时时间 默认1秒 ReadTimeout: 5000 # 请求处理的超时时间8.4.2 局部​ 一般我们会根据服务的压力大小配置不同的服务超时处理使用局部配置。# 负载均衡策略 service-provider 为调用的服务的名称 service-provider: ribbon: NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule okToRetryOnAllOperations: true # 对所有的请求都进行重试 MaxAutoRetries: 2 # 对当前示例的重试次数 MaxAutoRetriesNextServer: 0 # 切换实例的重试次数 ConnectionTimeout: 3000 # 请求连接的超时时间 ReadTimeout: 3000 # 请求处理的超时时间

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询