questions
In microservice, the request header will be lost in multithreading asynchronous + feign call
solving
-
- in the main thread, the request header parameters are first obtained and passed into the sub thread, and then the sub thread sets the request header parameters to the context. Finally, in feign forwarding processing, the request header data of the context set by the sub thread is obtained and forwarded to the downstream
Get context request parameter tool class
@Slf4j
public class RequestContextUtil {
/**
* Get request header data
*
* @return key-> request header name value-> request header value
* @author zhengqingya
* @date 2021/6/30 9:39 PM
*/
public static Map<String, String> getHeaderMap() {
Map<String, String> headerMap = Maps.newLinkedHashMap();
try {
ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
if (requestAttributes == null) {
return headerMap;
}
HttpServletRequest request = requestAttributes.getRequest();
Enumeration<String> enumeration = request.getHeaderNames();
while (enumeration.hasMoreElements()) {
String key = enumeration.nextElement();
String value = request.getHeader(key);
headerMap.put(key, value);
}
} catch (Exception e) {
log.error("《RequestContextUtil》 Failed to get request header parameters:", e);
}
return headerMap;
}
}
Request header context
@Slf4j
public class RequestHeaderHandler {
public static final ThreadLocal<Map<String, String>> THREAD_LOCAL = new ThreadLocal<>();
public static void setHeaderMap(Map<String, String> headerMap) {
THREAD_LOCAL.set(headerMap);
}
public static Map<String, String> getHeaderMap() {
return THREAD_LOCAL.get();
}
public static void remove() {
THREAD_LOCAL.remove();
}
}
Feign forwarding process RPC call parameter transfer
*/
@Slf4j
@Configuration
public class FeignRequestInterceptor implements RequestInterceptor {
@Override
@SneakyThrows
public void apply(RequestTemplate requestTemplate) {
log.debug("========================== ↓↓↓↓↓↓ 《FeignRequestInterceptor》 Start... ↓↓↓↓↓↓ ==========================");
Map<String, String> threadHeaderNameMap = RequestHeaderHandler.getHeaderMap();
if (!CollectionUtils.isEmpty(threadHeaderNameMap)) {
threadHeaderNameMap.forEach((headerName, headerValue) -> {
log.debug("《FeignRequestInterceptor》 Multi-threaded headerName:[{}] headerValue:[{}]", headerName, headerValue);
requestTemplate.header(headerName, headerValue);
});
}
Map<String, String> headerMap = RequestContextUtil.getHeaderMap();
headerMap.forEach((headerName, headerValue) -> {
log.debug("《FeignRequestInterceptor》 headerName:[{}] headerValue:[{}]", headerName, headerValue);
requestTemplate.header(headerName, headerValue);
});
log.debug("========================== ↑↑↑↑↑↑ 《FeignRequestInterceptor》 End... ↑↑↑↑↑↑ ==========================");
}
}
Use cases
@Slf4j
@RestController
@RequestMapping("/web/api/demo/test")
@Api(tags = "test api")
@AllArgsConstructor
public class RpcController extends BaseController {
private SystemTaskThread systemTaskThread;
@GetMapping("getContextUserId")
@ApiOperation("rpc Call test - Async")
public void getContextUserId() {
Map<String, String> headerMap = RequestContextUtil.getHeaderMap();
log.info("Main thread request header value: {}", headerMap.get("userId"));
this.systemTaskThread.getRequestHeaderUserId(RequestContextUtil.getHeaderMap());
}
}
@Slf4j
@Component
@AllArgsConstructor
public class SystemTaskThread {
private ISystemClient systemClient;
@SneakyThrows
@Async(ThreadPoolConstant.SMALL_TOOLS_THREAD_POOL)
public void getRequestHeaderUserId(Map<String, String> headerMap) {
RequestHeaderHandler.setHeaderMap(headerMap);
log.info("Sub-thread request header value: {}", this.systemClient.getRequestHeaderUserId());
}
}
Note: it is also mentioned on the Internet that the main thread obtains the request parameters
requestattributes, requestattributes = requestcontextholder. Getrequestattributes()
to the child thread, and then re assignrequestcontextholder. Setrequestattributes (requestattributes)
But this method is not effective. Please record it here by the way~
Read More:
- Feign declarative call service feign.codec.DecodeException: Error while extracting response for type [class **] and…
- Tomcat Error parsing HTTP request header Note: further occurrences of HTTP header parsing errors
- [How to Solve] java.lang.IllegalArgumentException: Request header is too large
- [Solved] Browser Access Error: Request Header or Cookie too large
- [Solved] Nginx Error: 400 Request Header Or Cookie Too Large
- feign.FeignException: status 404 reading XXXClient#XXMethod(String)
- [Solved] Feign Error: -‘oauth-client.FeignClientSpecification‘ could not be registered
- QT solves error: use of deleted function and is private within this context
- [Solved] Opencv error: assertion__acrt_first_block == header
- srs Error: demux SPS/PPS : avc decode sequence header
- Current request is not a multipart request [How to Solve]
- [Solved] PCH Warning: header stop not at file scope
- Mac Vscode C++ Customize Header File Error: linker command failed
- [Solved] fatal error: bits/libc-header-start.h: No such file or directory
- [Solved] Synchronous operations are disallowed. Call ReadAsync or set AllowSynchronousIO to true instead.
- VSCode Unable to find custom header file directory: fatal error: no such file or directory
- The request was rejected because the URL contained a potentially malicious String “;” [How to Solve]
- Grafana Error: 414 Request-URI Too Large [How to Solve]
- [Solved] FileUploadException: the request was rejected because no multipart boundary was found