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() + "\t" + 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 + "\t" + 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() + "\t" + 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 + "\t" + 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() + "\t" + 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 + "\t" + 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) "\xac\xed\x00\x05sr\x00\x11java.lang.Integer\x12\xe2\xa0\xa4\xf7\x81\x878\x02\x00\x01I\x00\x05valuexr\x00\x10java.lang.Number\x86\xac\x95\x1d\x0b\x94\xe0\x8b\x02\x00\x00xp\x00\x00\a\b"
3) "lastAccessedTime"
4) "\xac\xed\x00\x05sr\x00\x0ejava.lang.Long;\x8b\xe4\x90\xcc\x8f#\xdf\x02\x00\x01J\x00\x05valuexr\x00\x10java.lang.Number\x86\xac\x95\x1d\x0b\x94\xe0\x8b\x02\x00\x00xp\x00\x00\x01w\nBDs"
5) "creationTime"
6) "\xac\xed\x00\x05sr\x00\x0ejava.lang.Long;\x8b\xe4\x90\xcc\x8f#\xdf\x02\x00\x01J\x00\x05valuexr\x00\x10java.lang.Number\x86\xac\x95\x1d\x0b\x94\xe0\x8b\x02\x00\x00xp\x00\x00\x01w\nBDs"
7) "sessionAttr:currentUser"
8) "\xac\xed\x00\x05t\x00\x02zs"

  可以看到存到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() + "\t" + 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 + "\t" + 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共享方式也是這樣的思路。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM