学贵心悟,守旧无功。 ——《经学理窟》
串一下自己之前的东西
这个阶段该如何学
在学习新知识的同时不忘回顾自己以及拥有的知识
我自己的东西
我差了的东西
标准的变化
我们在之前以学过了ssm
我们的开发核心在哪里
javaEE标准
spring javaEE开发标准
spring几乎连接着我们开发中的一切,他就像一个中央集成一样
但是慢慢的我们发现,他真的轻量吗?
让他变得不再轻量,于是乎新的解决方案诞生了
javaEE新标准
springboot javaEE开发新的标准
他简化了繁琐的配置,自动化的帮助我们干了很多的配置上需要重复干的事情,
给了我们一套默认的解决方案,我们可以把boot理解成一个 spring的plus版,他集成了很多的启动器,从而让springboot逐渐取代了 ssm,springboot慢慢的变成了javaEE最好的解决方案,让无数企业喜爱
不管是新标准还是旧标准,他的特点是统一的:约定大于配置
最开始
我们现在开发的程序 all in one 的形式,所有的模块全在一个jar或者war包下
演进
那么随着架构的演进我们逐渐把功能拆分出来,代码并没有什么变化
但是一旦并发量高起来,这样的架构,我们的机器无法让业务正常实行了
现在
解决方法应运而生,微服务架构
把功能拆分多个设备上去,来解决性能上导致业务无法正常运行的问题
微服务四大核心问题:
对于这些问题,spring cloud是个生态
用来解决这四个问题的
Spring cloud netfix 一站式解决方案
api网关,zuul组件
Feign --HttpClinet ----Http通信方式
服务注册发现:Eureka
熔断机制: Hystrix
。。。。
Apache Dubbo zookeeper 半自动,需要整合别人的
API 没有,找第三方组件,或者自己实现
Dubbo 通信,高性能 rpc框架
服务注册发现:zookeeper
熔断机制并没有:借助 Hystrix
Spring Cloud Alibaba 最新的一站式解决方案!
新概念:服务网格!server mesh
概念都是一样的:
为什么会出现这个情况,因为:网络不可靠!
就是微服务的作用就是将传统的一个项目解决业务(一站式应用)根据业务拆分成一个一个的服务,去彻底的去耦合,每个微服务提供单个业务的功能服务,一个服务做一个事情,从技术角度来说就是一个小而独立的处理过程,类的进程的概念,能够自行单独启动或销毁,拥有自己独立的数据库
微服务
强调的是服务的大小 ,他关注的是一个点,是具体解决某一个问题提供落地对服务的应用,就是idea中一个个微服务的工程或者moudel
idea工具里面使用maven建立的一个个独立的小moudle,他具体是使用springboot开发的一个个小模块,专业的事情交给专业的模版来做,一个模块做着一件事情
强调的是一个个的个体,每个个体完成一个具体的任务或者功能!
微服务架构
一钟新的架构形式,Martin Fowler
2014推出
优点
缺点:
微服务技术条目 | 落地技术 |
---|---|
服务开发 | SpringBoot,Spring,SpringMVC |
服务配置与管理 | netflix公司的archaius和阿里的diamond等 |
服务注册与发现 | eureka,consul,zookeeper |
服务调用 | rest,rpc,grpc |
服务熔断器 | Hystrix,Envoy等 |
负载均衡 | RIbbon,nginx等 |
服务接口调用(服务端调用服务的简化工具) | Feign等 |
消息队列 | kafka,rabbitMQ,ActiveMQ |
服务配置中心管理 | SpringCloudconfig,chef等 |
服务路由 | Zuul等 |
服务监控 | zabbix,Nagios,M ertrics,Specatator |
全链路追踪 | Zipkin,Brave,Dapper |
服务部署 | DOCKER,openStack,kubernetes |
数据操作开发包 | Springcloud Stream(封装与rides,rabbit,kafka等发送接收消息) |
事件消息总线 | springcloud Bus |
2、当前各大公司微服务架构是那些
功能和服务框架 | Netflix/springCloud | Motan | grpc | thrift | Dubbo/dubbox |
---|---|---|---|---|---|
功能定位 | 完整的微服务框架 | rpc框架但是整合了zk或者consul可以实现集群环境和基本的服务注册发现 | rpc框架 | rpc框架 | 服务框架 |
支持rest | 支持,ribbon支持多种可插拔序列化选择 | 否 | 否 | 否 | 否 |
支持rpc | 否(但是可以和dubbo兼容) | 是 | 是 | 是 | 是 |
支持多语言 | 支持(rest形式) | 否 | 是 | 是 | 否 |
负载均衡 | 支持(服务端zuul+客户端ribbon),zuul服务,动态路由,云端负载均衡,eureka针对中间层服务器 | 支持(客户端) | 否 | 否 | 是(客户端) |
配置服务 | netfix archaius spring cloud config Server集中配置 | 是(zookeeper提供) | 否 | 否 | 否 |
服务调用链监 | 支持,zuul,zuul提供边缘服务,api网关 | 否 | 否 | 否 | 否 |
高可用/容错 | 支持,服务端hystrix+ribbon | 支持(客户端) | 否 | 否 | 支持(客户端) |
典型应用案例 | Netflix | sina | |||
社区活跃度 | 高 | 一般 | 高 | 一般 | 2017才开始重新维护,之前中断了五年 |
学习难度 | 中 | 低 | 高 | 高 | 低 |
文档丰富程度 | 高 | 一般 | 一般 | 一般 | 高 |
其他 | SpringCloud bus为我们的应用带来更多的管理端点 | 支持降级 | netflix内部在开发集成grpc | idl定义 | 实践的公司比较多 |
springcloud基于springboot提供了一套微服务解决方案,包括服务注册,发现,配置中心,全链路监控
服务网管,负载均衡,熔断器等组件,除了基于netflix的开源组件做高度抽象封装之外,还有一些选型中立得1开源组件。
springcloud利用springboot的开发便利性,巧妙的简化了分布式系统基础设施额开发,springcloud为开发人员提供了快速构建分布式系统的一些工具,包括配置管理,服务发现,断路器,路由,微代理,事件总线,全局锁,决策竞选,分布式会话等等,他们都可以用springboot的开发风格做到一键启动部署
springboot并没有重复造轮子,他只是将目前各家公司开发的比较成熟经得起实际考研的 服务框架组合起来,通过springboot风格进行封装,屏蔽掉了复杂的配置,和实现原理,最终给开发者留出一套简单易懂,易部署,和易维护的分布式系统开发工具包
springcloud是分布式微服务架构下的一站式解决方案,是各个微服务架构落地技术的集合体,俗称微服务全家桶
分布式+服务治理Dubbo
目前成熟的互联网架构:应用服务化拆分+消息中间件
Dubbo和springcloud对比
dubbo应为停更了之后,社区并不活跃,垂死状态,未来未知
springcloud的社区十分活跃,正值壮年,
对比图:
最大区别:springcloud抛弃了Dubbo的rpc通信,采用基于http的rest方式
严格来说,两种方式各有优劣,从一定程度上,后者牺牲了服务调用的性能,但是也比避免了原生rpc带来的问题,rest相比rpc更加的灵活,服务提供方和调用方的依赖只靠一个七月,不存在在吗级别的强依赖,这就是强调快速烟花的微服务环境下,显得更加合适
品牌机和组装机的区别
springcloud(品牌机):
很明显的一点就是,springcloud的功能比dubbo强大的太多,覆盖面更广,而且作为spring的明星项目,他也能够和其他的spring项目完美融合。
dubbo(组装机):
使用dubbo构建微服务架构就像组装电脑,各环节,我们的选择自由度非常高,但是最终结果可能是就是一个内存条不点亮了,总是不让人那么放心,但是如果是一个高手,那这些都不是问题,
springcloud就像品牌机,在spring source的整合下,做了大量的兼容性测试,保证了机器拥有更高的稳定性,但是如果要在使用非原装组件外的东西,就需要对其基础足够了解,
社区支持和更新力度
最重要的是,dubbo停止了5年狗熊,虽然17年重启了,对于技术发展的需求,更需要爱发展着自行拓展升级,比如dubbox,对于这很多想要采纳微服务的中小软件组织,显然是不太合适的,中小公司没有那么强大的技术去修改dubbo的源码+周边的一整套解决方案。并不是每个公司都有阿里的大牛+真实线上生产环境测试过
总结
曾风靡国内的rpc框架Dubbo在重启维护后,让很多用户为之雀跃,但是同时也要有质疑的声音,发展迅速的时代,dubbo能否跟上?dubbo和springcloud的差异 ?是否会有相关的举措保证dubbo的后续更新频率
dubbo是一个专注rpc框架,springcloud的目标是微服务架构下的一站式解决方案
设计模式+微服务拆分思想:不一定善于表达的技术人才,你可以领导他,软实力是职场关键的一点,你可能技术没有人才好,但是你的设计思维,架构理解和表达能力让你可以成为只会技术人才的团队leader,
springcloud的不同版本
以伦敦地铁站和字符开头来命名
接下来是需要知道的几个文档
springcloud的中文文档:https://www.springcloud.cc/spring-cloud-dalston.html
社区官网:http://docs.springcloud.cn/
以上的理论内容是和代码挂钩的,很多面试中淡资也是很重要的东西
一个父工程带着多个子模块
动手!
springcloud的大版本说明
springboot | springcloud | 关系 |
---|---|---|
1.2.x | 天使版angel | 兼容boot1.2.x |
1.3.x | brixton版本 | 兼容spring1.3,也兼容1.4 |
1.4.x | camden版本 | 兼容spring1.4,也兼容1.5 |
1.5.x | dalston版本 | 兼容spring1.5,不兼容2.0.x |
1.5.x | edgware | 兼容spring1.5,不兼容2.0 |
2.0.x | finchley | 兼容spring2.0,不兼容1.5 |
2.1.x | greenwich |
到了2020我们发现技术一代一代的换,有的技术慢慢的停止更新维护,又会有新的更全面的解决方案跟上,时代快速发展
就是子模块依赖版本的统一管理
这里呢我们就要用到dependencyManagement+properties来控制版本
下图就是关于dependencyManagement的一些知识复习
父项目pom
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0modelVersion>
<groupId>com.hyc.springcloudgroupId>
<artifactId>cloud2020artifactId>
<version>1.0-SNAPSHOTversion>
<modules>
<module>cloud-provider-payment8001module>
modules>
<packaging>pompackaging>
<properties>
<project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
<maven.compiler.source>1.8maven.compiler.source>
<maven.compiler.target>1.8maven.compiler.target>
<junit.version>4.12junit.version>
<log4j.version>1.2.17log4j.version>
<lombok.version>1.16.18lombok.version>
<mysql.version>8.0.11mysql.version>
<druid.version>1.1.16druid.version>
<mybatis.spring.boot.version>1.3.0mybatis.spring.boot.version>
properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-dependenciesartifactId>
<version>2.2.2.RELEASEversion>
<type>pomtype>
<scope>importscope>
dependency>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-dependenciesartifactId>
<version>Hoxton.SR1version>
<type>pomtype>
<scope>importscope>
dependency>
<dependency>
<groupId>com.alibaba.cloudgroupId>
<artifactId>spring-cloud-alibaba-dependenciesartifactId>
<version>2.1.0.RELEASEversion>
<type>pomtype>
<scope>importscope>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<version>${mysql.version}version>
dependency>
<dependency>
<groupId>com.alibabagroupId>
<artifactId>druidartifactId>
<version>${druid.version}version>
dependency>
<dependency>
<groupId>org.mybatis.spring.bootgroupId>
<artifactId>mybatis-spring-boot-starterartifactId>
<version>${mybatis.spring.boot.version}version>
dependency>
<dependency>
<groupId>junitgroupId>
<artifactId>junitartifactId>
<version>${junit.version}version>
dependency>
<dependency>
<groupId>log4jgroupId>
<artifactId>log4jartifactId>
<version>${log4j.version}version>
dependency>
<dependency>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
<version>${lombok.version}version>
<optional>trueoptional>
dependency>
dependencies>
dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-maven-pluginartifactId>
<configuration>
<fork>truefork>
<addResources>trueaddResources>
configuration>
plugin>
plugins>
build>
project>
搞定这边之后,我们就可以去编写子模块了
建cloud-provider-payment8001
在springboot的学习中我们发现一个模块的构建也是有迹可循的
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>cloud2020artifactId>
<groupId>com.atguigu.springcloudgroupId>
<version>1.0-SNAPSHOTversion>
parent>
<modelVersion>4.0.0modelVersion>
<artifactId>cloud-provider-payment8001artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-actuatorartifactId>
dependency>
<dependency>
<groupId>org.mybatis.spring.bootgroupId>
<artifactId>mybatis-spring-boot-starterartifactId>
dependency>
<dependency>
<groupId>com.alibabagroupId>
<artifactId>druid-spring-boot-starterartifactId>
<version>1.1.10version>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-jdbcartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-devtoolsartifactId>
<scope>runtimescope>
<optional>trueoptional>
dependency>
<dependency>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
<optional>trueoptional>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
<scope>testscope>
dependency>
dependencies>
project>
之后编写相关的配置文件 application.Yml
server:
port: 8001
spring:
application:
name: cloud-payment-service
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: org.gjt.mm.mysql.Driver
url: jdbc:mysql://localhost:3306/db2019?useUnicode=true&characterEncoding=utf-8&useSSL=false
username: root
password: 123456
mybatis:
mapperLocations: classpath:mapper/*.xml
type-aliases-package: com.atguigu.springcloud.entities
编写业务类
实体类
package com.atguigu.springcloud.entities;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Payment implements Serializable {
private Long id;
private String serial;
}
Json封装体CommonResult
package com.atguigu.springcloud.entities;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class CommonResult <T>{
private Integer code;
private String message;
private T data;
public CommonResult(Integer code,String message){
this(code,message,null);
}
}
mapper与映射文件
mapper接口
package com.hyc.cloud.mapper;
import com.hyc.cloud.pojo.payment;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
@Mapper
public interface PaymentMapper {
public int create(payment payment);
public payment getPaymentByid(@Param("id") long id);
}
对应的映射文件
DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.hyc.cloud.mapper.PaymentMapper">
<insert id="create" parameterType="com.hyc.cloud.pojo.payment" useGeneratedKeys="true" keyProperty="id">
insert into db01.paymemt (serial) values (#{name});
insert>
<select id="getPaymentByid" resultType="com.hyc.cloud.pojo.payment" parameterType="long" resultMap="BaseResultMap">
select *
from paymemt where id = #{id};
select>
<resultMap id="BaseResultMap" type="com.hyc.cloud.pojo.payment">
<id column="id" property="id" jdbcType="BIGINT"/>
<id column="serial" property="serial" jdbcType="VARCHAR"/>
resultMap>
mapper>
服务层
package com.atguigu.springcloud.service;
import com.atguigu.springcloud.entities.Payment;
import org.apache.ibatis.annotations.Param;
public interface PaymentService {
public int create(Payment payment); //写
public Payment getPaymentById(@Param("id") Long id); //读取
}
实现类
package com.atguigu.springcloud.service.impl;
import com.atguigu.springcloud.dao.PaymentDao;
import com.atguigu.springcloud.entities.Payment;
import com.atguigu.springcloud.service.PaymentService;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
@Service
public class PaymentServiceImpl implements PaymentService {
@Resource
private PaymentDao paymentDao;
public int create(Payment payment){
return paymentDao.create(payment);
}
public Payment getPaymentById( Long id){
return paymentDao.getPaymentById(id);
}
}
最后就是controller
package com.hyc.cloud.controller;
import com.hyc.cloud.pojo.CommonResult;
import com.hyc.cloud.pojo.payment;
import com.hyc.cloud.service.PaymentService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
@RestController
@Slf4j
public class PaymentController {
@Resource
private PaymentService paymentService;
@PostMapping("payment/create")
public CommonResult create(payment payment){
int result = paymentService.create(payment);
log.info("****新增结果:"+result);
if (result>0){
return new CommonResult(200,"插入数据库成功",result);
}else {
return new CommonResult(444,"插入数据库失败",null);
}
}
@GetMapping("payment/get/{id}")
public CommonResult getPaymentByid(@PathVariable("id") long id){
payment payment = paymentService.getPaymentByid(id);
log.info("****新增结果:"+payment);
if (payment!=null){
return new CommonResult(200,"查询成功",payment);
}else {
return new CommonResult(444,"没有对应的记录,失败,查询id"+id,null);
}
}
}
编写主启动类
package com.hyc.cloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class paymentMain8001 {
public static void main(String[] args) {
SpringApplication.run(paymentMain8001.class,args);
}
}
走过一遍流程,那我们就加快速度
新建消费者子模块
cloud-consumer-order80
修改pom文件
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>cloud2020artifactId>
<groupId>com.hyc.springcloudgroupId>
<version>1.0-SNAPSHOTversion>
parent>
<modelVersion>4.0.0modelVersion>
<artifactId>cloud-consumer-order80artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-actuatorartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-devtoolsartifactId>
<scope>runtimescope>
<optional>trueoptional>
dependency>
<dependency>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
<optional>trueoptional>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
<scope>testscope>
dependency>
dependencies>
project>
配置文件消费者十分的简单,就是配置一下端口号
server: port: 80
之后复制实体类到消费者项目里
springboot中有很多的template供我们使用
这里我们要用到的就是其中的resttemplate
他和网络编程中的httpclient有异曲同工之妙
这里我们需要编写一个config类,springboot需要什么我们就new什么
@Configuration
public class orderConfig {
@Bean
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
有了这个我们就可以在消费者里面调用resttemplate
了
因为是消费者所以我们只需要知道怎么使用服务就可以了
这里我们编写controller
package com.hyc.cloud.controller;
import com.hyc.cloud.pojo.CommonResult;
import com.hyc.cloud.pojo.payment;
import io.micrometer.core.instrument.Meter;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import javax.annotation.Resource;
@RestController
public class orderContorller {
@Resource
private RestTemplate restTemplate;
public final static String PAYMENT_URL = "http://localhost:8001";//服务提供者的地址(后面做负载均衡的时候会替换成application.name)
@GetMapping("/consumer/payment/create")
public CommonResult create(payment payment){
return restTemplate.postForObject(PAYMENT_URL+"/payment/create",payment,CommonResult.class);
}
@GetMapping("/consumer/payment/get/{id}")
public CommonResult getPament(@PathVariable("id") long id){
return restTemplate.getForObject(PAYMENT_URL+"/payment/get/"+ id,CommonResult.class);
}
}
当然不是
这里是的插入数据是存在问题的
会出现只有自增的主键没有内容
这个时候我们要回到服务提供者
在新增的对象参数前加上注解@requestbody
这个主机再次测试就解决了
@PostMapping("payment/create")
public CommonResult create(@RequestBody payment payment){
int result = paymentService.create(payment);
log.info("****新增结果:"+result);
if (result>0){
return new CommonResult(200,"插入数据库成功",result);
}else {
return new CommonResult(444,"插入数据库失败",null);
}
}
此时的数据库也新增成功了
到这里呢支付模块为例 体验demo就结束了
希望我的学习笔记可以在提升自己的同时为正在学习的同学们带来帮助