狂神说springcloud笔记1_p1-p13

网友投稿 245 2022-09-19

狂神说springcloud笔记1_p1-p13

参考博文:(5条消息) [狂神说Java]SpringCloud笔记_笶生的博客-.

​​(5条消息) 狂神说SpringCloud学习笔记(附带源码和笔记)_学不死就往死里学.​​

1、SpringCloud入门概述

1.1 SpringCloud是什么

springcloud官网: Dubbo 和 SpringCloud技术选型

1、分布式+服务治理Dubbo

目前成熟的互联网架构:应用服务化拆分+消息中间件

2、Dubbo 和 SpringCloud对比

可以看一下社区活跃度

​​SpringCloud能干什么

1.5 SpringCloud在哪下

官网 : version="1.0" encoding="UTF-8"?> insert into dept(dname,db_source) values (#{dname},DATABASE());

DeptMapper

@Mapper@Repositorypublic interface DeptMapper { //添加部门 boolean addDept(Dept dept); //根据ID查询部门 Dept queryById(@Param("deptno") long id); //查询全部部门 List queryall();}

DeptService

public interface DeptService { boolean addDept(Dept dept); Dept queryById(long id); List queryall();}

DeptServiceImpl

@Servicepublic class DeptServiceImpl implements DeptService { @Autowired private DeptMapper deptMapper; @Override public boolean addDept(Dept dept) { return deptMapper.addDept(dept); } @Override public Dept queryById(long id) { return deptMapper.queryById(id); } @Override public List queryall() { return deptMapper.queryall(); }}

mybatis-config.xml

application.yml

server: port: 8001mybatis: mapper-locations: classpath:mybatis/mapper/*.xml type-aliases-package: com.bupt.pojo configuration-properties: classpath:mybatis/mybatis-config.xmlspring: application: name: springcloud-provider-dept datasource: type: com.alibaba.druid.pool.DruidDataSource driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://127.0.0.1:3306/db01?useUnicode=true&characterEncoding=UTF-8&useSSL=true&serverTimezone=UTC username: root password: rooteureka: client: service-url: defaultZone: com.bupt.Controller;import com.bupt.DeptService.DeptServiceImpl;import com.bupt.pojo.Dept;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.web.bind.annotation.*;import java.util.List;//提供Restfull服务!!@RestControllerpublic class DeptController { @Autowired private DeptServiceImpl deptService; @RequestMapping("/dept/add") public boolean addDept(@RequestBody Dept dept) { System.out.println(dept); return deptService.addDept(dept); } @GetMapping("/dept/get/{id}") public Dept getDept(@PathVariable("id") Long id) { Dept dept = deptService.queryById(id); if (dept == null) { throw new RuntimeException("Fail"); } return dept; } @GetMapping("/dept/list") public List queryAll() { return deptService.queryall(); }}

DeptProvider_8001

package com.bupt;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;//@EnableEurekaClient@SpringBootApplicationpublic class DeptProvider_8001 { public static void main(String[] args) { SpringApplication.run(DeptProvider_8001.class,args); }}

最后启动项目访问Controller里面的接口测试即可,这个pojo类在别的项目里面,我们照样可以拿到,这就是微服务的简单拆分的一个小例子

6、服务消费者:springcloud-consumer-dept-80

pom.xml

map = new HashMap<>(); map.put("dname",dept.getDname()); map.put("deptNo",dept.getDeptno()); map.put("db_source",dept.getDb_source()); System.out.println(map); return restTemplate.postForObject(REST_URL_PREFIX + "/dept/add", map, Boolean.class); } @RequestMapping("/consumer/dept/list") @ResponseBody public List queryAll(){ return restTemplate.getForObject(REST_URL_PREFIX + "/dept/list",List.class); }}

然后你会发现,原来远程的post请求直接在url是拒绝访问的,但是在这个里面可以访问,只是结果为null

application.yml

server: port: 80

主启动类DeptConsumer_80

@SpringBootApplicationpublic class DeptConsumer_80 { public static void main(String[] args) { SpringApplication.run(DeptConsumer_80.class, args); }}

最后启动服务提供者 springcloud-provider-dept-8001

然后启动服务消费者 springcloud-consumer-dept-80

通过服务消费者的url请求去获取服务提供者对应的请求,照样可以拿到

7、Eureka服务注册与发现

7.1、什么是Eureka

7.2、原理讲解

7.3、springcloud-eureka-7001

pom.xml

services = client.getServices(); System.out.println("discovery=>services:" + services); //得到一个具体的微服务信息,通过具体的微服务ID applicationName List instances = client.getInstances("SPRINGCLOUD-PROVIDER-DEPT"); for (ServiceInstance instance : instances) { System.out.println( instance.getHost() + "\t" + instance.getPort() + "\t" + instance.getUri() + "\t" + instance.getServiceId() ); } return instances;}

然后在8001项目主启动类上添加服务发现注解即可

这个注解我试了一下,不加也可以访问上面的接口返回信息

@EnableDiscoveryClient //服务发现

1

重启8001项目并访问 eureka7001.com127.0.0.1 eureka7002.com127.0.0.1 eureka7003.com8.2、修改7001配置文件application.yml

server: port: 7001#Eureka配置eureka: instance: hostname: eureka7001.com #Eureka服务端的实例名字 client: register-with-eureka: false #表示是否向 Eureka 注册中心注册自己(这个模块本身是服务器,所以不需要) fetch-registry: false #fetch-registry如果为false,则表示自己为注册中心 service-url: #监控页面~ #重写Eureka的默认端口以及访问路径 ---> # 单机: defaultZone: # 集群(关联):7001关联7002、7003 defaultZone: 、springcloud-eureka-7002

创建Eureka注册中心7002项目(和7001一模一样)

pom.xml

依赖和7001一样

EurekaServer_7002

主启动类

package com.bupt;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;@SpringBootApplication@EnableEurekaServer //EnableEurekaServer表示服务端的启动类,可以接收别人注册进来public class EurekaServer_7002 { public static void main(String[] args) { SpringApplication.run(EurekaServer_7002.class, args); }}

application.yml

server: port: 7002#Eureka配置eureka: instance: hostname: eureka7002.com #Eureka服务端的实例名字 client: register-with-eureka: false #表示是否向 Eureka 注册中心注册自己(这个模块本身是服务器,所以不需要) fetch-registry: false #fetch-registry如果为false,则表示自己为注册中心 service-url: #监控页面~ #重写Eureka的默认端口以及访问路径 ---> # 单机: defaultZone: # 集群(关联):7002关联7001、7003 defaultZone: 、springcloud-eureka-7003

创建Eureka注册中心7003项目(和7001一模一样)

pom.xml

依赖和7001一样

EurekaServer_7003

主启动类

package com.bupt;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;@SpringBootApplication@EnableEurekaServer //EnableEurekaServer表示服务端的启动类,可以接收别人注册进来public class EurekaServer_7003 { public static void main(String[] args) { SpringApplication.run(EurekaServer_7003.class, args); }}

application.yml

server: port: 7003#Eureka配置eureka: instance: hostname: eureka7003.com #Eureka服务端的实例名字 client: register-with-eureka: false #表示是否向 Eureka 注册中心注册自己(这个模块本身是服务器,所以不需要) fetch-registry: false #fetch-registry如果为false,则表示自己为注册中心 service-url: #监控页面~ #重写Eureka的默认端口以及访问路径 ---> # 单机: defaultZone: # 集群(关联):7002关联7001、7003 defaultZone: 、、 port: 8001mybatis: mapper-locations: classpath:mybatis/mapper/*.xml type-aliases-package: com.bupt.pojo configuration-properties: classpath:mybatis/mybatis-config.xmlspring: application: name: springcloud-provider-dept datasource: type: com.alibaba.druid.pool.DruidDataSource driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://127.0.0.1:3306/db01?useUnicode=true&characterEncoding=UTF-8&useSSL=true&serverTimezone=UTC username: root password: root# Eureka配置:配置服务注册中心地址eureka: client: service-url: # 注册中心地址7001-7003 defaultZone: instance: instance-id: springcloud-provider-dept-8001 #修改Eureka上的默认描述信息info: app.name: wulei-springcloud company.name: blog.wulei2921625957.com

然后启动8001项目,刷新、、即可发现

9、CAP原则及对比Zookeeper

作为服务注册中心,Eureka比Zookeeper好在那里?

​​张大胖和CAP定理(分布式系统、可用性、一致性、分区容错性)_ITPUB博客​​

10、Ribbon负载均衡

ribbon是什么?

ribbon能干什么?

10.1、springcloud-consumer-dept-80使用Ribbon

首先80项目要添加两个依赖

pom.xml

最后还有一个问题,就是我们的RestTemplate实现了负载均衡,那么怎么体现它呢?我们现在就只是在它身上加了一个注解,那肯定是不行的,我们还要改变RestTemplate的请求路径,让其自动选择,而不是写死

package com.MyRule;import com.netflix.loadbalancer.IRule;import com.netflix.loadbalancer.RandomRule;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;@Configurationpublic class MyRules { @Bean public IRule testRule(){ return new MyRandomRule(); }}

DeptConsumerController//private static final String REST_URL_PREFIX = "static final String REST_URL_PREFIX = "com.bupt.controller;import com.bupt.pojo.Dept;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.PathVariable;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.ResponseBody;import org.springframework.web.client.RestTemplate;import java.util.HashMap;import java.util.List;@Controllerpublic class DeptConsumerController { @Autowired private RestTemplate restTemplate;// private static final String REST_URL_PREFIX = "static final String REST_URL_PREFIX = " private static final String REST_URL_PREFIX = " @RequestMapping("/consumer/dept/get/{id}") @ResponseBody public Dept getDept(@PathVariable("id") long id) { return restTemplate.getForObject(REST_URL_PREFIX + "/dept/get/" + id,Dept.class); } @RequestMapping("/consumer/dept/add") @ResponseBody public boolean add(Dept dept){ HashMap map = new HashMap<>(); map.put("dname",dept.getDname()); map.put("deptNo",dept.getDeptno()); map.put("db_source",dept.getDb_source()); System.out.println(map); return restTemplate.postForObject(REST_URL_PREFIX + "/dept/add", map, Boolean.class); } @RequestMapping("/consumer/dept/list") @ResponseBody public List queryAll(){ return restTemplate.getForObject(REST_URL_PREFIX + "/dept/list",List.class); }}

最后启动7001、7002、7003项目后再启动8001项目,等8001项目注册到它们3个中后启动80项目

然后访问 可以看到正常返回结果,当然了,在这里也看不出负载均衡,所以下面会配置多个服务提供者和多个数据库,来测试负载均衡的效果。

10.2、使用Ribbon实现负载均衡

创建另外两个数据库:db02、db03

创建另外两个服务提供者:8002、8003

直接新建两个子model,然后把8001的所有文件全部拷贝(提供相同的服务),一摸一样的,然后更改一下配置文件即可

pom.xml依赖

application.yml的端口号,对应的数据库,还有instance-id,例如:instance-id: springcloud-provider-dept8002

注意:下面的这个服务ID不要改

spring: application: name: springcloud-provider-dept # 3个服务名称一致是前提

现在的项目预览

然后,启动

springcloud-config-eureka-7001springcloud-config-eureka-7002springcloud-config-eureka-7003springcloud-provider-dept-8001springcloud-provider-dept-8002springcloud-provider-dept-8003springcloud-consumer-dept-80

然后访问,多访问几次,查询的数据没变,但是数据库变了

你会发现是轮询,就是每个服务轮流来,这也Ribbon的默认算法

Ribbon自定义均衡算法里面有个接口非常重要:IRule,基本上全部的均衡算法都实现了这个接口

里面有这么多均衡算法,因为默认是轮询算法,也就是RoundRobinRule,那我们要怎么使用别的算法呢?

只需要在80项目的config类里面注册Bean即可

//IRule//RoundRobinRule:轮询//RandomRule:随机//AvailabilityFilteringRule:会先过滤掉跳闸、访问故障的服务~,对剩下的进行轮询//RetryRule:会先按照轮询获取服务,如果服务获取失败,则会在指定的时间内进行重试@Beanpublic IRule myRule() { return new RandomRule(); //默认为轮询,现在我们使用随机的

然后启动80项目,访问com.MyRule;import com.netflix.client.config.IClientConfig;import com.netflix.loadbalancer.AbstractLoadBalancer;import com.netflix.loadbalancer.AbstractLoadBalancerRule;import com.netflix.loadbalancer.ILoadBalancer;import com.netflix.loadbalancer.Server;import java.util.List;import java.util.concurrent.ThreadLocalRandom;public class MyRandomRule extends AbstractLoadBalancerRule { //每个机器,访问5次,换下一个服务(总共3个) //total = 0 默认=0,如果=5,我们指向下一个服务结点 //index = 0 默认=0,如果total=5,那么index+1, private int total = 0; //被调用的次数 private int currentIndex = 0; //当前是谁在提供服务 public Server choose(ILoadBalancer lb, Object key) { if (lb == null) { return null; } Server server = null; while (server == null) { if (Thread.interrupted()) { return null; } List upList = lb.getReachableServers(); //获得还活着的服务 List allList = lb.getAllServers(); //获得全部的服务 int serverCount = allList.size(); if (serverCount == 0) { return null; } //============================================================= if (total < 5) { total++; } else { total = 0; currentIndex++; if (currentIndex >= serverCount) { currentIndex = 0; } } server = upList.get(currentIndex); //============================================================= if (server == null) { Thread.yield(); continue; } if (server.isAlive()) { return (server); } server = null; Thread.yield(); } return server; } protected int chooseRandomInt(int serverCount) { return ThreadLocalRandom.current().nextInt(serverCount); } @Override public Server choose(Object key) { return choose(getLoadBalancer(), key); } @Override public void initWithNiwsConfig(IClientConfig clientConfig) { }}

MyRules

package com.MyRule;import com.netflix.loadbalancer.IRule;import com.netflix.loadbalancer.RandomRule;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;@Configurationpublic class MyRules { @Bean public IRule testRule(){ return new MyRandomRule(); }}

最后还要在主启动类添加扫描注解,在微服务启动的时候就能去加载我们自定义的Ribbon类

DeptConsumer_80

package com.bupt;//import com.bupt.MyRule.MyRule;import com.MyRule.MyRules;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.cloud.netflix.eureka.EnableEurekaClient;import org.springframework.cloud.netflix.ribbon.RibbonClient;@EnableEurekaClient@SpringBootApplication@RibbonClient(name = "SPRINGCLOUD-PROVIDER-DEPT", configuration = MyRules.class)public class DeptConsumer_80 { public static void main(String[] args) { SpringApplication.run(DeptConsumer_80.class,args); }}

然后重启80项目,访问springcloud-consumer-dept-feign

创建一个springcloud-consumer-dept-feign空maven的空项目,这也是一个消费者,端口也是80,只是这个消费者使用Feign实现的负载均衡

pom.xml

queryAll() ;}

然后在springcloud-consumer-dept-feign项目的controller也要做相应的修改

DeptConsumerController

package com.bupt.controller;import com.bupt.pojo.Dept;import com.bupt.service.DeptClientService;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.web.bind.annotation.*;import java.util.List;@RestControllerpublic class DeptConsumerController { @Autowired private DeptClientService deptClientService = null; @RequestMapping("/consumer/dept/get/{id}") public Dept queryById(@PathVariable("id") long id){ return this.deptClientService.getDept(id); } @RequestMapping("/consumer/dept/add") public boolean add(@RequestBody Dept dept){ return this.deptClientService.addDept(dept); } @RequestMapping("/consumer/dept/list") public List queryAll(){ return this.deptClientService.queryAll(); }}

最后还要在启动类上添加FeignClient注解

FeignDeptConsumer_80

package com.bupt;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.cloud.openfeign.EnableFeignClients;import org.springframework.cloud.openfeign.FeignClient;@SpringBootApplication@EnableFeignClients(basePackages = {"com.bupt"})public class FeignDeptConsumer_80 { public static void main(String[] args) { SpringApplication.run(FeignDeptConsumer_80.class,args); }}

最后启动7001、… 、8001、… 、feign的80项目,测试

作者:​​你的雷哥​​

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:自学鸿蒙应用开发(15)- ScrollView
下一篇:英特尔联合Datawhale,发布学习项目!
相关文章

 发表评论

暂时没有评论,来抢沙发吧~