精华内容
下载资源
问答
  • 文件存储微服务搭建

    2019-08-15 01:14:32
    创建文件管理微服务service_file,该工程主要用于实现文件上传以及文件删除等功能。 (1)修改pom.xml,引入依赖 <?xml version="1.0" encoding="UTF-8"?> <project xmlns=...

    创建文件管理微服务service_file,该工程主要用于实现文件上传以及文件删除等功能。

    (1)修改pom.xml,引入依赖

    <?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>service-file</artifactId>
            <groupId>com.gzy</groupId>
            <version>1.0-SNAPSHOT</version>
        </parent>
        <modelVersion>4.0.0</modelVersion>
    
        <artifactId>service_file</artifactId>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
            <dependency>
                <groupId>net.oschina.zcx7878</groupId>
                <artifactId>fastdfs-client-java</artifactId>
                <version>1.27.0.0</version>
            </dependency>
            <dependency>
                <groupId>com.changgou</groupId>
                <artifactId>changgou_common</artifactId>
                <version>1.0-SNAPSHOT</version>
            </dependency>
        </dependencies>
    </project>

    (2)在resources文件夹下创建fasfDFS的配置文件fdfs_client.conf

    connect_timeout = 60
    network_timeout = 60
    charset = UTF-8
    http.tracker_http_port = 8080
    tracker_server = 192.168.200.128:22122

    connect_timeout:连接超时时间,单位为秒。

    network_timeout:通信超时时间,单位为秒。发送或接收数据时。假设在超时时间后还不能发送或接收数据,则本次网络通信失败

    charset: 字符集

    http.tracker_http_port :.tracker的http端口

    tracker_server: tracker服务器IP和端口设置

    (3)在resources文件夹下创建application.yml

    spring:
      servlet:
        multipart:
          max-file-size: 10MB  #单个文件大小
          max-request-size: 10MB #设置总上传文件大小
      application:
        name: file  #微服务的应用名称
    server:
      port: 9007
    eureka:
      client:
        service-url:
          defaultZone: http://127.0.0.1:6868/eureka
      instance:
        prefer-ip-address: true
    feign:
      hystrix:
        enabled: true

    max-file-size是单个文件大小,max-request-size是设置总上传的数据大小

    (4)启动类,创建启动类FileApplication

    @SpringBootApplication
    @EnableEurekaClient
    public class FileApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(FileApplication.class);
        }
    }
    展开全文
  • 分布式文件存储FastDFS(SpringBoot微服务搭建) ​ FastDFS是一个开源的轻量级分布式文件系统,它对文件进行管理,功能包括:文件存储、文件同步、文件访问(文件上传、文件下载)等,解决了大容量存储和负载均衡的...

    分布式文件存储FastDFS(SpringBoot微服务搭建)

    ​ FastDFS是一个开源的轻量级分布式文件系统,它对文件进行管理,功能包括:文件存储、文件同步、文件访问(文件上传、文件下载)等,解决了大容量存储和负载均衡的问题。特别适合以文件为载体的在线服务,如相册网站、视频网站等等。

    ​ FastDFS为互联网量身定制,充分考虑了冗余备份、负载均衡、线性扩容等机制,并注重高可用、高性能等指标,使用FastDFS很容易搭建一套高性能的文件服务器集群提供文件上传、下载等服务。

    ​ FastDFS 架构包括 Tracker server 和 Storage server。客户端请求 Tracker server 进行文件上传、下载,通过Tracker server 调度最终由 Storage server 完成文件上传和下载。

    ​ Tracker server 作用是负载均衡和调度,通过 Tracker server 在文件上传时可以根据一些策略找到Storage server 提供文件上传服务。可以将 tracker 称为追踪服务器或调度服务器。Storage server 作用是文件存储,客户端上传的文件最终存储在 Storage 服务器上,Storageserver 没有实现自己的文件系统而是利用操作系统的文件系统来管理文件。可以将storage称为存储服务器。

    • 图解:
      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OmiWhlmi-1585656023576)(C:\Users\86132\Desktop\1559117928459.png)]在这里插入图片描述

    • 上传图解:
      在这里插入图片描述

    • 客户端上传文件后存储服务器将文件 ID 返回给客户端,此文件 ID 用于以后访问该文件的索引信息。文件索引信息包括:组名,虚拟磁盘路径,数据两级目录,文件名。

    在这里插入图片描述

    组名:文件上传后所在的 storage 组名称,在文件上传成功后有storage 服务器返回,需要客户端自行保存。

    虚拟磁盘路径:storage 配置的虚拟路径,与磁盘选项store_path*对应。如果配置了

    store_path0 则是 M00,如果配置了 store_path1 则是 M01,以此类推。

    数据两级目录:storage 服务器在每个虚拟磁盘路径下创建的两级目录,用于存储数据

    文件。

    文件名:与文件上传时不同。是由存储服务器根据特定信息生成,文件名包含:源存储

    服务器 IP 地址、文件创建时间戳、文件大小、随机数和文件拓展名等信息。

    一丶docker搭建FastDFS开发环境

    • 拉取镜像

      docker pull morunchang/fastdfs
      
    • 运行tracker

      docker run -d --name tracker --net=host morunchang/fastdfs sh tracker.sh
      
    • 运行storage

      docker run -d --name storage --net=host -e TRACKER_IP=<your tracker server address>:22122 -e GROUP_NAME=<group name> morunchang/fastdfs sh storage.sh
      
    • 使用的网络模式是–net=host, 替换为你机器的Ip即可

    • 是组名,即storage的组

    • 如果想要增加新的storage服务器,再次运行该命令,注意更换 新组名

    • 修改nginx的配置

      • 进入storage的容器内部,修改nginx.conf
    docker exec -it storage  /bin/bash
    

    ​ 进入后

    vi /data/nginx/conf/nginx.conf
    

    ​ 添加以下内容

    location /group1/M00 {
       proxy_next_upstream http_502 http_504 error timeout invalid_header;
         proxy_cache http-cache;
         proxy_cache_valid  200 304 12h;
         proxy_cache_key $uri$is_args$args;
         proxy_pass http://fdfs_group1;
         expires 30d;
     }
    
    • 退出容器
    exit
    
    • 重启storage容器
    docker restart storage
    

    二丶文件存储微服务

    创建文件管理微服务changgou_service_file,该工程主要用于实现文件上传以及文件删除等功能。

    • 引入依赖

      <dependencies>
          <dependency>
              <groupId>org.springframework.boot</groupId>
              <artifactId>spring-boot-starter-web</artifactId>
          </dependency>
          <dependency>
              <groupId>net.oschina.zcx7878</groupId>
              <artifactId>fastdfs-client-java</artifactId>
              <version>1.27.0.0</version>
          </dependency>
          <dependency>
              <groupId>com.changgou</groupId>
              <artifactId>changgou_common</artifactId>
              <version>1.0-SNAPSHOT</version>
          </dependency>
      </dependencies>
      
    • 在resources文件夹下创建fasfDFS的配置文件fdfs_client.conf

      connect_timeout = 60
      network_timeout = 60
      charset = UTF-8
      http.tracker_http_port = 8080
      tracker_server = 192.168.200.128:22122
      
      • connect_timeout:连接超时时间,单位为秒。
      • network_timeout:通信超时时间,单位为秒。发送或接收数据时。假设在超时时间后还不能发送或接收数据,则本次网络通信失败
      • charset: 字符集
      • http.tracker_http_port :.tracker的http端口
      • tracker_server: tracker服务器IP和端口设置
    • 在resources文件夹下创建application.yml

      spring:
        servlet:
          multipart:
            max-file-size: 10MB
            max-request-size: 10MB
      server:
        port: 9008
      eureka:
        client:
          service-url:
            defaultZone: http://127.0.0.1:6868/eureka
        instance:
          prefer-ip-address: true
      feign:
        hystrix:
          enabled: true
      

      max-file-size是单个文件大小,max-request-size是设置总上传的数据大小

    • 创建启动类FileApplication

      @SpringBootApplication
      @EnableEurekaClient
      public class FileApplication {public static void main(String[] args) {
              SpringApplication.run(FileApplication.class);
          }
      }
      

    三丶文件上传文件信息封装

    ​ 文件上传一般都有文件的名字、文件的内容、文件的扩展名、文件的md5值、文件的作者等相关属性,我们可以创建一个对象封装这些属性,代码如下:

    • FastDFSFile.class

      public class FastDFSFile {
          //文件名字
          private String name;
          //文件内容
          private byte[] content;
          //文件扩展名
          private String ext;
          //文件MD5摘要值
          private String md5;
          //文件创建作者
          private String author;
      
          public FastDFSFile(String name, byte[] content, String ext, String height,
                             String width, String author) {
              super();
              this.name = name;
              this.content = content;
              this.ext = ext;
              this.author = author;
          }
      
          public FastDFSFile(String name, byte[] content, String ext) {
              super();
              this.name = name;
              this.content = content;
              this.ext = ext;
          }
      
          // getter and setter ...
      }
      

    四丶文件操作工具类

    public class FastDFSClient {
    
        private static org.slf4j.Logger logger = LoggerFactory.getLogger(FastDFSClient.class);
    
        /***
         * 初始化加载FastDFS的TrackerServer配置
         */
        static {
            try {
                String filePath = new ClassPathResource("fdfs_client.conf").getFile().getAbsolutePath();
                ClientGlobal.init(filePath);
            } catch (Exception e) {
                logger.error("FastDFS Client Init Fail!",e);
            }
        }
    
        /***
         * 文件上传
         * @param file
         * @return 1.文件的组名 2.文件的路径信息
         */
        public static String[] upload(FastDFSFile file) {
            //获取文件的作者
            NameValuePair[] meta_list = new NameValuePair[1];
            meta_list[0] = new NameValuePair("author", file.getAuthor());
    
            //接收返回数据
            String[] uploadResults = null;
            StorageClient storageClient=null;
            try {
                //创建StorageClient客户端对象
                storageClient = getTrackerClient();
    
                /***
                 * 文件上传
                 * 1)文件字节数组
                 * 2)文件扩展名
                 * 3)文件作者
                 */
                uploadResults = storageClient.upload_file(file.getContent(), file.getExt(), meta_list);
            } catch (Exception e) {
                logger.error("Exception when uploadind the file:" + file.getName(), e);
            }
    
            if (uploadResults == null && storageClient!=null) {
                logger.error("upload file fail, error code:" + storageClient.getErrorCode());
            }
            //获取组名
            String groupName = uploadResults[0];
            //获取文件存储路径
            String remoteFileName = uploadResults[1];
            return uploadResults;
        }
    
        /***
         * 获取文件信息
         * @param groupName:组名
         * @param remoteFileName:文件存储完整名
         * @return
         */
        public static FileInfo getFile(String groupName, String remoteFileName) {
            try {
                StorageClient storageClient = getTrackerClient();
                return storageClient.get_file_info(groupName, remoteFileName);
            } catch (Exception e) {
                logger.error("Exception: Get File from Fast DFS failed", e);
            }
            return null;
        }
    
        /***
         * 文件下载
         * @param groupName
         * @param remoteFileName
         * @return
         */
        public static InputStream downFile(String groupName, String remoteFileName) {
            try {
                //创建StorageClient
                StorageClient storageClient = getTrackerClient();
    
                //下载文件
                byte[] fileByte = storageClient.download_file(groupName, remoteFileName);
                InputStream ins = new ByteArrayInputStream(fileByte);
                return ins;
            } catch (Exception e) {
                logger.error("Exception: Get File from Fast DFS failed", e);
            }
            return null;
        }
    
        /***
         * 文件删除
         * @param groupName
         * @param remoteFileName
         * @throws Exception
         */
        public static void deleteFile(String groupName, String remoteFileName)
                throws Exception {
            //创建StorageClient
            StorageClient storageClient = getTrackerClient();
    
            //删除文件
            int i = storageClient.delete_file(groupName, remoteFileName);
        }
    
        /***
         * 获取Storage组
         * @param groupName
         * @return
         * @throws IOException
         */
        public static StorageServer[] getStoreStorages(String groupName)
                throws IOException {
            //创建TrackerClient
            TrackerClient trackerClient = new TrackerClient();
            //获取TrackerServer
            TrackerServer trackerServer = trackerClient.getConnection();
            //获取Storage组
            return trackerClient.getStoreStorages(trackerServer, groupName);
        }
    
        /***
         * 获取Storage信息,IP和端口
         * @param groupName
         * @param remoteFileName
         * @return
         * @throws IOException
         */
        public static ServerInfo[] getFetchStorages(String groupName,
                                                    String remoteFileName) throws IOException {
            TrackerClient trackerClient = new TrackerClient();
            TrackerServer trackerServer = trackerClient.getConnection();
            return trackerClient.getFetchStorages(trackerServer, groupName, remoteFileName);
        }
    
        /***
         * 获取Tracker服务地址
         * @return
         * @throws IOException
         */
        public static String getTrackerUrl() throws IOException {
            return "http://"+getTrackerServer().getInetSocketAddress().getHostString()+":"+ClientGlobal.getG_tracker_http_port()+"/";
        }
    
        /***
         * 获取Storage客户端
         * @return
         * @throws IOException
         */
        private static StorageClient getTrackerClient() throws IOException {
            TrackerServer trackerServer = getTrackerServer();
            StorageClient storageClient = new StorageClient(trackerServer, null);
            return  storageClient;
        }
    
        /***
         * 获取Tracker
         * @return
         * @throws IOException
         */
        private static TrackerServer getTrackerServer() throws IOException {
            TrackerClient trackerClient = new TrackerClient();
            TrackerServer trackerServer = trackerClient.getConnection();
            return  trackerServer;
        }
    }
    
    

    五丶文件上传测试,创建一个FileController.在该控制器中实现文件上传操作

    @RestController
    @RequestMapping("/file")
    public class FileController {@PostMapping("/upload")
        public Result uploadFile(MultipartFile file){
            try{
                //判断文件是否存在
                if (file == null){
                    throw new RuntimeException("文件不存在");
                }
                //获取文件的完整名称
                String originalFilename = file.getOriginalFilename();
                if (StringUtils.isEmpty(originalFilename)){
                    throw new RuntimeException("文件不存在");
                }//获取文件的扩展名称  abc.jpg   jpg
                String extName = originalFilename.substring(originalFilename.lastIndexOf(".") + 1);//获取文件内容
                byte[] content = file.getBytes();//创建文件上传的封装实体类
                FastDFSFile fastDFSFile = new FastDFSFile(originalFilename,content,extName);//基于工具类进行文件上传,并接受返回参数  String[]
                String[] uploadResult = FastDFSClient.upload(fastDFSFile);//封装返回结果
                String url = FastDFSClient.getTrackerUrl()+uploadResult[0]+"/"+uploadResult[1];
                return new Result(true,StatusCode.OK,"文件上传成功",url);
            }catch (Exception e){
                e.printStackTrace();
            }
            return new Result(false, StatusCode.ERROR,"文件上传失败");
        }
    }
    

    六丶测试:(Postman测试)

    步骤:

    1、选择post请求方式,输入请求地址 http://localhost:9008/upload

    2、填写Headers

    Key:Content-Type
    Value:multipart/form-data
    

    3、填写body

    选择form-data 然后选择文件file 点击添加文件,最后发送即可。上传后可通过返回值查看对应的file

    展开全文
  • 下面,我们将借助Spring Cloud OAuth和Spring Cloud Security搭建一个统一给微服务发放访问令牌的认证服务器elsa-auth。 Oauth2协议简介 在微服务架构下,我们通常根据不同的业务来构建不同的微服务子系统,各个子...

    通常的,单体架构,我们会采用Shiro对系统做防护以及权限控制。在搭建微服务系统时,同样也要对资源做保护,只有通过认证的资源才能被访问。下面,我们将借助Spring Cloud OAuth和Spring Cloud Security搭建一个统一给微服务发放访问令牌的认证服务器elsa-auth。

    Oauth2协议简介

    在微服务架构下,我们通常根据不同的业务来构建不同的微服务子系统,各个子系统对外提供相应的服务。客户端除了浏览器外,还可能是手机App,小程序等。在微服务架构出现之前,我们的系统一般为单体模式,客户端只是单一的浏览器,所以通常情况下都是通过Session进行客户端,服务端通信,Session模式有个弊端,就是在一般存在于应用内,而随着客户端种类越来越多,这种交互方式变得越来越困难(当然可以通过Session缓存化的方式来解决),于是OAuth协议应运而生。

    OAuth是一种用来规范令牌(Token)发放的授权机制,目前最新版本为2.0,其主要包含了四种授权模式:授权码模式、简化模式、密码模式和客户端模式。Spring Cloud OAuth对这四种授权模式进行了实现。如有不理解的,可以访问如下阮一峰介绍的Oauth2。

    1. OAuth 2.0 的一个简单解释
    2. OAuth 2.0 的四种方式

    由于我们的前端系统是通过用户名和密码来登录系统的,所以我们选用密码模式。

    认证服务器搭建

    创建认证服务器子项目

    File==>新建==>Other==>搜索Maven,选择Maven Module,然后Next
    在这里插入图片描述
    填写Module Name:elsa-auth,点击Next
    在这里插入图片描述
    一直Next至FInish为止,创建完成,项目结构如下
    在这里插入图片描述
    右键点击Elsa-Auth项目:点击Java Build Path,在Resouce资源下创建资源目录resources。
    在这里插入图片描述
    Elsa-Auth完整目录结构
    在这里插入图片描述
    认证服务器项目已经创建完成,下面我们做相关依赖和配置。

    认证服务器引入依赖

    <?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">
        <modelVersion>4.0.0</modelVersion>
        <parent>
            <groupId>com.elsa</groupId>
            <artifactId>elsa-cloud</artifactId>
            <version>1.0-SNAPSHOT</version>
        </parent>
    
        <artifactId>elas-auth</artifactId>
        <name>Elsa-Auth</name>
        <description>Elsa-Cloud认证服务器</description>
    
        <dependencies>
            <dependency>
                <groupId>com.elsa</groupId>
                <artifactId>elsa-common</artifactId>
                <version>1.0-SNAPSHOT</version>
            </dependency>
        </dependencies>
    
        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                </plugin>
            </plugins>
        </build>
    </project>
    

    通用模块引入依赖

    在elsa-common模块引入相关依赖

            <!-- redis -->
    		<dependency>
    		    <groupId>org.springframework.boot</groupId>
    		    <artifactId>spring-boot-starter-data-redis</artifactId>
    		</dependency>  
    		<!-- eureka client -->
    		<dependency>
    		    <groupId>org.springframework.cloud</groupId>
    		    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
    		</dependency>
    
    • spring-boot-starter-data-redis
      -因为后续我们需要将认证服务器生成的Token存储到Redis中,并且Redis依赖可能会被多个微服务使用到

    • spring-cloud-starter-netflix-eureka-client
      -因为每个微服务都可能需要通过Eureka客户端将服务注册到注册中心,所以将依赖添加到通用模块,以方便其他微服务依赖。

    认证服务器人口类

    @EnableDiscoveryClient
    @SpringBootApplication
    public class ElsaAuthApp 
    {
        public static void main(String[] args) {
            SpringApplication.run(ElsaAuthApp.class, args);
        }
    }
    

    @EnableDiscoveryClient注解,用于开启服务注册与发现功能

    基本配置文件配置

    编写配置文件application.yml,Eureka相关配置的含义已通过注解体现,可自行查看。在application.yml如果没有配置Redis相关配置,则采用的是Redis默认配置,但是为了更为直观,建议还是在application.yml中添加Resis配置。

    server:
      port: 8101
    
    spring:
      application:
        name: Elsa-Auth
      # redis相关配置
      redis:
        database: 0
        host: 127.0.0.1
        port: 6379
        jedis:
          pool:
            min-idle: 8
            max-idle: 500
            max-active: 2000
            max-wait: 10000
        timeout: 5000    
    
    eureka:
      instance:
        # 向Eureka 服务端发送心跳的间隔时间,单位为秒,用于服务续约。这里配置为20秒,即每隔20秒向febs-register发送心跳,表明当前服务没有宕机
        lease-renewal-interval-in-seconds: 20
      client:
        # 为true时表示将当前服务注册到Eureak服务端
        register-with-eureka: true
        # 为true时表示从Eureka 服务端获取注册的服务信息
        fetch-registry: true
        # 新实例信息的变化到Eureka服务端的间隔时间,单位为秒
        instance-info-replication-interval-seconds: 30
        # 默认值为30秒,即每30秒去Eureka服务端上获取服务并缓存,这里指定为3秒的原因是方便开发时测试,实际可以指定为默认值即可;
        registry-fetch-interval-seconds: 3
        serviceUrl:
          # 指定Eureka服务端地址
          defaultZone: http://elsa:123456@localhost:8001/register/eureka/
    

    安全配置类

    认证安全配置类

    首先我们需要定义一个WebSecurity类型的认证安全配置类ElsaSecurityConfigure,在com.elsa.auth路径下新增configure包,然后在configure包下新增ElsaSecurityConfigure类,代码如下所示:

    @Order(2)	// 增加过滤链的优先级,因为ElsaResourceServerConfigure的优先级为3
    @EnableWebSecurity	// 开启和Web相关的安全配置
    public class ElsaSecurityConfigure extends WebSecurityConfigurerAdapter {
    
        @Autowired
        private ElsaUserDetailService userDetailService;
    
        @Bean
        public PasswordEncoder passwordEncoder() {
            return new BCryptPasswordEncoder();//一个相同的密码,每次加密出来的加密串都不同
        }
    
        
        // 一个相同的密码,每次加密出来的加密串都不同
        public static void main(String[] args) {
            String password = "123456";
            PasswordEncoder encoder = new BCryptPasswordEncoder();
            System.out.println(encoder.encode(password));
            System.out.println(encoder.encode(password));
        }
        
        //密码模式需要使用到这个Bean:AuthenticationManager
        @Bean
        @Override
        public AuthenticationManager authenticationManagerBean() throws Exception {
            return super.authenticationManagerBean();
        }
    
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.requestMatchers()
                    .antMatchers("/oauth/**")	//安全配置类只对/oauth/开头的请求有效
                .and()
                    .authorizeRequests()
                    .antMatchers("/oauth/**").authenticated()
                .and()
                    .csrf().disable();
        }
    
        @Override
        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
            auth.userDetailsService(userDetailService).passwordEncoder(passwordEncoder());
        }
    }
    
    
    • @EnableWebSecurity
      注解标注,开启了和Web相关的安全配置
    • PasswordEncoder
      该类是一个接口,定义了几个和密码加密校验相关的方法,这里我们使用的是Spring Security内部实现好的BCryptPasswordEncoder(也可以自己实现PasswordEncoder接口)。BCryptPasswordEncoder的特点就是,对于一个相同的密码,每次加密出来的加密串都不同:
        // 一个相同的密码,每次加密出来的加密串都不同
        public static void main(String[] args) {
            String password = "123456";
            PasswordEncoder encoder = new BCryptPasswordEncoder();
            System.out.println(encoder.encode(password));
            System.out.println(encoder.encode(password));
        }
    

    运行该main方法,可以看到两次输出的结果并不一样:

    $2a$10$CztjcNZW8xMlol4EAN/L8eroQly7NZfZe5lNcih.arCEd9MDwkHAi
    $2a$10$Jstxp5K0rsp6xocA70M.aOfCYkrdZFV/6mIacOKb6ZtnpBN.r1waK
    
    • authenticationManagerBean
      注册了一个authenticationManagerBean,因为密码模式需要使用到这个Bean
    • configure(HttpSecurity http)方法
      requestMatchers().antMatchers("/oauth/**")的含义是:ElsaSecurityConfigure安全配置类只对/oauth/开头的请求有效
    • configure(AuthenticationManagerBuilder auth)方法
      重写了configure(AuthenticationManagerBuilder auth)方法,指定了userDetailsService和passwordEncoder
    • ElsaUserDetailService
    资源安全配置类

    虽然我们现在正在搭建的是一个认证服务器,但是认证服务器本身也可以对外提供REST服务,比如通过Token获取当前登录用户信息,注销当前Token等,所以它也是一台资源服务器。于是我们需要定义一个资源服务器的配置类,在com.elsa.auth.configure包下新建ElsaResourceServerConfigure类:

    @Configuration
    @EnableResourceServer	//开启资源服务器相关配置
    public class ElsaResourceServerConfigure extends ResourceServerConfigurerAdapter {
    
        @Override
        public void configure(HttpSecurity http) throws Exception {
            http.csrf().disable()
                    .requestMatchers().antMatchers("/**")	//表明该安全配置对所有请求都生效
                    .and()
                    .authorizeRequests()
                    .antMatchers("/**").authenticated();
        }
    }
    
    
    • @EnableResourceServer
      用于开启资源服务器相关配置
    • ResourceServerConfigurerAdapter
    • configure(HttpSecurity http)方法
      通过requestMatchers().antMatchers("/**")的配置表明该安全配置对所有请求都生效

    相信看到这里的人会发现,ElsaSecurityConfigure和ElsaResourceServerConfigure两个配置的功能似乎是一样的,都是对请求过滤的。
    ElsaSecurityConfigure对/oauth/开头的请求生效,而ElsaResourceServerConfigure对所有请求都生效,那么当一个请求进来时,到底哪个安全配置先生效?其实并没有哪个配置先生效这么一说,当在Spring Security中定义了多个过滤器链的时候,根据其优先级,只有优先级较高的过滤器链会先进行匹配。
    那么ElsaSecurityConfigure和ElsaResourceServerConfigure的优先级是多少?首先我们查看ElsaSecurityConfigure继承的类WebSecurityConfigurerAdapter的源码:

    @Order(100)
    public abstract class WebSecurityConfigurerAdapter implements WebSecurityConfigurer<WebSecurity> {
       ......
    }
    

    可以看到类上使用了@Order(100)标注,说明其顺序是100。
    再来看看ElsaResourceServerConfigure类上@EnableResourceServer注解源码:

    @Target({ElementType.TYPE})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Import({ResourceServerConfiguration.class})
    public @interface EnableResourceServer {
    }
    

    该注解引入了ResourceServerConfiguration配置类,查看ResourceServerConfiguration源码:

    @Configuration
    public class ResourceServerConfiguration extends WebSecurityConfigurerAdapter implements Ordered {
        private int order = 3;
        ......
    }
    

    所以ElsaResourceServerConfigure的顺序是3。在Spring中,数字越小,优先级越高,也就是说ElsaResourceServerConfigure的优先级要高于ElsaSecurityConfigure,这也就意味着所有请求都会被ElsaResourceServerConfigure过滤器链处理,包括/oauth/开头的请求。这显然不是我们要的效果,我们原本是希望以/oauth/开头的请求由ElsaSecurityConfigure过滤器链处理,剩下的其他请求由ElsaResourceServerConfigure过滤器链处理。

    为了解决上面的问题,我们可以手动指定这两个类的优先级,让ElsaSecurityConfigure的优先级高于ElsaResourceServerConfigure。在ElsaSecurityConfigure类上使用Order(2)注解标注即可:

    @Order(2)
    @EnableWebSecurity
    public class ElsaSecurityConfigure extends WebSecurityConfigurerAdapter {
        ......
    }
    

    ElsaSecurityConfigure和ElsaResourceServerConfigure的区别:

    ElsaSecurityConfigure用于处理/oauth开头的请求,Spring Cloud OAuth内部定义的获取令牌,刷新令牌的请求地址都是以/oauth/开头的,也就是说FebsSecurityConfigure用于处理和令牌相关的请求;
    ElsaResourceServerConfigure用于处理非/oauth/开头的请求,其主要用于资源的保护,客户端只能通过OAuth2协议发放的令牌来从资源服务器中获取受保护的资源。

    授权配置类

    接着我们定义一个和认证服务器相关的授权配置类。在configure包下新建ElsaAuthorizationServerConfigure,配置的解释在代码中体现,代码如下所示:

    @Configuration
    @EnableAuthorizationServer	//开启认证服务器相关配置
    public class ElsaAuthorizationServerConfigure extends AuthorizationServerConfigurerAdapter {
    
        @Autowired
        private AuthenticationManager authenticationManager;
        @Autowired
        private RedisConnectionFactory redisConnectionFactory;
        @Autowired
        private ElsaUserDetailService userDetailService;
        @Autowired
        private PasswordEncoder passwordEncoder;
    
        /**
         * 1.客户端从认证服务器获取令牌的时候,必须使用client_id为elsa,client_secret为123456的标识来获取;
    	 * 2. 该client_id支持password模式获取令牌,并且可以通过refresh_token来获取新的令牌;
     	 * 3. 在获取client_id为elsa的令牌的时候,scope只能指定为all,否则将获取失败
         */
        @Override
        public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
            clients.inMemory()
            		// 需要指定多个client,可以继续使用withClient配置
                    .withClient("elsa")
                    .secret(passwordEncoder.encode("123456"))
                    .authorizedGrantTypes("password", "refresh_token")
                    .scopes("all");
        }
    	// tokenStore使用的是RedisTokenStore,认证服务器生成的令牌将被存储到Redis中
        @Override
        public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
            endpoints.tokenStore(tokenStore())
                    .userDetailsService(userDetailService)
                    .authenticationManager(authenticationManager)
                    .tokenServices(defaultTokenServices());
        }
        
        // 认证服务器生成的令牌将被存储到Redis中
        @Bean
        public TokenStore tokenStore() {
            return new RedisTokenStore(redisConnectionFactory);
        }
    
        @Primary
        @Bean
        public DefaultTokenServices defaultTokenServices() {
            DefaultTokenServices tokenServices = new DefaultTokenServices();
            tokenServices.setTokenStore(tokenStore());
            // 设置为true表示开启刷新令牌的支持
            tokenServices.setSupportRefreshToken(true);
            // 指定了令牌的基本配置,比如令牌有效时间为60 * 60 * 24秒,刷新令牌有效时间为60 * 60 * 24 * 7秒
            tokenServices.setAccessTokenValiditySeconds(60 * 60 * 24);
            tokenServices.setRefreshTokenValiditySeconds(60 * 60 * 24 * 7);
            return tokenServices;
        }
    }
    
    

    其他相关类

    ElsaUserDetailService

    ElsaSecurityConfigure及ElsaAuthorizationServerConfigure用到的ElsaUserDetailService。在com.elsa.auth路径下新增service包,然后在service包下新增ElsaUserDetailService类,代码如下所示:

    @Service
    public class ElsaUserDetailService implements UserDetailsService {
    
        @Autowired
        private PasswordEncoder passwordEncoder;
    
        @Override
        public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
            ElsaAuthUser user = new ElsaAuthUser();
            user.setUsername(username);
            user.setPassword(this.passwordEncoder.encode("123456"));
    
            return new User(username, user.getPassword(), user.isEnabled(),
                    user.isAccountNonExpired(), user.isCredentialsNonExpired(),
                    user.isAccountNonLocked(), AuthorityUtils.commaSeparatedStringToAuthorityList("user:add"));
        }
    }
    

    ElsaUserDetailService实现了UserDetailsService接口的loadUserByUsername方法,主要用于校验用户账号和密码,以及授权等,我们模拟了一个用户,用户名为用户输入的用户名,密码为123456(后期再改造为从数据库中获取用户),然后返回org.springframework.security.core.userdetails.User。这里使用的是User类包含7个参数的构造器,其还包含一个三个参数的构造器User(String username, String password,Collection<? extends GrantedAuthority> authorities),由于权限参数不能为空,所以这里先使用AuthorityUtils.commaSeparatedStringToAuthorityList方法模拟一个user:add权限。

    ElsaAuthUser

    loadUserByUsername方法返回一个UserDetails对象,该对象也是一个接口,包含一些用于描述用户信息的方法,源码如下:

    public interface UserDetails extends Serializable {
    	//获取用户包含的权限,返回权限集合,权限是一个继承了GrantedAuthority的对象;
        Collection<? extends GrantedAuthority> getAuthorities();
    	//用于获取密码和用户名;
        String getPassword();
    	//方法返回boolean类型,用于判断账户是否未过期,未过期返回true反之返回false;
        String getUsername();
    	//方法用于判断账户是否未锁定;
        boolean isAccountNonExpired();
    	//用于判断用户凭证是否没过期,即密码是否未过期;
        boolean isAccountNonLocked();
    
        boolean isCredentialsNonExpired();
    	//方法用于判断用户是否可用。
        boolean isEnabled();
    }
    

    实际中我们可以自定义UserDetails接口的实现类,也可以直接使用Spring Security提供的UserDetails接口实现类org.springframework.security.core.userdetails.User。

    ElsaUserDetailService中ElsaAuthUser为我们自定义的用户实体类,代表我们从数据库中查询出来的用户。我们在febs-common中定义该实体类,在elsa-cmmon模块下新增com.elsa.common.entity包,然后在entity包下新增ElsaAuthUser:

    public class ElsaAuthUser implements Serializable {
        private static final long serialVersionUID = -1748289340320186418L;
    
        private String username;
    
        private String password;
    
        private boolean accountNonExpired = true;
    
        private boolean accountNonLocked= true;
    
        private boolean credentialsNonExpired= true;
    
        private boolean enabled= true;
    
    	public String getUsername() {
    		return username;
    	}
    
    	public void setUsername(String username) {
    		this.username = username;
    	}
    
    	public String getPassword() {
    		return password;
    	}
    
    	public void setPassword(String password) {
    		this.password = password;
    	}
    
    	public boolean isAccountNonExpired() {
    		return accountNonExpired;
    	}
    
    	public void setAccountNonExpired(boolean accountNonExpired) {
    		this.accountNonExpired = accountNonExpired;
    	}
    
    	public boolean isAccountNonLocked() {
    		return accountNonLocked;
    	}
    
    	public void setAccountNonLocked(boolean accountNonLocked) {
    		this.accountNonLocked = accountNonLocked;
    	}
    
    	public boolean isCredentialsNonExpired() {
    		return credentialsNonExpired;
    	}
    
    	public void setCredentialsNonExpired(boolean credentialsNonExpired) {
    		this.credentialsNonExpired = credentialsNonExpired;
    	}
    
    	public boolean isEnabled() {
    		return enabled;
    	}
    
    	public void setEnabled(boolean enabled) {
    		this.enabled = enabled;
    	}
        
        
    }
    

    SecurityController

    最后定义一个Controller,对外提供一些REST服务。在com.elsa.auth路径下新增controller包,在controller包下新增SecurityController:

    @RestController
    public class SecurityController {
    	@Autowired
        private ConsumerTokenServices consumerTokenServices;
    
        @GetMapping("oauth/test")
        public String testOauth() {
            return "oauth";
        }
    	//currentUser用户获取当前登录用户
        @GetMapping("user")
        public Principal currentUser(Principal principal) {
            return principal;
        }
    	//signout方法通过ConsumerTokenServices来注销当前Token
        @DeleteMapping("signout")
        public ElsaResponse signout(HttpServletRequest request) throws ElsaAuthException {
            String authorization = request.getHeader("Authorization");
            String token = StringUtils.replace(authorization, "bearer ", "");
            ElsaResponse elsaResponse = new ElsaResponse();
            if (!consumerTokenServices.revokeToken(token)) {
                throw new ElsaAuthException("退出登录失败");
            }
            return elsaResponse.message("退出登录成功");
        }
    }
    

    ElsaResponse

    ElsaResponse为系统的统一相应格式,我们在elsa-common模块中定义它,在elsa-common模块的com.elsa.common.entity路径下新增ElsaResponse类:

    public class ElsaResponse extends HashMap<String, Object> {
    
        private static final long serialVersionUID = -8713837118340960775L;
    
        public ElsaResponse message(String message) {
            this.put("message", message);
            return this;
        }
    
        public ElsaResponse data(Object data) {
            this.put("data", data);
            return this;
        }
    
        @Override
        public ElsaResponse put(String key, Object value) {
            super.put(key, value);
            return this;
        }
    
        public String getMessage() {
            return String.valueOf(get("message"));
        }
    
        public Object getData() {
            return get("data");
        }
    }
    
    

    ElsaAuthException

    ElsaAuthException为自定义异常,在elsa-common模块com.elsa.common路径下新增exception包,然后在该包下新增ElsaAuthException:

    public class ElsaAuthException extends Exception{
    
        private static final long serialVersionUID = -6916154462432027437L;
    
        public ElsaAuthException(String message){
            super(message);
        }
    }
    

    PostMan测试

    分别启动如下应用
    1.redis
    2.ElsaRegesterApp
    3.ElsaAuthApp

    测试令牌获取

    在这里插入图片描述
    grant_type填password,表示密码模式,然后填写用户名和密码,根据我们定义的ElsaUserDetailService逻辑,这里用户名随便填,密码必须为123456。
    除了这几个参数外,我们需要在请求头中配置Authorization信息,否则请求将返回401:
    值为Basic加空格加client_id:client_secret(就是在ElsaAuthorizationServerConfigure类configure(ClientDetailsServiceConfigurer clients)方法中定义的client和secret)经过base64加密后的值(可以使用http://tool.oschina.net/encrypt?type=3):
    在这里插入图片描述
    点击Send结果如下
    在这里插入图片描述
    查看Redis
    在这里插入图片描述

    获取受保护资源

    我们已经成功获取了访问令牌access_token,接下来使用这个令牌去获取/user资源。

    使用PostMan发送 localhost:8101/user GET请求,带上令牌,可以看到已经成功返回了数据。
    在这里插入图片描述

    /oauth/test测试

    接着我们使用PostMan发送 localhost:8101/oauth/test GET请求:
    在这里插入图片描述
    可以看到,虽然我们在请求头中已经带上了正确的令牌,但是并没有成功获取到资源,正如前面所说的那样,/oauth/开头的请求由ElsaSecurityConfigure定义的过滤器链处理,它不受资源服务器配置管理,所以使用令牌并不能成功获取到资源。

    注销测试

    在这里插入图片描述
    注销成功后Redis中数据已清空
    在这里插入图片描述

    刷新令牌

    然后使用refresh_token去换取新的令牌,使用PostMan发送 localhost:8101/oauth/token POST请求,请求参数如下:
    刷新令牌在Headers添加参数:
    Authorization=Basic ZWxzYToxMjM0NTY=
    Params中添加两个参数:
    grant_type=refresh_token
    refresh_token=登录时得到的refresh_token
    在这里插入图片描述
    在这里插入图片描述
    可以看到,成功获取到了新的令牌。

    源码下载

    源码地址:认证服务器

    展开全文
  • 这一节我们将使用Spring Cloud Zuul搭建微服务网关elsa-gateway。 网关服务器搭建 创建认证服务器子项目 File==>新建==>Other==>搜索Maven,选择Maven Module,然后Next 填写Module Name:elsa-gateway,

    在微服务的架构中,服务网关就是一个介于客户端与服务端之间的中间层。在这种情况下,客户端只需要跟服务网关交互,无需调用具体的微服务接口。这样的好处在于,客户端可以降低复杂性,无需关注具体是哪个微服务在提供服务。这一节我们将使用Spring Cloud Zuul搭建微服务网关elsa-gateway。

    网关服务器搭建

    创建认证服务器子项目

    File==>新建==>Other==>搜索Maven,选择Maven Module,然后Next
    在这里插入图片描述
    填写Module Name:elsa-gateway,点击Next
    在这里插入图片描述
    在这里插入图片描述

    一直Next至FInish为止,创建完成,项目结构如下
    在这里插入图片描述
    网关服务器项目已经创建完成,下面我们做相关依赖和配置。

    网关服务器引入依赖

    <?xml version="1.0"?>
    <project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
      <modelVersion>4.0.0</modelVersion>
      <parent>
        <groupId>com.elsa</groupId>
        <artifactId>elsa-cloud</artifactId>
        <version>1.0-SNAPSHOT</version>
      </parent>
        <artifactId>elsa-gateway</artifactId>
        <name>Elsa-Gateway</name>
        <description>Elsa-Gateway微服务网关</description>
    
        <dependencies>
            <dependency>
                <groupId>com.elsa</groupId>
                <artifactId>elsa-common</artifactId>
                <version>1.0-SNAPSHOT</version>
            </dependency>
             <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
            </dependency>
        </dependencies>
    
        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                </plugin>
            </plugins>
        </build>
    
    </project>
    
    

    网关服务器人口类

    @EnableZuulProxy
    @EnableDiscoveryClient
    @SpringBootApplication
    public class ElsaGatewayApp {
        public static void main(String[] args) {
            SpringApplication.run(ElsaGatewayApp.class, args);
        }
    }
    
    • @EnableDiscoveryClient注解,开启服务注册与发现
    • @EnableZuulProxy注解,开启Zuul服务网关功能

    基本配置文件配置

    在resources目下下创建application.xml文件,配置如下

    server:
      port: 8301
    
    spring:
      application:
        name: Elsa-Gateway
    
    zuul:
      routes:
        auth:
          # 以/auth开头的请求都会被转发到名称为Elsa-Auth的服务上
          path: /auth/**
          # 服务名
          serviceId: Elsa-Auth
          # 由于我们需要在请求头中携带令牌,所以sensitiveHeaders设置为*,表示不过滤请求头信息,即请求的请求头信息将原封不动的转发出去
          sensitiveHeaders: "*"
      # 设置为true时,表示开启重试机制;
      retryable: true
      # Zuul配合Eureka后会有一套默认的配置规则,这里我们只想请求根据我们显示配置的路由规则走,所以设置为*,表示关闭所有默认路由配置规则;
      ignored-services: "*"
      ribbon:
        eager-load:
          # Zuul内部通过Ribbon按照一定的负载均衡算法来获取服务,Ribbon进行客户端负载均衡的Client并不是在服务启动的时候就初始化好的,而是在调用的时候才会去创建相应的Client,所以第一次调用的耗时不仅仅包含发送HTTP请求的时间,还包含了创建RibbonClient的时间,这样一来如果创建时间速度较慢,同时设置的超时时间又比较短的话,第一次请求很容易出现超时的情况。设置为true的时候表示开启Ribbon的饥饿加载模式,即在应用启动的时候就去获取相应的Client备用。
          enabled: true
    
    ribbon:
      # 设置请求超时时间,单位为毫秒;
      ReadTimeout: 3000
    
    eureka:
      instance:
        # 向Eureka 服务端发送心跳的间隔时间,单位为秒,用于服务续约。这里配置为20秒,即每隔20秒向febs-register发送心跳,表明当前服务没有宕机
        lease-renewal-interval-in-seconds: 20
      client:
        # 为true时表示将当前服务注册到Eureak服务端
        register-with-eureka: true
        # 为true时表示从Eureka 服务端获取注册的服务信息
        fetch-registry: true
        # 新实例信息的变化到Eureka服务端的间隔时间,单位为秒
        instance-info-replication-interval-seconds: 30
        # 默认值为30秒,即每30秒去Eureka服务端上获取服务并缓存,这里指定为3秒的原因是方便开发时测试,实际可以指定为默认值即可;
        registry-fetch-interval-seconds: 3
        serviceUrl:
          # 指定Eureka服务端地址
          defaultZone: http://elsa:123456@localhost:8001/register/eureka/
    

    此文件主要配置eureka与zuul相关配置,主要说明请看注释。

    web安全配置类

    在elsa-gateway模块下的com.elsa.gateway路径下新增configure包,然后在该包下新增ElsaGatewaySecurityConfigure配置类:

    @EnableWebSecurity
    public class ElsaGatewaySecurityConfigure extends WebSecurityConfigurerAdapter {
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.csrf().disable();
        }
    }
    

    因为elsa-gateway引入了elsa-common模块,elsa-common模块包含了Spring Cloud Security依赖,所以我们需要定义一个自己的WebSecurity配置类,来覆盖默认的。这里主要是关闭了csrf功能,否则会报csrf相关异常。

    banner

    resources目录下新增banner.txt,具体参照从零开始搭建微服务:微服务注册中心

    PostMan测试

    分别启动应用
    1.redis
    2.ElsaRegesterApp
    3.ElsaAuthApp
    4.ElsaGateway
    PostMan测试内容与从零开始搭建微服务:认证服务器内容相似,主要是把端口由认证服务器的8101改为8301即可,就不再一一说明。

    测试令牌获取

    在这里插入图片描述

    获取受保护资源

    在这里插入图片描述

    /oauth/test测试

    在这里插入图片描述

    注销测试在这里插入图片描述

    刷新令牌

    在这里插入图片描述
    可以看到,认证服务器的几个测试都可以成功。

    源码下载

    源码地址:网关服务器

    展开全文
  • 文章目录一、框架搭建 (话说,如果只会增删改查,很容易被代码生成器取代 ???? 。) 一、框架搭建 需要知道 通用Mapper 和 PageHelper,
  • 微服务架构中,服务之间有着错综复杂的依赖关系,每一个服务都有本身的依赖配置,在运行期间不少配置会根据访问流量等因素进行调整,传统的配置信息处理方式是将配置信息写入xml、.properties等配置文件中,和应用...
  • Nginx微服务搭建-下载器 1、pcre软件安装 准备目录:mkdir -p /data/{server, softs}/nginx 切换目录:cd /data/softs 下载:wget ...
  • 1.微服务网关Gateway 不同的微服务一般会有不同的网络地址,而外部客户端可能需要调用多个服务的接 口才能完成一个业务需求,如果让客户端直接与各个微服务通信,会有以下的问题: 1.客户端会多次请求不同的...
  • SpringCloud微服务搭建过程记录

    千次阅读 2019-04-25 11:16:59
    公司为了微服务技术落地,采用SpringCloud搭建,但网上好多搭建过程真正使用的很少,所以自己记录了下来。方便后期查看, 微服务主要包含服务注册,服务发现,服务路由,服务配置,服务熔断,服务降级等一系列的...
  • Eureka由两个组件组成:Eureka服务器和Eureka客户端。Eureka服务器用作服务注册服务器。 Eureka客户端是一个java客户端,用来简化与服务器的交互、作为轮询负载均衡器,并提供服务的故障切换支持。 Netflix在其生产...
  • 接上一篇:Spring cloud微服务搭建(五)——Eureka注册服务 Ribbon是Netflix发布的开源项目,提供客户端的软件负载均衡算法。 Ribbon属于进程内负载均衡,作为一个类库,集成于消费方进程中。消费方通过ribbon连接到...
  • 极光推送Springboot微服务搭建教程

    千次阅读 2018-07-19 22:19:46
    前言: 本文介绍Spring boot 项目中如何搭建极光推送服务,并已将极光推...你只需在极光官网申请密钥,使用本文提供的配置和源码,5分钟即可搭建完极光推送的后端微服务。 一.服务端配置文件 在项目的applicatio...
  • 二、微服务各组件的用途1.eureka(注册中心)2.ribbon(负载均衡)3.zuul(网关)4.Hystrix(熔断器)三、微服务搭建(仔细看内容,最后有源码)1.eureka集群的搭建2.订单服务搭建3.仓库服务搭建4.网关服务搭建...
  • 学习计划安排如下: 继续后台管理系统的学习 昨天是搭建了前端页面,今天开始后端微服务搭建。 基础微服务、商品微服务搭建,本身还未涉及到具体的业务处理。 其中有一个比较复杂的点在于自定义异常。 一、创建...
  • 最初的解决方案:把视频当作静态资源放在Java SpringBoot微服务的静态文件里,每个视频对应一个播放的H5页面; 弊端: (1)视频越来越多(近10G),调试慢,且打包后jar太大; (2)每增加一个视频就需要写一个页面...
  • 整理这个的前提是因为一个移动的供应链的项目要做微服务,所以开始搭建,然后就申请了三台服务器准备搭建微服务框架 微服务测试环境主机随意,我申请的是超级电脑,重点是便宜。 三台机对微服务做对应Spring...
  • 因为spring cloud 配置中心默认用Git存储相关文件,所以在 application.properties 中添加Git相关配置。 spring.application.name = ebook-config-server server.port = 9100 #将服务注册到注册中心 eureka....
  • docker pull consul docker run --name=consul -p 8500:8500 -e CONSUL_BIND_INTERFACE=eth0 -d consul 访问页面 http://192.168.2.200:8500/ 四、启动服务器 进入hyperf-db容器启动服务提供者 cd /hyperf-db ...
  • 文件上传服务 1.分析页面请求 请求方式: POST 请求路径: upload/image,(这里我在Zuul网关中...请求参数:file 返回值:String Url (这里返回值为一个图片存储的路径字符串) 2.创建一个上传文件微服务 2.1导入相...
  • 微服务环境搭建

    2018-08-16 14:45:38
    一. 前置条件 1.1 服务器、vpn和git申请 ... 把微服务平台的配置文件派生一份作为自己的git仓库,比如,https://gitfh.com/fh_HIS/XXX(当前项目开发环境配置中心)https://gitfh.com/xrchenggit...
  • 1.Eureka简介 Eureka是Netflix开源的一款提供服务注册和发现的产品,它提供了完整的Service Registry和Service Discovery实现。也是springcloud体系中最重要最核心的组件之一。...而系统中的其他微服务,使用...
  • springCloud 微服务框架搭建入门

    万次阅读 2019-01-18 22:23:26
    有了服务发现与注册,你就不需要整天改服务调用的配置文件了,你只需要使用服务的标识符,就可以访问到服务。 cloud-eureka-server:eureka注册服务器 cloud-simple-service:一个使用mybatis的数据库应用,服务端...
  • FastDFS是一个开源的轻量级分布式文件系统,它对文件进行管理,功能包括:文件存储、文件同步、文件访问(文件上传、文件下载)等,解决了大容量存储和负载均衡的问题。特别适合以文件为载体的在线服务,如相册网站...
  • 上回说到,使用python搭建一个简易的web下载服务器,但是这个简易的服务器客户端不能够上传文件。这次来搭建一个简易的ftp服务器,来提供文件的下载和上传功能。一、首先我们来安装提供服务的pyftpdlib模块pip ...
  •  最近研究了一下springCloud的微服务集群,主要用到了SpringCloud的服务发现和服务器端负载均衡,所有的项目都是用的springboot,可以和springCloud无缝对接。 技术选型 服务发现:eureka 负载均衡:zuul ...
  • 本次先不管网关,先搭套微服务例子。包含一个注册中心eureka,两个生产者微服务,一个消费者微服务。生产消费者之间可使用RestTemplate直接调用http接口,也可使用feign调用。导入actuator依赖,feign简单搭配...
  • 微服务基础----搭建Eureka服务器

    千次阅读 2019-04-23 19:00:19
    1、pom文件里导入依赖:我用的是1.5.9版本,jdk用的1.8的 <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> ...
  • (整个项目的源码在最后一章,感兴趣的童鞋可以下载自己搭建试试,也可以将其作为脚手架搭建你自己的微服务) 二、搭建注册中心 在dubbo中,每一个服务都是分布式的,消费者与提供者的关系并不是一对一的关系,而是一...
  • Centos8搭建nfs共享服务器,注意第三步需要启动nfs实现微服务接口服务器的集群部署、上传文件保存到通过NFS服务器共享磁盘,微服务接口服务器1:192.168.3.3微服务接口服务器2:192.168.3.4微服务接口服务器3:192....

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 21,789
精华内容 8,715
关键字:

微服务搭建文件服务器