SpringCloud入门
SpringCloud
1、springcloud概述
SpringCloud是一种微服务架构,依赖于SpringBoot,主要用于服务治理(解耦),其中每一个服务都可以独立运行,服务之间没有依懒关系
2、Eureka注册中心搭建
1、pom.xml配置
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.2.RELEASE</version>
<relativePath />
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Dalston.RC1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
2、application.properties配置
spring.application.name=spring-cloud-eureka
server.port=8000
eureka.client.register-with-eureka=false
eureka.client.fetch-registry=false
eureka.client.serviceUrl.defaultZone=http://localhost:${server.port}/eureka/
eureka.client.register-with-eureka :表示是否将自己注册到Eureka Server,默认为true。
eureka.client.fetch-registry :表示是否从Eureka Server获取注册信息,默认为true。
eureka.client.serviceUrl.defaultZone :服务注册中心的配置内容,指定服务注册中心的位置。默认是http://localhost:8761/eureka ;多个地址可使用 , 分隔。
注:Eureka的yml配置文件中冒号后必须有空格,不能是’\t’;
3、服务启动
@SpringBootApplication
@EnableEurekaServer
public class EurekaApp {
public static void main(String[] args) {
SpringApplication.run(EurekaApp.class, args);
}
}
@EnableEurekaServer:启动一个服务注册中心提供给其他服务进行注册
@SpringBootApplication:扫描当前包及其子包下的带有@Component,@Controller,@Service,@Repository注解的类,并纳入spring容器进行管理配置
4、Eureka集群
1、application.properties配置
application.properties:
spring:
application:
name: spring-cloud-eureka
profiles:
active: peer1
application-peer1.properties:
spring.profiles=peer1
server.port=8000
eureka.client.serviceUrl.defaultZone=http://peer2:8001/eureka/, http://peer3:8002/eureka/
application-peer2.properties:
spring.profiles=peer2
server.port=8001
eureka.client.serviceUrl.defaultZone=http://peer1:8000/eureka/, http://peer3:8002/eureka/
application-peer3.properties:
spring.profiles=peer3
server.port=8002
eureka.client.serviceUrl.defaultZone=http://peer1:8000/eureka/, http://peer2:8001/eureka/
2、在C:\Windows\System32\drivers\etc下的hosts文件中加入
127.0.0.1 peer1
127.0.0.1 peer2
127.0.0.1 peer3
3、打包
--->maven build …--->clean package
4、依次启动
java -jar E:\java\spring-cloud-eureka\target\spring-cloud-eureka-0.0.1-SNAPSHOT.jar --spring.profiles.active=peer1
java -jar E:\java\spring-cloud-eureka\target\spring-cloud-eureka-0.0.1-SNAPSHOT.jar --spring.profiles.active=peer2
java -jar E:\java\spring-cloud-eureka\target\spring-cloud-eureka-0.0.1-SNAPSHOT.jar --spring.profiles.active=peer3
3、服务提供者
1、pom.xml配置
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.2.RELEASE</version>
<relativePath />
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Dalston.RC1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
2、application.properties配置
spring.application.name=spring-cloud-provider
server.port=9000
eureka.client.serviceUrl.defaultZone=http://localhost:8000/eureka/
3、服务启动
@SpringBootApplication
@EnableEurekaClient
public class ProviderApp {
public static void main(String[] args) {
SpringApplication.run(ProviderApp.class, args);
}
}
@EnableDiscoveryClient:启用服务注册与发现
@EnableEurekaClient:启用服务注册与发现
4、controller
@RestController
public class ProviderController {
@RequestMapping("/provider")
public String proindex(@RequestParam String name) {
return "hello "+name+",this is first provider messge";
}
}
4、服务消费者
1、pom.xml配置
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.2.RELEASE</version>
<relativePath />
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-feign</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix-dashboard</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Dalston.RC1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
2、application.properties配置
spring.application.name=spring-cloud-consumer
server.port=9100
eureka.client.serviceUrl.defaultZone=http://localhost:8000/eureka/
3、服务启动
1、rest启动
@SpringBootApplication
@EnableEurekaClient
public class ConsumerApp {
public static void main(String[] args) {
SpringApplication.run(ConsumerApp.class, args);
}
}
2、feign启动
@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients
public class Consumer1App {
public static void main(String[] args) {
SpringApplication.run(Consumer1App.class, args);
}
}
@EnableFeignClients:启用feign进行远程调用
4、rest调用
1、controller
@RestController
public class ConsumerController {
@Autowired
private ConsumerService cs;
@RequestMapping("/consumer")
public String conindex() {
return cs.getConsumer();
}
}
2、service
@Service
public class ConsumerService {
@Autowired
private RestTemplate rt;
public String getConsumer() {
return rt.getForObject("http://spring-cloud-provider/provider",String.class);
}
}
5、feign调用
1、controller
@RestController
public class Consumer1Controller {
@Autowired
HelloRemote helloRemote;
@RequestMapping("/consumer1/{name}")
public String index(@PathVariable("name") String name) {
return helloRemote.index(name);
}
}
2、service
@FeignClient(name="spring-cloud-provider1")
public interface HelloRemote {
@RequestMapping("/provider1")
public String index(@RequestParam(value = "name") String name);
}
@FeignClient:指定要绑定的远程调用的服务,参数为服务的名字
@RequestMapping为调用的提供者方法的映射名
在SpringMVC中@RequestParam和@RequestHeader注解,如果我们不指定value,则默认采用参数的名字作为其value,但是在Feign中,这个value必须明确指定,否则会报错。
5、hystrix
1、配置文件
feign.hystrix.enabled=true
2、客户端调用
@FeignClient(name="spring-cloud-provider",fallback=FallbackRemote.class)
public interface HelloRemote {
@RequestMapping(value = "/hello1", method = RequestMethod.GET)
String hello(@RequestParam("name") String name);
@RequestMapping(value = "/hello2", method = RequestMethod.GET)
User hello(@RequestHeader("name") String name, @RequestHeader("age") Integer age);
@RequestMapping(value = "/hello3", method = RequestMethod.POST)
String hello(@RequestBody User user);
}
3、启动类
@EnableCircuitBreaker
@EnableHystrixDashboard(开启监控)
6、zuul网关
1、pom文件配置
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zuul</artifactId>
</dependency>
2、配置
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8000/eureka/
server:
port: 9400
spring:
application:
name: zuul
zuul:
routes:
api-a:
path: /provider/**
service-id: spring-cloud-provider
api-b:
path: /consumer/**
service-id: spring-cloud-consumer
1、zuul默认配置
spring cloud zuul已经帮我们做了默认配置。默认情况下,Zuul会代理所有注册到Eureka Server的微服务,并且Zuul的路由规则如下:
http://ZUUL_HOST:ZUUL_PORT/微服务在Eureka上的serviceId/**
会被转发到serviceId对应的微服务
2、zuul熔断
Zuul 目前只支持服务级别的熔断,不支持具体到某个URL进行熔断。
3、启动类
@EnableZuulProxy
@EnableEurekaClient
@SpringBootApplication
public class AppZull {
public static void main(String[] args) {
SpringApplication.run(AppZull.class, args);
}
}
4、zuul负载均衡
Zuul负载均衡是属于客户端的负载均衡
客户端负载均衡:
基于客户端的负载均衡,简单的说就是在客户端程序里面,自己设定一个调度算法,在向服务器发起请求的时候,先执行调度算法计算出向哪台服务器发起请求,然后再发起请求给服务器。
特点:
- 由客户端内部程序实现,不需要额外的负载均衡器软硬件投入。
- 程序内部需要解决业务服务器不可用的问题,服务器故障对应用程序的透明度小。
- 程序内部需要解决业务服务器压力过载的问题。
使用场景:
- 可以选择为初期简单的负载均衡方案,和DNS负载均衡一样。
- 比较适合于客户端具有成熟的调度库函数,算法以及API等
- 比较适合对服务器入流量较大的业务,如HTTP POST文件上传,FTP文件上传,Memcache大流量写入。
- 可以结合其他负载均衡方案进行架构。
5、Zuul的核心Filter
1、概述
Filter是Zuul的核心,用来实现对外服务的控制。Filter的生命周期有4个,分别是“PRE”、“ROUTING”、“POST”、“ERROR”;
Zuul大部分功能都是通过过滤器来实现的,这些过滤器类型对应于请求的典型生命周期。
- PRE: 这种过滤器在请求被路由之前调用。我们可利用这种过滤器实现身份验证、在集群中选择请求的微服务、记录调试信息等。
- ROUTING:这种过滤器将请求路由到微服务。这种过滤器用于构建发送给微服务的请求,并使用Apache HttpClient或Netfilx Ribbon请求微服务。
- POST:这种过滤器在路由到微服务以后执行。这种过滤器可用来为响应添加标准的HTTP Header、收集统计信息和指标、将响应从微服务发送给客户端等。
- ERROR:在其他阶段发生错误时执行该过滤器。
除了默认的过滤器类型,Zuul还允许我们创建自定义的过滤器类型。例如,我们可以定制一种STATIC类型的过滤器,直接在Zuul中生成响应,而不将请求转发到后端的微服务。
2、Zuul中默认实现的Filter
类型 顺序 过滤器 功能
pre -3 ServletDetectionFilter 标记处理Servlet的类型
pre -2 Servlet30WrapperFilter 包装HttpServletRequest请求
pre -1 FormBodyWrapperFilter 包装请求体
route 1 DebugFilter 标记调试标志
route 5 PreDecorationFilter 处理请求上下文供后续使用
route 10 RibbonRoutingFilter serviceId请求转发
route 100 SimpleHostRoutingFilter url 请求转发
route 500 SendForwardFilter forward请求转发
post 0 SendErrorFilter 处理有错误的请求响应
post 1000 SendResponseFilter 处理正常的请求响应
3、禁用指定的Filter
zuul:
FormBodyWrapperFilter:
pre:
disable: true
4、自定义Filter
public class MyFilter extends ZuulFilter {
@Override
String filterType() {
return "pre"; //定义filter的类型,有pre、route、post、error四种
}
@Override
int filterOrder() {
return 10; //定义filter的顺序,数字越小表示顺序越高,越先执行
}
@Override
boolean shouldFilter() {
return true; //表示是否需要执行该filter,true表示执行,false表示不执行
}
@Override
Object run() {
return null; //filter需要执行的具体操作
/*
RequestContext ctx = RequestContext.getCurrentContext();
HttpServletRequest request = ctx.getRequest();
log.info(String.format("%s >>> %s", request.getMethod(), request.getRequestURL().toString()));
Object accessToken = request.getParameter("token");
String refer=request.getHeader("refer");
if (accessToken != null) {
return 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;
*/
}
}
5、将TokenFilter加入到请求拦截队列,在启动类中添加代码:
@Bean
public TokenFilter tokenFilter() {
return new TokenFilter();
}
7、config配置中心
1、config-server搭建
1、pom依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
</dependency>
2、配置
spring.application.name=config-server
server.port=9200
spring.cloud.config.server.git.uri=https://gitee.com/archimedes123/config.git
spring.cloud.config.server.git.username=
spring.cloud.config.server.git.password=
eureka.client.serviceUrl.defaultZone=http://localhost:8000/eureka/
假设远程配置文件名为config-dev.properties
内容为:hello:hello im dev
它的application是config,profile是dev。client会根据填写的参数来选择读取对应的配置。
仓库中的配置文件会被转换成web接口,访问可以参照以下的规则:
1、/{application}/{profile}[/{label}]
2、/{application}-{profile}.*
3、/{label}/{application}-{profile}.*
3、启动类
@SpringBootApplication
@EnableConfigServer
@EnableEurekaClient
public class ConfigServerApp {
public static void main(String[] args) {
SpringApplication.run(ConfigServerApp.class, args);
}
}
4、webhook机制检测更新配置(需要消息中间件支持rabbitMQ)
1、pom依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bus-amqp</artifactId>
</dependency>
2、配置文件
server:
port: 8001
spring:
application:
name: spring-cloud-config-server
cloud:
config:
server:
git:
uri: https://github.com/ityouknow/spring-cloud-starter/
# 配置git仓库的地址
search-paths: config-repo
# git仓库地址下的相对地址,可以配置多个,用,分割。
username: username
# git仓库的账号
password: password
# git仓库的密码
rabbitmq:
host: 192.168.0.6
port: 5672
username: admin
password: 123456
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8000/eureka/ ## 注册中心eurka地址
management:
security:
enabled: false
2、config-client搭建
1、pom依赖
<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.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
2、bootstrap.properties配置
spring.application.name=config-client
spring.cloud.config.name=config
spring.cloud.config.profile=dev
spring.cloud.config.label=master
server.port=9300
eureka.client.serviceUrl.defaultZone=http://localhost:8000/eureka/
spring.cloud.config.discovery.enabled=true
spring.cloud.config.discovery.serviceId=config-server
- · spring.cloud.config.name:对应{application}部分
- · spring.cloud.config.profile:对应{profile}部分
- · spring.cloud.config.label:对应git的分支。如果配置中心使用的是本地存储,则该参数无用
- · spring.cloud.config.uri:配置中心的具体地址
- · spring.cloud.config.discovery.service-id:指定配置中心的service-id,便于扩展为高可用配置集群。
特别注意:上面这些与spring-cloud相关的属性必须配置在bootstrap.properties中,config部分内容才能被正确加载。因为config的相关配置会先于application.properties,而bootstrap.properties的加载也是先于application.properties。
@RefreshScope:使用该注解的类,会在接到SpringCloud配置中心配置刷新的时候,自动将新的配置更新到该类对应的字段中。
3、启动类
@SpringBootApplication
@EnableEurekaClient
public class ConfigClientApp {
public static void main(String[] args) {
SpringApplication.run(ConfigClientApp.class, args);
}
}
4、controller
@RestController
@RefreshScope//客户端启动配置中心自动更新
public class TestController {
@Value("${hello}")
private String hello;
@RequestMapping("/getHello")
public String getHello() {
return this.hello;
}
}
8、springcloud负载均衡
zuul也有负载均衡的功能,它是针对外部请求做负载,那客户端ribbon的负载均衡又是怎么一回事?
客户端ribbon的负载均衡,解决的是服务发起方(在Eureka注册的服务)对被调用的服务的负载,比如我们查询商品服务要调用显示库存和商品明细服务,通过商品服务的接口将两个服务组合,可以减少外部应用的请求,比如手机App发起一次请求即可,可以节省网络带宽,也更省电。
ribbon是对服务之间调用做负载,是服务之间的负载均衡,zuul是可以对外部请求做负载均衡。
1、负载均衡策略设置
1、rabbion配置文件
service-B.ribbon.NFLoadBalancerRuleClassName=com.netflix.loadbalancer.RandomRule
其中service-B是我注册到Eureka的serviceID。
2、启动类
@Bean
public IRule ribbonRule() {
return new RandomRule();//这里配置策略,和配置文件对应
}
3、controller
@RestController
public class ConsumerController {
@Autowired
private RestTemplate restTemplate;
@Autowired
private LoadBalancerClient loadBalancerClient;
@RequestMapping(value = "/add", method = RequestMethod.GET)
public String add(@RequestParam Integer a,@RequestParam Integer b) {
this.loadBalancerClient.choose("service-B");//负载均衡策略
return restTemplate.getForEntity("http://service-B/add?a="+a+"&b="+b, String.class).getBody();
}
}
9、springcloud注解
1、@EnableEurekaServer:
启动一个服务注册中心提供给其他应用进行对话
2、@EnableZuulProxy:
开启网关;
3、@FeignClient:
发现服务
4
、
@EnableFeignClients
:
启用feign进行远程调用
5、@EnableCircuitBreaker:
启动断路器
6、@EnableDiscoveryClient:
启用服务注册与发现
7、@EnableEurekaClient:
启用服务注册与发现
@EnableDiscoveryClient基于spring-cloud-commons; @EnableEurekaClient基于spring-cloud-netflix;其实用更简单的话来说,就是如果选用的注册中心是eureka,那么就推荐@EnableEurekaClient,如果是其他的注册中心,那么推荐使用@EnableDiscoveryClient。