微服务简述
微服务是一种用于构建应用的架构方式,它与传统的单体应用架构相比,它将应用拆分为多个功能,每个功能称为一个服务,可以单独的构建与部署,因此,在各项服务工作的同时不会互相影响。
对于单体应用架构相较
优点:
- 单个项目的复杂性降低
- 项目技术更新更容易
- 版本迭代频率提升
- 扩展性提升,可以水平扩展(加服务器)
- 可靠性提升,一个服务器出问题,其他服务器可以继续访问
- 性能提升,每个项目分开,反应更快
缺点:
- 成本更高,会需要多台服务器
- 整体项目的复杂性大大提升
- 运维会更困难
SpringCloud框架
主要的组件
- 注册中心,服务的注册和发现机制,Eureka、Nacos、Zookeeper等
- 配置中心,集中管理服务的配置文件,Config、Nacos
- API网关,实现路由和权限管理,Zuul、Gateway
- 服务通信,实现Restful的服务调用,Openfeign、Dubbo
- 负载均衡,平衡每个服务的负载量,Ribbon
- 熔断器,提高系统的可靠性,Hystrix、Sentinel
- 分布式事务,全局事务管理多个服务,Seata
- Netflix
Eureka、Ribbon、Hystrix、Zuul
- Alibaba
Nacos、Sentinel、Seata、RocketMQ
注册中心
1、先创建一个父项目
org.springframework.boot spring-boot-starter-parent2.6.1 com.hopu spring_cloud0.0.1-SNAPSHOT spring_cloud Demo project for Spring Boot 1.8 2021.0.0 org.springframework.cloud spring-cloud-dependencies${spring.cloud-version} pom import org.projectlombok lomboktrue org.springframework.boot spring-boot-starter-testtest org.springframework.boot spring-boot-maven-pluginorg.projectlombok lombok
2、创建子项目,继承父项目后创建订单和商品服务
3、商品服务提供访问商品的接口
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Product {
private Long id;
private String name;
private Double price;
private String image;
}
@RestController
public class ProductController {
@GetMapping("/product/{id}")
public ResponseEntity findProductById(@PathVariable("id")Long id){
//返回模拟数据
Product product = new Product(id, "测试商品" + port, 100.0,null);
return ResponseEntity.ok(product);
}
}
4、订单服务通过商品服务获得商品
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Order {
private Long id;
private Long userId;
private Long count;
private Long productId;
private Timestamp buyTime;
private Product product;
}
@Configuration
public class RestTemplateConfig {
@Bean
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
@RestController
public class OrderController {
//通过Restful访问其它服务的模板对象
@Autowired
private RestTemplate restTemplate;
@GetMapping("/order/{id}")
public ResponseEntity findOrderById(@PathVariable("id")Long id){
//模拟订单数据
Order order = new Order(id,10L,10L,10L,null,null);
//调用商品服务获得商品
ResponseEntity entity = restTemplate.getForEntity("http://127.0.0.1:8001/product/3", Product.class);
order.setProduct(entity.getBody());
return ResponseEntity.ok(order);
}
}
多个微服务之间互相通信需要ip和端口
"http://127.0.0.1:8001/product/3"
这里的ip和端口是写死了的程序代码,如果服务的ip和端口发生改变调用就会出现错误,并且无法实现集群部署。
注册中心Eureka服务的提供者和消费者都在注册中心上注册(保存ip和端口),服务消费者调用服务提供者时,通过注册中心查找对方服务器的ip和端口,进行通信
- 提供者将ip和端口注册到注册中心
- 注册中心和提供者每隔一段时间(默认30秒)会发送一次心跳
- 如果一段时间(默认90秒)内没有收到心跳,会将该服务移除
- 消费者需要调用提供者时,回到注册中心上查找,注册中心会提供一个服务清单
- 消费者通过服务清单中的ip和端口来调用提供者
- 服务清单每隔一段时间(默认30秒)更新一次
1、创建子项目,继承父项目
2、引入eureka服务器依赖
org.springframework.cloud spring-cloud-starter-netflix-eureka-server
3、在启动类上加@EnableEurekaServer
4、编写配置文件
server.port=8888
spring.application.name=eureka-server
eureka.instance.hostname=127.0.0.1
# 是否注册到Eureka上,false 本身就是服务器 默认为true
eureka.client.register-with-eureka=false
# 是否拉取服务清单,false 默认为true
eureka.client.fetch-registry=false
# 服务的地址配置
eureka.client.serviceUrl.defaultZone=http://${eureka.instance.hostname}:${server.port}/eureka/
修改RestTemplate的配置
@Configuration
public class RestTemplateConfig {
@LoadBalanced
@Bean
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
修改调用服务的代码
restTemplate.getForEntity("http://product-service/product/8", Product.class);



