统一网关接口设计

一,什么是网关

API网关是一个系统的一个入口,它类似于面向对象设计中的外观模式。API网关封装了内部系统架构,为每个客户端单独提供一个API。API网关可能还有其他的职责,例如授权、监控、负载均衡、缓存、请求的修改和管理、静态响应的处理。

目前,我们的系统的整体架构是app端请求一个统一的网关入口,http://www.xxx.com/gateway.action,然后通过nginx反向代理到网关层,然后网关根据前端传的method路由跳转到真实的后台接口层,最后再由接口层请求dubbo服务层,完成整个请求;

至此,大致明白了网关这层所在的位置,接下来,描述下网关的作用。

 

二,网关的作用

  • 路由转发

根据前端传递的method拿到真实的url地址,然后使用 httpclient 去调用这个地址,并获取到这个接口返回的参数。

  • 权限控制

根据前端传的appId和method参数去校验该app是否有调用该接口的权限

  • 接口签名

使用rsa2,对请求参数(content里面的内容和appid,method,timestamp)进行排序,然后进行验签。

  • 解密参数

对于一些敏感数据,需要进行加密保证接口的安全,比如登录,设置用户密码的接口;

  • 性能监控

通过拦截器,监控接口访问的性能,如接口请求的花费时间,内存分配

 

三,细节的实现

主要还是利用了拦截器,对请求的接口进行权限控制,接口签名的验签,前端传递过来的参数进行解密,然后再由统一的控制层进行url地址的转发;

性能监控的代码实现

public class PerformanceInteceptor implements HandlerInterceptor {

    @Autowired
    private AccessLogRepository accessLogRepository;

    private static final ThreadLocal<Long> startTimeThreadLocal = new NamedThreadLocal<>("ThreadLocal StartTime");

    @Override
    public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
        long beginTime = System.currentTimeMillis();
        startTimeThreadLocal.set(beginTime);
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
        if (modelAndView != null) {
            log.info("ViewName: " + modelAndView.getViewName());
        }
    }

    @Override
    public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
        long beginTime = startTimeThreadLocal.get();

        RequestGatewayDTO requestGatewayDTO = WebHelper.getRequestDTOByJson(httpServletRequest);
        String method = requestGatewayDTO.getMethod();
        long endTime = System.currentTimeMillis();
        log.info("请求方法:{} 响应结束时间: 【{} - {}】  耗时:{}ms  最大内存: {}m  已分配内存: {}m  已分配内存中的剩余空间: {}m  最大可用内存: {}m", method,
                new SimpleDateFormat("HH:mm:ss.SSS").format(beginTime),  new SimpleDateFormat("HH:mm:ss.SSS").format(endTime), (endTime - beginTime),
                Runtime.getRuntime().maxMemory() / 1024 / 1024, Runtime.getRuntime().totalMemory() / 1024 / 1024, Runtime.getRuntime().freeMemory() / 1024 / 1024,
                (Runtime.getRuntime().maxMemory() - Runtime.getRuntime().totalMemory() + Runtime.getRuntime().freeMemory()) / 1024 / 1024);
        //删除线程变量中的数据,防止内存泄漏
        startTimeThreadLocal.remove();
    }
}

 

 

 

 

 

 

 

 

Add a Comment

电子邮件地址不会被公开。 必填项已用*标注