Spring Cloud Zuul网关搭建详解

网关的英文名称:gateway,又叫做网间连接器、协议转换器。网关是在采用不同体系结构或协议的网络之间进行互通时,用于提供协议转换、路由选择、数据交换、日志埋点、负载均衡、容灾、鉴权、限流等网络兼容功能的设施。

后台服务肯定不能暴露在外,而且都是内网,这里的网关就至关重要,为了防止单点故障,实现高可用。可以搭建多节点

springboot2.1.1 springcloud Finchley.RELEASE版本,第一次使用spring boot这么高的版本

创建一个spring boot项目,搭建过程也很简单

构建时通过maven project module方式构建的

父pom.xml:

<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.chwl.cn</groupId>
	<artifactId>chwl</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>pom</packaging>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<maven.compiler.source>1.8</maven.compiler.source>
		<maven.compiler.target>1.8</maven.compiler.target>
		<junit.version>4.12</junit.version>
		<log4j.version>1.2.17</log4j.version>
		<lombok.version>1.16.18</lombok.version>
	</properties>

	<dependencyManagement>
		<dependencies>
			<dependency>
				<groupId>org.springframework.cloud</groupId>
				<artifactId>spring-cloud-dependencies</artifactId>
				<version>Finchley.RELEASE</version>
				<type>pom</type>
				<scope>import</scope>
			</dependency>
			<dependency>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-dependencies</artifactId>
				<version>2.1.1.RELEASE</version>
				<type>pom</type>
				<scope>import</scope>
			</dependency>
			<dependency>
				<groupId>mysql</groupId>
				<artifactId>mysql-connector-java</artifactId>
				<!-- <version>5.0.4</version> -->
				<version>8.0.11</version>
			</dependency>
			<dependency>
				<groupId>com.alibaba</groupId>
				<artifactId>druid</artifactId>
				<version>1.0.31</version>
			</dependency>
			<dependency>
				<groupId>org.mybatis.spring.boot</groupId>
				<artifactId>mybatis-spring-boot-starter</artifactId>
				<version>1.3.0</version>
			</dependency>
			<dependency>
				<groupId>ch.qos.logback</groupId>
				<artifactId>logback-core</artifactId>
				<version>1.2.3</version>
			</dependency>
			<dependency>
				<groupId>junit</groupId>
				<artifactId>junit</artifactId>
				<version>${junit.version}</version>
				<scope>test</scope>
			</dependency>
			<dependency>
				<groupId>org.apache.httpcomponents</groupId>
				<artifactId>httpclient</artifactId>
				<version>4.5.4</version>
			</dependency>
			<dependency>
				<groupId>org.apache.commons</groupId>
				<artifactId>commons-lang3</artifactId>
				<version>3.1</version>
			</dependency>
		</dependencies>
	</dependencyManagement>

	<build />
	<modules>
		<module>chwl-eureka-server</module>
		<module>chwl-entity</module>
		<module>chwl-common</module>
		<module>chwl-provider-order</module>
		<module>chwl-provider-product</module>
		<module>chwl-api-gateway-zuul-7001</module>
	</modules>
</project>

zuul  pom.xml依赖:

<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>

启动类:添加@EnableZuulProxy注解

package com.chwl.cn;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;

@EnableZuulProxy
@EnableEurekaClient
@SpringBootApplication
public class APIGatewayApplication {
	public static void main(String[] args) {
		SpringApplication.run(APIGatewayApplication.class, args);
	}
}

@EnableZuulProxy默认集成了hystrix熔断器@EnableCircuitBreaker

源码:

 * Copyright 2013-2017 the original author or authors.

package org.springframework.cloud.netflix.zuul;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.context.annotation.Import;

/**
 * Sets up a Zuul server endpoint and installs some reverse proxy filters in it, so it can
 * forward requests to backend servers. The backends can be registered manually through
 * configuration or via DiscoveryClient.
 *
 * @see EnableZuulServer for how to get a Zuul server without any proxying
 *
 * @author Spencer Gibb
 * @author Dave Syer
 * @author Biju Kunjummen
 */
@EnableCircuitBreaker
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Import(ZuulProxyMarkerConfiguration.class)
public @interface EnableZuulProxy {
}

application.yml:

server: 
  port: 7001
#服务的名称
spring:
  application:
    name: chwl-api-gateway-zuul-7001
#  main:
#    allow-bean-definition-overriding: true
    
eureka: 
  client: #客户端注册进eureka服务列表内
    service-url: 
      #defaultZone: http://localhost:2001/eureka    #这个地址就是EurekaServer注册中心的地址
       defaultZone: http://ypp:[email protected]:2001/eureka/,http://ypp:[email protected]:2002/eureka/
  instance: 
    instance-id: chwl-api-gateway-zuul-7001
    prefer-ip-address: true     #访问路径可以显示IP地址
    
#自定义路由映射    
zuul: 
  routes: 
    chwl-provider-product: /apigateway/**
    chwl-provider-order: /apigateway/**
  #统一入口为上面的配置,其他入口忽略
  ignored-patterns: /*-provider-*/**
  #忽略整个服务,对外提供接口
  #ignored-services: chwl-provider-product

如果不需要自定义路由映射,可以不要zuul那几项配置,默认的规则是 host:port/spring:application:name/uri

比如商品服务访问就是:localhost:9001/chwl-provider-product/product/get/1

商品服务application.yml:

server: 
  port: 8003
#开启断路器,Feign接口API的实现类方法处理   
feign: 
  hystrix:
    enabled: true
    
hystrix:
  command:
    default:  #default全局有效,service id指定应用有效
      execution:
        timeout:
          #如果enabled设置为false,则请求超时交给ribbon控制,为true,则超时作为熔断根据
          enabled: true
        isolation:
          thread:
            timeoutInMilliseconds: 3000 #断路器超时时间,默认1000ms
    
spring: 
  application: 
    name: chwl-provider-product         #很重要,很重要,很重要,这是微服务向外部暴露的微服务的名字
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.mysql.cj.jdbc.Driver
    platform: mysql
    url: jdbc:mysql://120.79.81.103:5306/chwl?useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true&useSSL=false
    username: root
    password: admin
  redis: 
#    database: 1
    host: 127.0.0.1
    port: 6379
    password: 
    timeout: 10000
    lettuce:
          pool:
            minIdle: 0
            maxIdle: 10
            maxWait: 10000
            max-active: 10
    sentinel:
      master: master-6379
      nodes: 127.0.0.1:26379,127.0.0.1:26380,127.0.0.1:26381
#    cluster:
#      nodes:
#        - 192.168.91.5:9001
#        - 192.168.91.5:9002
#        - 192.168.91.5:9003
#        - 192.168.91.5:9004
#        - 192.168.91.5:9005
#        - 192.168.91.5:9006
    
mybatis: 
  config-location: classpath:mybatis/mybatis.cfg.xml
  #typeAliasesPackage: com.ypp.springcloud.entites
  mapper-locations: classpath:mybatis/mapper/**/*Mapper.xml
mapper:
  mappers: com.chwl.cn.basemapper.BaseMapper
  identity: mysql
  
eureka:
  client: #客户端注册进eureka服务列表内
    service-url: 
      #defaultZone: http://localhost:2001/eureka    #这个地址就是EurekaServer注册中心的地址
       defaultZone: http://ypp:[email protected]:2001/eureka/,http://ypp:[email protected]:2002/eureka/
  instance: 
    instance-id: chwl-provider-product
    prefer-ip-address: true     #访问路径可以显示IP地址

如果自定义路由映射,那么会存在一个问题。

/apigateway/product/xx/xx

/chwl-provider-product/product/xx/xx

2种路由都可以进行。

所以我们一般忽略本身的,忽略chwl-provider-product等。

统一使用apigateway的方式:

#统一入口为上面的配置,其他入口忽略
  ignored-patterns: /*-provider-*/**

那么现在只能通过/gateway/product/xx/xxx/xx的方式进行访问

最终的项目结构:

启动报错:

Description:

The bean 'proxyRequestHelper', defined in class path resource [org/springframework/cloud/netflix/zuul/ZuulProxyAutoConfiguration$NoActuatorConfiguration.class], could not be registered. A bean with that name has already been defined in class path resource [org/springframework/cloud/netflix/zuul/ZuulProxyAutoConfiguration$EndpointConfiguration.class] and overriding is disabled.

Action:

Consider renaming one of the beans or enabling overriding by setting spring.main.allow-bean-definition-overriding=true

一种说法是版本springcloud和springboot版本不一致,更换版本也有可能解决。

还有可能原因是因为类名和某些方法名重复了,提示已经很明显,让重新设置一个bean(意思修改类名或方法名)或设置spring.main.allow-bean-definition-overriding=true允许spring进行覆盖。没有找到哪里重复了,更换版本出错的几率有点大,因为要更换版本又容易造成版本不一致,暂时解决先设置spring.main.allow-bean-definition-overriding=true

在application.yml添加配置:spring.main.allow-bean-definition-overriding=true

启动继续报错:

Description:

An attempt was made to call the method org.springframework.boot.autoconfigure.web.ServerProperties$Servlet.getServletPrefix()Ljava/lang/String; but it does not exist. Its class, org.springframework.boot.autoconfigure.web.ServerProperties$Servlet, is available from the following locations:

    jar:file:/E:/java/repository/org/springframework/boot/spring-boot-autoconfigure/2.1.1.RELEASE/spring-boot-autoconfigure-2.1.1.RELEASE.jar!/org/springframework/boot/autoconfigure/web/ServerProperties$Servlet.class

It was loaded from the following location:

    file:/E:/java/repository/org/springframework/boot/spring-boot-autoconfigure/2.1.1.RELEASE/spring-boot-autoconfigure-2.1.1.RELEASE.jar


Action:

Correct the classpath of your application so that it contains a single, compatible version of org.springframework.boot.autoconfigure.web.ServerProperties$Servlet

一看就是jar冲突了

然后发现是spring boot和spring cloud版本不一致造成。网上的解决办法是spring boot 2.1.1.RELEASE版本对应的是spring cloud Greenwich.M3版本,修改了,然而并没有什么卵用,maven根本没有相关依赖。然后翻官网没找到相关对应的版本信息。然后试了一下spring cloud Greenwich.RELEASE的版本。成功,取消之前的spring.main.allow-bean-definition-overriding=true。

第一次使用spring 2.1.1版本,依赖也变了,问题出现的早,还好花了几分钟解决了,慢慢熟悉高版本

zuul测试

使用localhost:7001/chwl-provider-order/  失败

网关自定义路由配置成功了,

问题一:直接使用微服务的地址和端口加路径是可以访问的。但这种情况在应用生产部署基本是内外网隔离的,别人是访问不到的,也不知道到底是哪台服务器。只有通过网关统一入口进行访问

问题二:以下自定义路由配置product和order服务都是使用的apigateway统一访问的,会产生一个问题。后面的会覆盖前面的,所以product的服务是完全访问不了,会提示404,因为ignored-patterns: /*-provider-*/**也把它给忽略了

#自定义路由映射    
zuul: 
  routes: 
    chwl-provider-product: /apigateway/**
    chwl-provider-order: /apigateway/**
  #统一入口为上面的配置,其他入口忽略
  ignored-patterns: /*-provider-*/**
  #忽略整个服务,对外提供接口
  #ignored-services: chwl-provider-product

改造后:

#自定义路由映射    
zuul: 
  routes: 
    chwl-provider-product: /apigateway/product/**
    chwl-provider-order: /apigateway/order/**
  #统一入口为上面的配置,其他入口忽略
  ignored-patterns: /*-provider-*/**
  #忽略整个服务,对外提供接口
  #ignored-services: chwl-provider-product

测试:

网关配置完成

代码已上传github,包括feign、hystrix、ribbon、eureka等      https://github.com/yfcgklypp/chwl.git

发布了288 篇原创文章 · 获赞 88 · 访问量 43万+

猜你喜欢

转载自blog.csdn.net/ypp91zr/article/details/90245204