zuul上传文件

1)nginx

client_max_body_size 10M; 设置文件最大上传大小
keepalive_timeout 1800; 设置最大响应时间
sendfile on; 是否启用高效上传模式

2)springboot
在这里插入图片描述

spring:
  http:
    multipart:
      max-file-size: 500Mb
      max-request-size: 500Mb
 或者
spring:
  servlet:
    multipart:
      # 是否启用分段上传支持,默认:true
      enabled: true # 启用上传处理,默认是true
      # 文件写入磁盘的阈值,当上传文件达到 1M 事开始写入磁盘。值可以使用后缀“MB”或“KB”分别表示兆字节或千字节。默认:0
      file-size-threshold: 1MB   # 当上传文件达到1MB的时候进行磁盘写入
      # 最大单个文件大小。值可以使用后缀“MB”或“KB”分别表示兆字节或千字节。默认:1MB
      max-file-size: 500MB
       # 最大请求大小。值可以使用后缀“MB”或“KB”分别表示兆字节或千字节。默认:10MB
      max-request-size: 500MB   
      location: /    # 上传文件的临时位置

Spring Boot 1.4.x 版之前:

multipart:
enabled: true
max-file-size: 100MB

Spring Boot 1.5.x - 2.x 版之间:

spring:
  http:
    multipart:
      enabled: true
      max-file-size: 100MB

Spring Boot 2.x 版之后

spring:
  servlet:
    multipart:
      enabled: true
      max-file-size: 20MB

3)hystrix 超时

hystrix:
  command:
    default:
      execution:
        isolation:
          thread:
            timeoutInMilliseconds: 50000
zuul:
  host:
    socket-timeout-millis: 12000
    connect-timeout-millis: 12000
  1. ribbon
    修改熔断器的连接时间和读取超时时间
    在Zuul中默认是使用Ribbon进行看来进行服务调度的,Ribbon会根据实际情况来做请求分发,所以对于文件上传来说,我们需要适当的设置超时时间,这样可以避免Zuul返回错误的消息。
ribbon:
  ReadTimeout: 300000  #主要该属性
  ConnectTimeout: 300000
  MaxAutoRetries: 1     #同一个Server重试的次数(除去首次)
  MaxAutoRetriesNextServer: 1  #切换到不同Server的次数
  okToRetryOnAllOperations: true  #对所有方法进行重试
  eureka:
    enabled: true
zuul默认的是信号量方式,也就是控制进来的请求总量,可以全局配置,也可以配置单个服务的最大信号量,还有一种方式是线程隔离,每种路由方式会创建单独的线程池,这样的好处是一个服务的影响不会扩散到其他的服务,但是在资源有限,且服务有限的情况下,还是信号量合适,这样我们可以充分利用tomcat创建的线程池,而不用创建过多的hystrix线程池
如果你使用@enablezuulproxy,你可以使用代理路径来上传文件,只要文件很小,它就可以工作。对于大文件,有另一种路径,可以绕过Spring DispatcherServlet(以避免多部分处理)在“/zuul/”中。换句话说,如果你有zuul.route.customers=/customers/*,然后您可以将大文件发布到/zuul/customers/*。servlet路径通过zuul.servletPath外部化。如果代理路由带您经历一个带负载均衡器,那么超大的文件也需要更高的超时设置

使用Zuul也可以进行文件上传处理,但是在文档中明确说明,Zuul在做文件上传的
时候只支持小文件的上传,大文件上传会报错。但是Zuul给出了备选的方案,Zuul
实质是一个Servlet,它会默认集成SpringMVC,当你上传小文件的时候,Zuul会将
请求交给SpringMVC代理处理,但是如果你不想交给SpringMVC,此时你就需要使
用Zuul提供Servlet路径绕过SpringMVC,这个Servlet的默认路径为:/zuul/*。当你
提供的zuul.routes.customers=/customers/**,那么你访问"/zuul/customers/*"会直
接访问对应微服务的接口。

@SpringBootApplication
@EnableDiscoveryClient
@EnableZuulProxy
@EnableFeignClients
@EnableEurekaClient
@EnableRetry
public class GatewayApplication {

    public static void main(String[] args) {
        SpringApplication.run(GatewayApplication.class, args);
    }


    /**
     * 解决上传文件重置问题
     * @return
     */
    @Bean
    public TomcatEmbeddedServletContainerFactory tomcatEmbeddedServletContainerFactory(){
        TomcatEmbeddedServletContainerFactory factory = new TomcatEmbeddedServletContainerFactory();

        factory.addConnectorCustomizers((TomcatConnectorCustomizer)  connector -> {
            if(connector.getProtocolHandler() instanceof AbstractHttp11Protocol<?>){
                ( (AbstractHttp11Protocol<?>)connector.getProtocolHandler()).setMaxSwallowSize(-1);
            }
        });

        return factory;
    }
}
修改配置,让网关只做简单处理后就直接交给服务的上传接口处理
对于大文件,可以绕过Spring DispatcherServlet(以避免多部分处理)在“/zuul/”
中。换句话说,如果你有zuul.route.customers=/customers/*,然后您可以将大文
件发布到/zuul/customers/*。servlet路径通过zuul.servletPath外部化。
或者在配置文件加 zuul.servlet-path=/
spring:
  application:
    name: zuul-service
  ##启用retry机制
  cloud:
    loadbalancer:
      retry:
        enabled: true
  http:
    encoding:
      charset: UTF-8

<dependency>
    <groupId>org.springframework.retry</groupId>
    <artifactId>spring-retry</artifactId>
</dependency>
<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
</dependency>

@RestController
@RequestMapping("/api")
public class FileUploadController {
    
    @PostMapping("/upload")
    public @ResponseBody String uploadFile(@RequestParam("file") MultipartFile file) throws IOException {
        //1.将文件转换为字节流
        byte[] bytes=file.getBytes();
        //  根据文件名来创建一个名字,上传到指定路径
        File newFile=new File("upload\\"+file.getOriginalFilename());
        FileCopyUtils.copy(bytes,newFile);
        return newFile.getAbsolutePath();
        //使用命令,测试文件上全 curl -F "file=@文件全名" localhost:8050/upload
    }
}
通过在ZuulFilter过滤器的run()方法中使用下面方法:
RequestContext ctx = RequestContext.getCurrentContext();
HttpServletRequest request = context.getRequest();
String token = request.getParameter("token");
发现无法获取到token,token为空。
解决
通过下面代码就可以获取到multipart/form-data类型的参数。
HttpServletRequestWrapper httpServletRequestWrapper = (HttpServletRequestWrapper) request;
token = httpServletRequestWrapper.getRequest().getParameter("token");

解决过程
在这里插入图片描述

通在继续DEBUG我发现context.getRequest()获取到的是Servlet30RequestWrapper
直接通过该包装类,无法获取到multipart/form-data类型的参数。
Servlet30RequestWrapper 继承自HttpServletRequestWrapper
HttpServletRequestWrapper中有个一个方法
public HttpServletRequest getRequest(){...}
通过该方法可以获取一个HttpServletRequest,这个HttpServletRequest实际上也就是StandardMultipartHttpServletRequest。
于是便可以通过StandardMultipartHttpServletRequest获取到请求中的表单参数。

#actuator  启用所有的监控端点 “*”号代表启用所有的监控端点,可以单独启用,例如,health,info,metrics
#  spring boot 升为 2.0 后,为了安全,默认 Actuator 只暴露了2个端点,heath 和 info
management:
  endpoints:
    web:
      exposure:
        include: "*"
  endpoint:
      health:
        show-details: ALWAYS
@EnableCircuitBreaker //开启断路器
总结
目前的学习和测试结果来看:

单纯的 Ribbon + Hystrix 搭配使用时,配置是最灵活的,二者没有相互干涉,能够自由定义 commandKey 来实现超时时间的配置
Feign + Hystrix 搭配时,因为 Feign 封装了 Hystrix 所需的 commandKey,咱们不能自定义,因此同一个 FeignClient 下的服务接口不能方便的统一配置,若是有相应的业务需求,或许只能对每一个特殊的接口方法作独立的超时配置(找到新方法的话再回来更新)
Zuul + Hystrix 搭配时,和上述的状况相反,能对不一样服务实例作不一样的超时配置,但不能再细化到服务下的具体接口方法
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值