分享两个spring cloud地址:中文社区 http://springcloud.cn/ ,官方文档 https://springcloud.cc/
spring cloud技术栈已经已经变越发流行,是众多中小企业开发项目的首选技术,也是很多大公司新项目的考虑方法,也是java开发人员面试时必问知识点。因此作为java开发人员很有必须要学习这门新技术。
首先spring cloud不是指具体某一种技术,而是一堆技术栈,类似于dubbo,但却要比dubbo功能强大、完善很多,共有21种技术,其中常用的有五大技术,俗称"spring cloud 五大神兽",spring cloud是基于spring boot的。
"五大神兽"
1.服务发现——Netflix Eureka
2.客服端负载均衡——Netflix Ribbon
3.断路器——Netflix Hystrix
4.服务网关——Netflix Zuul
5.分布式配置——Spring Cloud Config
这里搭建的spring cloud技术栈组成如下,我们前期先搭建简单的架子,并做负载均衡,再慢慢集成熔断器hystrix 、网关zuul、配置中心config、监控dashboard 等。
前期:2个Eureka + 3个provider + 2个consumer (基于ribbon和feign负载均衡)
后期集成:hystrix + dashboard + Zuul + Config。
一、搭建Eureka注册中心:
2.创建完空的springcloud后,在弹出的窗口中选择modules,点击 “➕”,选择new module,选择spring initializr 方式创建子模块,jdk选择自己的安装jdk。
子模块命名为eureka,完成后idea中会看到已创建的模块。
3. 将application.properties修改为.yml后缀(两种后缀都可以),并复制一份命名为application-dev1.yml ,一定要是application-{}.yml这种格式,这是springboot的约定,添加配置文件内容如下,注意yml的格式有缩进,正确缩进后key颜色为黄色:
========================
application.yml
application-dev1.yml
#启动端口
server:
port: 7001
#应用名
spring:
application:
name: eureka
#eureka实例名
eureka:
instance:
hostname: eureka7001
client:
register-with-eureka: false #false 是否将自己注册进eureka,单机版false,集群版设置为true
fetch-registry: false #false 是否将自己注册进eureka,单机版false,集群版设置为true
service-url:
defaultZone: http://127.0.0.1:7001/eureka/ #查询服务和注册服务都需要依赖这个地址,多个地址可用","分割
4.在主启东类上加注解@EnableEurekaServer,启动eureka,并在浏览器查看eureka注册中心:http://127.0.0.1:7001,可以看到如下界面代表eureka注册中心启动成功,目前还没有服务注册上来!
5.启动eureka集群
5.1复制一份application-dev2.yml,修改端口为7002。
5.2 idea配置启动集群,通过启动不同不配置文件方式,过程如下图:配置2份启动。
5.2.1 在idea右上角点击Edit Configurations…
5.2.2 配置主启动类和启动配置文件,这里启动的是7001配置文件,点击apply后生效。
5.2.3 点击 “➕”,新建一个spring boot启动配置,在7002端口配置一份,步骤同上一步,点击OK,最终效果如下图:
5.2.4 因为这里我们要配置成集群版的eureka,所以配置文件要做一些修改,如下,client的2个register设置为true,url设置为集群中别的节点地址,eureka的replicas机制,我们只需注册任意一台eureka,服务器自动会把服务同步到别的eureka上:
application-dev1.yml
#启动端口
server:
port: 7001
#应用名
spring:
application:
name: eureka
#eureka实例名
eureka:
instance:
hostname: eureka7001
client:
register-with-eureka: true #false 是否将自己注册进eureka,单机版false,集群版设置为true
fetch-registry: true #false 是否将自己注册进eureka,单机版false,集群版设置为true
service-url:
defaultZone: http://127.0.0.1:7002/eureka/ #查询服务和注册服务都需要依赖这个地址,多个地址可用","分割
application-dev2.yml
#启动端口
server:
port: 7002
#应用名
spring:
application:
name: eureka
#eureka实例名
eureka:
instance:
hostname: eureka7002
client:
register-with-eureka: true #false 是否将自己注册进eureka,单机版false,集群版设置为true
fetch-registry: true #false 是否将自己注册进eureka,单机版false,集群版设置为true
service-url:
defaultZone: http://127.0.0.1:7001/eureka/ #查询服务和注册服务都需要依赖这个地址,多个地址可用","分割
5.2.5 启动集群,分别查看http://127.0.0.1:7001/ http://127.0.0.1:7002/, 至此简单的eureka注册中心搭建完成:
二、搭建服务提供者 provider
1.新建provider,步骤和上面新建eureka类似,不在累述.
注意:需要注意的是我们新建provider的入口选择的是File -->Project structure… 建议这样做,如果是从File -->new --> module 入口,需要修改路径,容易出错。
2.选择需要的依赖,
在如下界面勾选对面选项,idea会把我们自动导入相关maven坐标。根据自己的需要选择,我们这里选择core选了Lombok、web选择了web、SQL选择了MySQL和mybatis、Cloud Discovery选择了eureka discovery。
3.配置文件
完成后效果如下图,我们这里打算搭建3个provider,所以复制三份配置文件出来,分别为:
application-dev1.yml、application-dev2.yml、application-dev3.yml,在application.yml中激活dev1用户测试项目启动。
application-dev1.yml配置如下,dev2和dev3修改端口为8002和8003即可,数据库改为testdb2和testdb3
server:
port: 8001
#数据源配置
spring:
datasource:
url: jdbc:mysql://127.0.0.1:3306/testdb1 #这里为了演示后面的负载均衡,三个provicer分别连了3个库
username: root
password: root123
driver-class-name: com.mysql.jdbc.Driver
cloud:
refresh:
refreshable: none #如果启动时报dataSource单例重复,加上这个,或者用注解在启动类上排除自动注入
application:
name: provider
eureka:
client:
service-url:
defaultZone: http://127.0.0.1:7001/eureka/
#eureka集群有复制机制,我们只需要注册一个,其余节点会自动复制,如果想保险,就都注册,这里只是验证eureka集群 的#replicas机制
mybatis:
mapper-Locations: classpath:com/learn/provider/mapper/.xml
4.搭建一个简单的provider服务
和ssm框架搭建类似,功能为通过mybatis查询mysql 的 testdb1数据库,并返回json数据,不再累述,效果如下,有2点要注意的地方:
一、在provider主启动类上加注解@MapperScan(basePackages = {“dao接口路径”}),或者在每个dao接口上加@Mapper注解。
二、和eclipse不同,idea不会自动编译xml文件,需要添加相应的插件,如下:
添加xml编译插件:
5.配置启动
在idea右上角的edit configurations…界面配置,过程不再累述,和上述配置eureka启动配置意义,分别在8001、8002、8003端口启动配置文件dev1、dev2、dev3,以此搭建3个provider集群,完成后效果如下图:
6.启动3个provider,
主启动类加上@EnableEurekaClient注解,启动3个provider,查看eureka注册中心7001和7002,可以发现3个provider均已注册上来。我们在provider的配置文件中只配置了7001的地址,但是7002注册中心发现也有了3个provider实例,这说明了eureka复制机制生效了。
至此,我们的eureka集群和provider集群搭建完毕,这里要保证provider提供的服务是没问题,这是后续consumer通过eureka调用provider的前提。
三、搭建consumer 服务消费者
1.过程和前面类似,从File --> Project Structure …为入口进入,新建一个consumer 模块,过程和上面类似。效果如下:
2.搭建消费者,通过restTemplate调用provider服务,我们这里要要配置RestTemplate 这个bean后才能使用RestTemplate 模板调用provider。
controller代码如下:
@RestController
@RequestMapping("consumer")
public class ConsumerController {
@Autowired
private IConsumerService consumerService;
@GetMapping("list")
public Object queryAll(){
List list = consumerService.queryAll();
return list;
}
}
service层代码如下:
@Service
public class ConsumerServiceImpl implements IConsumerService {
@Autowired
private RestTemplate template;
@Override
public List queryAll() {
return template.getForObject("http://provider/student/list",List.class);
}
}
config配置restTemplate代码如下:
@Configuration
public class Config {
@Bean
@LoadBalanced
RestTemplate restTemplate() {
return new RestTemplate();
}
}
3.主启动类加上注解@EnableEurekaClient后启动consumer,查看eureka注册中心。
4.通过consumer调用provider服务
多次调用会发现,返回的数据在testdb1库、testdb2库、testdb3库来回重复。
这里使用restTemplate模板调用provider的方式,称为ribbon,负载均策略默认是轮询策略。ribbon支持7种预定义策略和自定义策略,如需切换预定义负载均衡策略,可在config中加入如下代码修改,如下把策略改为了随机策略:
@Bean
public IRule myRule(){
return new RandomRule();
}
/**
* 1.RoundRobinRule #轮询
* 2.RandomRule #随机选择一个server
* 3.RetryRule #在轮询负载均衡策略基础上添加了重试机制。
* 4.WeightedResponseTimeRule #根据响应时间分配一个weight,响应时间越长,weight越小,被选中的可能性越低。
* 5.ZoneAvoidanceRule #复合判断server所在区域的性能和server的可用性选择server
* 6.BestAvailableRule #选择一个最小的并发请求的server
* 7.AvailabilityFilteringRule #过滤掉那些因为一直连接失败的后端server,并过滤掉那些高并发的的后端server
*/
这里采用的是ribbon的方式,是通过rest http方式调用的。下面我们来改造一下项目,将客户端的调用方式改为feign方式,也即是面向接口开发,可以降低耦合,让代码变得更优雅。
四、修改consumer的调用方式为feign
使用feign方式,只需要三步:1.提供一个接口 2.添加一个注解和mapping 3.注入接口调用
1.提供一个provider接口,里面是我们需要调用的抽象方法
2.接口加注解@FeignClient(“name”),name为provider注册的application.name,抽象方法上加上映射路径,即@RequestMapping
@FeignClient("PROVIDER")
public interface IStudentService {
@GetMapping("/student/list")
List queryList();
}
3.在需要使用的地方@Autowired注入
@RestController
@RequestMapping("consumer")
public class ConsumerController {
@Autowired
private IStudentService studentService;
@GetMapping("/feign/list")
public List queryAllFeign(){
List list = studentService.queryList();
return list;
}
}
4.在consumer的主启动类上加注解@EnableFeignClients。
启动,测试,成功调用,且一样可以轮询。
至此,我们完成了springcloud最基本的几个功能搭建,下一篇博客我们来集成hystrix和zuul功能。