当前位置: 代码网 > it编程>编程语言>Java > Zuul实现服务网关路由全过程

Zuul实现服务网关路由全过程

2025年07月17日 Java 我要评论
前言为什么会有路由层?因为在微服务架构设计中,往往并不会直接将服务暴漏给调用端,而是通过调用路由层进行业务隔离,以达到不同的业务调用对应的服务模块。spring cloud zuulspring cl

前言

为什么会有路由层?

因为在微服务架构设计中,往往并不会直接将服务暴漏给调用端,而是通过调用路由层进行业务隔离,以达到不同的业务调用对应的服务模块。

spring cloud zuul

spring cloud zuul 路由是微服务架构的不可或缺的一部分,提供动态路由、监控、弹性、安全等的边缘服务。

zuul 是 netflix 出品的一个基于 jvm 路由和服务端的负载均衡器。


环境准备

1.jdk 1.8、idea2018、maven3

2.spring boot 2.0.6.release

3.spring cloud finchley.sr2

代码示例

itstack-demo-springcloud-08
├── itstack-demo-springcloud-eureka-client
│   └── src
│       └── main
│           ├── java
│           │   └── org.itstack.demo
│           │        ├── web
│           │        │   └── eurekaclientcontroller.java
│           │        └── eurekaclientapplication.java
│           └── resources   
│               └── application.yml
├── itstack-demo-springcloud-eureka-server
│   └── src
│       └── main
│           ├── java
│           │   └── org.itstack.demo
│           │        └── eurekaserverapplication.java
│           └── resources   
│               └── application.yml
├── itstack-demo-springcloud-hystrix-feign
│   └── src
│       └── main
│           ├── java
│           │   └── org.itstack.demo
│           │        ├── service
│           │        │   ├── hystrix
│           │        │   │   └── feignservicehystrix.java
│           │        │   └── feignservice.java
│           │        ├── web
│           │        │   └── feigncontroller.java
│           │        └── feignapplication.java
│           └── resources   
│               └── application.yml
├── itstack-demo-springcloud-hystrix-ribbon
│   └── src
│       └── main
│           ├── java
│           │   └── org.itstack.demo
│           │        ├── service
│           │        │   └── ribbonservice.java
│           │        ├── web
│           │        │   └── ribboncontroller.java      
│           │        └── ribbonapplication.java
│           └── resources   
│               └── application.yml
└── itstack-demo-springcloud-zuul
    └── src
        └── main
            ├── java
            │   └── org.itstack.demo   
            │        └── zuulapplication.java
            └── resources   
                └── application.yml

itstack-demo-springcloud-eureka-client | 服务提供方

提供一个查询用户信息的简单方法,在配置文件中通过修改端口启动2次,模拟双实例应用,为调用方负载做准备。

  • web/eurekaclientcontroller.java & 注意@enableeurekaclient用于向注册中心提供服务
@enableeurekaclient
@restcontroller
public class eurekaclientcontroller {

    @value("${server.port}")
    private int port;

    @requestmapping(path = "/api/queryuserinfo", method = requestmethod.get)
    public string queryuserinfo(@requestparam string userid) {
        return "hi 微信公众号:bugstack虫洞栈 | " + userid + " >: from eureka client port: " + port;
    }

}
  • eurekaclientapplication.java & 服务启动类
@springbootapplication
public class eurekaclientapplication {

    public static void main(string[] args) {
        springapplication.run(eurekaclientapplication.class, args);
    }

}
 
  • pom.xml & 配置文件指向注册中心
server:
  port: 8001

spring:
  application:
    name: itstack-demo-springcloud-eureka-client

eureka:
  client:
    serviceurl:
      defaultzone: http://localhost:7397/eureka/

itstack-demo-springcloud-eureka-server | 单个服务注册中心

服务注册中心用于承载接口提供方向上注册,同时正在调用方链接后可以获取指定应用的服务实例。

  • eurekaserverapplication.java & 通过注解@enableeurekaserver启动服务注册与发现中心
@springbootapplication
@enableeurekaserver
public class eurekaserverapplication {

    public static void main(string[] args) {
        springapplication.run( eurekaserverapplication.class, args );
    }

}
  • pom.xml & 服务注册中心
server:
  port: 7397

eureka:
  instance:
    hostname: localhost
  client:
    registerwitheureka: false
    fetchregistry: false
    serviceurl:
      defaultzone: http://${eureka.instance.hostname}:${server.port}/eureka/

spring:
  application:
    name: itstack-demo-springcloud-eureka-server

itstack-demo-springcloud-feign | feign服务调用方

feign 是一个声明式的 web service 客户端,它的目的就是让 web service 调用更加简单。它整合了 ribbon 和 hystrix,从而让我们不再需要显式地使用这两个组件。feign 还提供了 http 请求的模板,通过编写简单的接口和插入注解,我们就可以定义好 http 请求的参数、格式、地址等信息。接下来,feign 会完全代理 http 的请求,我们只需要像调用方法一样调用它就可以完成服务请求。

feign 具有如下特性:

可插拔的注解支持,包括 feign 注解和 jax-rs 注解 支持可插拔的 http 编码器和解码器 支持 hystrix 和它的 fallback 支持 ribbon 的负载均衡 支持 http 请求和响应的压缩

service/feignservice.java |

注解方式调用,方便易用。@feignclient会在调用时进行解析服务到具体的http://ip:port/

@feignclient(value = "itstack-demo-springcloud-eureka-client", fallback = feignservicehystrix.class)
public interface feignservice {

    @requestmapping(value = "/api/queryuserinfo", method = requestmethod.get)
    string queryuserinfo(@requestparam string userid);

}
  • service/hystrix/feignservicehystrix.java | 提供熔断服务,当发生异常时主动返回预定结果
@component
public class feignservicehystrix implements feignservice {

    @override
    public string queryuserinfo(string userid) {
        return "queryuserinfo by userid:" + userid + " err!from feign hystrix";
    }
    
}
  • web/feigncontroller.java | 使用接口提供服务 from feign
@restcontroller
public class feigncontroller {

    @resource
    private feignservice ribbonservice;

    @requestmapping(path = "/api/queryuserinfo", method = requestmethod.get)
    public string queryuserinfo(@requestparam string userid) {
        return ribbonservice.queryuserinfo(userid) + " from feign";
    }

}

feignapplication.java |

  • 注解@enableeurekaclient、@enablefeignclients、@enablediscoveryclient获取调用注册中心服务
@springbootapplication
@enableeurekaclient
@enablediscoveryclient
@enablefeignclients
@enablehystrix
public class feignapplication {

    public static void main(string[] args) {
        springapplication.run(feignapplication.class, args);
    }

}
  • application.yml | eureka服务配置,从注册中心获取可用服务。开启hystrix=true
server:
  port: 9001

spring:
  application:
    name: itstack-demo-springcloud-feign

eureka:
  client:
    serviceurl:
      defaultzone: http://localhost:7397/eureka/

feign.hystrix.enabled: true

itstack-demo-springcloud-ribbon | ribbon服务调用方

ribbon是一个基于 http 和 tcp 的客户端负载均衡器。它可以通过在客户端中配置 ribbonserverlist 来设置服务端列表去轮询访问以达到均衡负载的作用。

当 ribbon 与 eureka 联合使用时,ribbonserverlist 会被 discoveryenabledniwsserverlist 重写,扩展成从 eureka 注册中心中获取服务实例列表。同时它也会用 niwsdiscoveryping 来取代 iping,它将职责委托给 eureka 来确定服务端是否已经启动。

service/ribbonservice.java |

  • 接口式硬编码调用不太易于维护,因此也是比较少用的方式。hystrix实际通过getfallback()返回熔断结果
@service
public class ribbonservice {

    @autowired
    private resttemplate resttemplate;

    @hystrixcommand(fallbackmethod = "queryuserinfofallback")
    public string queryuserinfo(string userid) {
        return resttemplate.getforobject("http://itstack-demo-springcloud-eureka-client/api/queryuserinfo?userid=" + userid, string.class);
    }

    /**
     * specifies a method to process fallback logic.
     * a fallback method should be defined in the same class where is hystrixcommand.
     * also a fallback method should have same signature to a method which was invoked as hystrix command.
     * for example:
     * <code>
     *      @hystrixcommand(fallbackmethod = "getbyidfallback")
     *      public string getbyid(string id) {...}
     *
     *      private string getbyidfallback(string id) {...}
     * </code>
     * also a fallback method can be annotated with {@link hystrixcommand}
     * <p/>
     * default => see {@link com.netflix.hystrix.contrib.javanica.command.genericcommand#getfallback()}
     *
     * @return method name
     *
     * getfallback()
     * 
     * @override
     * protected object getfallback() {
     *     final commandaction commandaction = getfallbackaction();
     *     if (commandaction != null) {
     *         try {
     *             return process(new action() {
     *                 @override
     *                 object execute() {
     *                     metaholder metaholder = commandaction.getmetaholder();
     *                     object[] args = createargsforfallback(metaholder, getexecutionexception());
     *                     return commandaction.executewithargs(metaholder.getfallbackexecutiontype(), args);
     *                 }
     *             });
     *         } catch (throwable e) {
     *             logger.error(fallbackerrormessagebuilder.create()
     *                     .append(commandaction, e).build());
     *             throw new fallbackinvocationexception(unwrapcause(e));
     *         }
     *     } else {
     *         return super.getfallback();
     *     }
     * }
     */
    public string queryuserinfofallback(string userid) {
        return "queryuserinfo by userid:" + userid + " err!from ribbon hystrix";
    }

}
  • web/ribboncontroller.java | 使用接口提供服务 from ribbon
@restcontroller
public class ribboncontroller {

    @resource
    private ribbonservice ribbonservice;

    @requestmapping(path = "/api/queryuserinfo", method = requestmethod.get)
    public string queryuserinfo(@requestparam string userid) {
        return ribbonservice.queryuserinfo(userid) + " from ribbon";
    }
    
}

ribbonapplication.java |

  • 通过注解@loadbalanced注册rest模版,用于ribbon接口调用。并启动@enablehystrix
@springbootapplication
@enableeurekaclient
@enablediscoveryclient
@enablehystrix
public class ribbonapplication {

    public static void main(string[] args) {
        springapplication.run(ribbonapplication.class, args);
    }

    @bean
    @loadbalanced
    resttemplate resttemplate() {
        return new resttemplate();
    }

}
  • application.yml | eureka服务配置,从注册中心获取可用服务
server:
  port: 9002

spring:
  application:
    name: itstack-demo-springcloud-ribbon

eureka:
  client:
    serviceurl:
      defaultzone: http://localhost:7397/eureka/

itstack-demo-springcloud-zuul | zull路由层

spring cloud zuul 路由是微服务架构的不可或缺的一部分,提供动态路由、监控、弹性、安全等的边缘服务。zuul 是 netflix 出品的一个基于 jvm 路由和服务端的负载均衡器。

  • zuulapplication.java & 路由服务启动
@springbootapplication
@enablezuulproxy
@enableeurekaclient
@enablediscoveryclient
public class zuulapplication {

    public static void main(string[] args) {
        springapplication.run(zuulapplication.class, args);
    }

}
  • pom.mxl & 路由配置
server:
  port: 10001

spring:
  application:
    name: itstack-demo-ddd-zuul

eureka:
  client:
    serviceurl:
      defaultzone: http://localhost:7397/eureka/

# http://localhost:10001/route-a/api/queryuserinfo?userid=111
# http://localhost:10001/route-b/api/queryuserinfo?userid=111
zuul:
  routes:
    api-a:
      path: /route-a/**
      serviceid: itstack-demo-springcloud-feign
    api-b:
      path: /route-b/**
      serviceid: itstack-demo-springcloud-ribbon

测试验证

1.分别启动如下系统模拟

  • itstack-demo-springcloud-eureka-server 服务注册发现中心
  • itstack-demo-springcloud-eureka-client 测试接口提供方
  • itstack-demo-springcloud-hystrix-feign 接口调用方feign
  • itstack-demo-springcloud-hystrix-ribbon 接口调用方ribbon
  • itstack-demo-springcloud-zuul 路由服务

2.测试接口

  • 访问feign、ribbon接口,验证服务是否可用;http://localhost:9001/api/queryuserinfo?userid=111、http://localhost:9002/api/queryuserinfo?userid=111
  • 访问路由接口a;http://localhost:10001/route-a/api/queryuserinfo?userid=111
  • 访问路由接口b;http://localhost:10001/route-b/api/queryuserinfo?userid=111

hello| 111 >: from eureka client port: 8001 from ribbon

综上总结

  • zuul目前springcloud结合的是zuul 1, netflix 已经发布了 zuul 2但目前还未整合
  • springcloud还有自己的网关服务;spring cloud gateway
  • 通过最上层的路由功能可以很方便的隔离业务,但是路由层一定是高可用的,否则路由瘫痪整个服务将不可用

以上为个人经验,希望能给大家一个参考,也希望大家多多支持代码网。

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com