Zuul是Spring Cloud的微服务API网关,下面直接编写一个简单的例子,还是order
和member
两个微服务,假设这两个服务都在内网,外网访问不到,需要通过网关进行访问,代码如下
注册中心:
package com.zzk;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@SpringBootApplication
@EnableEurekaServer//表示开启EurekaServer服务,即注册中心
public class AppEureka {
public static void main(String[] args) {
SpringApplication.run(AppEureka.class, args);
}
}
###服务端口号
server:
port: 8080
###服务别名集群注册中心
spring:
application:
name: app-zzk-eureka
###eureka 基本信息配置
eureka:
instance:
###注册到eureka的ip地址
hostname: 127.0.0.1
client:
serviceUrl:
defaultZone: http://127.0.0.1:8080/eureka/,http://127.0.0.1:80900/eureka/
###因为自己是为注册中心,不需要把自己当成一个服务注册自己
register-with-eureka: true
###因为自己是为注册中心,不需要检索服务
fetch-registry: true
4.0.0
com.springcloud
springcloud-eureka
0.0.1-SNAPSHOT
org.springframework.boot
spring-boot-starter-parent
2.0.1.RELEASE
org.springframework.cloud
spring-cloud-dependencies
Finchley.RELEASE
pom
import
org.springframework.cloud
spring-cloud-starter-netflix-eureka-server
org.springframework.boot
spring-boot-starter-web
spring-milestones
Spring Milestones
https://repo.spring.io/libs-milestone
false
org.springframework.boot
spring-boot-maven-plugin
package com.zzk.api.controller;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
@SpringBootApplication
@EnableEurekaClient
public class AppOrder {
public static void main(String[] args) {
SpringApplication.run(AppOrder.class, args);
}
// 将restTemplate注册到springboot中
// 如果使用rest方式以别名方式进行调用依赖ribbon负载均衡器,需要加上@LoadBalanced
// 加上@LoadBalanced就会使得restTemplate在请求时拥有客户端负载均衡能力
@Bean
@LoadBalanced
RestTemplate restTemplate() {
return new RestTemplate();
}
}
package com.zzk.api.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class OrderController {
@RequestMapping("/getOrder")
public String getOrder() {
return "this is order";
}
}
###被注册服务的端口号
server:
port: 8081
##服务别名,即注册到注册中心的一个名称
spring:
application:
name: app-zk-order
###eureka 基本信息配置
eureka:
client:
serviceUrl:
###当前服务注册到eureka服务
defaultZone: http://localhost:8080/eureka
###需要将自身的服务注册到eureka上面去
register-with-eureka: true
###需要检索服务
fetch-registry: true
4.0.0
com.springcloud
springcloud-eureka-order
0.0.1-SNAPSHOT
org.springframework.boot
spring-boot-starter-parent
2.0.1.RELEASE
org.springframework.cloud
spring-cloud-dependencies
Finchley.RELEASE
pom
import
org.springframework.cloud
spring-cloud-starter-netflix-eureka-client
org.springframework.boot
spring-boot-starter-web
spring-milestones
Spring Milestones
https://repo.spring.io/libs-milestone
false
org.springframework.boot
spring-boot-maven-plugin
package com.zzk.api.controller;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
@SpringBootApplication
@EnableEurekaClient
public class AppMember {
public static void main(String[] args) {
SpringApplication.run(AppMember.class, args);
}
}
package com.zzk.api.controller;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class MemberController {
@RequestMapping("/getMember")
public String getMember() {
return "this is member";
}
}
###被注册服务的端口号
server:
port: 8082
##服务别名,即注册到注册中心的一个名称
spring:
application:
name: app-zk-member
###eureka 基本信息配置
eureka:
client:
serviceUrl:
###当前服务注册到eureka服务
defaultZone: http://localhost:8080/eureka
###需要将自身的服务注册到eureka上面去
register-with-eureka: true
###需要检索服务
fetch-registry: true
4.0.0
com.springcloud
springcloud-eureka-member
0.0.1-SNAPSHOT
org.springframework.boot
spring-boot-starter-parent
2.0.1.RELEASE
org.springframework.cloud
spring-cloud-dependencies
Finchley.RELEASE
pom
import
org.springframework.cloud
spring-cloud-starter-netflix-eureka-client
org.springframework.boot
spring-boot-starter-web
spring-milestones
Spring Milestones
https://repo.spring.io/libs-milestone
false
org.springframework.boot
spring-boot-maven-plugin
package com.zzk;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
import org.springframework.cloud.netflix.zuul.filters.ZuulProperties;
@SpringBootApplication
@EnableEurekaClient
@EnableZuulProxy // 开启网关代理
@EnableDiscoveryClient
// zuul默认开启本地ribbon负载均衡
public class ZuulServiceApplication {
public static void main(String[] args) {
SpringApplication.run(ZuulServiceApplication.class, args);
}
@RefreshScope
@ConfigurationProperties("zuul")
public ZuulProperties zuulProperties() {
return new ZuulProperties();
}
}
###服务端口号
server:
port: 82
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8080/eureka/
zuul:
routes:
api-a:
service-id: app-zk-member
path: /api-member/**
stripPrefix: true
api-b:
service-id: app-zk-order
path: /api-order/**
stripPrefix: true
###eureka 注册中心基本信息配置
management:
endpoints:
web:
exposure:
include: "*" #注意这里*要加引号,暴露全部,也可以只暴露相应endpoint
endpoint:
routes:
enabled: true # 默认为true,可以省略
4.0.0
com.springcloud5
springcloud5-zuul
0.0.1-SNAPSHOT
org.springframework.boot
spring-boot-starter-parent
2.0.1.RELEASE
org.springframework.cloud
spring-cloud-dependencies
Finchley.RELEASE
pom
import
org.springframework.cloud
spring-cloud-config-client
org.springframework.cloud
spring-cloud-starter-netflix-eureka-client
org.springframework.cloud
spring-cloud-starter-netflix-zuul
org.springframework.boot
spring-boot-starter-actuator
org.springframework.boot
spring-boot-starter-web
org.springframework.cloud
spring-cloud-config-client
org.springframework.boot
spring-boot-configuration-processor
true
org.springframework.boot
spring-boot-maven-plugin
spring-milestones
Spring Milestones
https://repo.spring.io/libs-milestone
false
启动注册中心—》order和member–》zuul
由于我们在zuul服务的yml配置了两个网关,启动后,可以通过地址http://localhost:82/actuator/routes
查看
然后通过网关访问order
服务http://localhost:82/api-order/getOrder
成功访问order
服务,同理访问member
服务
说明网关配置成功
由于网关是访问项目的入口,所以这里需要做一些过滤操作,下面做个简单的例子,即在zuul项目加一个过滤类,如果没有输入tiken就不给通过
package com.zzk.filter;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.protocol.RequestContent;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import com.ctc.wstx.util.StringUtil;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
@Component
public class TokenFilter extends ZuulFilter {
@Override
// 过滤器拦截业务
public Object run() throws ZuulException {
// 案例:拦截不带有token的请求
// 获取上下文
RequestContext currenContrxt = RequestContext.getCurrentContext();
// 获取request
HttpServletRequest request = currenContrxt.getRequest();
// 获取token的时候一般从请求头获取
String token = request.getParameter("token");
if (StringUtils.isEmpty(token)) {
// 没有token就停止执行,网关直接响应给客户端
currenContrxt.setSendZuulResponse(false);
currenContrxt.setResponseBody("please give me a token");
currenContrxt.setResponseStatusCode(401);
return null;
}
return null;
}
@Override
// 判断过滤器是否生效
public boolean shouldFilter() {
return true;
}
@Override
// 过滤器请执行顺序,即同一阶段多个过滤器的顺序执行问题
public int filterOrder() {
// TODO Auto-generated method stub
return 0;
}
@Override
// 过滤器类型pre,请求前执行
public String filterType() {
System.out.println("请求前执行");
// TODO Auto-generated method stub
return "pre";
}
// 网关过滤器编写
}
重启zuul
微服务,然后访问地址http://localhost:82/api-order/getOrder
然后再访问地址http://localhost:82/api-order/getOrder?token=1
可以看到成功通过了!说明配置成功
我们在服务里的配置文件配置了一些信息,如果需要修改的话,需要重启服务很麻烦。所以可以将配置文件统一放在同一台服务器,放在后台管理,这样子如果修改了配置文件,则不需要重启服务。
为什么使用分布式配置:在我们的项目中,配置文件跟我们项目的耦合性太高,如果我们修改了配置文件,则需要重新打包启动项目,十分麻烦。
什么是分布式配置中心:说白了就是将所有的配置文件都放在同一台服务器上管理,我们的项目只需要调用这些配置文件即可,这样子我们不用重启项目也可以实现修改配置信息。
管理配置文件的框架有以下三种:
1)阿波罗:携程写分布式中心有图形界面可管理配置文件信息,配置信息放在数据库里
2) config:没有后台可管理分布式配置中心,配置文件放在版本控制器里(git、svn)
3) zookeeper实现分布式配置中心,持久节点+事件通知
后面将介绍springcloud自带的config分布式配置文件框架,版本控制器使用git
以前面的zuu网关为例,现在将zuul网关的配置存在git中,然后由一个服务器统一读取。读取完后,由微服务调用!
package com.zzk;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.config.server.EnableConfigServer;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
@SpringBootApplication
@EnableEurekaClient
@EnableConfigServer
public class AppEurekaServer {
// 在git上创建文件名称的规范:服务名称-环境名称.properties
public static void main(String[] args) {
SpringApplication.run(AppEurekaServer.class, args);
}
}
###服务端口号
server:
port: 8081
###eureka 注册中心基本信息配置
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8080/eureka/
###服务别名集群注册中心,一定要相同
spring:
application:
name: config-server
cloud:
config:
server:
git:
###git克隆地址
uri: https://gitee.com/TianZhenRe/zzk-springcloud.git
search-paths:
- config
label: master
4.0.0
com.springcloud5
springcloud5-config-server
0.0.1-SNAPSHOT
org.springframework.boot
spring-boot-starter-parent
2.0.1.RELEASE
org.springframework.cloud
spring-cloud-dependencies
Finchley.RELEASE
pom
import
org.springframework.cloud
spring-cloud-starter-netflix-eureka-client
org.springframework.cloud
spring-cloud-config-server
org.springframework.boot
spring-boot-starter-web
spring-milestones
Spring Milestones
https://repo.spring.io/libs-milestone
false
org.springframework.boot
spring-boot-maven-plugin
配置完,启动服务,然后访问地址http://127.0.0.1:8081/service-zuul-prd.yml
可以查看到自己再git的配置
3. 配置“网关服务”读取“git管理服务”的配置
package com.zzk;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
import org.springframework.cloud.netflix.zuul.filters.ZuulProperties;
@SpringBootApplication
@EnableEurekaClient
@EnableZuulProxy // 开启网关代理
@EnableDiscoveryClient
// zuul默认开启本地ribbon负载均衡
public class ZuulServiceApplication {
public static void main(String[] args) {
SpringApplication.run(ZuulServiceApplication.class, args);
}
@RefreshScope
@ConfigurationProperties("zuul")
public ZuulProperties zuulProperties() {
return new ZuulProperties();
}
}
###服务端口号
server:
port: 82
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8080/eureka/
##服务别名集群注册中心,一定要相同
spring:
application:
name: service-zuul #跟git仓库一致
cloud:
config:
##版本读取环境,跟git仓库一致
profile: prd
discovery:
##读取config-server环境
service-id: config-server
##开启读取权限
enabled: true
management:
endpoints:
web:
exposure:
include: "*" #注意这里*要加引号,暴露全部,也可以只暴露相应endpoint
endpoint:
routes:
enabled: true # 默认为true,可以省略
4.0.0
com.springcloud5
springcloud5-zuul
0.0.1-SNAPSHOT
org.springframework.boot
spring-boot-starter-parent
2.0.1.RELEASE
org.springframework.cloud
spring-cloud-dependencies
Finchley.RELEASE
pom
import
org.springframework.cloud
spring-cloud-config-client
org.springframework.cloud
spring-cloud-starter-netflix-eureka-client
org.springframework.cloud
spring-cloud-starter-netflix-zuul
org.springframework.boot
spring-boot-starter-actuator
org.springframework.boot
spring-boot-starter-web
org.springframework.cloud
spring-cloud-config-client
org.springframework.boot
spring-boot-configuration-processor
true
org.springframework.boot
spring-boot-maven-plugin
spring-milestones
Spring Milestones
https://repo.spring.io/libs-milestone
false
启动网关服务,然后输入http://localhost:82/actuator/routes
查看
可以看到配置成功,网关服务,成功间接的读取到git仓库上的配置文件!
注:修改git文件后,虽然不用重启服务,但是需要手动刷新,即post
调用actuator/refresh
方法!举个例子,我现在在git
的yml
文件添加一个网关配置,这里使用postman
接口测试工具,post
请求http://127.0.0.1:82/actuator/refresh
方法,可以看到以下结果: