Spring Cloud包含多个子项目,Spring Cloud Config(可扩展配置服务)、Spring Cloud Netflix、Spring Cloud CloudFoundry(开源PaaS云平台)、Spring Cloud AWS(亚马逊云服务平台)、Spring Cloud Security、Spring Cloud Commons、pring Cloud Zookeeper、Spring Cloud CLI等项目。
html
1、服务注册中心java
一、eureka服务注册中心
git
Spring Cloud Eureka是Spring Cloud Netflix项目下的服务治理模块。而Spring Cloud Netflix项目是Spring Cloud的子项目之一,主要内容是对Netflix公司一系列开源产品的包装,它为Spring Boot应用提供了自配置的Netflix OSS整合。经过一些简单的注解,开发者就能够快速的在应用中配置一下经常使用模块并构建庞大的分布式系统。它主要提供的模块包括:服务发现(Eureka),断路器(Hystrix),智能路由(Zuul),客户端负载均衡(Ribbon)等。github
建立服务注册中心eureka-server,引入eureka依赖:web
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.4.RELEASE</version> <relativePath/> </parent> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka-server</artifactId> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Dalston.SR1</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>
经过@EnableEurekaServer
注解启动一个服务注册中心提供给其余应用进行对话。spring
@EnableEurekaServer @SpringBootApplication public class Application { public static void main(String[] args) { new SpringApplicationBuilder(Application.class).web(true).run(args); } }
application.properties
配置文件中增长以下信息:
#应用名 spring.application.name=eureka-server #tomcat监听端口 server.port=1001 #eureka主机地址 eureka.instance.hostname=localhost #禁用eureka客户端的注册行为 eureka.client.register-with-eureka=false #若是为true,启动时报警. eureka.client.fetch-registry=false在http://127.0.0.1:1001/ 可看到eureka的服务管理页面
二、Consul服务治理bootstrap
Spring Cloud Consul项目是针对Consul的服务治理实现。Consul是一个分布式高可用的系统,它包含多个组件,可是做为一个总体,在微服务架构中为咱们的基础设施提供服务发现和服务配置的工具。它包含了下面几个特性:api
Consul自身提供了服务端,因此咱们不须要像以前实现Eureka的时候建立服务注册中心,直接经过下载consul的服务端程序就可使用。浏览器
consul服务器启动命令:缓存
consul agent -dev
服务管理界面:http://127.0.0.1:8500
2、服务提供方
一、向eureka注册
服务的客户端,并向服务注册中心注册本身
建立一个基本的Spring Boot应用。命名为eureka-client
,在pom.xml
中,加入以下配置:
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.4.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Dalston.SR1</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>
配置文件配置:
#指定微服务的名称后续在调用的时候只须要使用该名称就能够进行服务的访问 spring.application.name=eureka-client #修改tomcat端口为2001 server.port=2001 #指定服务注册中心的位置 eureka.client.serviceUrl.defaultZone=http://localhost:1001/eureka/
@RestController public class DcController { private final Logger log=Logger.getLogger(getClass()); @Autowired private DiscoveryClient discoveryClient;//经过DiscoveryClient对象,在日志中打印出服务实例的相关内容。 @RequestMapping(value="/dc") public String dc(){ String services="eclipse services:"+discoveryClient.getServices(); log.info(services); return services; } }
@EnableDiscoveryClient
注解,该注解能激活Eureka中的DiscoveryClient实现,这样才能实现Controller中对服务信息的输出。
@EnableEurekaClient @SpringBootApplication public class Application { public static void main(String[] args) { new SpringApplicationBuilder(Application.class).web(true).run(args); } }
二、向consul注册
接口和以前同样,只要改变依赖和配置信息就行
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-consul-discovery</artifactId> </dependency>
修改application.properties配置文件以下:
#consul服务注册与发现 spring.application.name=consul-client spring.cloud.consul.host=127.0.0.1 spring.cloud.consul.port=8500
3、服务消费方
一、使用Spring Cloud提供的负载均衡器客户端接口LoadBalancerClient来实现服务的消费
建立一个服务消费者工程,命名为:eureka-consumer
。并在pom.xml
中引入依赖:
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.4.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka</artifactId> <version>1.3.1.RELEASE</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> <scope>test</scope> </dependency> </dependencies>
配置application.properties,指定eureka注册中心的地址:
spring.application.name=eureka-consumers server.port=2101 #服务注册中心地址 eureka.client.serviceUrl.defaultZone=http://localhost:1001/eureka/
建立应用主类。初始化RestTemplate
,用来真正发起REST请求。@EnableDiscoveryClient
注解用来将当前应用加入到服务治理体系中。
@EnableDiscoveryClient//注解用来将当前应用加入到服务治理体系中。 @SpringBootApplication public class Application { @Bean public RestTemplate restTemplate(){ return new RestTemplate(); } public static void main(String[] args) { new SpringApplicationBuilder(Application.class).web(true).run(args); } }
@RestController public class DcController { @Autowired private RestTemplate restTemplate;//利用RestTemplate对象实现对服务提供者接口的调用 @Autowired private LoadBalancerClient loadBalancerClient; @GetMapping("/consumer")//注解get请求 public String dc(){ //经过loadBalancerClient的choose负载均衡的选出一个eureka-client的服务实例 ServiceInstance serviceInstance=loadBalancerClient.choose("eureka-client"); String url="http://"+serviceInstance.getHost()+":"+serviceInstance.getPort()+"/dc"; System.out.println(url); return restTemplate.getForObject(url, String.class); } }
能够看到这里,咱们注入了LoadBalancerClient
和RestTemplate
,并在/consumer
接口的实现中,先经过loadBalancerClient
的choose
函数来负载均衡的选出一个eureka-client
的服务实例,这个服务实例的基本信息存储在ServiceInstance
中,而后经过这些对象中的信息拼接出访问/dc
接口的详细地址,最后再利用RestTemplate
对象实现对服务提供者接口的调用。
二、Spring Cloud Ribbon
Spring Cloud Ribbon是基于Netflix Ribbon实现的一套客户端负载均衡的工具。它是一个基于HTTP和TCP的客户端负载均衡器。它能够经过在客户端中配置ribbonServerList来设置服务端列表去轮询访问以达到均衡负载的做用。
导入依赖:
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.4.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka</artifactId> <version>1.3.1.RELEASE</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <!-- 负载均衡的工具 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-ribbon</artifactId> <version>1.3.1.RELEASE</version> </dependency> </dependencies>application.properties配置文件的配置不变,仍是从eureka中拿服务。
修改应用主类。为RestTemplate
增长@LoadBalanced
注解:
@EnableDiscoveryClient @SpringBootApplication public class Application { @Bean @LoadBalanced public RestTemplate restTemplate(){ return new RestTemplate(); } public static void main(String[] args) { new SpringApplicationBuilder(Application.class).web(true).run(args); } }
LoadBalancerClient
选取实例和拼接URL的步骤,直接经过RestTemplate发起请求。
@RestController public class DcController { @Autowired private RestTemplate restTemplate; @GetMapping("/consumer") public String dc(){ return restTemplate.getForObject("http://eureka-client/dc", String.class); } /* * Spring Cloud Ribbon有一个拦截器,它可以在这里进行实际调用的时候,自动的去选取服务实例, * 并将实际要请求的IP地址和端口替换这里的服务名,从而完成服务接口的调用。 */ }
Spring Cloud Feign是一套基于Netflix Feign实现的声明式服务调用客户端。它使得编写Web服务客户端变得更加简单。咱们只须要经过建立接口并用注解来配置它既可完成对Web服务接口的绑定。它具有可插拔的注解支持,包括Feign注解、JAX-RS注解。它也支持可插拔的编码器和解码器。Spring Cloud Feign还扩展了对Spring MVC注解的支持,同时还整合了Ribbon和Eureka来提供均衡负载的HTTP客户端实现。
pom.xml
中的依赖:
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.4.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka</artifactId> <version>1.3.1.RELEASE</version> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-feign</artifactId> <version>1.3.1.RELEASE</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> </dependencies>修改应用主类。经过
@EnableFeignClients
注解开启扫描Spring Cloud Feign客户端的功能:
@EnableFeignClients//注解开启扫描Spring Cloud Feign客户端的功能 @EnableDiscoveryClient @SpringBootApplication public class Application { public static void main(String[] args) { new SpringApplicationBuilder(Application.class).web(true).run(args); } }
@FeignClient
注解来指定这个接口所要调用的服务名称,接口中定义的各个函数使用Spring MVC的注解就能够来绑定服务提供方的REST接口,好比下面就是绑定
eureka-client
服务的
/dc
接口的例子:
/* * 经过@FeignClient定义的接口来统一的生成咱们须要依赖的微服务接口。而在具体使用的时候就跟调用本地方法一点的进行调用便可 */ @FeignClient("eureka-client")//使用@FeignClient注解来指定这个接口所要调用的服务名称 public interface DcClient { @GetMapping("/dc")//接口中定义的各个函数使用Spring MVC的注解就能够来绑定服务提供方的REST接口 public String consumer(); }
@RestController public class DcController { @Autowired private DcClient dcClient; @GetMapping("/consumer") public String consumer(){ return dcClient.consumer(); } }
4、配置中心
Spring Cloud Config为服务端和客户端提供了分布式系统的外部化配置支持。配置服务器为各应用的全部环境提供了一个中心化的外部配置。配置服务器默认采用git来存储配置信息,这样就有助于对环境配置进行版本管理,而且能够经过git客户端工具来方便的管理和访问配置内容。
一、构建服务端Config-Server
pom.xml中引入spring-cloud-config-server
依赖,完整依赖配置以下:
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.4.RELEASE</version> <relativePath/> </parent> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-config-server</artifactId> </dependency> <!-- config-server也注册为服务,这样全部客户端就能以服务的方式进行访问 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka</artifactId> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Brixton.RELEASE</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>
application.properties
中配置服务信息以及git信息,例如:
#服务器应用名 spring.application.name=config-server #远程仓库地址 spring.cloud.config.server.git.uri=https://github.com/jlzl123/config-repo-demo.git spring.cloud.config.server.git.username=jlzl123 spring.cloud.config.server.git.password=******* server.port:1201 #eureka注册中心配置 eureka.client.serviceUrl.defaultZone=http://localhost:1001/eureka/
spring.cloud.config.server.git.uri是git远程配置文件仓库地址
建立Spring Boot的程序主类,并添加@EnableConfigServer
注解,开启Config Server:
package org.config.server.git; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; import org.springframework.cloud.config.server.EnableConfigServer; @EnableDiscoveryClient//用来将config-server注册到上面配置的服务注册中心上去。 @EnableConfigServer//开启Spring Cloud Config的服务端功能。 @SpringBootApplication public class Application { public static void main(String[] args) { new SpringApplicationBuilder(Application.class).web(true).run(args); } }
spring.profiles.active=native
,Config Server会默认从应用的
src/main/resource
目录下检索配置文件。也能够经过
spring.cloud.config.server.native.searchLocations=file:F:/properties/
属性来指定配置文件的位置。虽然Spring Cloud Config提供了这样的功能,可是为了支持更好的管理内容和版本控制的功能,仍是推荐使用git的方式。
完成上面后咱们就能够经过URL访问远程配置信息了:
http://localhost:1201/config-client-dev/dev/master
URL与配置文件的映射关系以下:
{application}-{profile}.properties
对应的配置文件,{label}
对应git上不一样的分支,默认为master。profile是配置文件对应的不一样开发环境。
好比:要访问config-label-test分支,didispace应用的prod环境,能够经过这个url:http://localhost:7001/didispace/prod/config-label-test。
二、构建客户端config-client
pom.xml中引入spring-cloud-starter-config依赖,完整依赖关系以下:
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> <exclusions><!-- 排除对[spring-boot-starter-logging]的依赖,解决log4j依赖jar包冲突 --> <exclusion> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-logging</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-config</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-log4j</artifactId> <version>1.3.8.RELEASE</version> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka</artifactId> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Brixton.RELEASE</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <!--这个元素描述了项目相关的全部资源路径列表,例如和项目相关的属性文件,这些资源被包含在最终的打包文件里。--> <repositories> <repository> <id>spring-milestones</id> <name>Spring Milestones</name> <url>https://repo.spring.io/milestone</url> <snapshots> <enabled>false</enabled> </snapshots> </repository> </repositories>
建立Spring Boot启动主类,并利用@EnableDiscoveryClient注解将客户端以服务的形式注册到eureka再服务注册中心。
package org.config.client; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; @EnableDiscoveryClient @SpringBootApplication public class Application { public static void main(String[] args) { new SpringApplicationBuilder(Application.class).web(true).run(args); } }
bootstrap.properties
配置,来指定config server,例如:
#远程配置仓库配置文件名 spring.application.name=config-client-dev,test,config-test,datasource #配置中心服务器地址 spring.cloud.config.uri=http://localhost:1201/ #当前配置环境,相同配置文件的不一样环境,经过profile区分 spring.cloud.config.profile=dev #git仓库分支,默认为master spring.cloud.config.label=master server.port=2003 #git的yml配置文件的格式好象有问题,最好用properties #eureka注册中心配置 eureka.client.serviceUrl.defaultZone=http://localhost:1001/eureka/
bootstrap.properties
中,config部份内容才能被正确加载。由于config的相关配置会先于application.properties
,而bootstrap.properties
的加载也是先于application.properties
。即配置客户端启动,先加载bootstrap.properties配置文件,而后从远程配置仓库获取配置,因此这些配置会优于application.properties的配置被容器加载,即远程仓库的配置会覆盖掉application的配置。这样,就能够直接把项目配置文件写在远程仓库。
注意,springboot并不加载bootstrap.properties,只用config client的jar封装ConfigServerBootstrapConfiguration先加bootstrap.properties。
建立一个Rest Api来返回配置中心的from属性,具体以下:
@RefreshScope @RestController class TestController { @Value("${from}") private String from; @RequestMapping("/from") public String from() { return this.from; } }
也能够经过@ConfigurationProperties注解来绑定配置属性,建立以下配置类:
package org.config.client.dataSourceConfig; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Configuration; @Configuration //@ConfigurationProperties注解绑定属性,prefix为属性名的前缀,如:jdbc.url @ConfigurationProperties(prefix="jdbc",ignoreUnknownFields=false) public class DataSourceProperties { private String driver; private String url; private String username; private String password; public String getDriver() { return driver; } public void setDriver(String driver) { this.driver = driver; } public String getUrl() { return url; } public void setUrl(String url) { this.url = url; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } }
5、断路器
在分布式架构中,当某个服务单元发生故障(相似用电器发生短路)以后,经过断路器的故障监控(相似熔断保险丝),向调用方返回一个错误响应,而不是长时间的等待。这样就不会使得线程因调用故障服务被长时间占用不释放,避免了故障在分布式系统中的蔓延。
在Spring Cloud中使用了Hystrix 来实现断路器的功能。Hystrix是Netflix开源的微服务框架套件之一,该框架目标在于经过控制那些访问远程系统、服务和第三方库的节点,从而对延迟和故障提供更强大的容错能力。Hystrix具有拥有回退机制和断路器功能的线程和信号隔离,请求缓存和请求打包,以及监控和配置等功能。
一、eureka-consumer-ribbon添加断路器
pom.xml
中引入依赖hystrix依赖:
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-hystrix</artifactId> <version>1.3.1.RELEASE</version> </dependency>
Application
中使用
@EnableCircuitBreaker
注解开启断路器功能:
package org.eureka.consumer.ribbon; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; import org.springframework.cloud.client.loadbalancer.LoadBalanced; import org.springframework.context.annotation.Bean; import org.springframework.web.client.RestTemplate; @EnableDiscoveryClient @SpringBootApplication @EnableCircuitBreaker//@EnableCircuitBreaker注解开启断路器功能 public class Application { @Bean @LoadBalanced//加载负载均衡 public RestTemplate restTemplate(){ return new RestTemplate(); } public static void main(String[] args) { new SpringApplicationBuilder(Application.class).web(true).run(args); } }
ComputeService
类,在使用ribbon消费服务的函数上增长
@HystrixCommand
注解来指定回调方法。
package org.eureka.consumer.ribbon.service; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.web.client.RestTemplate; import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand; @Service public class ComputeService { @Autowired private RestTemplate restTemplate; //注解实现断路器回调,当调用服务失败后,调用addServiceFallback方法 @HystrixCommand(fallbackMethod="addServiceFallback") public String addService(){ return restTemplate.getForObject("http://eureka-client/add?a=10&b=20", String.class); } @SuppressWarnings("unused") private String addServiceFallback(){ return "error"; } }
@RequestMapping(value="/addService",method=RequestMethod.GET) public String addService(){ return computeService.addService(); }这样添加断路器后,调用/addService接口服务,当服务提供者断线或获取服务超时,会调用fallback。
二、eureka-consumer-feign
fegin集成了hystrix断路器,只要在配置文件中配置下面参数开启就能够了,不用导入hystrix依赖。
feign.hystrix.enabled=true
@FeignClient
注解中的fallback属性指定回调类:
package org.eureka.consumer.feign.service; import org.eureka.consumer.feign.fallback.DcClientHystrix; import org.springframework.cloud.netflix.feign.FeignClient; import org.springframework.web.bind.annotation.GetMapping; /* * 经过@FeignClient定义的接口来统一的生成咱们须要依赖的微服务接口。而在具体使用的时候就跟调用本地方法一点的进行调用便可 */ //使用@FeignClient注解来指定这个接口所要调用的服务名称,如过开启了断路器,经过fallback参数指定熔断后的回调类,该回调类实现当前接口 @FeignClient(value="eureka-client",fallback=DcClientHystrix.class) public interface DcClient { @GetMapping("/dc")//接口中定义的各个函数使用Spring MVC的注解就能够来绑定服务提供方的REST接口 public String consumer(); }
ComputeClientHystrix
,实现
@FeignClient
的接口,此时实现的方法就是对应
@FeignClient
接口中映射的fallback函数。
package org.eureka.consumer.feign.fallback; import org.eureka.consumer.feign.service.DcClient; import org.springframework.stereotype.Component; /* * 回调类,实现@FeignClient的接口,此时实现的方法就是对应@FeignClient接口中映射的fallback函数。 */ @Component public class DcClientHystrix implements DcClient{ @Override public String consumer() { // TODO Auto-generated method stub return "调用失败,执行回调函数"; } }
6、服务网关
服务网关对微服务架构的做用:
使用Spring Cloud Netflix中的Zuul作服务网关,引入依赖spring-cloud-starter-zuul、spring-cloud-starter-eureka,若是不是经过指定serviceId的方式,eureka依赖不须要,可是为了对服务集群细节的透明性,仍是用serviceId来避免直接引用url的方式吧。
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-zuul</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka</artifactId> </dependency>
@EnableZuulProxy
注解开启Zuul
package org.api.gateway; import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.cloud.client.SpringCloudApplication; import org.springframework.cloud.netflix.zuul.EnableZuulProxy; @EnableZuulProxy//注解开启Zuul服务网关 @SpringCloudApplication//它整合了@SpringBootApplication、@EnableDiscoveryClient、@EnableCircuitBreaker等 public class GatewayApplication { public static void main(String[] args) { new SpringApplicationBuilder(GatewayApplication.class).web(true).run(args); } }
application.properties配置文件配置:
spring.application.name=api-gateway server.port=5555 #配置注册服务中心地址,若是下面路由不用serviceId就不用配置,也不用导入eureka依赖 eureka.client.serviceUrl.defaultZone=http://localhost:1001/eureka/ #路由配置 #配置属性zuul.routes.api-a-url.path中的api-a-url部分为路由的名字,能够任意定义. zuul.routes.api-a.path=/eureka-client/** zuul.routes.api-a.url=http://127.0.0.1:2001/ zuul.routes.ribbon.path=/ribbon/** zuul.routes.ribbon.serviceId=eureka-ribbon-consumer zuul.routes.api-b.path=/feign/** zuul.routes.api-b.serviceId=eureka-feign-consumer
这样/api-a/**
的访问都映射到http://localhost:2001/
上,也就是说当咱们访问http://localhost:5555/api-a/add?a=1&b=2
的时候,Zuul会将该请求路由到:http://localhost:2222/add?a=1&b=2
上。
服务网关还能够作服务过滤,在完成了服务路由以后,咱们对外开放服务还须要一些安全措施来保护客户端只能访问它应该访问到的资源。因此咱们须要利用Zuul的过滤器来实现咱们对外服务的安全控制。在服务网关中定义过滤器只须要继承ZuulFilter
抽象类实现其定义的四个抽象函数就可对请求进行拦截与过滤。
package org.api.gateway.filter; import javax.servlet.http.HttpServletRequest; import org.springframework.stereotype.Component; import com.netflix.zuul.ZuulFilter; import com.netflix.zuul.context.RequestContext; @Component//须要实例化该过滤器 public class AccessFilter extends ZuulFilter{ /* * shouldFilter:返回一个boolean类型来判断该过滤器是否要执行 */ @Override public boolean shouldFilter() { // TODO Auto-generated method stub return true; } /* * filterOrder:经过int值来定义过滤器的执行顺序 */ @Override public int filterOrder() { // TODO Auto-generated method stub return 0; } /* * filterType:返回一个字符串表明过滤器的类型,在zuul中定义了四种不一样生命周期的过滤器类型,具体以下: pre:能够在请求被路由以前调用 routing:在路由请求时候被调用 post:在routing和error过滤器以后被调用 error:处理请求时发生错误时被调用 */ @Override public String filterType() { // TODO Auto-generated method stub return "pre"; } /* * run:过滤器的具体逻辑。 */ @Override public Object run() { // TODO Auto-generated method stub RequestContext ctx=RequestContext.getCurrentContext(); HttpServletRequest request=ctx.getRequest(); String token=request.getParameter("token"); if(token==null){ ctx.setSendZuulResponse(false); // ctx.getResponse().setCharacterEncoding("utf-8"); //设置浏览器解码 ctx.getResponse().setContentType("text/html;charset=utf-8"); ctx.setResponseBody("非法访问!!"); ctx.setResponseStatusCode(401); return null; } return null; } }
网关做为为外部提供访问内部服务的接口,外网经过该接口访问内部服务,因此只要在网关统一作认证和鉴权就行了,而内部服务都部署在内网,不提供外网访问接口,网网经过内网映射路由到相关服务。