提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
前言
这篇文章主要是用来记录自己学习spring-cloud的内容
一、架构的演变
- 单体架构:
一个war包或一个jar包里面包含了一个程序的所有功能就是单体架构,难以对程序进行扩充,因为耦合度太高,对于项目初期用户量不大的情况使用。 - 集群和垂直化:
横向增加服务器,一个Tomcat服务器变成多个Tomcat服务器,形成一个集群。并且按业务的垂直领域进行拆分成多个war包,使得耦合度降低,以及降低单个war包带来的伸缩性困难问题。而对于数据库,也要进行相应的拆分,例如:用户库,商品库等等。 - SOA:
SOA (Service-Oriented Architecture )就是⾯向服务的架构。核心思想是把⼀些通⽤的、会被多个上层服务调⽤的共享业务提取成独⽴的基础服务,这些基础服务相对独立并可以进行重用。在SOA中,ESB(企业服务总线)是系统和服务之间的通信桥梁。调⽤端不需要关⼼⽬标服务的位置,从⽽使得服务之间的交互是动态的,这样做的好处是实现了服务的调⽤者和服务的提供者之间的⾼度解耦。SOA也可以解决信息孤岛的问题,可以使不同的系统达成一定程度的信息共享。 - 微服务架构:
⾯向服务(SOA)和微服务本质上都是服务化思想的⼀种体现。
与SOA的区别:
1. SOA关注的是服务的重⽤性及解决信息孤岛问题。
2. 微服务关注的是解耦,虽然解耦和可重⽤性从特定的⻆度来看是⼀样的,但本质上是有区别的,解耦是降低业务之间的耦合度,⽽重⽤性关注的是服务的复⽤。
3. 微服务会更多地关注在DevOps的持续交付上,因为服务粒度细化之后使得开发运维变得更加重要,因此微服务与容器化技术的结合更加紧密。
二、Spring cloud的简介及使用案例
1.简介
Spring Cloud是Spring提供的微服务框架。它利⽤Spring Boot的开发特性简化了微服务开发的复杂性,如服务发现注册、配置中⼼、消息总线、负载均衡、断路器、数据监控等,这些⼯作都可以借助Spring Boot的开发⻛格做到⼀键启动和部署。
2.使用案例
创建两个微服务:订单微服务和支付微服务,订单微服务将通过调用支付微服务完成支付的功能。
支付微服务的配置文件(application.yml):
server:
port: 9001
PaymentController:
@RestController
@RequestMapping("/payment")
public class PaymentController {
@GetMapping("/{id}")
public ResponseEntity<Payment> payment(@PathVariable("id") Integer id) {
Payment payment = new Payment(id, "支付成功,服务端口=" + serverPort);
return ResponseEntity.ok(payment);
}
}
订单微服务的启动器:
这里使用RestTepleate调⽤⽀付微服务,完成⽀付功能。
RestTemplate模板⼯具类,对基于Http的客户端进⾏了封装,并且实现了对象与json的序列化和反序列化。
@SpringBootApplication
public class OrderApplication {
public static void main(String[] args) {
SpringApplication.run(OrderApplication.class, args);
}
@Bean
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
application.yml:
server:
port: 9002
OrderController:
@RestController
@RequestMapping("/order")
public class OrderController {
@Autowired
private RestTemplate restTemplate;
@GetMapping("/payment/{id}")
public ResponseEntity<Payment> getPaymentById(@PathVariable("id") Integer id) {
String url = "http://localhost:9001/payment/" + id;
Payment payment = restTemplate.getForObject(url, Payment.class);
return ResponseEntity.ok(payment);
}
}
三、Eureka的注册和发现微服务
1.Eureka简介
Eureka是⼀个⽤于服务注册和发现的组件,Eureka分为Eureka Server和Eureka Client,Eureka Server为Eureka服务注册中⼼,Eureka Client为Eureka客户端。
Eureka原理图:
2.Eureka的使用
创建一个EurekaServer的项目:
启动器:
@EnableEurekaServer,声明当前应⽤为Eureka Server
@SpringBootApplication
@EnableEurekaServer
public class EurekaApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaApplication.class, args);
}
}
配置文件application.yml
erver:
port: 9004
spring:
application:
name: eureka-server
eureka:
client:
service-url:
# eureka 的服务地址,如果是集群,需要指定其他eureka server的地址
defaultZone: http://127.0.0.1:9004/eureka
# 不注册自己
register-with-eureka: false
# 本身不拉取服务列表
fetch-registry: false
instance:
# 心跳间隔时间
lease-renewal-interval-in-seconds: 30
# 没收到心跳多久时间剔除
lease-expiration-duration-in-seconds: 90
启动效果(localhost:9004)
在支付微服务的配置文件中添加Eureka的相关配置:
添加name属性指定应用名称,将会被作为服务的id使用
server:
port: 9001
spring:
application:
name: cloud-payment-service
eureka:
client:
service-url:
defaultZone: http://127.0.0.1:9004/eureka
# 可以不用指定以下两个属性的值,因为默认为true
fetch-registry: true
register-with-eureka: true
启动器:
添加@EnableDiscoveryClient,使Eureka发现
@SpringBootApplication
@EnableDiscoveryClient
public class PaymentApplication {
public static void main(String[] args) {
SpringApplication.run(PaymentApplication.class, args);
}
}
在订单微服务的配置文件中添加Eureka的相关配置:
server:
port: 9002
spring:
application:
name: cloud-order-service
eureka:
client:
service-url:
defaultZone: http://127.0.0.1:9004/eureka
# 可以不用指定以下两个属性的值,因为默认为true
fetch-registry: true
register-with-eureka: true
启动器:
添加@EnableDiscoveryClient,使Eureka发现
@SpringBootApplication
@EnableDiscoveryClient
public class OrderApplication {
public static void main(String[] args) {
SpringApplication.run(OrderApplication.class, args);
}
@Bean
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
OrderController:
public class OrderController {
@Autowired
private RestTemplate restTemplate;
@Autowired
private DiscoveryClient discoveryClient;
@GetMapping("/payment/{id}")
public ResponseEntity<Payment> getPaymentById(@PathVariable("id") Integer id) throws Exception{
String url = "http://localhost:9001/payment/" + id;
List<ServiceInstance> serviceInstances = discoveryClient.getInstances("CLOUD-PAYMENT-SERVICE");
ServiceInstance serviceInstance = serviceInstances.get(0);
String url = "http://" + serviceInstance.getHost() + ":" + serviceInstance.getPort() + "/payment/" + id;
Payment payment = restTemplate.getForObject(url, Payment.class);
return ResponseEntity.ok(payment);
}
}
测试效果:
3.Eureka的基本概念
-
Register — 服务注册:当Eureka Client向Eureka Server注册时,Eureka Client提供⾃身的元数据,⽐如IP地址、端⼝、运⾏状况指标的URL,主⻚地址等信息。
-
Renew — 服务续约:Eureka Client在默认情况下会每隔30秒发送⼀次⼼跳来进⾏服务续约,通过服务续约来告知 Eureka Server该Eureka Client依然可⽤,正常情况下,如果Eureka Server在90秒内没有收到Eureka Client的⼼跳,Eureka Server会将Eureka Client实例从注册列表中删除。
-
Fetch Registries — 获取服务注册列表信息:Eureka Client从Eureka Server获取服务注册表信息,并将其缓存到本地。Eureka Client 会使⽤服务注册列表信息查找其他服务的信息,从⽽进⾏远程调⽤,改注册列表信息定时(每隔30秒)更新⼀次,每次返回的注册列表信息可能与Eureka Client的缓存信息不同,Erueka Client会重新获取整个注册表信息。
-
Cancel — 服务下线:Eureka Client在程序关闭时可以向Eureka Server发送下线请求,发送请求后,该客户端的实例信息将从Eureka Server的服务注册列表信息中删除。注意:下线请求不会⾃动完成,需要在程序关闭时调⽤以下代码:
DiscoveryManager.getInstance().shutdownComponent();
-
Eviction — 服务:在默认情况下,Eureka Client连续90秒没有想Eureka Server发送服务续约(⼼跳)时,Eureka Server会将该服务实例从服务列表中删除。即服务剔除。