微服务系列(一)聊聊服务网关

微服务系列(一)聊聊服务网关

前几年随着分布式架构的演变,微服务开始兴起,自然也产生了一系列支持微服务的框架,例如本文要聊到的Spring Cloud。

Spring 相信做Java的小伙伴们已经耳熟能详了,也正是应该这个Spring生态获得广大的关注,在Spring之上开发的新兴框架如Spring Boot、Spring Cloud也很快让大家熟知。

下面主要针对Spring Cloud聊聊它所实现的服务网关,并针对市面上常用的Nginx做一些分析和比较。

由于笔者比较熟悉和擅长的语言是Java,所以仅针对Java框架来做一些源码层面的分析。

服务网关的角色

常见微服务架构

微服务基础架构

可以看到,网关层是最外层,浏览器与服务器交互时经过的第一个服务节点,它主要起屏蔽下游业务服务的作用,对于浏览器而言,只需要跟网关交互就相当于在与下游多个业务服务节点交互,让浏览器觉得他在和一台服务器交互。

这样的好处显而易见,不管是下游业务服务、支撑服务、基础服务,都对于浏览器屏蔽,与服务器的交互变的非常简单,浏览器无需关心各个节点的依赖关系、如何协同工作,浏览器只会了解到本次请求是否成功;开发者可以灵活的增加业务服务模块;可以在网关层做一些最上层的公用的操作,如过滤恶意请求、设置ip黑白名单、做身份认证、限流、负载均衡等。

换个角度考虑一下,如果去掉网关层,浏览器交互的最外层服务是业务服务层,由于需要解决单点登陆问题,必须在每个业务服务节点上多扮演一个auth client的角色,从开发的角度上看,明显增加了复杂度,试问本可以只需要在一个网关服务上构建auth client,为何要选择在多个(并且可能还会增加)的业务服务上构建auth client呢?

另外,从开发上讲可能还需要解决跨域请求的问题,前后端分离架构中后端api的展示也会是一个问题,也不便于管理;对于同一服务多节点的负载均衡也不好实现,难道需要浏览器每次访问前都去访问一次注册中心?

通过分析发现,微服务架构中,对于再小的业务量的项目,服务网关都是必不可少的。

Spring Cloud Netflix Zuul和Spring Cloud Gateway

Zuul在早期微服务架构中用的非常广泛,如今Spring Cloud推出了Spring Cloud Gateway,那么作为开发者,应该考虑以下问题:该如何选择?他们之间的差异有哪些?各有什么优势呢?

下面从源码入手,探索Zuul的工作原理,尝试理解他的设计理念。

为了图方便,就不去github上download源码了,直接在pom引入依赖,开干…

进入com.netflix.zuul.http.ZuulServlet

public class ZuulServlet extends HttpServlet {
   
    
 	private ZuulRunner zuulRunner;
    
    public void init(ServletConfig config) throws ServletException {
   
        ...
    }
    public void service(javax.servlet.ServletRequest servletRequest, javax.servlet.ServletResponse servletResponse) throws ServletException, IOException {
   
        ...
    }
}

它继承了HttpServlet,熟悉吗?不熟悉的话,可以打开你熟悉的DispatchServlet,看看它继承了谁?

也就是说,它本质上用了java.servlet API,实现了一个有网关功能的servlet。

那么继续观察一下它的com.netflix.zuul.http.ZuulServlet#service方法:

try {
   
    init((HttpServletRequest) servletRequest, (HttpServletResponse) servletResponse);

    // Marks this request as having passed through the "Zuul engine", as opposed to servlets
    // explicitly bound in web.xml, for which requests will not have the same data attached
    RequestContext context = RequestContext.getCurrentContext();
    context.setZuulEngineRan();

    try {
   
        preRoute();
    } catch (ZuulException e) {
   
        error(e);
        postRoute();
        return;
    }
    try {
   
        route();
    } catch (ZuulException e) {
   
        error(e);
        postRoute();
        return;
    }
    try {
   
        postRoute();
    } catch (ZuulException e) {
   
        error(e);
        return;
    }

} catch (Throwable e) {
   
    error(new ZuulException(e, 500, "UNHANDLED_EXCEPTION_" + e.getClass().getName()));
} finally {
   
    RequestContext.getCurrentContext().unset();
}

可以看到,它做了以下几件事:

  1. 前置路由
  2. 路由
  3. 后置路由
  4. 异常处理

不管是preRoute()route()postRoute()error(),它们最终调用了com.netflix.zuul.FilterProcessor#runFilters

public Object runFilters(String sType) throws Throwable {
   
    if (RequestContext.getCurrentContext().debugRouting()<
  • 10
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值