互联网应用和传统应用的区别
传统应用
传统的后台管理软件或信息系统
某个机构或公司内部使用的,比如:
-
OA 办公自动化
-
ERP 企业资源计划
-
CRM 客户资源管理
-
CMS 内容管理系统
-
银行、金融、国企....
特点:
-
用户不会太多
-
对用户体验要求不太高
-
对数据的一致要求高
互联网应用
面向所有的互联网用户
分类:
-
游戏
-
电商(淘宝、京东、美团.....)
-
社交(微信、QQ....)
-
视频(B站、抖音、优酷....)
-
教育(慕课...)
-
医疗
-
购票
-
...
特点:
-
用户量特别大
-
对用户体验要求高
带来的问题:
-
高并发
-
高可用
-
高性能
微服务和单体应用的区别
单体应用
传统管理系统一般采用单体应用
一个项目打一个包部署到一台服务器
问题:
-
项目越来越复杂,代码量越来越大
-
项目技术更新比较难
-
服务器不能水平扩展
-
项目的启动和部署比较困难
-
系统的可用性不高,出现bug服务器崩溃
-
系统的性能比较低
微服务
将项目分割成一个个小项目,每个项目单独打包部署到自己的服务器,每个服务之间可以相互调用
优点:
-
每个项目的代码量降低,容易维护
-
项目的技术更新迭代方便
-
方便系统的水平扩展
-
系统的并发量提高
-
系统的可用性提高
-
系统的性能提高
缺点:
-
系统整体的复杂性大大提高
-
系统开发和部署成本提高
-
系统运维困难
SpringCloud介绍
SpringCloud提供了一系列工具让我们更快地开发分布式/微服务应用。
功能包含:
-
配置中心 Config
-
服务的注册和发现 Eureka
-
路由 Gateway、Zuul
-
服务和服务之间的调用 OpenFeign
-
负载均衡 Ribbon
-
熔断器 Hystrix
-
服务跟踪 Slauth、zipkin
搭建SpringCloud
在父项目中配置SpringCloud版本
<properties> <spring.cloud-version>2021.0.3</spring.cloud-version> </properties> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>${spring.cloud-version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>
开发微服务项目
开发商品微服务和订单微服务
服务提供者:商品服务
服务消费者:订单服务
查询订单时需要查询相关商品的信息
服务之间可以通过RestTemplate进行http调用
商品服务
@RestController public class ProductController { @GetMapping("/product/{id}") public ResponseEntity<Product> getProductById(@PathVariable Long id){ Product product = new Product(id,"测试商品",new BigDecimal("99.99999")); return ResponseEntity.ok(product); } }
订单服务
/** * 配置RestTemplate */ @Configuration public class RestTemplateConfig { @Bean public RestTemplate restTemplate(){ return new RestTemplate(); } }
@Service public class OrderService { @Autowired private RestTemplate restTemplate; public Order getOrderById(Long id){ Order order = new Order(id,88L,10L, LocalDateTime.now(),null); //调用商品服务查询商品 ResponseEntity<Product> entity = restTemplate.getForEntity("http://localhost:8001/product/" + order.getProductId(), Product.class); order.setProduct(entity.getBody()); return order; } }
@RestController public class OrderController { @Autowired private OrderService orderService; @GetMapping("/order/{id}") public ResponseEntity<Order> getOrderById(@PathVariable Long id){ return ResponseEntity.ok(orderService.getOrderById(id)); } }
直接通过IP和端口调用另一个服务
问题:
1) 服务提供者的IP和端口如果发生改变,服务消费者调用出现错误
2) 无法配置集群
Eureka注册中心
Netflix公司提供的服务注册和发现组件
Netflix相关的组件:Eureka、Ribbon、Hystrix、Zuul、Config等
注册中心的作用:服务提供者启动后将自己的IP和端口注册到注册中心上,服务消费者从注册中心获得服务提供者的IP和端口进行连接,
服务提供者和消费者每隔30s向注册中心发送心跳,如果90s没有发送,注册中心会剔除掉失效的服务器。
注册中心的组件有:Eureka、Nacos、Consul等
Eureka的简单入门
1) 父项目设置SpringCloud版本
2) 创建Eureka服务
-
继承父项目
-
引入依赖
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId> </dependency>
-
启动类加: @EnableEurekaServer
-
服务器配置
server.port=8888 # 服务名称 spring.application.name=eureka-server # 配置是否从eureka拉取服务清单 eureka.client.fetch-registry=false # 配置否则注册到eureka eureka.client.register-with-eureka=false # 配置eureka服务器的ip地址 eureka.instance.hostname=127.0.0.1 # 配置完整地址 eureka.client.serviceUrl.defaultZone=http://${eureka.instance.hostname}:${server.port}/eureka/
-
3) 客户端配置
-
继承父项目,添加依赖
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency>
-
启动类加: @EnableEurekaClient 或 @EnableDiscoveryClient
-
添加配置
server.port=8001 spring.application.name=product-service # 注册到eureka上 eureka.client.register-with-eureka=true # 是否拉取服务清单 eureka.client.fetch-registry=true # 配置eureka地址 eureka.client.serviceUrl.defaultZone=http://127.0.0.1:8888/eureka
-
RestTemplate加@LoadBalanced注解
@Configuration public class RestTemplateConfig { @LoadBalanced @Bean public RestTemplate restTemplate(){ return new RestTemplate(); } }
-
调用服务时,使用服务名称调用
ResponseEntity<Product> entity = restTemplate.getForEntity("http://product-service/product/" + order.getProductId(), Product.class);