在上一篇博文中,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
4.0.0 com.triheart eurekaserver 1.0-SNAPSHOT org.springframework.cloud spring-cloud-dependencies Dalston.SR1 pom import org.springframework.cloud spring-cloud-starter-eureka-server
在application.yml配置文件中配置应用端口以及eureka客户端以及服务端的相关属性
application.yml
server: port: 8761eureka: 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@EnableEurekaServerpublic class ServerApp { public static void main(String[] args){ SpringApplication.run(ServerApp.class, args); }}
Eureka服务器项目搭建完毕。
1.2 服务提供者
新建一个名为bookservice的maven项目,并编写代码实现相应的功能,项目的目录结构如下
在pom.xml中引入相关的依赖,代码请但如下
pom.xml
4.0.0 com.triheart bookservice 1.0-SNAPSHOT org.springframework.cloud spring-cloud-dependencies Dalston.SR1 pom import org.springframework.cloud spring-cloud-starter-config org.springframework.cloud spring-cloud-starter-eureka
在application.yml中配置应用名称以及Eureka的客户端实例的名称和该实例所注册的服务器的地址
application.yml
spring: application: name: bookserviceeureka: 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@EnableEurekaClientpublic 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; }}
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 */@RestControllerpublic 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
4.0.0 com.triheart salesservice 1.0-SNAPSHOT org.springframework.cloud spring-cloud-dependencies Dalston.SR1 pom import org.springframework.cloud spring-cloud-starter-config org.springframework.cloud spring-cloud-starter-eureka org.springframework.cloud spring-cloud-starter-ribbon org.springframework.cloud spring-cloud-starter-feign
编写配置文件application.yml,配置应用的启动端口、应用的名称以及注册到eureka对应的名称和注册的eureka服务器的地址
server: port: 9100spring: application: name: saleserviceeureka: 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@EnableFeignClientspublic 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; }}
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 */@RestControllerpublic 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
4.0.0 com.triheart zuulgateway 1.0-SNAPSHOT org.springframework.cloud spring-cloud-dependencies Dalston.SR1 pom import org.springframework.cloud spring-cloud-starter-config org.springframework.cloud spring-cloud-starter-eureka org.springframework.cloud spring-cloud-starter-zuul org.apache.httpcomponents httpclient 4.5.3
编写配置文件application.yml
application.yml
spring: application: name: zuulgatewayeureka: 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@EnableZuulProxypublic 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,可以看到在浏览器中返回如下
销售模块的控制台返回如下
根据输出可知,销售模块和图书模块均被调用。