SpringCloud 路由网关(zuul)(Finchley版本) (五)

本文只是个人学习笔记

原创地址: 
http://blog.csdn.net/forezp/article/details/69939114 
本文出自方志朋的博客

在微服务架构中,需要几个基础的服务治理组件,包括服务注册与发现、服务消费、负载均衡、断路器、智能路由、配置管理等,由这几个基础组件相互协作,共同组建了一个简单的微服务系统。一个简答的微服务系统如下图:

Azure (1).png 
注意:A服务和B服务是可以相互调用的,作图的时候忘记了。并且配置服务也是注册到服务注册中心的。

在Spring Cloud微服务系统中,一种常见的负载均衡方式是,客户端的请求首先经过负载均衡(zuul、Ngnix),再到达服务网关(zuul集群),然后再到具体的服。,服务统一注册到高可用的服务注册中心集群,服务的所有的配置文件由配置服务管理(下一篇文章讲述),配置服务的配置文件放在git仓库,方便开发人员随时改配置。

一、Zuul简介

Zuul的主要功能是路由转发和过滤器。路由功能是微服务的一部分,比如/api/user转发到到user服务,/api/shop转发到到shop服务。zuul默认和Ribbon结合实现了负载均衡的功能。

zuul有以下功能:

  • Authentication 【身份验证】
  • Insights
  • Stress Testing 【压力测试】
  • Canary Testing 【金丝雀测试】
  • Dynamic Routing 【动态路由】
  • Service Migration 【服务迁移】
  • Load Shedding 【甩负荷】
  • Security 【安全】
  • Static Response handling 【静态响应处理】
  • Active/Active traffic management

二、准备工作

继续使用上一节的工程。在原有的工程上,创建一个新的工程。

三、创建service-zuul工程

其pom.xml文件如下:

<?xml version="1.0" encoding="UTF-8"?>
<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.forezp</groupId>
	<artifactId>service-zuul</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>jar</packaging>

	<name>service-zuul</name>
	<description>Demo project for Spring Boot</description>

	<parent>
		<groupId>com.forezp</groupId>
		<artifactId>spring-cloud</artifactId>
		<version>0.0.1-SNAPSHOT</version>
	</parent>

	<dependencies>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
		</dependency>
	</dependencies>
</project>

在其入口applicaton类加上注解@EnableZuulProxy,开启zuul的功能:

package com.forezp.servicezuul;

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

@SpringBootApplication
@EnableZuulProxy
@EnableEurekaClient
@EnableDiscoveryClient
public class ServiceZuulApplication {

	public static void main(String[] args) {
		SpringApplication.run(ServiceZuulApplication.class, args);
	}
}

加上配置文件application.properties加上以下的配置代码:

## 该服务发布的端口
server.port=8769

## 注意这里是作为服务注册名称,在eureka注册中心注册这个名称,自动转化为全大写,之后调用服务用服务名调用
spring.application.name=service-zuul
## 注册服务中心的配置
eureka.client.service-url.defaultZone=http://localhost:8761/eureka/

zuul.routes.api-a.path =/api-a/**
zuul.routes.api-a.serviceId =service-ribbon

zuul.routes.api-b.path =/api-b/**
zuul.routes.api-b.serviceId =service-feign

 

四. 新建一个 service-hihi 项目

原创上二个返回值一样,为了体现区别,新建一个 service-hihi 项目,

ServiceHihiApplication启动类中 /hi 方法的返回值hihi做个区别。
@RequestMapping("/hi")
public String home(@RequestParam(value = "name", defaultValue = "forezp") String name) {
   return "hihi " + name + " ,i am from port:" + port;
}

配置文件和 service-hi 一样,端口改成8763 spring.application.name=service-hihi 

启动访问 http://localhost:8763/hi?name=forezp

显示

五.修改 service-ribbon 

HelloService方法中 return restTemplate.getForObject("http://SERVICE-HIHI/hi?name="+name,String.class);
package com.forezp.serviceribbon;

import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

@Service
public class HelloService {
    @Autowired
    RestTemplate restTemplate;

    @HystrixCommand(fallbackMethod = "hiError")
    public String hiService(String name) {
        return restTemplate.getForObject("http://SERVICE-HIHI/hi?name="+name,String.class);
    }
    public String hiError(String name) {
        return "hi,"+name+",sorry,error!";
    }
}

启动访问 http://localhost:8764/hi?name=forezp

首先指定服务注册中心的地址为http://localhost:8761/eureka/,服务的端口为8769,服务名为service-zuul;以/api-a/ 开头的请求都转发给service-ribbon服务;以/api-b/开头的请求都转发给service-feign服务;

依次运行这六个工程;打开浏览器访问:http://localhost:8769/api-a/hi?name=forezp ;浏览器显示:

hihi forezp ,i am from port:8763

打开浏览器访问:http://localhost:8769/api-b/hi?name=forezp ;

hi forezp,i am from port:8762

 

七、服务过滤

zuul不仅只是路由,并且还能过滤,做一些安全验证。继续改造工程;新建 MyFilter

package com.forezp.servicezuul;

import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;

@Component
public class MyFilter extends ZuulFilter {

    private static Logger log = LoggerFactory.getLogger(MyFilter.class);
    @Override
    public String filterType() {
        return "pre";
    }

    @Override
    public int filterOrder() {
        return 0;
    }

    @Override
    public boolean shouldFilter() {
        return true;
    }

    @Override
    public Object run() {
        RequestContext ctx = RequestContext.getCurrentContext();
        HttpServletRequest request = ctx.getRequest();
        log.info(String.format("%s >>> %s", request.getMethod(), request.getRequestURL().toString()));
        Object accessToken = request.getParameter("token");
        if(accessToken == null) {
            log.warn("token is empty");
            ctx.setSendZuulResponse(false);
            ctx.setResponseStatusCode(401);
            try {
                ctx.getResponse().getWriter().write("token is empty");
            }catch (Exception e){}

            return null;
        }
        log.info("ok");
        return null;
    }
}

filterType:返回一个字符串代表过滤器的类型,在zuul中定义了四种不同生命周期的过滤器类型,具体如下: 

  • pre:路由之前
  • routing:路由之时
  • post: 路由之后
  • error:发送错误调用
  • filterOrder:过滤的顺序
  • shouldFilter:这里可以写逻辑判断,是否要过滤,本文true,永远过滤。
  • run:过滤器的具体逻辑。可用很复杂,包括查sql,nosql去判断该请求到底有没有权限访问。

这时访问:http://localhost:8769/api-a/hi?name=forezp ;网页显示:

token is empty

访问 http://localhost:8769/api-a/hi?name=forezp&token=22 ; 
网页显示:

hihi forezp ,i am from port:8763

本文源码下载: 
对应源码下载【five_one】分支:https://gitee.com/tangzhengfeng/SpringCloud/tree/five_one/

五、参考资料:

http://blog.csdn.net/forezp/article/details/69939114

http://cloud.spring.io/spring-cloud-static/Finchley.RELEASE/single/spring-cloud.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值