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}的销售服务。

  下面就来创建相应的项目并实现对应的功能,创建名为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服务器项目搭建完毕。

  接下来我们创建服务提供者项目,新建一个名为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服务提供者项目搭建完毕。

  接下来我们创建服务调用这项目,新建一个名为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,可以看到在浏览器中返回如下

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

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

猜你喜欢

转载自www.cnblogs.com/a-yuan/p/9581481.html
12