单体架构:1.将业务的所有功能集中在一个项目中开发,打成一个包部署。
2.单体架构的优点,架构简单部署成本低
3.单体架构的缺点,耦合度高,维护困难,升级困难。
分布式架构: 1.根据业务功能对系统架构做拆分,每一个业务功能模块作为独立的项目开发,称之为服务
2.分布式架构的优点,降低服务之间耦合度,有利用服务的升级和扩展。
3.分布式架构的缺点,服务之间的关系错综复杂。
微服务的架构特征:1.单一职责,微服务拆分粒度更小,每一个服务都对应唯一的业务能力,做到单一职责。
2.自治,技术独立、团队独立、数据独立,独立部署和交付。
3.面向服务,服务提供统一标准的接口,与语言和技术无关。
4.隔离性强,服务调用做好隔离、容错、降级,避免出现级联问题。
SpringCloud:SpringCloud集成各种微服务功能组件,并基于SpringBoot实现这些组件的自动装配,提供良好的开箱及用体验。
比如常见的组件:1.服务注册发现包括Eureka,Nacos,Consul。
2.服务远程调用OpenFeign,Dubbo。
3.服务链路监控,Zipkin,Sleuth。
4.统一配置管理,SpringCloudConfig,Nacos。
5.统一网关路由,SpringCloudGateway,Zuul。
6.流控,降级,保护,Hystix,Sentinel。
服务拆分:微服务拆分的几个原则
1.不同微服务项目,不要开发相同业务。
2.微服务数据独立,不要访问其他微服务的数据库。
3.微服务可以将自己的业务暴露接口,让其它微服务调用。
实现远程调用功能:1.注册RestTemplate
package com.chengxin.order;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
@MapperScan("com.chengxin.order.mapper")
@SpringBootApplication
public class OrderApplication {
public static void main(String[] args) {
SpringApplication.run(OrderApplication.class, args);
}
/*
服务调用
*/
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
2.在Service层实现自动装配,引入远程调用功能
package com.chengxin.order.service;
import com.chengxin.order.mapper.OrderMapper;
import com.chengxin.order.pojo.Order;
import com.chengxin.order.pojo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
@Service
public class OrderService {
@Autowired
private OrderMapper orderMapper;
@Autowired
private RestTemplate restTemplate;
public Order queryOrderById(Long orderId) {
// 1.查询订单
Order order = orderMapper.findById(orderId);
// 2. 定义url地址
String url ="http://user-service/user/"+ order.getUserId();
// 3.调用远程用户订单
User user = restTemplate.getForObject(url, User.class);
order.setUser(user);
// 4.返回
return order;
}
}
提供者和消费者的讲述,在服务调用关系中,会有两个不同的角色:
1.服务提供者,一次业务中,被其它微服务调用的服务。
2.服务消费者,一次业务中,调用其它微服务的服务。
服务提供者与服务消费者的角色并不是绝对的,而是相对于业务而言:
如果服务C调用了服务D,而服务D又调用了服务E,服务D的角色是么?
1.C调用D的业务而言,C是服务消费者,D是服务提供者。
2.D调用E的业务而言,D是服务消费者,E是服务提供者。
D是消费者也可以是服务的提供者。
Eureka注册中心:
如我们部署多个实例
要考虑的问题:
1.服务消费者在发起远程调用的时候,如何得知服务提供者实例的IP地址和端口。
2. 有多个服务提供者,服务消费者调用如何选择。
3. 服务消费者如何得知服务提供者实例是否依然健康的,是否已经宕机 。
接下来说一说Eureka的结构和作用:
以上的这些问题需要用注册中心来解决,使用主流的Eureka来解决此问题。
Euaeka的作用:
1. 注册服务消息 。
2.拉取服务提供者的信息。
3.负载均衡轮询。
4.服务消费者远程调用服务提供者。
4. 心跳续约,每30秒1次。
一个微服务,可以是服务提供者,也可以是服务消费者,所以Eureka将服务注册中心 服务发现等功能统一封装到Eureka-client。
实践Eureka注册中心功能:
1.搭建注册中心,EurekaServer
2.服务注册,将服务提供者和服务消费者注册到Eureka注册中心
3.服务发现,在服务消费者中完成服务拉取,通过负载均衡轮询一个服务,实现远程调用功能。
引入Eureka依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
编写启动器类:
要添加一个@EnableEurekaServer注解,开启eureka的注册中心功能
package com.chengxin.eureka;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@SpringBootApplication
@EnableEurekaServer
public class EurekaApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaApplication.class, args);
}
}
编写配置文件:application.yml文件
server:
port: 8090
spring:
application:
name: eureka-server
eureka:
client:
service-url:
defaultZone: http://127.0.0.1:8090/eureka
启动Eureka服务注册中心:
启动微服务,在浏览器访问:http://localhost:8090
服务注册: 将服务提供者添加到Erueka注册中心去
引入依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
编写application.yml文件
spring:
application:
name: userservice
eureka:
client:
service-url:
defaultZone: http://127.0.0.1:8090/eureka
服务拉取和负载均衡:
在服务消费者启动类加上
/*
服务远程调用
*/
@Bean
@LoadBalanced
public RestTemplate restTemplate(){
return new RestTemplate();
}
Ribbon负载均衡和负载均衡原理:
添加了@LoadBalanced注解,可实现负载均衡功能,这是什么原理。
1.发起请求 2.拉取服务提供者3.返回服务列表4.轮询的服务端口
总结:
1.拦截我们的RestTemplate请求http://userservice/user/1。
2.RibbonLoadBalancerClient会从请求url中获取服务名称,也就是user-service。
3.DynamicServerListLoadBalancer根据user-service到eureka拉取服务列表。
4. eureka返回列表,localhost:8081、localhost:8082。
5. Rule利用内置负载均衡规则,从列表中选择一个。
负载均衡策略:
负载均衡的规则都定义在IRule接口中,而IRule有很多不同的实现类:
默认的实现就是ZoneAvoidanceRule,是一种轮询方案。
自定义负载均衡策略
服务消费者上提供负载均衡
@Bean
public IRule randomRule(){
return new RandomRule();
}
服务消费者中的application.yml文件中
userservice: # 给某个微服务配置负载均衡规则,这里是userservice服务
ribbon:
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule # 负载均衡规则
饥饿加载:
Ribbon默认是采用懒加载,即第一次访问时才会去创建LoadBalanceClient,请求时间会很长。
而饥饿加载则会在项目启动时创建,降低第一次访问的耗时,配置开启饥饿加载。
ribbon:
eager-load:
enabled: true
clients: userservice