• 12 在微服务集群中使用Zuul


      在上一篇博文中,Zuul将请求转发给了一个Web项目进行处理,如果处理的请求不是一个Web项目,而是整个微服务集群,那么Zuul将成为整个集群的网关。在加入Zuul前,Spring Cloud集群的结构如下图所示

      为微服务集群加入Zuul的网关后,结构如下图所示

                      

      接下来我们就来实现在Spring Cloud中加入Zuul网关。

    1.搭建集群

      我们本例要实现一个书本销售的业务,在销售模块中需要调用书本模块的服务来查找书本。建立一下的项目

      》 eurekaserver: Eureka服务器,应用端口为8761。

      》 bookservice: 书本模块,属于服务的提供者,提供/book/{bookId}的服务,用于查找图书,最后返回的是JSON字符串,应用的端口是9000。

      》saleservice: 销售模块,属于服务调用者,在该服务中会使用Feign框架来调用bookservice发布的查找图书的服务,其自身也会对外发布/salebook/{bookId}的销售服务。

      1.1 eureka服务器

      创建名为eurekaserver的maven项目,并编写代码实现相应的功能。项目的目录结构如下

      

      在pom.xml文件中引入对应的依赖

      pom.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
    
        <groupId>com.triheart</groupId>
        <artifactId>eurekaserver</artifactId>
        <version>1.0-SNAPSHOT</version>
    
        <dependencyManagement>
            <dependencies>
                <dependency>
                    <groupId>org.springframework.cloud</groupId>
                    <artifactId>spring-cloud-dependencies</artifactId>
                    <version>Dalston.SR1</version>
                    <type>pom</type>
                    <scope>import</scope>
                </dependency>
            </dependencies>
        </dependencyManagement>
    
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-eureka-server</artifactId>
            </dependency>
        </dependencies>
        
    </project>

      在application.yml配置文件中配置应用端口以及eureka客户端以及服务端的相关属性

      application.yml

    server:
      port: 8761
    eureka:
      client:
        registerWithEureka: false
        fetchRegistry: false
      server:
        enable-self-preservation: false

      编写启动类,加入@EnableEurekaServer注解以及@SpringBootApplication注解

      ServerApp.java

    package com.triheart.eurekaserver;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
    
    /**
     * @author 阿遠
     * Date: 2018/9/3
     * Time: 10:25
     */
    @SpringBootApplication
    @EnableEurekaServer
    public class ServerApp {
        public static void main(String[] args){
            SpringApplication.run(ServerApp.class, args);
        }
    }

      Eureka服务器项目搭建完毕。

      1.2 服务提供者

      新建一个名为bookservice的maven项目,并编写代码实现相应的功能,项目的目录结构如下

      

      在pom.xml中引入相关的依赖,代码请但如下

      pom.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
    
        <groupId>com.triheart</groupId>
        <artifactId>bookservice</artifactId>
        <version>1.0-SNAPSHOT</version>
    
        <dependencyManagement>
            <dependencies>
                <dependency>
                    <groupId>org.springframework.cloud</groupId>
                    <artifactId>spring-cloud-dependencies</artifactId>
                    <version>Dalston.SR1</version>
                    <type>pom</type>
                    <scope>import</scope>
                </dependency>
            </dependencies>
        </dependencyManagement>
    
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-config</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-eureka</artifactId>
            </dependency>
        </dependencies>
    </project>

       在application.yml中配置应用名称以及Eureka的客户端实例的名称和该实例所注册的服务器的地址

      application.yml

    spring:
      application:
        name: bookservice
    eureka:
      instance:
        hostname: localhost
      client:
        service-url:
          defaultZone: http://localhost:8761/eureka/

       编写应用启动类,加入@EnableEurekaClient注解以及@SpringBootApplication注解

      BookService.java

    package com.triheart.bookservice;
    
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.boot.builder.SpringApplicationBuilder;
    import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
    /**
     * @author 阿遠
     * Date: 2018/9/3
     * Time: 10:33
     */
    @SpringBootApplication
    @EnableEurekaClient
    public class BookServiceApp {
        public static void main(String[] args){
            new SpringApplicationBuilder(BookServiceApp.class).properties(
                    "server.port=9000").run(args);
        }
    }

       编写Controller类,发布Web服务,代码清单如下

      Book.java

    package com.triheart.bookservice.web;
    
    /**
     * @author 阿遠
     * Date: 2018/9/3
     * Time: 10:37
     */
    public class Book {
    
        private Integer id;
    
        private String name;
    
        private String author;
    
        public Integer getId() {
            return id;
        }
    
        public void setId(Integer id) {
            this.id = id;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public String getAuthor() {
            return author;
        }
    
        public void setAuthor(String author) {
            this.author = author;
        }
    }
    View Code

       BookController.java

    package com.triheart.bookservice.web;
    
    import org.springframework.http.MediaType;
    import org.springframework.web.bind.annotation.PathVariable;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestMethod;
    import org.springframework.web.bind.annotation.RestController;
    
    /**
     * @author 阿遠
     * Date: 2018/9/3
     * Time: 10:38
     */
    @RestController
    public class BookController {
    
        @RequestMapping(value = "/book/{bookId}", method = RequestMethod.GET,produces = MediaType.APPLICATION_JSON_VALUE)
        public Book findBook(@PathVariable("bookId") Integer bookId) {
            Book book = new Book();
            book.setId(bookId);
            book.setName("Spring Cloud");
            book.setAuthor("ayuan");
            return book;
        }
    }

      bookservice服务提供者项目搭建完毕。

      1.3 服务调用者

      新建一个名为saleservice的maven项目,编写代码实现相应的功能,目录结构如下

      

      在pom.xml文件中引入相应的依赖   

      pom.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
    
        <groupId>com.triheart</groupId>
        <artifactId>salesservice</artifactId>
        <version>1.0-SNAPSHOT</version>
    
        <dependencyManagement>
            <dependencies>
                <dependency>
                    <groupId>org.springframework.cloud</groupId>
                    <artifactId>spring-cloud-dependencies</artifactId>
                    <version>Dalston.SR1</version>
                    <type>pom</type>
                    <scope>import</scope>
                </dependency>
            </dependencies>
        </dependencyManagement>
    
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-config</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-eureka</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-ribbon</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-feign</artifactId>
            </dependency>
        </dependencies>
    </project>

       编写配置文件application.yml,配置应用的启动端口、应用的名称以及注册到eureka对应的名称和注册的eureka服务器的地址

    server:
      port: 9100
    spring:
      application:
        name: saleservice
    eureka:
      instance:
        hostname: localhost
      client:
        serviceUrl:
          defaultZone: http://localhost:8761/eureka/

      编写应用启动类,加入@EnableEurekaClient注解以及@SpringBootApplication注解,由于该模块需要用到Feign客户端框架来调用bookservice发布的服务,故需要在启动类中加入@EnableFeignClients的注解

      SaleServiceApp.java

    package com.triheart.salesservice;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
    import org.springframework.cloud.netflix.feign.EnableFeignClients;
    
    /**
     * @author 阿遠
     * Date: 2018/9/3
     * Time: 12:43
     */
    @SpringBootApplication
    @EnableEurekaClient
    @EnableFeignClients
    public class SalesServiceApp {
    
        public static void main(String[] args){
            SpringApplication.run(SalesServiceApp.class, args);
        }
    }

       编写Feign框架对应的BookService接口,以调用bookservice项目发布的服务,代码清单如下

      Book.java

    package com.triheart.salesservice.feign;
    
    /**
     * @author 阿遠
     * Date: 2018/9/3
     * Time: 12:48
     */
    public class Book {
    
        private Integer id;
    
        private String name;
    
        private String author;
    
        public Integer getId() {
            return id;
        }
    
        public void setId(Integer id) {
            this.id = id;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public String getAuthor() {
            return author;
        }
    
        public void setAuthor(String author) {
            this.author = author;
        }
    }
    View Code

      BookService.java

    package com.triheart.salesservice.feign;
    
    import org.springframework.cloud.netflix.feign.FeignClient;
    import org.springframework.web.bind.annotation.PathVariable;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestMethod;
    
    /**
     * @author 阿遠
     * Date: 2018/9/3
     * Time: 12:49
     */
    @FeignClient("bookservice")
    public interface BookService {
        /**
         * 调用书本服务接口,获取一个Book的实例
         */
        @RequestMapping(value = "/book/{bookId}", method = RequestMethod.GET)
        Book getBook(@PathVariable("bookId") Integer bookId);
    }

       编写SaleController控制器,发布图书销售的Web服务

      SaleController.java

    package com.triheart.salesservice.web;
    
    import com.triheart.salesservice.feign.Book;
    import com.triheart.salesservice.feign.BookService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.PathVariable;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestMethod;
    import org.springframework.web.bind.annotation.RestController;
    
    /**
     * @author 阿遠
     * Date: 2018/9/3
     * Time: 12:47
     */
    @RestController
    public class SaleController {
    
        @Autowired
        private BookService bookService;
        /**
         * 进行图书销售
         */
        @RequestMapping(value = "/salebook/{bookId}", method = RequestMethod.GET)
        public String saleBook(@PathVariable Integer bookId) {
            // 利用book服务查找相应的book
            Book book = bookService.getBook(bookId);
            // 控制台输出,模拟图书的销售
            System.out.println("要销售的图书为id:"+ book.getId()+", 图书的名称为:"+book.getName());
            return "success";
    
        }
    }

      saleservice服务调用项目搭建完毕。至此,我们已经将Eureka微服务集群搭建完成。接下来我们将搭建Zuul网关项目来实现Zuul在微服务集群中的使用。

    2.路由到集群服务

      新建一个名为zuulgetaway的maven项目,编写代码实现相应的功能,项目的目录结构如下

      

      编写pom.xml文件,引入相关的依赖

      pom.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
    
        <groupId>com.triheart</groupId>
        <artifactId>zuulgateway</artifactId>
        <version>1.0-SNAPSHOT</version>
    
        <dependencyManagement>
            <dependencies>
                <dependency>
                    <groupId>org.springframework.cloud</groupId>
                    <artifactId>spring-cloud-dependencies</artifactId>
                    <version>Dalston.SR1</version>
                    <type>pom</type>
                    <scope>import</scope>
                </dependency>
            </dependencies>
        </dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-config</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-eureka</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-zuul</artifactId>
            </dependency>
            <dependency>
                <groupId>org.apache.httpcomponents</groupId>
                <artifactId>httpclient</artifactId>
                <version>4.5.3</version>
            </dependency>
        </dependencies>
        
    </project>

      编写配置文件application.yml

      application.yml

    spring:
      application:
        name: zuulgateway
    eureka:
      instance:
        hostname: localhost
      client:
        service-url:
          defaultZone: http://localhost:8761/eureka/
    zuul:
      routes:
        sale:
          path: /sale/**
          serviceId: saleservice

      在配置文件中,我们配置了应用的名称,由于网关项目需要加入到集群中,我们需要在配置文件中进行配置让其注册到Eureka服务器中,最后我们配置了Zuul,在配置Zuul时声明了所有的/sale/**的请求都会被转发到Id为saleservice的服务进行处理,一般情况下,配置了serviceId后,在处理请求的routing阶段,将会使用一个名称为RibbonRoutingFilter的过滤器,该过滤器会调用Ribbon的API来思想负载均衡。

      编写应用启动类

      ZuulGatewayApp.java

    package com.triheart.zuulgateway;
    
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.boot.builder.SpringApplicationBuilder;
    import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
    
    /**
     * @author 阿遠
     * Date: 2018/9/3
     * Time: 16:36
     */
    @SpringBootApplication
    @EnableZuulProxy
    public class ZuulGatewayApp {
        public static void main(String[] args){
            new SpringApplicationBuilder(ZuulGatewayApp.class).properties("server.port=8080").run(args);
        }
    }

      在应用的启动类中,我们需要添加@EnableZuulProxy注解来使用Zuul。

    3.启动项目

      我们按照以下顺序启动集群

      》 启动eurekaserver

      》启动bookservice

      》启动saleservice

      》启动zuulgeteway

      在浏览器中访问http://localhost:8080/sale/salebook/1,可以看到在浏览器中返回如下

      销售模块的控制台返回如下

      根据输出可知,销售模块和图书模块均被调用。

  • 相关阅读:
    Node.js缓冲模块Buffer
    hashMap底层put和get方法逻辑
    减少GC开销的措施
    mybatis中#{}和${}的区别
    AngularJS 用 Interceptors 来统一处理 HTTP 请求和响应
    点击页面的悬浮窗口实现随意拖动
    RabbitMQ 基本概念介绍-----转载
    Spring+Quartz实现定时执行任务的配置
    springmvc导出excel并弹出下载框
    AtomicInteger类保证线程安全的用法
  • 原文地址:https://www.cnblogs.com/a-yuan/p/9581481.html
Copyright © 2020-2023  润新知