IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> Spring Cloud Gateway整合Nacos实现服务路由及集群负载均衡 -> 正文阅读

[Java知识库]Spring Cloud Gateway整合Nacos实现服务路由及集群负载均衡

一、序言

我们都知道Spring Cloud Gateway是一个基于Spring BootSpring WebFluxProject Reactor构建的高性能网关,旨在提供简单、高效的API路由。

Spring Cloud Gateway基于Netty运行,因此在传统Servlet容器中或者打成war包是不能正常运行的。



二、代码示例

这里我们注册中心选型的是Nacos,如果还没有安装Nacos,请参考:Nacos快速安装部署

1、父工程spring-cloud-gateway-learning

	<modules>
	        <module>spring-cloud-api-gateway</module>
	        <module>spring-cloud-user-service</module>
	        <module>spring-cloud-message-service</module>
	</modules>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <spring.boot.version>2.3.7.RELEASE</spring.boot.version>
        <spring.cloud.version>Hoxton.SR12</spring.cloud.version>
        <spring.cloud.alibaba.version>2.2.6.RELEASE</spring.cloud.alibaba.version>
        <commons.lang3.version>3.12.0</commons.lang3.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>${commons.lang3.version}</version>
        </dependency>
    </dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-parent</artifactId>
                <version>${spring.boot.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>

            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring.cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>${spring.cloud.alibaba.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

备注:具体Spring Cloud各版本说明请参考Spring Cloud Alibaba版本说明

2、子工程spring-cloud-api-gateway

(1) pom.xml

<parent>
        <groupId>com.universe</groupId>
        <artifactId>spring-cloud-gateway-learning</artifactId>
        <version>1.0-SNAPSHOT</version>
</parent>

<dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
</dependencies>

(2) 配置文件和代码示例

  1. bootstrap.yml
spring:
  application:
    name: api-gateway
server:
  port: 9000
  1. application.yml
spring:
  cloud:
    gateway:
      routes:
        - id: user-service
          uri: lb://user-service
          predicates:
            - Path=/user/**
        - id: message-service
          uri: lb://message-service
          predicates:
            - Path=/message/**
    nacos:
      discovery:
        server-addr: localhost:8848

如果URI以lb开头,比如如上配置中的lb://user-serviceSpring Cloud Gateway会用ReactiveLoadBalancerClientFilter 解析服务名为user-service的实例对应的实际host和端口,并做集群负载均衡。

这项功能通过全局过滤器ReactiveLoadBalancerClientFilter 实现,官网描述如下:
在这里插入图片描述

  1. RouteRecordGlobalFilter
@Slf4j
@Component
public class RouteRecordGlobalFilter implements GlobalFilter, Ordered {

	@Override
	public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
		// RouteToRequestUrlFilter会把实际路由的URL通过该属性保存
		URI proxyRequestUri = exchange.getAttribute(ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR);
		long start = System.currentTimeMillis();

		return chain.filter(exchange).then(Mono.fromRunnable(() -> {
			long end = System.currentTimeMillis();
			log.info("实际调用地址为:{},调用耗时为:{}ms", proxyRequestUri, (end - start));
		}));
	}

	@Override
	public int getOrder() {
		// 优先级设为最低,先让RouteToRequestUrlFilter先调用
		return Ordered.LOWEST_PRECEDENCE;
	}
}

RouteRecordGlobalFilter 这个全局过滤器我们主要用来记录路由后的实际代理地址,以及调用耗时。

我们看下RouteToRequestUrlFilter的描述会发现实际路由地址会通过ServerWebExchange中名为ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR的属性保存。

在这里插入图片描述

关于RouteToRequestUrlFilter的部分源码如下:

@Override
	public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
		Route route = exchange.getAttribute(GATEWAY_ROUTE_ATTR);
		if (route == null) {
			return chain.filter(exchange);
		}
		log.trace("RouteToRequestUrlFilter start");
		URI uri = exchange.getRequest().getURI();
		boolean encoded = containsEncodedParts(uri);
		URI routeUri = route.getUri();

		if (hasAnotherScheme(routeUri)) {
			// this is a special url, save scheme to special attribute
			// replace routeUri with schemeSpecificPart
			exchange.getAttributes().put(GATEWAY_SCHEME_PREFIX_ATTR,
					routeUri.getScheme());
			routeUri = URI.create(routeUri.getSchemeSpecificPart());
		}

		if ("lb".equalsIgnoreCase(routeUri.getScheme()) && routeUri.getHost() == null) {
			// Load balanced URIs should always have a host. If the host is null it is
			// most
			// likely because the host name was invalid (for example included an
			// underscore)
			throw new IllegalStateException("Invalid host: " + routeUri.toString());
		}

		URI mergedUrl = UriComponentsBuilder.fromUri(uri)
				// .uri(routeUri)
				.scheme(routeUri.getScheme()).host(routeUri.getHost())
				.port(routeUri.getPort()).build(encoded).toUri();
		exchange.getAttributes().put(GATEWAY_REQUEST_URL_ATTR, mergedUrl);
		return chain.filter(exchange);
	}

备注:更多关于全局过滤器的介绍请参考 Spring Cloud Gateway全局过滤器

3、子工程spring-cloud-user-service

(1) pom.xml

<parent>
        <groupId>com.universe</groupId>
        <artifactId>spring-cloud-gateway-learning</artifactId>
        <version>1.0-SNAPSHOT</version>
</parent>

<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
</dependencies>

(2) 配置文件

  1. bootstrap.yml
spring:
  application:
    name: user-service
server:
  servlet:
    context-path: /user

---
spring:
  profiles: user-service-master
server:
  port: 9091

---
spring:
  profiles: user-service-slave
server:
  port: 9092

  1. application.yml
spring:
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848
  1. UserController
@RestController
public class UserController {

	@GetMapping("/info")
	public Map<String, Object> getUserInfo() {
	Random random = new Random();
		int waitTime = random.nextInt(1000);
		LockSupport.parkNanos(1000 * 1000 * waitTime);
		
		Map<String, Object> result = new HashMap<>();
		result.put("name", "Nick");
		result.put("age", 25);
		return result;
	}
}

4、子工程spring-cloud-message-service

(1) pom.xml

<parent>
        <groupId>com.universe</groupId>
        <artifactId>spring-cloud-gateway-learning</artifactId>
        <version>1.0-SNAPSHOT</version>
</parent>

<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
</dependencies>

(2) 配置文件和代码示例

  1. bootstrap.yml
spring:
  application:
    name: message-service
server:
  servlet:
    context-path: /message

---
spring:
  profiles: message-service-master
server:
  port: 9093

---
spring:
  profiles: message-service-slave
server:
  port: 9094
  1. application.yml
spring:
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848
  1. MessageController
@RestController
public class MessageController {

	@GetMapping("/info")
	public Map<String, Object> getMessageInfo() {
	Random random = new Random();
		int waitTime = random.nextInt(1000);
		LockSupport.parkNanos(1000 * 1000 * waitTime);
	
		Map<String, Object> result = new HashMap<>();
		result.put("id", 1);
		result.put("title", "我爱中国");
		return result;
	}
}


三、测试结果

分别启动api-gateway、指定概要文件启动两个user-service服务实例、和两个message-service服务实例,查看Nacos控制台。
在这里插入图片描述

可以看到,api-gateway启动了一个服务实例,user-service和message-service都启动了两个服务实例。

备注:IDEA运行时指定Active Profiles即可。

1、集群负载均衡测试

连续访问http://localhost:9000/user/info,可以看到user-service集群服务实例被轮询调用。
在这里插入图片描述

2、服务路由测试

分别访问 http://localhost:9000/user/infohttp://localhost:9000/message/info,我们可以看到基于路径匹配的服务路由分发是成功的。
在这里插入图片描述

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-06-21 21:21:07  更:2022-06-21 21:21:42 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 16:36:33-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码