spring基础知识、springcloud基础配置

目录

1、spring基础配置

2、微服务基础知识

3、eureka基础配置

eureka-server端的配置文件基本配置

eureka-client端的配置文件基本配置

4、Ribbon基础

5、Feign基础


1、spring基础配置

Lombok 中常用的四个注解:
@Data:作用于类上,是以下注解的集合:@ToString @EqualsAndHashCode @Getter @Setter @RequiredArgsConstructor
@NoArgsConstructor:生成无参构造器
@AllArgsConstructor:生成全参构造器
@NonNull:作用于成员变量和参数中,标识不能为空
=============================================================================

//spring整合mybatis常见配置=============================================================
	configuration/settings:
		mapUnderscoreToCamelCase;	true | false	默认值False
			是否开启驼峰命名自动映射,即从经典数据库列名 A_COLUMN 映射到经典 Java 属性名 aColumn。
				
			
	type-aliases-package: 
		类型别名可为 Java 类型设置一个缩写名字。意在降低冗余的全限定类名书写
		
		
	日志配置
		logging.level.*
			日志级别严重性映射。例如,`日志级别. org.springframework=DEBUG `
			
		logging.pattern.dateformat	yyyy-MM-dd HH:mm:ss.SSS
			日志日期格式的附加模式。仅支持默认的回退设置。
				
		/*
		server:
		  port: 8082
		spring:
		  datasource:
			url: jdbc:mysql://localhost:3306/xxx?useSSL=false
			username: xxx
			password: xxx
			driver-class-name: com.mysql.jdbc.Driver
		mybatis:
		  type-aliases-package: cn.itcast.user.pojo
		  configuration:
			map-underscore-to-camel-case: true
		logging:
		  level:
			cn.itcast: debug
		  pattern:
			dateformat: MM-dd HH:mm:ss:SSS */
	

//mybatis-plus常用配置===============================================================
	idType
		类型:com.baomidou.mybatisplus.annotation.IdType
		默认值:ASSIGN_ID
		全局默认主键类型
	tablePrefix
		类型:String
		默认值:null
		表名前缀
	logImpl	
			指定 MyBatis 所用日志的具体实现,未指定时将自动查找。
		/*mybatis-plus:
		  global-config:
			db-config:
			  table-prefix: tb1_
			  id-type: auto
		  configuration:
			log-impl: org.apache.ibatis.logging.stdout.StdOutImpl*/
	
//springboot常用日志配置=================================================================
	
	logging.pattern.level
		日志级别的附加器模式。仅支持默认的回退设置。
	

//druid常用配置============================================================================
	/* spring:
		  datasource:
			druid:
			  driver-class-name: com.mysql.cj.jdbc.Driver
			  url: jdbc:mysql://localhost:3306/数据库名
			  username: xxx
			  password: xxx
			  filter:
				wall:
				  config:
					strict-syntax-check: false //是否开启语法检查
					function-check: false */ //是否开启函数检查

2、微服务基础知识

/*
	declarative:加注解
	programmatic:写代码
什么是微服务呢?
	就是将一个大的应用,拆分成多个小的模块,每个模块都有自己的功能和职责,每个模块可以
	进行交互,这就是微服务。
微服务架构的风格:
	就是将单一程序开发成一个微服务,
	每个微服务运行在自己的进程中,并使用轻量级通信机制,通常是
	HTTP RESTFUL API 。这些服务围绕业务能力来划分构建的,并通
	过完全自动化部署机制来独立部署这些服务可以使用不同的编程语
	言,以及不同数据存储技术,以保证最低限度的集中式管理
微服务有三大难题:
	服务故障的传播性(熔断)、服务的划分和分布式事务
微服务的特点
	1. 按业务(功能)划分为一个独立运行的程序,即服务单元。
	2. 服务之间通过 HTTP 协议相互通信。 http 是一个万能的协议 (web 应用都支持的模式)
	3. 自动化部署。
	4. 可以用不同的编程语言。
	5. 可以用不同的存储技术。
	6. 服务集中化管理。
	7. 微服务是一个分布式系统。
	微服务的不足(正视它的不足)
微服务也不例外,微服务相对于单体应用来说具有很多的优势,当然也有它
的不足:
	1. 微服务的复杂度
	2. 分布式事务问题
	3. 服务的划分(按照功能划分 还是按照组件来划分呢) 分工
	4. 服务的部署(不用自动化部署 自动化部署
SpringCloud 常用组件表 (管家)
	服务的注册和发现。(eureka,nacos,consul)
	服务的负载均衡。(ribbon,dubbo)
	服务的相互调用。(openFeign,dubbo)
	服务的容错。(hystrix,sentinel)
	服务网关。(gateway,zuul)
	服务配置的统一管理。(config-server,nacos,apollo)
	服务消息总线。(bus)
	服务安全组件。(security,Oauth2.0)
	服务监控。(admin) (jvm)
	链路追踪。(sleuth+zipkin)	
SpringCloud 就是微服务理念的一种具体落地实现方式,帮助微服务架构提供了必备的功能
	目前开发中常用的落地实现有三种:
	Dubbo+Zookeeper 半自动化的微服务实现架构 (别的管理没有)
	SpringCloud Netflix 一站式微服务架构
	SpringCloud Alibaba 新的一站式微服务架构
	三大公司
	Spring Netflix A
负载均衡,英文名称为 Load Balance(LB)http:// lb://(负载均衡协议),其含义
	就是指将负载(工作任务)进行平衡、分摊到多个操作单元上进行运行,例如 Web 服务器、
	企业核心应用服务器和其它主要任务服务器等,从而协同完成工作任务
**/

3、eureka基础配置

/*eureka基础:========================================================================
springbootapplication类中,加上注解@EnableEurekaClient。
1 什么是 CAP 原则(面试)
	问:为什么 zookeeper 不适合做注册中心?
	CAP 原则又称 CAP 定理,指的是在一个分布式系统中,
	一致性(Consistency)
	可用性(Availability)
	分区容错性(Partition tolerance)(这个特性是不可避免的)
	CAP 原则指的是,这三个要素最多只能同时实现两点,不可能三者兼顾
	
	C : 数据的一致性 (A,B,C 里面的数据是一致的)
		Zk 注重数据的一致性。
		Eureka 不是很注重数据的一致性!
	A: 服务的可用性(若 zk 集群里面的 master 挂了怎么办)Paxos(多数派)
		在 zk 里面,若主机挂了,则 zk 集群整体不对外提供服务了,需要选一个新的出来(120s
		左右)才能继续对外提供服务!
		Eureka 注重服务的可用性,当 Eureka 集群只有一台活着,它就能对外提供服务
	P:分区的容错性(在集群里面的机器,因为网络原因,机房的原因,可能导致数据不会里面
		同步),它在分布式必须需要实现的特性!
		Zookeeper 注重数据的一致性,CP zk(注册中心,配置文件中心,协调中心)
		Eureka 注重服务的可用性 AP eureka	
	*/
//eureka服务发现
配置文件:	spring.application.name=serviceName1
servlet:
	@Autowired
    private DiscoveryClient discoveryClient;
	// 这就是服务发现  通过服务的应用名 找到服务的具体信息
    List instances = discoveryClient.getInstances(serviceName1);

eureka-server端的配置文件基本配置

   

    服务器主机name一般设为ip地址;

    eureka-server本身即是服务端又是客户端,而是客户端就都要与注册它的服务端续约【发送心跳】,来表示客户端还活着。所以要注册defaultZone【不写,默认注册到8761/eureka】,和设置renewal-interval。

spring:
    application:
        name: eureka-server-xxx

spring基础知识、springcloud基础配置_第1张图片

         如果设置集群,则不同server之间ip应该设为不同【也可以改配置文件进行ip映射】,端口号设置为不同的,应用name设置成相同的。两辆之间相互注册,所以要注册当前defaultZone为另外两个server的注册地址。         

spring基础知识、springcloud基础配置_第2张图片

        win+R 输入drivers,进入etc/hosts文件,进行配置映射peer1,peer2,peer3。在设置主机name时,设置为映射地址即可。 在设置defaultZone时,主机名也设为映射地址。

 spring基础知识、springcloud基础配置_第3张图片

eureka-client端的配置文件基本配置

  交互地址即注册【传数据】地址;缓解服务列表脏读问题要配置interval,事件越短脏读越少

,但性能消耗越大。客户端就要与注册它的服务端续约【发送心跳】,来表示客户端还活着。
spring:
    application:
        name: eureka-client-xxx

spring基础知识、springcloud基础配置_第4张图片

4、Ribbon基础

/* Ribbon 概述:==========================================================================
	Spring Cloud Ribbon 是一个基于 HTTP 和 TCP 的客户端负载均衡工具,它基于 Netflix
		Ribbon 实现。通过 Spring Cloud 的封装,可以让我们轻松地将面向服务的 REST 模版请求
		自动转换成客户端负载均衡的服务调用。轮询、hash、权重...主要功能是提供客户端负载均衡算法和服务调用。
		最好先启动provider,在启动consumer
	Ribbon 是客户端实现负载均衡的远程调用组件,用法简单
	Ribbon 源码核心:
		ILoadBalancer 接口:起到承上启下的作用
1. 承上:从 eureka 拉取服务列表
2. 启下:使用 IRule 算法实现客户端调用的负载均
使用:1、导依赖
	
		org.springframework.cloud
		spring-cloud-starter-netflix-ribbon
		x.x.x.RELEASE
	
	2、consummer配置类中声明RestTemplate时加注解@LoadBalanced,让其被ribbon来托管,
										然后再在servlet中直接使用此RestTemplate
	 	配置类 @Bean
		@LoadBalanced 使用该注解后,这个restTemplate就不能用原生的url了,只能在servlet中new一个新RestTemplate
		public RestTemplate restTemplate(){
			return new RestTemplate();
		}
 */
//consumer 和 provider-xxx 依赖都是 eureka-client
provider-xxx:
	配置文件:	spring.application.name=providerName1
	servlet:	@xxxmapping("yyy")
consummer-xxx:
	配置文件:	spring.application.name=consummerName1
	servlet:	restTemplate.getForObject("http://" +  providerName1 + "/yyy", String.class); 
	 思考 路径不合法,ribbon是怎么将 http://providerName1/yyy 路径请求成功的
		 * 1.Ribbon拦截这个请求
		 * 2.截取主机名称
		 * 3.借助eureka来做服务发现,通过服务名称拿到服务端集合,list<>
		 * 4.通过负载均衡算法 拿到集合中的一个服务
		 * 5.reConstructURL 自动把url进行重构,把providerName1替换为这个服务对应的ip和port
		 * 6.发起请求
//Ribbon服务发现
【servlet】
	@Autowired
    private LoadBalancerClient loadBalancerClient;
	ServiceInstance choose = loadBalancerClient.choose(serviceName1);

//Ribbon 负载均衡的实现和几种算法
	在 ribbon 中有一个核心的负载均衡算法接口 IRule
	1.RoundRobinRule--轮询 请求次数 % 机器数量
	2.RandomRule--随机
	3.权重
	4. iphash
	3.AvailabilityFilteringRule --会先过滤掉由于多次访问故障处于断路器跳闸状态的服
		务,还有并发的连接数量超过阈值的服务,然后对于剩余的服务列表按照轮询的策略进行访问
	4.WeightedResponseTimeRule--根据平均响应时间计算所有服务的权重,响应时间越快服
		务权重越大被选中的概率越大。刚启动时如果同统计信息不足,则使用轮询的策略,等统计信
		息足够会切换到自身规则
	5.RetryRule-- 先按照轮询的策略获取服务,如果获取服务失败则在指定的时间内会进行重
		试,获取可用的服务
	6.BestAvailableRule --会先过滤掉由于多次访问故障而处于断路器跳闸状态的服务,然后
		选择一个并发量小的服务
	7.ZoneAvoidanceRule -- 默认规则,复合判断 Server 所在区域的性能和 Server 的可用
		行选择服务器。
		Ribbon 默认使用哪一个负载均衡算法:
		ZoneAvoidanceRule :区间内亲和轮询的算法!通过一个 key 来区
//如何修改默认的负载均衡算法

//其他配置
	ribbon: #全局的设置
	  eager-load:
		enabled: false # ribbon 一启动不会主动去拉取服务列表,当实际使用时才去拉取【懒加载】 是否立即加载
	  http:
		client:
		  enabled: false # 在 ribbon 最后要发起 Http 的调用调用,我们认为是RestTemplate 完成的,
					其实最后是 HttpURLConnection 来完成的,这里面设置为 true,可以把 HttpUrlConnection->HttpClient
	  okhttp:
		enabled: false #HttpUrlConnection 来完成的,这里面设置为 true ,可以把
									HttpUrlConnection->OkHttpClient(也是发 http 请求的,它在移动端的开发用的多)
//修改consumer的yml配置文件(指定某一个服务使用什么算法)
	 providerName1: //提供者的服务名称,那么访问该服务的时候就会按照自定义的负载均衡算法
	   ribbon:
		  NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule //几种算法的全限定类名
		#修改默认负载均衡算法,几种算法的全限定类名
		# NFLoadBalancerClassName: #loadBalance 策略
		# NFLoadBalancerPingClassName: #ping 机制策略
		# NIWSServerListClassName: #服务列表策略
		# NIWSServerListFilterClassName: #服务列表过滤策略
		ZonePreferenceServerListFilter 默认是优先过滤非一个区的服务列表

5、Feign基础

/*
分布式服务调用思想:不同的服务【客户端或服务端】所执行的功能不同,当一个服务consumer需要另一个服务provider的某些功能时
	则就要相互调用服务获取功能。provider需要提供其接口【servlet资源】。==============================================
Ribbon 做负载均衡,用 Eureka-Client来做服务发现,通过RestTemplate来完成服务调用,
	服务之间相互调用终极方案是使用 OpenFeign 
Feign 是声明性(注解)Web 服务客户端。Spring Cloud 添加了对 Spring MVC 注解的支持,并
	支持使用 HttpMessageConverters,Spring Web 中默认使用的注解。Spring Cloud 集成
	了 Ribbon 和 Eureka 以及 Spring Cloud LoadBalancer,以在使用 Feign 时提供负载平衡
	的 http 客户端。要使用 Feign,要创建一个接口并对其进行注解.
Feign只是帮你封装了远程调用的功能  底层还是ribbon。

	OpenFeign 主要基于接口和注解实现了远程调用
	源码总结:面试
	1. OpenFeign 用过吗?它是如何运作的?
	在主启动类上加上@EnableFeignClients 注解后,启动会进行包扫描,把所有加了
	@FeignClient(value=”xxx-service”)注解的接口进行创建代理对象通过代理对象,使用
	ribbon 做了负载均衡和远程调用
	2. 如何创建的代理对象?
	当 项 目 在 启 动 时 , 先 扫 描 , 然 后 拿 到 标 记 了 @FeignClient 注 解 的 接 口 信 息 , 由
	ReflectiveFeign 类的 newInstance 方法创建了代理对象 JDK 代理
	3. OpenFeign 到底是用什么做的远程调用?
	使用的是 HttpURLConnection (java.net)
	4. OpenFeign 怎么和 ribbon 整合的?
	在代理对象执行调用的时候

使用:
	1.1、provider需要提供其接口【servlet资源	xxxMapping("providermethod1url")】
	1.2、consumer要选择依赖:OpenFeign,EurekaDiscoveryClient,SpringWeb,Lombok	
	2、SpringBootApplication中加注解@EnableFeignClients、@EnableEurekaClient
	3、建立feign文件夹下创建自定义接口 xxxI,并加注解@FeignClient,指定provider的服务名
	4、consumer下的controller中,先注入xxxI创建的对象,然后调用对象的方法即可
	*/
//1.1 provider 
【controller】
	 @GetMapping("providermethod1url")
		public String providerMethodName1(){
			try {
				// 服务的具体实现
				TimeUnit.SECONDS.sleep(2);//模拟操作数据库等 耗时2s
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			return ...;
		}
//3 
*consumer 
【feign】
	@FeignClient(value = "providerName1")
	public interface InterfaceName1 {
		/*你需要调用哪个provider的服务,就写provider提供接口的方法签名
		 * 方法签名(就是包含一个方法的所有的属性,修饰符,返回值,注解...)*/
		@GetMapping("providermethod1url")
		String methodName1();

	}
【controller】
	@RestController
	public class defController {
		/**
		 * 接口是不能做事情的
		 * 如果想做事 必须要有对象
		 * 那么这个接口肯定是被创建出代理对象的
		 * 动态代理 jdk(java interface 接口 $Proxy )  cglib(subClass 子类)
		 * jdk动态代理 只要是代理对象调用的方法必须走invoke方法 java.lang.reflect.InvocationHandler.invoke
		 * (java.lang.Object, java.lang.reflect.Method, java.lang.Object[])
		 */
		@Autowired
		public InterfaceName1 interfaceName1;
		/**
	* 浏览器(前端)-------> provider-service(/consumermethodurl1)-----RPC(feign)--->consumer-service(/providermethod1url)
		 * feign的默认等待时间时1s
		 * 超过1s就在直接报错超时
		 * @return
		 */
		@GetMapping("consumermethodurl1")
		public String consumerMethodName1() {
			// 这里需要发起远程调用
			String s = interfaceName1.methodName1();
			return s;
		}

/* Feign 传参确保消费者和提供者的参数列表一致 包括返回值 方法签名要一致
	1. 通过 URL 传参数,GET 请求,参数列表使用@PathVariable(“”)
	2. 如果是 GET 请求,每个基本参数必须加@RequestParam(“”)
	3. 如果是 POST 请求,而且是对象集合等参数,必须加@Requestbody 或者@RequestPar
	如果不加注解,默认会把参数放在请求体中,但其请求体只能放一个类型的参数,所以最好加注解。*/
/**练习:
 * url    /doOrder/热干面/add/油条/aaa
 * get传递一个参数
 * get传递多个参数
 * post传递一个对象
 * post传递一个对象+一个基本参数
 */
 * provider
【domain】
	@Data
	@AllArgsConstructor
	@NoArgsConstructor
	@Builder//构建者模式
	public class Order {

		private Integer id;
		private String name;
		private Double price;
		private Date time;

	}
【servlet】
	@RestController
	public class ParamController {
		
		@GetMapping("testUrl/{name}/and/{age}")
		public String testUrl(@PathVariable("name") String name, @PathVariable("age") Integer age) {
			...
			return "ok";
		}

		@GetMapping("oneParam")
		public String oneParam(@RequestParam(required = false) String name) {
			...
			return "ok";
		}

		@GetMapping("twoParam")
		public String twoParam(@RequestParam(required = false) String name, @RequestParam(required = false) Integer age) {
			System.out.println(name);
			System.out.println(age);
			return "ok";
		}

		@PostMapping("oneObj")
		public String oneObj(@RequestBody Order order) {
			System.out.println(order);
			return "ok";
		}

		@PostMapping("oneObjOneParam")
		public String oneObjOneParam(@RequestBody Order order,@RequestParam("name") String name) {
			System.out.println(name);
			System.out.println(order);
			return "ok";
		}
		//单独传递时间对象
		@GetMapping("testTime")
		public String testTime(@RequestParam Date date){
			System.out.println(date);
			return "ok";
		}
		
*consumer
【application.yml】
	server:
		port: xxx
	spring:
		application:
			name: user-service-xxx
	eureka:
		client:
			service-url:
				defaultZone: http://xxx/eureka
	# feign只是帮你封装了远程调用的功能  底层还是ribbon 所以我们需要去修改ribbon的时间
	ribbon:
		ReadTimeout: 3000 # 给3s超时时间因为provider有一个耗时处理过程,所以要设计超时时间
		ConnectTimeout: 3000 # 连接服务的超时时间
	logging:
		level:
			com.zrx.feign.interfaceName1: debug  # 我需要打印指定接口下面的日志

【applicationboot】
	@SpringBootApplication
	@EnableEurekaClient
	@EnableFeignClients(basePackages = {"com.zrx.feign"}) // 开启feign的客户端功能 才可以帮助我们发起调用
	public class UserServiceApplication {
		public static void main(String[] args) {
			SpringApplication.run(UserServiceApplication.class, args);
		}

		@Bean
		@LoadBalanced
		public RestTemplate restTemplate() {
			return new RestTemplate();
		}
		/**
		 * 打印fein日志信息 级别
		 */
		@Bean
		public Logger.Level level(){
			return Logger.Level.FULL;
		}

	}
	
【feign】
	@FeignClient(value = "provider-service-name")
	public interface InterfaceName1 {
		
		@GetMapping("testUrl/{name}/and/{age}")
		public String testUrl(@PathVariable("name") String name, @PathVariable("age") Integer age);

		@GetMapping("oneParam")
		public String oneParam(@RequestParam(required = false) String name);

		@GetMapping("twoParam")
		public String twoParam(@RequestParam(required = false) String name, @RequestParam(required = false) Integer age);

		@PostMapping("oneObj")
		public String oneObj(@RequestBody Order order);

		@PostMapping("oneObjOneParam")
		public String oneObjOneParam(@RequestBody Order order, @RequestParam("name") String name);

		@GetMapping("testTime")
		public String testTime(@RequestParam Date date);
	}
【servlet】
	@RestController
	public class UserController {
		
		@Autowired
		public UserOrderFeign userOrderFeign;

		@GetMapping("testParam")
		public String testParam(){
			String cxs = userOrderFeign.testUrl("cxs", 18);
			System.out.println(cxs);

			String t = userOrderFeign.oneParam("老唐");
			System.out.println(t);

			String lg = userOrderFeign.twoParam("雷哥", 31);
			System.out.println(lg);

			/*传统构建对象
			Order o=new Order();
			o.setName(...);
			o.setAge(...); */
			//使用构建者模式
			Order order = Order.builder()
					.name("牛排")
					.price(188D)
					.time(new Date())
					.id(1)
					.build();

			String s = userOrderFeign.oneObj(order);
			System.out.println(s);

			String param = userOrderFeign.oneObjOneParam(order, "稽哥");
			System.out.println(param);
			return "ok";
		}

		/**
		 *发送与接受时间差距  +- 14个小时
		 * 1.不建议单独传递时间参数
		 * 2.转成字符串   2022-03-20 10:25:55:213 因为字符串不会改变
		 * 3.jdk LocalDate 年月日    LocalDateTime 会丢失秒
		 * 4.改feign的源码
		 *
		 * @return
		 */
		@GetMapping("time")
		public String time(){
			Date date = new Date();
			System.out.println(date);
			String s = userOrderFeign.testTime(date);

			LocalDate now = LocalDate.now();//年月日
			LocalDateTime now1 = LocalDateTime.now();//年月日时分秒

			return s;
		}
	}

你可能感兴趣的:(配置语法,spring_知识_课堂笔记,spring,java,后端)