zoukankan      html  css  js  c++  java
  • Springcloud分布式服务如何保证会话一致性

      在Springcloud分布式项目中,服务与服务之间调用是非常常见的。有时候服务与服务间调用的时候涉及到用户的身份,比如当前登录的用户的身份获取与传递。

      在之前boot单体应用前后端分离的时候,常见的两种方式,一种是基于session机制+nginx代理;另一种是基于token,也就是每个请求的header中携带token,token的值就是当前登录的标识,可以是后端返回的一个UUID,该UUID对应redis的一个key,每次访问根据UUID从redis获取到当前用户的信息。

    1. sessionId不一致问题

      基于feign调用的sessionId不一致问题。

    1. 被调用方controller(payment服务)

        @GetMapping("/getSessionId")
        public JSONResultUtil<Map<String, Object>> getSessionId() {
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
                    .getRequest();
            String id = sessionId();
            System.out.println(id);
            Cookie[] cookies = request.getCookies();
            if (ArrayUtils.isNotEmpty(cookies)) {
                System.out.println("====S cookie");
                for (Cookie cookie : cookies) {
                    System.out.println(cookie.getName() + "	" + cookie.getValue());
                }
                System.out.println("====E cookie");
            }
            Enumeration<String> headerNames = request.getHeaderNames();
            System.out.println("====S header");
            while (headerNames.hasMoreElements()) {
                String s = headerNames.nextElement();
                System.out.println(s + "	" + request.getHeader(s));
            }
            System.out.println("====E header");
    
            HashMap<String, Object> stringObjectHashMap = new HashMap<>();
            stringObjectHashMap.put("payment", id);
            return JSONResultUtil.successWithData(stringObjectHashMap);
        }
    
        public String sessionId() {
            RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
            if (requestAttributes == null) {
                return null;
            }
            HttpServletRequest request = ((ServletRequestAttributes) requestAttributes).getRequest();
            return request.getSession().getId();
        }    

    2.调用方(order服务)

    1.Controller

        /************s 测试获取sessionId*********/
        @GetMapping("/getSessionId")
        public JSONResultUtil<Map<String, Object>> getSessionId() {
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
                    .getRequest();
            String id = sessionId();
            System.out.println(id);
            Cookie[] cookies = request.getCookies();
            if (ArrayUtils.isNotEmpty(cookies)) {
                System.out.println("====S cookie");
                for (Cookie cookie : cookies) {
                    System.out.println(cookie.getName() + "	" + cookie.getValue());
                }
                System.out.println("====E cookie");
            }
            Enumeration<String> headerNames = request.getHeaderNames();
            System.out.println("====S header");
            while (headerNames.hasMoreElements()) {
                String s = headerNames.nextElement();
                System.out.println(s + "	" + request.getHeader(s));
            }
            System.out.println("====E header");
    
            HashMap<String, Object> stringObjectHashMap = new HashMap<>();
            stringObjectHashMap.put("order", id);
            Map<String, Object> data = paymentHystrixService.getSessionId().getData();
            stringObjectHashMap.putAll(data);
            return JSONResultUtil.successWithData(stringObjectHashMap);
        }
    
        public String sessionId() {
            RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
            if (requestAttributes == null) {
                return null;
            }
            HttpServletRequest request = ((ServletRequestAttributes) requestAttributes).getRequest();
            return request.getSession().getId();
        }
        /************E 测试获取sessionId*********/

    2.Feign接口

    package cn.qz.cloud.service;
    
    import cn.qz.cloud.utils.JSONResultUtil;
    import org.springframework.cloud.openfeign.FeignClient;
    import org.springframework.stereotype.Component;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.PathVariable;
    
    import java.util.Map;
    
    /**
     * @Author: qlq
     * @Description
     * @Date: 14:31 2020/10/18
     */
    @Component
    // 只调用,不降级。
    @FeignClient(value = "CLOUD-PROVIDER-HYSTRIX-PAYMENT")
    //@FeignClient(value = "CLOUD-PROVIDER-HYSTRIX-PAYMENT", fallback = PaymentFallbackService.class)
    public interface PaymentHystrixService {
    
        @GetMapping("/hystrix/payment/getSessionId")
        JSONResultUtil<Map<String, Object>> getSessionId();
    }

    3. 启动后测试

    1.访问接口

    liqiang@root MINGW64 /e/IDEAWorkSpace/cloud (master)
    $ curl http://localhost:8011//consumer/hystrix/payment/getSessionId
      % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                     Dload  Upload   Total   Spent    Left  Speed
    100   139    0   139    0     0   1275      0 --:--:-- --:--:-- --:--:--  1782{"success":true,"code":"200","msg":"","data":{"payment":"30e4e45e-258e-499f-9170-e9c7e0f4acb7","order":"6A261DF8C0CBFB3867FA1DE3A785D7FA"}}

    2.order服务日志

    6A261DF8C0CBFB3867FA1DE3A785D7FA
    ====S header
    host    localhost:8011
    user-agent    curl/7.54.1
    accept    */*
    ====E header

    3. payment日志

    30e4e45e-258e-499f-9170-e9c7e0f4acb7
    ====S header
    accept    */*
    user-agent    Java/1.8.0_121
    host    root:8081
    connection    keep-alive
    ====E header

      可以看到两个服务的sessionId不一样。

    2. 引入Spring-session解决会话共享-session信息存入redis

    用第一个服务payment服务测试。

    1.pom增加

            <!--session 共享-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-redis</artifactId>
                <version>1.4.4.RELEASE</version>
            </dependency>
            <dependency>
                <groupId>org.springframework.session</groupId>
                <artifactId>spring-session-data-redis</artifactId>
            </dependency>
            <dependency>
                <groupId>redis.clients</groupId>
                <artifactId>jedis</artifactId>
            </dependency>

    2.yml增加配置

    spring:
      application:
        name: cloud-provider-hystrix-payment
      redis:
        port: 6379
        host: localhost
      session:
        store-type: redis

      上面关于redis合session的配置也是默认的配置,可以参考:org.springframework.boot.autoconfigure.session.SessionProperties 和 org.springframework.boot.autoconfigure.data.redis.RedisProperties。

    3. 修改Controller

        @GetMapping("/getSessionId")
        public JSONResultUtil<Map<String, Object>> getSessionId() {
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
                    .getRequest();
    
            // 模拟当前用户登录 zs 存进去
            request.getSession().setAttribute("currentUser", "zs");
    
            String id = sessionId();
            System.out.println(id);
            Cookie[] cookies = request.getCookies();
            if (ArrayUtils.isNotEmpty(cookies)) {
                System.out.println("====S cookie");
                for (Cookie cookie : cookies) {
                    System.out.println(cookie.getName() + "	" + cookie.getValue());
                }
                System.out.println("====E cookie");
            }
            Enumeration<String> headerNames = request.getHeaderNames();
            System.out.println("====S header");
            while (headerNames.hasMoreElements()) {
                String s = headerNames.nextElement();
                System.out.println(s + "	" + request.getHeader(s));
            }
            System.out.println("====E header");
    
            HashMap<String, Object> stringObjectHashMap = new HashMap<>();
            stringObjectHashMap.put("payment", id);
            stringObjectHashMap.put("paymentCurrentUser", request.getSession().getAttribute("currentUser"));
            return JSONResultUtil.successWithData(stringObjectHashMap);
        }
    
        public String sessionId() {
            RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
            if (requestAttributes == null) {
                return null;
            }
            HttpServletRequest request = ((ServletRequestAttributes) requestAttributes).getRequest();
            return request.getSession().getId();
        }

    4.测试:

    1.curl:

    $ curl http://localhost:8081/hystrix/payment/getSessionId
      % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                     Dload  Upload   Total   Spent    Left  Speed
    100   122    0   122    0     0    748      0 --:--:-- --:--:-- --:--:--   753{"success":true,"code":"200","msg":"","data":{"paymentCurrentUser":"zs","payment":"a8547342-c959-4209-a964-b58f60585a10"}}

    2.控制台日志如下:

    a8547342-c959-4209-a964-b58f60585a10
    ====S header
    host    localhost:8081
    user-agent    curl/7.71.1
    accept    */*
    ====E header

    3. 用浏览器访问查看返回的响应头如下:

     可以看到,返回的setcookie中SESSION为:ZmViZjBkM2YtNGQ5Zi00ZGU3LThjZjAtNDE3MzgxNWNmZDhj。 SESSION也是Spring-session存sessionId的name,tomcat默认的为JSESSIONID。

    程序控制台日志如下:

    febf0d3f-4d9f-4de7-8cf0-4173815cfd8c
    ====S cookie
    sensorsdata2015jssdkcross    %7B%22distinct_id%22%3A%2217608e35e0b169-09416062df57be-51a2f73-1327104-17608e35e0c18d%22%2C%22%24device_id%22%3A%2217608e35e0b169-09416062df57be-51a2f73-1327104-17608e35e0c18d%22%2C%22props%22%3A%7B%22%24latest_referrer%22%3A%22url%E7%9A%84domain%E8%A7%A3%E6%9E%90%E5%A4%B1%E8%B4%A5%22%2C%22%24latest_referrer_host%22%3A%22url%E7%9A%84domain%E8%A7%A3%E6%9E%90%E5%A4%B1%E8%B4%A5%22%2C%22%24latest_traffic_source_type%22%3A%22url%E7%9A%84domain%E8%A7%A3%E6%9E%90%E5%A4%B1%E8%B4%A5%22%2C%22%24latest_search_keyword%22%3A%22url%E7%9A%84domain%E8%A7%A3%E6%9E%90%E5%A4%B1%E8%B4%A5%22%7D%7D
    ====E cookie
    ====S header
    accept    text/html, application/xhtml+xml, image/jxr, */*
    accept-language    zh-Hans-CN,zh-Hans;q=0.5
    user-agent    Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko
    accept-encoding    gzip, deflate
    host    127.0.0.1:8081
    connection    Keep-Alive
    cookie    sensorsdata2015jssdkcross=%7B%22distinct_id%22%3A%2217608e35e0b169-09416062df57be-51a2f73-1327104-17608e35e0c18d%22%2C%22%24device_id%22%3A%2217608e35e0b169-09416062df57be-51a2f73-1327104-17608e35e0c18d%22%2C%22props%22%3A%7B%22%24latest_referrer%22%3A%22url%E7%9A%84domain%E8%A7%A3%E6%9E%90%E5%A4%B1%E8%B4%A5%22%2C%22%24latest_referrer_host%22%3A%22url%E7%9A%84domain%E8%A7%A3%E6%9E%90%E5%A4%B1%E8%B4%A5%22%2C%22%24latest_traffic_source_type%22%3A%22url%E7%9A%84domain%E8%A7%A3%E6%9E%90%E5%A4%B1%E8%B4%A5%22%2C%22%24latest_search_keyword%22%3A%22url%E7%9A%84domain%E8%A7%A3%E6%9E%90%E5%A4%B1%E8%B4%A5%22%7D%7D
    ====E header

    注意:

    (1)这里发行程序打出的会话ID,sessionId为:febf0d3f-4d9f-4de7-8cf0-4173815cfd8c,而程序返回给设置Cookie头的是:ZmViZjBkM2YtNGQ5Zi00ZGU3LThjZjAtNDE3MzgxNWNmZDhj。其实ZmViZjBkM2YtNGQ5Zi00ZGU3LThjZjAtNDE3MzgxNWNmZDh 是base64 编码之后的,我们经过base64 解码后就是febf0d3f-4d9f-4de7-8cf0-4173815cfd8c,这也是Spring-session 默认做的操作。 可以参考类:org.springframework.session.web.http.DefaultCookieSerializer。 

    (2)到redis查看如下:

    127.0.0.1:6379> keys *
    1) "spring:session:sessions:expires:febf0d3f-4d9f-4de7-8cf0-4173815cfd8c"
    2) "spring:session:expirations:1610786700000"
    3) "spring:session:sessions:febf0d3f-4d9f-4de7-8cf0-4173815cfd8c"
    127.0.0.1:6379> hget spring:session:sessions:febf0d3f-4d9f-4de7-8cf0-4173815cfd8c
    (error) ERR wrong number of arguments for 'hget' command
    127.0.0.1:6379> keys *
    1) "spring:session:sessions:expires:febf0d3f-4d9f-4de7-8cf0-4173815cfd8c"
    2) "spring:session:expirations:1610786700000"
    3) "spring:session:sessions:febf0d3f-4d9f-4de7-8cf0-4173815cfd8c"
    127.0.0.1:6379> hlen spring:session:sessions:febf0d3f-4d9f-4de7-8cf0-4173815cfd8c
    (integer) 4
    127.0.0.1:6379> hgetall spring:session:sessions:febf0d3f-4d9f-4de7-8cf0-4173815cfd8c
    1) "maxInactiveInterval"
    2) "xacxedx00x05srx00x11java.lang.Integerx12xe2xa0xa4xf7x81x878x02x00x01Ix00x05valuexrx00x10java.lang.Numberx86xacx95x1dx0bx94xe0x8bx02x00x00xpx00x00a"
    3) "lastAccessedTime"
    4) "xacxedx00x05srx00x0ejava.lang.Long;x8bxe4x90xccx8f#xdfx02x00x01Jx00x05valuexrx00x10java.lang.Numberx86xacx95x1dx0bx94xe0x8bx02x00x00xpx00x00x01w
    BDs"
    5) "creationTime"
    6) "xacxedx00x05srx00x0ejava.lang.Long;x8bxe4x90xccx8f#xdfx02x00x01Jx00x05valuexrx00x10java.lang.Numberx86xacx95x1dx0bx94xe0x8bx02x00x00xpx00x00x01w
    BDs"
    7) "sessionAttr:currentUser"
    8) "xacxedx00x05tx00x02zs"

      可以看到存到session中的属性也被存储到redis中

    补充:如果想去掉base编码或者修改cookie中session的名称,可以用手动注入一个CookieSerializer,亲测有效

    package cn.qz.cloud.config;
    
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.session.web.http.CookieSerializer;
    import org.springframework.session.web.http.DefaultCookieSerializer;
    
    /**
     * @author: 乔利强
     * @date: 2021/1/16 16:29
     * @description:
     */
    @Configuration
    public class SpringSessionConfiguration {
    
        @Bean
        public CookieSerializer defaultCookieSerializer() {
            DefaultCookieSerializer defaultCookieSerializer = new DefaultCookieSerializer();
            defaultCookieSerializer.setUseBase64Encoding(false);
            defaultCookieSerializer.setCookieName("mysession");
            return defaultCookieSerializer;
        }
    }

    测试:访问后返回的响应头如下:

      这种做法是Spring在自动注入的时候留了个入口:参考类:org.springframework.session.config.annotation.web.http.SpringHttpSessionConfiguration。 自动注入的时候非必须,在代码中判断注入的为null就使用默认配置。

     补充:Spring-session封装了session,同时抽取了操作的工具类

    1.接口如下:

    //
    // Source code recreated from a .class file by IntelliJ IDEA
    // (powered by FernFlower decompiler)
    //
    
    package org.springframework.session;
    
    public interface SessionRepository<S extends Session> {
        S createSession();
    
        void save(S var1);
    
        S findById(String var1);
    
        void deleteById(String var1);
    }

    2.测试:

        @Autowired
        private SessionRepository sessionRepository;
    
        @GetMapping("/test")
        public void test() {
            Session byId = sessionRepository.findById(sessionId());
            System.out.println(ToStringBuilder.reflectionToString(byId, ToStringStyle.MULTI_LINE_STYLE));
        }

    3.访问后控制台如下:

    org.springframework.session.data.redis.RedisIndexedSessionRepository$RedisSession@a2fcd88[
    cached=org.springframework.session.MapSession@a2aeb552
    originalLastAccessTime=2021-01-16T08:49:30.766Z
    delta={}
    isNew=false
    originalPrincipalName=<null>
    originalSessionId=5fddf9ec-53fe-4f73-8205-7d3a3f9431a8
    ]

    3. Order调用者服务配置Feign调用的时候携带请求头,可以做到session共享

    1.修改被调用者服务payment

        @GetMapping("/getSessionId")
        public JSONResultUtil<Map<String, Object>> getSessionId() {
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
                    .getRequest();
            String id = sessionId();
    
            System.out.println(id);
            Cookie[] cookies = request.getCookies();
            if (ArrayUtils.isNotEmpty(cookies)) {
                System.out.println("====S cookie");
                for (Cookie cookie : cookies) {
                    System.out.println(cookie.getName() + "	" + cookie.getValue());
                }
                System.out.println("====E cookie");
            }
            Enumeration<String> headerNames = request.getHeaderNames();
            System.out.println("====S header");
            while (headerNames.hasMoreElements()) {
                String s = headerNames.nextElement();
                System.out.println(s + "	" + request.getHeader(s));
            }
            System.out.println("====E header");
    
            HashMap<String, Object> stringObjectHashMap = new HashMap<>();
            stringObjectHashMap.put("payment", id);
            stringObjectHashMap.put("paymentCurrentUser", request.getSession().getAttribute("currentUser"));
            return JSONResultUtil.successWithData(stringObjectHashMap);
        }
    
        public String sessionId() {
            RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
            if (requestAttributes == null) {
                return null;
            }
            HttpServletRequest request = ((ServletRequestAttributes) requestAttributes).getRequest();
            return request.getSession().getId();
        }

    2.修改调用者Order

    1.修改Controller

        /************s 测试获取sessionId*********/
        @GetMapping("/getSessionId")
        public JSONResultUtil<Map<String, Object>> getSessionId() {
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
                    .getRequest();
    
            // 模拟登录成功之后存user信息
            request.getSession().setAttribute("currentUser", "张三");
            String id = sessionId();
            System.out.println(id);
    
            HashMap<String, Object> stringObjectHashMap = new HashMap<>();
            stringObjectHashMap.put("order", id);
            stringObjectHashMap.put("orderCurrentUser", request.getSession().getAttribute("currentUser"));
            Map<String, Object> data = paymentHystrixService.getSessionId().getData();
            stringObjectHashMap.putAll(data);
            return JSONResultUtil.successWithData(stringObjectHashMap);
        }
    
        public String sessionId() {
            RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
            if (requestAttributes == null) {
                return null;
            }
            HttpServletRequest request = ((ServletRequestAttributes) requestAttributes).getRequest();
            return request.getSession().getId();
        }
        /************E 测试获取sessionId*********/

    2.修改Feign调用的时候增加header(实际cookie也是在header中传递的,header的key为cookie)

    package cn.qz.cloud.config;
    
    import com.google.common.collect.Lists;
    import feign.Logger;
    import feign.RequestInterceptor;
    import feign.RequestTemplate;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.web.context.request.RequestAttributes;
    import org.springframework.web.context.request.RequestContextHolder;
    import org.springframework.web.context.request.ServletRequestAttributes;
    
    import javax.servlet.http.HttpServletRequest;
    import java.util.*;
    
    /**
     * @author: 乔利强
     * @date: 2020/12/30 20:35
     * @description:
     */
    @Configuration
    @Slf4j
    public class FeignConfiguration {
    
        public final static String HEADER_CALLER = "cloud_caller";
    
        public final static String COOKIE_COOKIE_NAME = "cookie";
        public final static String SESSIONID_COOKIE_NAME = "SESSION";
    
        @Value("${spring.application.name}")
        String application;
    
        // 对系统中允许后向传递的头进行控制
        private static List<String> disallowhHeaderNames = Lists.newArrayList(
                "cache-control"
                , "origin"
                , "upgrade-insecure-requests"
                , "user-agent"
                , "referer"
                , "accept"
                , "accept-language"
                , "connection"
        );
    
        @Bean
        public RequestInterceptor requestHeaderInterceptor() {
            return new RequestInterceptor() {
                @Override
                public void apply(RequestTemplate requestTemplate) {
                    //记录调用方信息
                    requestTemplate.header(HEADER_CALLER, application);
                    if (RequestContextHolder.getRequestAttributes() == null) {
                        return;
                    }
    
                    // 注意子线程问题(RequestContextHolder 内部使用的是ThreadLocal)
                    HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
                            .getRequest();
                    // 当前请求携带的header
                    Enumeration<String> headerNames = request.getHeaderNames();
                    // 已经存在feign的requestTemplate的header
                    Map<String, Collection<String>> headers = requestTemplate.headers();
                    if (headerNames != null) {
                        while (headerNames.hasMoreElements()) {
                            String name = headerNames.nextElement();
                            boolean exists = false; // 避免重复header往后传播,如content-type传播会影响后续body解析
                            for (String th : headers.keySet()) {
                                if (name.equalsIgnoreCase(th)) {// 忽略大小写
                                    exists = true;
                                    break;
                                }
                            }
                            if (!exists && !disallowhHeaderNames.contains(name.toLowerCase())) {
                                requestTemplate.header(name, Collections.list(request.getHeaders(name)));
                            }
                        }
                    }
                }
            };
        }
    
        private String sessionId() {
            RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
            if (requestAttributes == null) {
                return null;
            }
            HttpServletRequest request = ((ServletRequestAttributes) requestAttributes).getRequest();
            return request.getSession().getId();
        }
    
        @Bean
        Logger.Level feignLoggerLevel() {
            return Logger.Level.FULL;
        }
    
        /**
         * 自定义feignlogger
         *
         * @return
         */
        @Bean
        public feign.Logger feignLogger() {
            return new FeignLogger();
        }
    }

    3.测试

    1. 访问http://localhost:8011/consumer/hystrix/payment/getSessionId, 返回结果如下:

    {"success":true,"code":"200","msg":"","data":{"orderCurrentUser":"张三","paymentCurrentUser":"张三","payment":"53972a2b-9324-4078-8446-268e13071f06","order":"53972a2b-9324-4078-8446-268e13071f06"}}

    2.查看控制台日志如下:

    (1)order 调用者

    53972a2b-9324-4078-8446-268e13071f06
    2021-01-16 23:06:18.022  INFO 16260 --- [nio-8011-exec-5] cn.qz.cloud.config.FeignLogger           : [PaymentHystrixService#getSessionId] GET http://CLOUD-PROVIDER-HYSTRIX-PAYMENT/hystrix/payment/getSessionId HTTP/1.1, log request begin. <---
    2021-01-16 23:06:18.023  INFO 16260 --- [nio-8011-exec-5] cn.qz.cloud.config.FeignLogger           : [PaymentHystrixService#getSessionId] ---> GET http://CLOUD-PROVIDER-HYSTRIX-PAYMENT/hystrix/payment/getSessionId HTTP/1.1
    2021-01-16 23:06:18.023  INFO 16260 --- [nio-8011-exec-5] cn.qz.cloud.config.FeignLogger           : [PaymentHystrixService#getSessionId] accept-encoding: gzip, deflate, br
    2021-01-16 23:06:18.024  INFO 16260 --- [nio-8011-exec-5] cn.qz.cloud.config.FeignLogger           : [PaymentHystrixService#getSessionId] cloud_caller: order80
    2021-01-16 23:06:18.024  INFO 16260 --- [nio-8011-exec-5] cn.qz.cloud.config.FeignLogger           : [PaymentHystrixService#getSessionId] cookie: Idea-599589ea=7e4185c4-b2de-45e1-9f54-6ae34bfbe678; Webstorm-e34e7d83=831b2048-d1c1-45e6-b4e2-77d667e3f1c4; Hm_lvt_b393d153aeb26b46e9431fabaf0f6190=1605535026; SESSION=NTM5NzJhMmItOTMyNC00MDc4LTg0NDYtMjY4ZTEzMDcxZjA2
    2021-01-16 23:06:18.025  INFO 16260 --- [nio-8011-exec-5] cn.qz.cloud.config.FeignLogger           : [PaymentHystrixService#getSessionId] host: localhost:8011
    2021-01-16 23:06:18.025  INFO 16260 --- [nio-8011-exec-5] cn.qz.cloud.config.FeignLogger           : [PaymentHystrixService#getSessionId] sec-fetch-dest: document
    2021-01-16 23:06:18.025  INFO 16260 --- [nio-8011-exec-5] cn.qz.cloud.config.FeignLogger           : [PaymentHystrixService#getSessionId] sec-fetch-mode: navigate
    2021-01-16 23:06:18.026  INFO 16260 --- [nio-8011-exec-5] cn.qz.cloud.config.FeignLogger           : [PaymentHystrixService#getSessionId] sec-fetch-site: none
    2021-01-16 23:06:18.026  INFO 16260 --- [nio-8011-exec-5] cn.qz.cloud.config.FeignLogger           : [PaymentHystrixService#getSessionId] sec-fetch-user: ?1
    2021-01-16 23:06:18.027  INFO 16260 --- [nio-8011-exec-5] cn.qz.cloud.config.FeignLogger           : [PaymentHystrixService#getSessionId] ---> END HTTP (0-byte body)
    2021-01-16 23:06:18.028  INFO 16260 --- [nio-8011-exec-5] cn.qz.cloud.config.FeignLogger           : [PaymentHystrixService#getSessionId] GET http://CLOUD-PROVIDER-HYSTRIX-PAYMENT/hystrix/payment/getSessionId HTTP/1.1, log request end. <---
    2021-01-16 23:06:18.089  INFO 16260 --- [nio-8011-exec-5] cn.qz.cloud.config.FeignLogger           : [PaymentHystrixService#getSessionId] 200 HTTP/1.1 (59ms) log logAndRebufferResponse begin. <---
    2021-01-16 23:06:18.091  INFO 16260 --- [nio-8011-exec-5] cn.qz.cloud.config.FeignLogger           : [PaymentHystrixService#getSessionId] <--- HTTP/1.1 200 (59ms)
    2021-01-16 23:06:18.091  INFO 16260 --- [nio-8011-exec-5] cn.qz.cloud.config.FeignLogger           : [PaymentHystrixService#getSessionId] connection: keep-alive
    2021-01-16 23:06:18.092  INFO 16260 --- [nio-8011-exec-5] cn.qz.cloud.config.FeignLogger           : [PaymentHystrixService#getSessionId] content-type: application/json
    2021-01-16 23:06:18.092  INFO 16260 --- [nio-8011-exec-5] cn.qz.cloud.config.FeignLogger           : [PaymentHystrixService#getSessionId] date: Sat, 16 Jan 2021 15:06:18 GMT
    2021-01-16 23:06:18.093  INFO 16260 --- [nio-8011-exec-5] cn.qz.cloud.config.FeignLogger           : [PaymentHystrixService#getSessionId] keep-alive: timeout=60
    2021-01-16 23:06:18.094  INFO 16260 --- [nio-8011-exec-5] cn.qz.cloud.config.FeignLogger           : [PaymentHystrixService#getSessionId] transfer-encoding: chunked
    2021-01-16 23:06:18.094  INFO 16260 --- [nio-8011-exec-5] cn.qz.cloud.config.FeignLogger           : [PaymentHystrixService#getSessionId] 
    2021-01-16 23:06:18.096  INFO 16260 --- [nio-8011-exec-5] cn.qz.cloud.config.FeignLogger           : [PaymentHystrixService#getSessionId] {"success":true,"code":"200","msg":"","data":{"paymentCurrentUser":"张三","payment":"53972a2b-9324-4078-8446-268e13071f06"}}
    2021-01-16 23:06:18.097  INFO 16260 --- [nio-8011-exec-5] cn.qz.cloud.config.FeignLogger           : [PaymentHystrixService#getSessionId] <--- END HTTP (126-byte body)
    2021-01-16 23:06:18.098  INFO 16260 --- [nio-8011-exec-5] cn.qz.cloud.config.FeignLogger           : [PaymentHystrixService#getSessionId] 200 HTTP/1.1 (59ms) log logAndRebufferResponse end. <---

    (2) payment 被调用者服务日志如下:

    53972a2b-9324-4078-8446-268e13071f06
    ====S cookie
    Idea-599589ea    7e4185c4-b2de-45e1-9f54-6ae34bfbe678
    Webstorm-e34e7d83    831b2048-d1c1-45e6-b4e2-77d667e3f1c4
    Hm_lvt_b393d153aeb26b46e9431fabaf0f6190    1605535026
    SESSION    NTM5NzJhMmItOTMyNC00MDc4LTg0NDYtMjY4ZTEzMDcxZjA2
    ====E cookie
    ====S header
    accept-encoding    gzip, deflate, br
    cloud_caller    order80
    cookie    Idea-599589ea=7e4185c4-b2de-45e1-9f54-6ae34bfbe678; Webstorm-e34e7d83=831b2048-d1c1-45e6-b4e2-77d667e3f1c4; Hm_lvt_b393d153aeb26b46e9431fabaf0f6190=1605535026; SESSION=NTM5NzJhMmItOTMyNC00MDc4LTg0NDYtMjY4ZTEzMDcxZjA2
    accept    */*
    user-agent    Java/1.8.0_121
    host    root:8081
    connection    keep-alive
    ====E header

      至此实现了Cloud分布式项目Feign调用共享session,其实就是传递header,同时服务调用者与被调用者服务共享header中的session标识。基于Token共享方式也是这样的思路。

    【当你用心写完每一篇博客之后,你会发现它比你用代码实现功能更有成就感!】
  • 相关阅读:
    QT::QString 很全的使用
    QString与TCHAR/wchar_t/LPWSTR之间的类型转换
    Django day24 cbv和APIView的源码分析 和 resful的规范
    Django day17 博客项目(一)
    Django day16 Auth组件
    Git 和 Redis 的基本认识
    Django day15 (二) csrf的 跨站请求伪造 与 局部禁用 , 局部使用
    Django day15 (一) cbv装饰器 , 中间件
    Django day14(二) Session
    Django基础必备三件套: HttpResponse render redirect
  • 原文地址:https://www.cnblogs.com/qlqwjy/p/14279958.html
Copyright © 2011-2022 走看看