Spring Cloud Alibaba 4 使用Gateway网关


Spring Cloud Alibaba 使用Gateway网关

项目搭建

  • 项目结构
  • 搭建pped-api网关项目(在之前项目基础上添加网关)
  • pom.xml
    <!--springBoot-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter</artifactId>
                <version>2.3.12.RELEASE</version>
            </dependency>
    
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <optional>true</optional>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <scope>test</scope>
            </dependency>
    
            <!--nacos-->
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
            </dependency>
    
            <!--gateway-->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-gateway</artifactId>
                <version>2.2.3.RELEASE</version>
            </dependency>
    (注意版本:具体版本可到官网查看:https://spring.io/projects/spring-cloud#learn ,点击版本后面的Reference Doc.查看)
  • application.yml:(注意格式,两个路由是之前的两个子项目)
    server:
      port: 8888
    spring:
      application:
        name: pped-api
      cloud:
        nacos:
          discovery:
            server-addr: 127.0.0.1:8848
            group: PPED_GROUP
        gateway:
          routes: #数组形式
            - id: nacos #路由唯一标识
              uri: lb://pped-nacos #想要转发到的地址,从nacos注册中心上拉取,lb:负载均衡轮询
              predicates: #断言 配置哪个路径才转发
                - Path=/nacos/**
              filters:
                - StripPrefix=1 #去掉第一层前缀
            - id: sentinel
              uri: lb://pped-sentinel
              predicates:
                - Path=/sentinel/**
              filters:
                - StripPrefix=1
          discovery:
            locator:
              enabled: true
  • 启动类加上注释
    @EnableDiscoveryClient
    public class PpedApiApplication {
    
    	public static void main(String[] args) {
    		SpringApplication.run(PpedApiApplication.class, args);
    	}
    
    }

测试

  • 访问localhost:8888/nacos/test
  • 完成

负载均衡

  • nacos默认存在负载均衡
  • 在之前基础上启动两个实例进行测试
  • 修改TestController
    访问时返回端口
    @Value("${local.server.port}")
    private int port;
    	
    return stringBuilder.toString() + " port:" + port;
  • 配置端口:idea右上角点击Edit Configurations
  • 点击左上角复制图标,复制配置(copy configuration)配置端口
  • 设置Programs arguments: –server.port=17072
  • 保存
  • 以新配置文件再启动一个服务
  • 进入nacos控制台可以发现两个实例
  • 不断访问localhost:8888/nacos/test
  • 可以发现在交替访问两个实例

自定义权重

  • 通过nacos控制台设置权重时,实际上并未生效,因为负载均衡器里使用的默认规则是 RoundRobinRule(轮询)
  • 想要自定义权重需要启用Robin的NacosRule,替换默认的Rule
  • 改动启动类
    public class PpedApiApplication {
    
    	public static void main(String[] args) {
    		SpringApplication.run(PpedApiApplication.class, args);
    	}
    
    	@Bean
    	public IRule loadBalanceRule(){
    	    return new NacosRule();
    	}
    
    }
  • 改动之后发现使用网关进行转发时报错,服务找不到
  • 原因是gateway默认使用DEFAULT_GROUP,这里改动了group所以服务找不到
  • 需要写一个自定义Rule
    @Slf4j
    public class NacosWeightedRule extends AbstractLoadBalancerRule {
    
    	@Autowired
    	private NacosDiscoveryProperties nacosDiscoveryProperties;
    
    	/**
    	 * 读取配置文件,并初始化NacosWeightedRule
    	 *
    	 * @param iClientConfig iClientConfig
    	 */
    	@Override
    	public void initWithNiwsConfig(IClientConfig iClientConfig) {
    		// do nothing
    	}
    
    	@Override
    	public Server choose(Object key) {
    		BaseLoadBalancer loadBalancer = (BaseLoadBalancer) this.getLoadBalancer();
    
    		// 需要请求的微服务名称
    		String name = loadBalancer.getName();
    		// 获取服务发现的相关API
    		NamingService namingService = nacosDiscoveryProperties.namingServiceInstance();
    		String group = nacosDiscoveryProperties.getGroup();
    		try {
    			// 调用该方法时nacos client会自动通过基于权重的负载均衡算法选取一个实例
    			Instance instance = namingService.selectOneHealthyInstance(name, group, true);
    			log.info("=============invoke serviceName:{}, ip:{}, port:{}", instance.getServiceName(), instance.getIp(), instance.getPort());
    			return new NacosServer(instance);
    		} catch (NacosException e) {
    			return null;
    		}
    	}
    }
  • 修改启动类
    public class PpedApiApplication {
    
    	public static void main(String[] args) {
    		SpringApplication.run(PpedApiApplication.class, args);
    	}
    
    	@Bean
    	public IRule loadBalanceRule(){
    		return new NacosWeightedRule();
    	}
    
    }
  • 在控制台给两个服务设置权重,可以发现两服务按权重交替被访问

  目录