五、Spring Cloud

来源:互联网 发布:浙江剑龙网络案件 编辑:程序博客网 时间:2024/06/05 19:43

五、Spring Cloud - Netflix(Zuul服务网关构建代码层面)

本文依然是基于http://blog.didispace.com/springcloud5/博主提供的部分代码,以及大部分的使用思路。大笑

1)项目的结构(5个都要用到,不单单2017-Netflix_Zuul哦得意


2)看代码

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.sample</groupId><artifactId>2017-Netflix_Zuul</artifactId><version>1.0.1-SNAPSHOT</version><packaging>war</packaging><build>      <plugins>          <plugin>              <groupId>org.apache.maven.plugins</groupId>              <artifactId>maven-compiler-plugin</artifactId>              <version>3.3</version>              <configuration>                  <!-- 指定source和target的版本 -->                                 <source>1.8</source>                  <target>1.8</target>              </configuration>          </plugin>      </plugins>  </build> <parent>    <groupId>org.springframework.boot</groupId>    <artifactId>spring-boot-starter-parent</artifactId>    <version>1.5.2.RELEASE</version></parent><dependencyManagement>    <dependencies>        <dependency>            <groupId>org.springframework.cloud</groupId>            <artifactId>spring-cloud-dependencies</artifactId>            <version>Dalston.RELEASE</version>            <type>pom</type>            <scope>import</scope>        </dependency>    </dependencies></dependencyManagement><dependencies>    <dependency>        <groupId>org.springframework.cloud</groupId>        <artifactId>spring-cloud-starter-config</artifactId>    </dependency>    <dependency>        <groupId>org.springframework.cloud</groupId>        <artifactId>spring-cloud-starter-eureka</artifactId>    </dependency><!-- <dependency>    <groupId>org.springframework.cloud</groupId>    <artifactId>spring-cloud-starter-hystrix</artifactId></dependency>    <dependency><groupId>com.netflix.hystrix</groupId><artifactId>hystrix-javanica</artifactId></dependency>  --><dependency>    <groupId>org.springframework.cloud</groupId>    <artifactId>spring-cloud-starter-zuul</artifactId></dependency></dependencies></project>
application.properties
spring.application.name=api-gatewayserver.port=5555# 启动2017-Netflix_ServiceA和2017-Netflix_ServiceB, 它们两提供不同的两个服务# routes to url (第一种 url映射方式)zuul.routes.api-a-url.path=/api-a-url/**zuul.routes.api-a-url.url=http://localhost:8091/# routes to serviceId (第二种 serviceId映射方式)zuul.routes.api-a.path=/api-a/**zuul.routes.api-a.serviceId=netflix-service-azuul.routes.api-b.path=/api-b/**zuul.routes.api-b.serviceId=netflix-service-b# 用于验证zuul自带的负载均衡功能, 启动2017-Netflix_Service1和2017-Netflix_Service2, 它们两提供同一个服务netflix-servicezuul.routes.api-service.path=/api-service/**zuul.routes.api-service.serviceId=netflix-serviceeureka.client.serviceUrl.defaultZone=http://localhost:8761/eureka/# Zuul测试连接如下#http://localhost:5555/api-a-url/add?a=1&b=2#http://localhost:5555/api-a/add?a=1&b=2#http://localhost:5555/api-service/add?a=1&b=2# 下面其实还是走原有Ribbon, 已经测试过了#http://localhost:5555/zuulRibbonCallAddServicezuul.routes.customers=/customers/**
package com.jack.ssm.fallback;import java.io.ByteArrayInputStream;import java.io.IOException;import java.io.InputStream;import org.springframework.cloud.netflix.zuul.filters.route.ZuulFallbackProvider;import org.springframework.http.HttpHeaders;import org.springframework.http.HttpStatus;import org.springframework.http.MediaType;import org.springframework.http.client.ClientHttpResponse;/** * ClassName:GenericZuulFallbackProvider.java *  * http://tachniki.blogspot.in/2017/02/generic-ZuulFallbackProvider.html参考这篇文章 * 将多个熔断器抽象成一个公共的熔断类,然后在spring boot application里面根据不同的route ID,实现对应的熔断器. *   * Date:     2017年6月7日下午1:49:35 * @author   Jack.Huang * @version  V1.0 * @since    JDK 1.7.0_60/JDK 1.8.0_45 */public class GenericZuulFallbackProvider implements ZuulFallbackProvider {private String responseBody = "{\"message\":\"Service Unavailable. Please try after sometime\"}";private HttpHeaders headers = null;private String route = null;private int rawStatusCode = 503;private HttpStatus statusCode = HttpStatus.SERVICE_UNAVAILABLE;private String statusText = "Service Unavailable";@Overridepublic String getRoute() {if (route == null) route = "route";//若为空, 则熔断默认route ID="route", 但我配置文件没配这个这只是一种实现的样例.return route;}/** * 熔断器会调用下面的fallbackResponse方法,最终模拟返回一个ClientHttpResponse. * 里面包含HttpHeaders、rawStatusCode、statusCode和responseBody等信息,这些信息都可以自定义返回值. * MediaType则包含多种返回信息的格式Json、Pdf、Image等等. *  * @see org.springframework.cloud.netflix.zuul.filters.route.ZuulFallbackProvider#fallbackResponse() */@Overridepublic ClientHttpResponse fallbackResponse() {return new ClientHttpResponse(){@Overridepublic InputStream getBody() throws IOException {if (responseBody == null) responseBody ="{\"message\":\"Service Unavailable. Please try after sometime\"}";return new ByteArrayInputStream(responseBody.getBytes());}@Overridepublic HttpHeaders getHeaders() {if (headers == null) { headers = new HttpHeaders();headers.setContentType(MediaType.APPLICATION_JSON);}return headers;}@Overridepublic void close() {}@Overridepublic int getRawStatusCode() throws IOException {return rawStatusCode;}@Overridepublic HttpStatus getStatusCode() throws IOException {if (statusCode == null) statusCode = HttpStatus.SERVICE_UNAVAILABLE;return statusCode;}@Overridepublic String getStatusText() throws IOException {if (statusText == null)statusText = "Service Unavailable";return statusText;}};}public String getResponseBody() {return responseBody;}public void setResponseBody(String responseBody) {this.responseBody = responseBody;}public HttpHeaders getHeaders() {return headers;}public void setHeaders(HttpHeaders headers) {this.headers = headers;}public int getRawStatusCode() {return rawStatusCode;}public void setRawStatusCode(int rawStatusCode) {this.rawStatusCode = rawStatusCode;}public HttpStatus getStatusCode() {return statusCode;}public void setStatusCode(HttpStatus statusCode) {this.statusCode = statusCode;}public String getStatusText() {return statusText;}public void setStatusText(String statusText) {this.statusText = statusText;}public void setRoute(String route) {this.route = route;}}
package com.jack.ssm;import java.io.ByteArrayInputStream;import java.io.IOException;import java.io.InputStream;import org.springframework.boot.SpringApplication;import org.springframework.cloud.client.SpringCloudApplication;import org.springframework.cloud.client.loadbalancer.LoadBalanced;import org.springframework.cloud.netflix.zuul.EnableZuulProxy;import org.springframework.cloud.netflix.zuul.filters.route.ZuulFallbackProvider;import org.springframework.context.annotation.Bean;import org.springframework.http.HttpHeaders;import org.springframework.http.HttpStatus;import org.springframework.http.MediaType;import org.springframework.http.client.ClientHttpResponse;import org.springframework.web.client.RestTemplate;import com.jack.ssm.fallback.GenericZuulFallbackProvider;/** * ClassName:RibbonApplication.java  * Date:     2017年6月5日下午5:06:00 * @author   Jack.Huang * @version  V1.0 * @since    JDK 1.7.0_60/JDK 1.8.0_45 */@EnableZuulProxy//@EnableZuulServer@SpringCloudApplication//它整合了@SpringBootApplication、@EnableDiscoveryClient、@EnableCircuitBreakerpublic class ZuulRibbonApplication {@Bean@LoadBalancedRestTemplate restTemplate() {return new RestTemplate();}public static void main(String[] args) {SpringApplication.run(ZuulRibbonApplication.class, args);}@Beanpublic ZuulFallbackProvider routeAPIAZuulFallbackProvider() {GenericZuulFallbackProvider routeZuulFallback = new GenericZuulFallbackProvider();routeZuulFallback.setRoute("netflix-service-a");return routeZuulFallback;}@Beanpublic ZuulFallbackProvider routeAPIbZuulFallbackProvider() {GenericZuulFallbackProvider routeZuulFallback = new GenericZuulFallbackProvider();routeZuulFallback.setRoute("netflix-service-b");return routeZuulFallback;}@Beanpublic ZuulFallbackProvider netflixServiceZuulFallbackProvider() {GenericZuulFallbackProvider portalZullFallback = new GenericZuulFallbackProvider();portalZullFallback.setRoute("netflix-service");portalZullFallback.setRawStatusCode(200);        portalZullFallback.setStatusCode(HttpStatus.OK);        portalZullFallback.setResponseBody("We are little busy. Comeback After Sometime");return portalZullFallback;}/*@Beanpublic ZuulFallbackProvider zuulFallbackProvider() {return new ZuulFallbackProvider() {            @Override            public String getRoute() {                return "customers";            }            @Override            public ClientHttpResponse fallbackResponse() {                return new ClientHttpResponse() {                    @Override                    public HttpStatus getStatusCode() throws IOException {                        return HttpStatus.OK;                    }                    @Override                    public int getRawStatusCode() throws IOException {                        return 200;                    }                    @Override                    public String getStatusText() throws IOException {                        return "OK";                    }                    @Override                    public void close() {                    }                    @Override                    public InputStream getBody() throws IOException {                        return new ByteArrayInputStream("fallback".getBytes());                    }                    @Override                    public HttpHeaders getHeaders() {                        HttpHeaders headers = new HttpHeaders();                        headers.setContentType(MediaType.APPLICATION_JSON);                        return headers;                    }                };            }        };}*/}
3) 验证Zuul路由跳转功能

启动2017-Netflix_Server

java -jar 2017_Netflix_Eureka_Server-1.0.1-SNAPSHOT.jar --spring.profiles.active=eureka

再分别启动2017-Netflix_ServiceA、2017-Netflix_ServiceB以及2017-Netflix_Zuul

他们的启动命令都是这个, spring boot嘛: G:\GIT-WORKPLACE\project\2017-Netflix_Zuul>mvn spring-boot:run


Zuul测试连接如下:
http://localhost:5555/api-a-url/add?a=1&b=2&accessToken=token
http://localhost:5555/api-a/add?a=1&b=2&accessToken=token
http://localhost:5555/api-b-url/add?a=1&b=2&accessToken=token
http://localhost:5555/api-b/add?a=1&b=2&accessToken=token


4) 验证Zuul负载均衡功能

启动2017-Netflix_Server

java -jar 2017_Netflix_Eureka_Server-1.0.1-SNAPSHOT.jar --spring.profiles.active=eureka

再分别启动2017-Netflix_Service1、2017-Netflix_Service1以及2017-Netflix_Zuul


Zuul测试连接如下:

http://localhost:5555/api-service/add?a=1&b=2&accessToken=token

Zuul负载均衡功能默认是实现的,代码不需要写任何东西。


5) 验证Zuul熔断功能

Zuul熔断功能默认也是实现的,但是需要写东西哦。

官网有例子http://cloud.spring.io/spring-cloud-static/Dalston.RELEASE/#hystrix-fallbacks-for-routes,

但是很tm坑啊,按官网的是没效果的,还需要在ZuulRibbonApplication加入如下类似代码。

@Beanpublic ZuulFallbackProvider routeAPIAZuulFallbackProvider() {GenericZuulFallbackProvider routeZuulFallback = new GenericZuulFallbackProvider();routeZuulFallback.setRoute("netflix-service-a");return routeZuulFallback;}
参考歪国友人的文章:大笑
http://tachniki.blogspot.in/2017/02/generic-ZuulFallbackProvider.html

歪果友人同时也提供了一个公共熔断的实现方案,以及不同服务路由的不同熔断规则的实现方案。


附带源码

https://Git.coding.NET/JackHuang0801/project.git

拉分支release-spring-cloud-1.1



原创粉丝点击