微服务网关介于客户端与服务器端之间,所有的外部请求都会讲过微服务网关。 使用微服务网关的优点:
客户端只需和网关交互,而无需调用特定的微服务接口。易于监控易于认证减少了客户端与各个微服务之间的交互次数Zuul是Netflix开源的微服务网关,可以和Eureka、Ribbon、Hystrix等组件配合使用。其核心似乎一系列过滤器,可完成如下功能。
身份认证与安全:识别每个资源的验证要求,拒绝不符合要求的请求。审查与监控:在边缘位置追踪有意义的数据和统计结果,从而带来精确的生产视图。动态路由:动态地将请求路由到不同地后端集群。压力测试:逐渐增加指向集群的流量,以了解性能。负载分配:为每一种负载类型分配对应地容量,并启用超出限定值的请求。静态响应处理:在边缘位置直接建立部分响应,从而避免其转发到内部集群。多区域弹性:跨越AWS Region进行请求路由,旨在实现ELB(Elastic Load Balancing)使用的多样化,已经让系统的边缘更贴近系统的使用者。上述内容截取自书籍 《Spring Cloud与Docker微服务架构与实战》
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> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.5.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.dfyang</groupId> <artifactId>eureka-server</artifactId> <version>0.0.1-SNAPSHOT</version> <name>eureka-server</name> <description>Demo project for Spring Boot</description> <properties> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Greenwich.RELEASE</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>application.xml
server: port: 8761 spring: application: name: eureka-server eureka: client: #是否将自己注册到Eureka Server,由于当前应用为Eureka Service,故为false register-with-eureka: false #是否从Eureka Server获取注册信息,由于是单点,所以为false fetch-registry: false #与Eureka Server交互的地址 serviceUrl: defaultZone: http://localhost:8761/eureka/启动类
package com.dfyang; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer; @SpringBootApplication @EnableEurekaServer public class EurekaServerApplication { public static void main(String[] args) { SpringApplication.run(EurekaServerApplication.class, args); } }启动项目,访问localhost:8761成功跳转页面即编写成功
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> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.5.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.dfyang</groupId> <artifactId>service-producer</artifactId> <version>0.0.1-SNAPSHOT</version> <name>service-producer</name> <description>Demo project for Spring Boot</description> <properties> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Greenwich.RELEASE</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>application.xml
server: port: 8080 spring: application: name: service-producer eureka: client: serviceUrl: defaultZone: http://localhost:8761/eureka/启动类
package com.dfyang; import com.netflix.hystrix.contrib.metrics.eventstream.HystrixMetricsStreamServlet; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.web.servlet.ServletRegistrationBean; import org.springframework.cloud.netflix.eureka.EnableEurekaClient; import org.springframework.cloud.netflix.hystrix.EnableHystrix; import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard; import org.springframework.cloud.netflix.turbine.EnableTurbine; import org.springframework.context.annotation.Bean; @SpringBootApplication @EnableEurekaClient public class ServiceProducerApplication { public static void main(String[] args) { SpringApplication.run(ServiceProducerApplication.class, args); } }提供的服务
package com.dfyang.serviceProducer.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class ProducerController { @RequestMapping("/serviceA") public String serviceA() { return "服务A"; } @RequestMapping("/serviceB") public String serviceB() { return "服务B"; } }启动项目,访问localhost:8761,出现如下即成功
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> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.5.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.dfyang</groupId> <artifactId>service-consumer</artifactId> <version>0.0.1-SNAPSHOT</version> <name>service-consumer</name> <description>Demo project for Spring Boot</description> <properties> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Greenwich.RELEASE</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>application.yml
server: port: 8082 spring: application: name: service-consumer eureka: client: service-url: defaultZone: http://localhost:8761/eureka/启动类
package com.dfyang; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; import org.springframework.cloud.openfeign.EnableFeignClients; @SpringBootApplication @EnableEurekaClient @EnableFeignClients public class ServiceConsumerApplication { public static void main(String[] args) { SpringApplication.run(ServiceConsumerApplication.class, args); } }使用Fegin远程调用服务
package com.dfyang.serviceConsumer.controller; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.stereotype.Service; import org.springframework.web.bind.annotation.GetMapping; @Service @FeignClient(name = "service-producer") public interface ProducerService { @GetMapping("/serviceA") public String serviceA(); @GetMapping("/serviceB") public String serviceB(); }消费服务
package com.dfyang.serviceConsumer.controller; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class ConsumerController { @Autowired private ProducerService producerService; @GetMapping("/consumeA") public String consumeA() { return producerService.serviceA(); } @GetMapping("/consumeB") public String consumeB() { return producerService.serviceB(); } }启动项目,输入localhost:8761 访问 localhost:8082/consumeA 和 localhost:8082/consumeB 成功!
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> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.5.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.dfyang</groupId> <artifactId>eureka-zuul</artifactId> <version>0.0.1-SNAPSHOT</version> <name>eureka-zuul</name> <description>Demo project for Spring Boot</description> <properties> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-zuul</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Greenwich.RELEASE</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>application.yml
server: port: 8084 spring: application: name: eureka-zuul eureka: client: service-url: defaultZone: http://localhost:8761/eureka/ #为应用程序显示详细的健康指标,并未actuator开启所有的endpoint management: endpoints: web: exposure: include: "*" endpoint: health: show-details: always启动类
package com.dfyang; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.zuul.EnableZuulProxy; @SpringBootApplication @EnableZuulProxy public class EurekaZuulApplication { public static void main(String[] args) { SpringApplication.run(EurekaZuulApplication.class, args); } }启动项目,访问localhost:8761 输入localhost:8084/service-consumer/consumeA 和 localhost:8084/service-consumer/consumeB 将出现与访问 localhost:8082/consumeA 和 localhost:8082/consumeB相同的结果
也就是我们所有的请求都交给了Zuul,再由Zuul将请求转发到微服务。 访问 http://localhost:8084/actuator/routes 从上面可以看出 请求的格式为: http://zuul_host:zuul_port/微服务在Eureka的serviceId/** 如果我们需要将 [微服务在Eureka的serviceId] 替换为别的,只需要添加如下
zuul: routes: service-producer: /producer/** service-consumer: /consumer/**访问ocalhost:8084/consumer/consumeA 和 localhost:8084/consumer/consumeB(但之前的仍然可以访问) 可以添加忽略的服务
zuul: routes: service-producer: /producer/** service-consumer: /consumer/** ignored-services: service-producer,service-consumer再次访问,成功!