网关的英文名称:gateway,又叫做网间连接器、协议转换器。网关是在采用不同体系结构或协议的网络之间进行互通时,用于提供协议转换、路由选择、数据交换、日志埋点、负载均衡、容灾、鉴权、限流等网络兼容功能的设施。
后台服务肯定不能暴露在外,而且都是内网,这里的网关就至关重要,为了防止单点故障,实现高可用。可以搭建多节点
springboot2.1.1 springcloud Finchley.RELEASE版本,第一次使用spring boot这么高的版本
创建一个spring boot项目,搭建过程也很简单
构建时通过maven project module方式构建的
父pom.xml:
4.0.0
com.chwl.cn
chwl
0.0.1-SNAPSHOT
pom
UTF-8
1.8
1.8
4.12
1.2.17
1.16.18
org.springframework.cloud
spring-cloud-dependencies
Finchley.RELEASE
pom
import
org.springframework.boot
spring-boot-dependencies
2.1.1.RELEASE
pom
import
mysql
mysql-connector-java
8.0.11
com.alibaba
druid
1.0.31
org.mybatis.spring.boot
mybatis-spring-boot-starter
1.3.0
ch.qos.logback
logback-core
1.2.3
junit
junit
${junit.version}
test
org.apache.httpcomponents
httpclient
4.5.4
org.apache.commons
commons-lang3
3.1
chwl-eureka-server
chwl-entity
chwl-common
chwl-provider-order
chwl-provider-product
chwl-api-gateway-zuul-7001
zuul pom.xml依赖:
org.springframework.cloud
spring-cloud-starter-netflix-eureka-client
org.springframework.cloud
spring-cloud-starter-netflix-zuul
启动类:添加@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