千家信息网

nacos中DistroFilter的作用是什么

发表于:2025-12-03 作者:千家信息网编辑
千家信息网最后更新 2025年12月03日,本篇文章为大家展示了nacos中DistroFilter的作用是什么,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。CanDistronacos-1.1.3/n
千家信息网最后更新 2025年12月03日nacos中DistroFilter的作用是什么

本篇文章为大家展示了nacos中DistroFilter的作用是什么,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。

CanDistro

nacos-1.1.3/naming/src/main/java/com/alibaba/nacos/naming/web/CanDistro.java

@Retention(RetentionPolicy.RUNTIME)public @interface CanDistro {}
  • CanDistro用于标识一个方法需要判断是否应该根据distro被重定向

DistroFilter

nacos-1.1.3/naming/src/main/java/com/alibaba/nacos/naming/web/DistroFilter.java

public class DistroFilter implements Filter {    private static final int PROXY_CONNECT_TIMEOUT = 2000;    private static final int PROXY_READ_TIMEOUT = 2000;    @Autowired    private DistroMapper distroMapper;    @Autowired    private SwitchDomain switchDomain;    @Autowired    private FilterBase filterBase;    @Override    public void init(FilterConfig filterConfig) throws ServletException {    }    @Override    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {        HttpServletRequest req = (HttpServletRequest) servletRequest;        HttpServletResponse resp = (HttpServletResponse) servletResponse;        String urlString = req.getRequestURI();        if (StringUtils.isNotBlank(req.getQueryString())) {            urlString += "?" + req.getQueryString();        }        try {            String path = new URI(req.getRequestURI()).getPath();            String serviceName = req.getParameter(CommonParams.SERVICE_NAME);            // For client under 0.8.0:            if (StringUtils.isBlank(serviceName)) {                serviceName = req.getParameter("dom");            }            Method method = filterBase.getMethod(req.getMethod(), path);            if (method == null) {                throw new NoSuchMethodException(req.getMethod() + " " + path);            }            String groupName = req.getParameter(CommonParams.GROUP_NAME);            if (StringUtils.isBlank(groupName)) {                groupName = Constants.DEFAULT_GROUP;            }            // use groupName@@serviceName as new service name:            String groupedServiceName = serviceName;            if (StringUtils.isNotBlank(serviceName) && !serviceName.contains(Constants.SERVICE_INFO_SPLITER)) {                groupedServiceName = groupName + Constants.SERVICE_INFO_SPLITER + serviceName;            }            // proxy request to other server if necessary:            if (method.isAnnotationPresent(CanDistro.class) && !distroMapper.responsible(groupedServiceName)) {                String userAgent = req.getHeader("User-Agent");                if (StringUtils.isNotBlank(userAgent) && userAgent.contains(UtilsAndCommons.NACOS_SERVER_HEADER)) {                    // This request is sent from peer server, should not be redirected again:                    Loggers.SRV_LOG.error("receive invalid redirect request from peer {}", req.getRemoteAddr());                    resp.sendError(HttpServletResponse.SC_BAD_REQUEST,                        "receive invalid redirect request from peer " + req.getRemoteAddr());                    return;                }                List headerList = new ArrayList<>(16);                Enumeration headers = req.getHeaderNames();                while (headers.hasMoreElements()) {                    String headerName = headers.nextElement();                    headerList.add(headerName);                    headerList.add(req.getHeader(headerName));                }                HttpClient.HttpResult result =                    HttpClient.request("http://" + distroMapper.mapSrv(groupedServiceName) + urlString, headerList,                        StringUtils.isBlank(req.getQueryString()) ? HttpClient.translateParameterMap(req.getParameterMap()) : new HashMap<>(2)                        , PROXY_CONNECT_TIMEOUT, PROXY_READ_TIMEOUT, "UTF-8", req.getMethod());                try {                    resp.setCharacterEncoding("UTF-8");                    resp.getWriter().write(result.content);                    resp.setStatus(result.code);                } catch (Exception ignore) {                    Loggers.SRV_LOG.warn("[DISTRO-FILTER] request failed: " + distroMapper.mapSrv(groupedServiceName) + urlString);                }                return;            }            OverrideParameterRequestWrapper requestWrapper = OverrideParameterRequestWrapper.buildRequest(req);            requestWrapper.addParameter(CommonParams.SERVICE_NAME, groupedServiceName);            filterChain.doFilter(requestWrapper, resp);        } catch (AccessControlException e) {            resp.sendError(HttpServletResponse.SC_FORBIDDEN, "access denied: " + UtilsAndCommons.getAllExceptionMsg(e));            return;        } catch (NoSuchMethodException e) {            resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED, "no such api: " + e.getMessage());            return;        } catch (Exception e) {            resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,                "Server failed," + UtilsAndCommons.getAllExceptionMsg(e));            return;        }    }    @Override    public void destroy() {    }}
  • DistroFilter实现了servlet的Filter接口;其doFilter方法会从servletRequest中读取serviceName、method、groupName等,然后判断method是否标注CanDistro,如果是而且distroMapper不负责该service则构建http请求然后将结果写回Filter;如果不需要重定向则继续filterChain.doFilter

HttpClient.request

nacos-1.1.3/naming/src/main/java/com/alibaba/nacos/naming/misc/HttpClient.java

public class HttpClient {    private static final int TIME_OUT_MILLIS = 10000;    private static final int CON_TIME_OUT_MILLIS = 5000;    private static AsyncHttpClient asyncHttpClient;    private static CloseableHttpClient postClient;    //......    public static HttpResult request(String url, List headers, Map paramValues, int connectTimeout, int readTimeout, String encoding, String method) {        HttpURLConnection conn = null;        try {            String encodedContent = encodingParams(paramValues, encoding);            url += (null == encodedContent) ? "" : ("?" + encodedContent);            conn = (HttpURLConnection) new URL(url).openConnection();            conn.setConnectTimeout(connectTimeout);            conn.setReadTimeout(readTimeout);            conn.setRequestMethod(method);            conn.addRequestProperty("Client-Version", UtilsAndCommons.SERVER_VERSION);            conn.addRequestProperty("User-Agent", UtilsAndCommons.SERVER_VERSION);            setHeaders(conn, headers, encoding);            conn.connect();            return getResult(conn);        } catch (Exception e) {            Loggers.SRV_LOG.warn("Exception while request: {}, caused: {}", url, e);            return new HttpResult(500, e.toString(), Collections.emptyMap());        } finally {            if (conn != null) {                conn.disconnect();            }        }    }    private static HttpResult getResult(HttpURLConnection conn) throws IOException {        int respCode = conn.getResponseCode();        InputStream inputStream;        if (HttpURLConnection.HTTP_OK == respCode) {            inputStream = conn.getInputStream();        } else {            inputStream = conn.getErrorStream();        }        Map respHeaders = new HashMap(conn.getHeaderFields().size());        for (Map.Entry> entry : conn.getHeaderFields().entrySet()) {            respHeaders.put(entry.getKey(), entry.getValue().get(0));        }        String gzipEncoding = "gzip";        if (gzipEncoding.equals(respHeaders.get(HttpHeaders.CONTENT_ENCODING))) {            inputStream = new GZIPInputStream(inputStream);        }        HttpResult result = new HttpResult(respCode, IOUtils.toString(inputStream, getCharset(conn)), respHeaders);        inputStream.close();        return result;    }    public static class HttpResult {        final public int code;        final public String content;        final private Map respHeaders;        public HttpResult(int code, String content, Map respHeaders) {            this.code = code;            this.content = content;            this.respHeaders = respHeaders;        }        public String getHeader(String name) {            return respHeaders.get(name);        }    }    //......}
  • HttpClient的request方法直接使用jdk的HttpURLConnection进行请求,返回结果封装为HttpResult,其content即为响应的body

小结

DistroFilter实现了servlet的Filter接口;其doFilter方法会从servletRequest中读取serviceName、method、groupName等,然后判断method是否标注CanDistro,如果是而且distroMapper不负责该service则构建http请求然后将结果写回Filter;如果不需要重定向则继续filterChain.doFilter

上述内容就是nacos中DistroFilter的作用是什么,你们学到知识或技能了吗?如果还想学到更多技能或者丰富自己的知识储备,欢迎关注行业资讯频道。

方法 结果 作用 内容 技能 接口 知识 UTF-8 简明 简明扼要 小结 就是 文章 更多 标识 篇文章 行业 资讯 资讯频道 频道 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 tcp服务器向指定客户端通信 数据库面试100题 山东省科技厅互联网 网络安全管理岗位竞聘演讲稿 服务器组装哪个好 电脑打开b站显示找不到服务器 spl数据库添加图片 如何提高学生网络安全 各类网络安全事件应急预案 周末文摘加强网络安全 服务器上的cpu在哪买 数码科技与互联网 保险公司 数据库 丽水计算机网络技术咨询服务 软件开发公司怎样做帐 小鸟云服务器安全吗 国家网络安全科技园员工宿舍 wily数据库是属于哪个国家的 软件开发小程序报告 网络安全学科宣传 基础设施包括网络安全 计算机三级应用题网络技术 浙江金服杭州网络技术有限公司 王牌战争有不可以拆家的服务器吗 数据库的建立与操作实验报告 服务器如何切换语言 网络技术公司应聘人员简历 家庭linux服务器搭建 从数据库查询某个数据库 奥丁神叛手游登录服务器繁忙
0