每单元存1比特和4比特差多远?Flash颗粒SLC到QLC的物理极限与工程突围
2026/6/26 7:59:26
外部客户端(浏览器、App、其他服务)通过 HTTP 协议直接调用,由 Spring MVC 处理。
外部调用方 │ HTTP Request(含 Header:userId、orgId 等) ▼ Servlet Filter(如 UserFilter)→ 填充 UserContext ▼ DispatcherServlet → HandlerMapping → Controller 方法 ▼ 返回 JSON 响应微服务之间内部调用的方式。调用方像调本地方法一样调用,底层由 Feign 框架转成 HTTP 请求发出去。
服务 A(调用方) │ 调用 Java 接口方法(如 searchDocsFacade.searchCenterDocs(param)) ▼ Feign 动态代理(拦截方法调用) │ 构造 HTTP Request(序列化参数、拼接路径) │ RequestInterceptor(注入 Header) ▼ 负载均衡(Ribbon / LoadBalancer)→ 选一个服务实例 ▼ HTTP 请求发出 → 服务 B(被调方,如 bm-search) ▼ 服务 B 的 Filter → Controller/FacadeImpl 处理 ▼ HTTP 响应 → Feign 反序列化 → 返回 Java 对象给调用方HTTP Request │ ▼ Tomcat(Servlet 容器) │ 接收请求,封装为 HttpServletRequest ▼ FilterChain(责任链模式) │ UserFilter、CorsFilter、AuthFilter 等依次执行 ▼ DispatcherServlet(前端控制器,Spring MVC 核心) │ ├─ HandlerMapping:根据路径找到 Controller 方法(HandlerMethod) ├─ HandlerAdapter:调用方法前处理参数绑定 │ ├─ @RequestBody → HttpMessageConverter(如 Jackson)反序列化 JSON │ ├─ @PathVariable / @RequestParam → 从 URL 提取 │ └─ @RequestHeader → 从 Header 提取 ├─ Controller 方法执行 └─ HandlerAdapter:处理返回值 └─ @ResponseBody → HttpMessageConverter 序列化为 JSON │ ▼ HTTP Response| 类 | 职责 |
|---|---|
DispatcherServlet | Spring MVC 入口,统一调度 |
RequestMappingHandlerMapping | 维护 URL → HandlerMethod 的映射表 |
RequestMappingHandlerAdapter | 处理参数绑定、执行方法、处理返回值 |
HttpMessageConverter | Java 对象 ↔ JSON/XML 互转(Jackson) |
OncePerRequestFilter | 每次请求只执行一次的过滤器基类(UserFilter 继承它) |
// UserFilter 拦截 /v1/search/* 路径// 从 Header 读取 userId、orgId 写入 ThreadLocal(UserContext)// 请求结束后 finally 块清理,防止线程复用时的数据污染USER_CONTEXT.put(UserContext.USER_ID,userId);// ...filterChain.doFilter(request,response);// ...USER_CONTEXT.remove(UserContext.USER_ID);// finally 块Feign 的核心是JDK 动态代理。启动时扫描@FeignClient注解的接口,为每个接口生成代理类。
// 你注入的其实不是 SearchDocsFacade 的实现类// 而是 Feign 生成的代理对象@AutowiredprivateSearchDocsFacadesearchDocsFacade;// → 实际是 HardCodedTarget$FeignInvocationHandler// 调用方法时触发 InvocationHandler.invoke()searchDocsFacade.searchCenterDocs(param);// ↓// ReflectiveFeign.FeignInvocationHandler.invoke()// ↓// SynchronousMethodHandler.invoke() → 真正构造并发送请求SynchronousMethodHandler.invoke(args) │ ├─ 1. RequestTemplate 构造 │ 读取接口方法上的 @PostMapping、@RequestBody 等注解 │ 将方法参数序列化填入 body / path / query │ ├─ 2. RequestInterceptor 执行(可扩展点) │ 遍历所有注册的 RequestInterceptor.apply(template) │ → 可在此注入 userId、orgId 等 Header │ ├─ 3. 编码(Encoder) │ 将 RequestBody 对象序列化为 JSON 字节流 │ 默认使用 SpringEncoder(内部用 Jackson) │ ├─ 4. 负载均衡(LoadBalancerFeignClient) │ 将 http://bm-search/v1/search/docs 中的服务名 │ 替换为真实 IP:Port(如 http://192.168.1.10:8080/v1/search/docs) │ ├─ 5. 发送 HTTP 请求(OkHttpClient / HttpURLConnection) │ ├─ 6. 解码(Decoder) │ 将响应 JSON 反序列化为 Result<?> 对象 │ └─ 7. 错误处理(ErrorDecoder) 非 2xx 响应 → 抛出 FeignException 或自定义异常@FeignClient(name="bm-search",// 服务名,用于从注册中心查找实例contextId="searchDocsFacade",// 同一服务多个 FeignClient 时区分 Bean 名称url