乐优商城:笔记(六):上传微服务:LyUpload
文章目录
- 1 项目搭建
- 1.1 引入依赖
- 1.2 配置文件
- 1.3 启动类
- 2 实现文件上传功能
- 2.1 分布式文件上传系统
- 2.1.1 分布式文件系统
- 2.1.2 FastDFS
- 2.1.3 FastDFS架构
- 2.1.4 上传文件
- 2.1.5 引入FastDFS的依赖
- 2.1.6 引入配置类
- 2.1.7 配置FastDFS属性
- 2.2 代码实现
- 2.2.1 controller
- 2.2.2 service
1 项目搭建
1.1 引入依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><parent><artifactId>leyou</artifactId><groupId>com.leyou.parent</groupId><version>1.0.0-SNAPSHOT</version></parent><modelVersion>4.0.0</modelVersion><groupId>com.leyou.page.service</groupId><artifactId>ly-upload</artifactId><dependencies><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-client</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId></dependency><dependency><groupId>com.leyou.common</groupId><artifactId>ly-common</artifactId><version>1.0.0-SNAPSHOT</version></dependency><dependency><groupId>com.github.tobato</groupId><artifactId>fastdfs-client</artifactId></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build>
</project>
1.2 配置文件
ly-upload的配置文件:
server:port: 8082
spring:application:name: upload-serviceservlet:multipart:max-file-size: 5MB # 限制文件上传的大小
eureka:client:service-url:defaultZone: http://127.0.0.1:10086/eurekainstance:prefer-ip-address: trueip-address: 127.0.0.1
fdfs:so-timeout: 2500connect-timeout: 600thumb-image: # 缩略图width: 60height: 60tracker-list: # tracker地址- 192.168.124.128:22122
当实现写好(此处的实现是指的上传到本地,代码省略)以后一跑代码发现报错,如下:
原因是没有在网关中配置路由。
但是
网关捕获到upload之后页面的url只剩下/image(前缀会被剥离),例如:HTTP调用 “/user” 会转到 “user” 服务(例如:”/user/1”跳转到”/1”),但是controller里面是/upload/image,所以不能去除upload的前缀,有以下两种方法:
ly-gategay的配置文件:
- 配置方式1(笔记中的方式,因为视频笔记不一致…):
zuul:prefix: /api # 添加路由前缀routes:item-service: /item/**search-service: /search/**user-service: /user/**auth-service: /auth/**cart-service: /cart/**order-service: /order/**ignored-services:- upload-service # 忽略upload-service服务add-host-header: truesensitive-headers:
忽略表达式并不是完全的忽略请求, 只是配置这个代理不处理这些请求,因此上述配置表示所有upload-service的服务都不会被处理,自然也不会自动剥离前缀。
- 配置方式2(视频中的方式):
zuul:prefix: /api # 添加路由前缀routes:item-service: /item/**search-service: /search/**user-service: /user/**auth-service: /auth/**cart-service: /cart/**order-service: /order/**upload-service: /upload/**path: /upload/**serviceId: upload-servicestrip-prefix: falseadd-host-header: truesensitive-headers:
设置前缀不自动剥离。
以上相关参考资料:智能路由和过滤
但是还有一个问题:
图片上传是文件的传输,如果也经过Zuul网关的代理,文件就会经过多次网路传输,造成不必要的网络负担。在高并发时,可能导致网络阻塞,Zuul网关不可用。这样我们的整个系统就瘫痪了,所以,上传文件的请求不经过网关来处理。
那怎么做呢?
方式一(笔记):
请求的地址不经过网关api:
修改nginx配置,将以/api/upload开头的请求拦截下来,转交到真实的服务地址,但是前面多了一个/api,此时利用Nginx提供了rewrite指令,用于对地址进行重写(并不是真的去掉api,而是重写路径结束后,不再重新匹配路径):
# 上传路径的映射
location /api/upload { proxy_pass http://192.168.124.128:8082;proxy_connect_timeout 600;proxy_read_timeout 600;rewrite "^/api/(.*)$" /$1 break; }
rewrite "^/api/(.*)$" /$1 break
,路径重写:
"^/api/(.*)$"
:匹配路径的正则表达式,用了分组语法,把/api/
以后的所有部分当做1组/$1
:重写的目标路径,这里用$1引用前面正则表达式匹配到的分组(组编号从1开始),即/api/
后面的所有。这样新的路径就是除去/api/
以外的所有,就达到了去除/api
前缀的目的break
:指令,常用的有2个,分别是:last、break- last:重写路径结束后,将得到的路径重新进行一次路径匹配
- break:重写路径结束后,不再重新匹配路径。
我们这里不能选择last,否则以新的路径/upload/image来匹配,就不会被正确的匹配到8082端口了。
方式二(视频):
先来看一段官方文档的翻译:
zuul的底层是一个servlet,通常情况下zuul会将请求交给Spring Dispatch去处理,SpringMVC去控制路由。这种情况下,zuul就会去缓存这个请求,如果你有直接通过zuul但是不需要缓存的服务:比如大文件的上传服务,这时候你应该跳过Spring Dispatch。这时候你应该在你的地址前面加一个
/zuul
。
简而言之,当你的请求前面加上/zuul,就会跳过缓存服务,如下:
那么如何实现——还是依靠Nginx的rewrite指令!
# 上传路径的映射
location /api/upload { write "^/(.*)$" /zuul/$1;
}
1.3 启动类
@SpringBootApplication
@EnableDiscoveryClient
public class LyUploadApplication {public static void main(String[] args) {SpringApplication.run(LyUploadApplication.class);}
}
2 实现文件上传功能
2.1 分布式文件上传系统
无论是保存在本地还是tomcat下都是有问题的
- 文件越传越多,启动加载的速度会越来越慢
- tomcat解析静态资源速度非常慢
- 有单点故障问题,如果一台服务器挂了整体图片功能都会受到影响
- 无法进行水平扩展,因为多台机器的文件无法共享,会出现访问不到的情况
因此图片地址需要使用另外的url + 分布式文件上传系统来解决!
2.1.1 分布式文件系统
分布式文件系统(Distributed File System)是指文件系统管理的物理存储资源不一定直接连接在本地节点上,而是通过计算机网络与节点相连。
通俗来讲:
- 传统文件系统管理的文件就存储在本机。
- 分布式文件系统管理的文件存储在很多机器,这些机器通过网络连接,要被统一管理。无论是上传或者访问文件,都需要通过管理中心来访问
2.1.2 FastDFS
FastDFS是一个轻量级、高性能的开源分布式文件系统,用纯C语言开发,功能如下:
- 文件存储
- 文件同步
- 文件访问(上传、下载)
- 存取负载均衡
- 在线扩容
适合有大容量存储需求的应用或系统。同类的分布式文件系统有谷歌的GFS、HDFS(Hadoop)、TFS(淘宝)等。
2.1.3 FastDFS架构
每一个Storage启动以后都会向Tracker注册自己的信息,并且维持一个心跳
Storage:存储服务器。文件存储的地方,每个Storage Server存储的文件都不一样,数据分片
Tracker:跟踪服务器。顾名思义,他可以知道每个文件存储在哪个Storage,类似于仓库管理员
2.1.4 上传文件
上传流程:
- Client通过Tracker server查找可用的Storage server。
- Tracker server向Client返回一台可用的Storage server的IP地址和端口号。
- Client直接通过Tracker server返回的IP地址和端口与其中一台Storage server建立连接并进行文件上传。
- 上传完成,Storage server返回Client一个文件ID,文件上传结束。
下载流程:
5. Client通过Tracker server查找要下载文件所在的的Storage server。
6. Tracker server向Client返回包含指定文件的某个Storage server的IP地址和端口号。
7. Client直接通过Tracker server返回的IP地址和端口与其中一台Storage server建立连接并指定要下载文件。
8. 下载文件成功。
2.1.5 引入FastDFS的依赖
见前述pom.xml文件
2.1.6 引入配置类
注入FastDFS客户端:
@Configuration
@Import(FdfsClientConfig.class)
// 解决jmx重复注册bean的问题
@EnableMBeanExport(registration = RegistrationPolicy.IGNORE_EXISTING)
public class FastClientImporter {}
2.1.7 配置FastDFS属性
见前述application.yml文件
2.2 代码实现
2.2.1 controller
@RestController
@RequestMapping("upload")
public class UploadController {@Autowiredprivate UploadService uploadService;@PostMapping("image")public ResponseEntity<String> uploadImage(@RequestParam("file")MultipartFile file){String url = uploadService.uploadImage(file);return ResponseEntity.ok(url);}
}
2.2.2 service
@Service
@Slf4j
public class UploadService {@Autowiredprivate FastFileStorageClient storageClient;//文件上传的最终地址private static final List<String> ALLOWTYPES = Arrays.asList("image/jpeg","image/png");public String uploadImage(MultipartFile file) {try {//校验格式String contentType = file.getContentType();if(!ALLOWTYPES.contains(contentType)){throw new LyException(ExceptionEnum.CONTENT_TYPE_ERROE);}//校验内容BufferedImage image = ImageIO.read(file.getInputStream());if(image == null){throw new LyException(ExceptionEnum.INVALID_IMAGE_ERROE);}/*//准备目标路径File dest = new File("D:/javacode/idea/upload/", file.getOriginalFilename());//保存到本地file.transferTo(dest);*///上传到FastDFSString extension = StringUtils.substringAfterLast(file.getOriginalFilename(), ".");StorePath storePath = storageClient.uploadFile(file.getInputStream(), file.getSize(), extension, null);//System.out.println(storePath.getFullPath());//返回路径return "http://image.leyou.com/" + storePath.getFullPath();} catch (Exception e) {log.error("文件上传失败", e);throw new LyException(ExceptionEnum.UPLOAD_FAILED_ERROE);}}
}
这一篇写的也太乱了点…
乐优商城:笔记(六):上传微服务:LyUpload相关推荐
- 乐优商城笔记六:商品详情页
使用模板引擎 Thymeleaf + nginx 完成商品详情页静态化 完成乐优商城商品详情页 搭建商品详情页微服务 创建子工程 GroupId:com.leyou.service ArtifactI ...
- 乐优商城day15(redis,短信微服务)
所有代码发布在 [https://github.com/hades0525/leyou] Redis • 1.指令 • 1.1通用指令 o keys 获取符合规则的键名列表 keys pattern( ...
- 在项目开发时创建上传微服务,我们一些纠结的点
微服务除了可以进行业务处理之外,也可以针对上传功能进行创建,所有的上传微服务依然需要向Eureka中注册,这样就可以在zuul中进行微服务代理操作. 注意:不建议构建上传微服务 在实 ...
- 3.从零开始搭建基于SpringCloud的京东整站_文件上传微服务
本次目标 本次实现的目标:实现图片上传微服务. 文件上传在很多项目和很多模块都要用到,所以将其单独作为一个微服务. 如下图蓝色箭头所示:FileUploadMicroservice 静态资源 本案例图 ...
- 乐优商城笔记-商城系统功能编写
索引数据库导入 创建搜索微服务 new module Group id:com.leyou.search Artifactid: leyou-search Module name:leyou-sear ...
- 乐优商城第六篇:域名访问与品牌查询
域名访问与品牌查询 使用域名访问本地项目 统一环境 域名解析 解决域名解析问题 nginx解决端口问题 什么是Nginx nginx作为web服务器 nginx作为反向代理 安装和使用 反向代理配置 ...
- 乐优商城架构介绍(一)
一.架构图 二.微服务模块 1 网关微服务ly-gateway:10010 不管是来自于客户端(PC或移动端)的请求,还是服务内部调用.一切对服务的请求都会经过Zuul这个网关,然后再由网关来实现 鉴 ...
- 乐优商城源码/数据库及笔记总结
文章目录 1 源码 2 笔记 2.1 项目概述 2.2 微服务 3 项目优化 4 项目或学习过程中涉及到的设计模式 5 安全问题 6 高内聚低耦合的体现 7 项目中待优化的地方 1 源码 Github ...
- 【javaWeb微服务架构项目——乐优商城day15】——会调用订单系统接口,实现订单结算功能,实现微信支付功能
0.学习目标 会调用订单系统接口 实现订单结算功能 实现微信支付功能 源码笔记及资料: 链接:https://pan.baidu.com/s/1_opfL63P1pzH3rzLnbFiNw 提取码:v ...
最新文章
- python 如何查看模块所有方法-Python查看模块函数,查看函数方法的详细信息
- /dev、/sys/dev 和/sys/devices 和udev的关系
- 安装多个java后,java版本不对
- 一起来看流星雨剧情简介/剧情介绍/剧情分集介绍第六集
- 大佬!莫言获颁第13个荣誉博士学位
- php学习总结,PHP学习的技巧和学习的要素总结
- 95-10-132-启动-TransactionCoordinator-源码
- 无法为jsp编译类_《刺激战场》改名为《和平精英》,有2类玩家或可能无法登陆游戏...
- php公众号后台,微信公众号后台管理系统
- 图片转excel软件有哪些?这些软件你值得拥有
- django generic view - ListView
- 树莓派python摄像头文字识别_古德微树莓派摄像头文字识别
- Unity Editor 基础篇(三):自定义窗口
- Lab3:自行车码表
- 计算机视觉最新研究方向,计算机视觉的主要研究的内容是什么?,计算机视觉研究方向...
- pathon真的那么好用吗?
- 华硕主板M2N-电源跳线怎么接
- java-net-php-python-12ssm商家后台管理系统计算机毕业设计程序
- 蓝桥ROS之f1tenth简单PID沿墙跑起来(Python)
- Android WebView 精简Demo
热门文章
- squid 3 反向代理 缓存服务器 安装配置精华指南 by lbj
- 3.6 常用符号在数据输入中的使用 [原创Excel教程]
- 1.RecyclerView设置clipToPadding=“false“,scrollbars无法跟随列表滚动到底部的解决方案
- Shell显示系统时间的全年日
- (Tiled官方文档翻译)第四节:对象的编辑和使用
- 2D 游戏工具系列:unity自带Tilemap和地图编辑器Tiled的基本使用以及Super Tiled2Unity如何导入tmx到Unity中(2)
- 【硬件基础】舵机基础知识
- 小木虫好中的ei期刊图像处理
- 智能手表的突破和新发展机遇
- 清华大学计算机国际大赛,动态 | 清华大学超算团队摘得 SC 2018 总冠军,包揽三大国际大学生超算竞赛总冠军...