微服务入门 | 项目分割 | 远程调度Feign | 用户中心erueka 和 nacos


认识微服务

微服务架构演变:

单体架构:所有功能集中在一个项目中开发,打成一个包部署

分布式架构:就是各功能模块的代码不在同一个项目中写了,到时候修改其中一个过能的代码,对另一个功能完全没有任何影响(如果在一个项目中,修改这个功能的代码,就得将所有功能代码给重新编译)

服务治理

问题:
服务拆分力度
服务集群地址如何维护
服务之间如何实现远程 调用
服务健康状态如何感知

微服务

良好架构设计的分布式架构方案,微服务架构特征
单一职责:功能单一
面向服务:对外暴露接口(让其他服务调用)
自治:团队独立,技术独立,数据独立,部署独立
隔离降级:服务做好隔离,容器,降级,避免出现级联问题

维护服务节点信息 – 注册中心
微服务配置的修改 – 配置中心
用户访问的微服务 – 服务网关
微服务间调用报错 – 服务保护

微服务入门案例

微服务技术.png

服务拆分与远程调用

服务拆分

拆分原则

这里我总结了微服务拆分时的几个原则:

  • 不同微服务,不要重复开发相同业务
  • 微服务数据独立,不要访问其它微服务的数据库
  • 微服务可以将自己的业务暴露为接口,供其它微服务调用

入门案例

  1. 创建父项目
  • 导入依赖:
<?xml version="1.0" encoding="UTF-8"?>
<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.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.3.12.RELEASE</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>com.zjh</groupId><artifactId>cloud-demo</artifactId><version>0.0.1-SNAPSHOT</version><name>cloud-demo</name><description>cloud-demo</description><!--父工程--><packaging>pom</packaging><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding><java.version>8</java.version></properties><dependencies><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency></dependencies><dependencyManagement><dependencies><!--  springCloud  --><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-dependencies</artifactId><version>Hoxton.SR10</version><type>pom</type><scope>import</scope></dependency><!--  mysql驱动  --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><scope>runtime</scope><version>8.0.15</version></dependency><!-- mybatis --><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.5.5</version></dependency></dependencies></dependencyManagement><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>

注意:
这里的环境是jdk8(建议大家和我一样)

  1. 创建子项目user-service
  • 导入依赖
<?xml version="1.0" encoding="UTF-8"?>
<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.0</modelVersion><parent><groupId>com.zjh</groupId><artifactId>cloud-demo</artifactId><version>0.0.1-SNAPSHOT</version></parent><groupId>com.zjh</groupId><artifactId>user-service</artifactId><version>0.0.1-SNAPSHOT</version><name>user-service</name><description>user-service</description><properties><java.version>8</java.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency><!--mybatis--><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>
  • 创建实体类,mapper,service,controller

image.png

  • 添加mybatis-plus包扫描配置
@SpringBootApplication
@MapperScan("com.zjh.userservice.mapper")
public class UserServiceApplication {public static void main(String[] args) {SpringApplication.run(UserServiceApplication.class, args);}}
  • yml配置设置
server:port: 8089
spring:application:name: userservicedatasource:url: jdbc:mysql://localhost:3306/cloud?useSSL=false&useUnicode=true&characterEncoding=utf8&serverTimezone=UTCusername: rootpassword: 888888driver-class-name: com.mysql.cj.jdbc.Driver
mybatis-plus:configuration:log-impl: org.apache.ibatis.logging.stdout.StdOutImplmap-underscore-to-camel-case: truetype-aliases-package: com.zjh.order.pojo
  1. 创建子项目order-service

和user-service一模一样,唯一的区别是,需要再order-service中添加user-service的依赖

<dependency><groupId>com.zjh</groupId><artifactId>user-service</artifactId><version>0.0.1-SNAPSHOT</version>
</dependency>

远程调度

远程调用就是在代码中访问到另一个项目的地址,这样就可以通过url来使用对方的方法,从而得到对方的信息
我们这里order中查询中的user属性直接查询时得不到的,需要通过访问user的信息,通过user-service中的getById()来得到,所以我们远程调度user-service项目

步骤:

  1. 在OrderServiceApplication中将RestTemplate添加到bean
@SpringBootApplication
@MapperScan("com.hwadee.order.mapper")
public class OrderServiceApplication {public static void main(String[] args) {SpringApplication.run(OrderServiceApplication.class, args);}@Beanpublic RestTemplate restTemplate() {return new RestTemplate();}
}
  1. 调用RestTemplate来实现远程调度
@Service
public class OrderService {@Autowiredprivate OrderMapper orderMapper;@Autowiredprivate RestTemplate restTemplate;public Order queryOrderById(Long orderId) {// 1.查询订单Order order = orderMapper.findById(orderId);// 2.利用RestTemplate发起http请求,查询用户// 2.1.url路径String url = "http://localhost:8081/user/" + order.getUserId();// 2.2.发送http请求,实现远程调用User user = restTemplate.getForObject(url, User.class);// 3.封装user到Orderorder.setUser(user);// 4.返回return order;}
}

支持请求:get,post,

存在问题:

  • order-service在发起远程调用的时候,该如何得知user-service实例的ip地址和端口?
  • 有多个user-service实例地址,order-service调用时该如何选择?
  • order-service如何得知某个user-service实例是否依然健康,是不是已经宕机?

我们接下来就使用用户中心来看一看这个问题

Eureka注册中心

介绍

eureka工作流程
eureka注册中心.png
调用者就是服务消费者,被调用的对象就是服务提供者。注册中心,就是我们将服务提供者的路径给存到注册中心中,当服务消费者每次调用对面的服务,就通过注册中心来访问对面的服务

使用步骤

创建注册中心项目

  1. 添加依赖spring-cloud-starter-netflix-eureka-server
<?xml version="1.0" encoding="UTF-8"?>
<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.0</modelVersion><parent><groupId>com.hwadee</groupId><artifactId>cloud-demo</artifactId><version>0.0.1-SNAPSHOT</version></parent><artifactId>eureka-server</artifactId><dependencies><!--eureka服务端--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-server</artifactId><version>2.2.10.RELEASE</version></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>
  1. 编写eureka启动类
@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {public static void main(String[] args) {SpringApplication.run(EurekaServerApplication.class, args);}
  1. 编写服务配置文件
server:port: 10086
spring:application:name: eureka-server
eureka:client:service-url:defaultZone: http://127.0.0.1:10086/eureka
  1. 启动服务

启动微服务,然后在浏览器访问:http://127.0.0.1:10086

注册服务

  1. 在user-service的pom文件中,引入下面的eureka-client依赖:
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-client</artifactId><version>2.2.10.RELEASE</version>
</dependency>
  1. 修改服务配置文件,向eureka注册服务,并添加名字
server:port: 8081spring:application: # 给服务起名字name: user-servicedatasource:url: jdbc:mysql://localhost:3306/hwadee?useSSL=false&useUnicode=true&characterEncoding=utf8&serverTimezone=UTCusername: rootpassword: rootdriver-class-name: com.mysql.cj.jdbc.Driver# 向eureka注册服务
eureka:client:service-url:defaultZone: http://127.0.0.1:10086/eurekamybatis-plus:configuration:log-impl: org.apache.ibatis.logging.stdout.StdOutImplmap-underscore-to-camel-case: truetype-aliases-package: com.hadee.user.pojo

使用

  1. 在order-service的pom文件中,引入下面的eureka-client依赖:
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-client</artifactId><version>2.2.10.RELEASE</version>
</dependency>
  1. 修改服务配置文件,向eureka注册服务,并添加名字
  2. 添加@LoadBalanced注解
  • @LoadBalanced,进行轮循(将同一个名字的服务进行轮询访问)
@Bean
@LoadBalanced
public RestTemplate restTemplate() {return new RestTemplate();
}
  1. 使用
public Order queryOrderById(Long orderId) {// 1.查询订单Order order = orderMapper.findById(orderId);// 2.利用RestTemplate发起http请求,查询用户// 2.1.url路径String url = "http://user-service/user/" + order.getUserId();// 2.2.发送http请求,实现远程调用User user = restTemplate.getForObject(url, User.class);// 3.封装user到Orderorder.setUser(user);// 4.返回return order;
}

Ribuu负载均衡

Nacos注册中心

nacos介绍和安装

  1. 安装
  2. 运行

打开安装的nacos文件夹,在bin文件上建立终端页,输入以下语句启动

sh startup.sh -m standalone
  1. 访问

nacos注册中心地址: http://127.0.0.1:8848/nacos/index.html#/login (账号密码都是nacos)
如果读取不到,可以尝试将nacos注册中心中的内容删除,然后重新运行项目

简单使用

  1. 引入依赖
<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-alibaba-dependencies</artifactId><version>2.2.5.RELEASE</version><type>pom</type><scope>import</scope>
</dependency>
<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
  1. 添加配置(user和order的.xml都需要)
spring:cloud:nacos:server-addr: 127.0.0.1:8848

Nacos配置管理

将配置放到nacos中

springboot启动加载配置文件顺序
bootstrap.yml
application.properties
application.yml

增加dev,创建开发环境

dev – namespace 开发环境
public – namespace 生产环境

远程调用OpenFeign

  1. 引入依赖
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId><version>2.2.10.RELEASE</version>
</dependency>
  1. 添加注解@EnableFeignClients
@SpringBootApplication
@MapperScan("com.zjh.orderservice.mapper")
@EnableFeignClients
public class OrderServiceApplication {public static void main(String[] args) {SpringApplication.run(OrderServiceApplication.class, args);}
}
  1. 编写Feign的接口类
@FeignClient("user-service")
public interface UserClient {@GetMapping("/user/{id}")User findById(@PathVariable("id") Long id);
}
  1. 使用
public Order queryOrderById(Long orderId) {// 1.查询订单Order order = orderMapper.findById(orderId);// 2.设置用户// 2.1 查询用户User user = userClient.findById(order.getUserId());// 2.2 设置userorder.setUser(user);// 3.返回return order;
}

和使用mapper类似,就是调用接口的方法

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/631470.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

循环异步调取接口使用数组promiseList保存,Promise.all(promiseList)获取不到数组内容,then()返回空数组

在使用 vue vant2.13.2 技术栈的项目中&#xff0c;因为上传文件的接口是单文件上传&#xff0c;当使用批量上传时&#xff0c;只能循环调取接口&#xff1b;然后有校验内容&#xff1a;需要所有文件上传成功后才能保存&#xff0c;在文件上传不成功时点击保存按钮&#xff0c…

非常有趣的AI应用-用大语言模型来玩星际争霸2(附代码链接)

非常有趣的AI应用-用大语言模型来玩星际争霸2&#xff08;附代码链接&#xff09; 偶然看到的&#xff0c;比较有意思&#xff0c;分享一下&#xff1a; GitHub地址&#xff1a;Large-Language-Models-play-StarCraftII arxiv&#xff1a;Large Language Models Play StarCra…

ChatGPT 报:“Unable to load history…”如何处理?

ChatGPT界面出现&#xff1a;“Unable to load history…” 说明&#xff1a;无法加载历史记录。。。 原因&#xff1a; 一般是代理的问题&#xff0c;网络加载延迟严重&#xff0c;也可能是官方请求过多&#xff0c;造成响应不及时。 解决&#xff1a; 出现这个问题时&#…

新三板操作指南!哪家证券公司开通新三板交易佣金费率最低?

新三板操作指南&#xff1a;掌握规则&#xff0c;赢得先机&#xff01; 随着中国资本市场的蓬勃发展&#xff0c;新三板市场日益成为投资者关注的焦点。然而&#xff0c;对于许多新手投资者来说&#xff0c;新三板市场的交易规则和流程可能较为陌生。本文将为您详细解读新三板…

移动端开发进阶之蓝牙通讯(一)

移动端开发进阶之蓝牙通讯&#xff08;一&#xff09; 移动端进阶之蓝牙通讯需要综合考虑蓝牙版本选择、协议栈使用、服务匹配、设备连接、安全性和硬件支持等方面。 一、蓝牙版本选择 根据实际需求和应用场景选择合适的蓝牙版本&#xff1b; 1.0&#xff0c;1M/s。 2.0EDR…

线程安全的集合类

Java中提供了许多集合类&#xff0c;其中有的是线程安全的&#xff0c;有的是线程不安全的。线程安全的集合类有&#xff1a; 1. Vector&#xff1a;Vector类实现了一个动态数组&#xff0c;与ArrayList相似&#xff0c;但Vector是同步访问的 2. Stack&#xff1a;Stack是Vec…

C++ 数论相关题目(约数)

1、试除法求约数 主要还是可以成对的求约数进行优化&#xff0c;不然会超时。 时间复杂度根号n #include <iostream> #include <vector> #include <algorithm>using namespace std;int n;vector<int> solve(int a) {vector<int> res;for(int i…

leetcode 每日一题 2024年01月18日 拿出最少数目的魔法豆

题目 给定一个 正整数 数组 beans &#xff0c;其中每个整数表示一个袋子里装的魔法豆的数目。 请你从每个袋子中 拿出 一些豆子&#xff08;也可以 不拿出&#xff09;&#xff0c;使得剩下的 非空 袋子中&#xff08;即 至少还有一颗 魔法豆的袋子&#xff09;魔法豆的数目 …

保证Kafka消息有序性

一、Kafka特性 写入同一个partion分区中的数据是一定有顺序的kafka中一个消费者消费一个partion的数据&#xff0c;消费者取出数据时&#xff0c;也是有顺序的 二、保证消息Kafka消息有序性 在生产者端&#xff0c;应保证消息被写入同一分区。可以在构造消息时指定消息的key…

如何将音频转文字?4个方法帮你轻松搞定!

如何将音频转文字&#xff1f;在日常生活中&#xff0c;将音频转换为文字的应用可以带来很多便利。例如&#xff0c;在会议、讲座、课堂等场合&#xff0c;我们可以使用识别软件将语音转换为文字&#xff0c;方便记录和整理。此外&#xff0c;在语言学习、语音翻译等领域&#…

基于springboot+vue的在线拍卖系统(前后端分离)

博主主页&#xff1a;猫头鹰源码 博主简介&#xff1a;Java领域优质创作者、CSDN博客专家、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战 主要内容&#xff1a;毕业设计(Javaweb项目|小程序等)、简历模板、学习资料、面试题库、技术咨询 文末联系获取 项目背景…

预处理详解(#和##运算符、命名约定、#undef​​、命令行定义​、条件编译、头文件的包含​)

目录 一、#和## 1.1#运算符 1.2## 运算符​ 二、命名约定​ 三、#undef​ 四、命令行定义​ 五、条件编译​ 六、头文件的包含​ 4.1 头文件被包含的方式&#xff1a;​ 4.1.1 本地文件包含​ Linux环境的标准头文件的路径&#xff1a;​ VS环境的标准头文件的路径&…

Vue3在点击菜单切换路由时,将ElementPlus UI库中el-main组件的内容滚动恢复到顶部

功能&#xff1a;Vue3在点击菜单切换路由时&#xff0c;将页面el-main的内容滚动到顶部&#xff0c;布局如下&#xff0c;使用UI组件库为ElementPlus 在网上搜很多都是在route.js中的router.beforeEach中使用window.scrollTop(0,0) 或 window.scrollTo(0,0) 滚动&#xff0c;但…

如何用GPT 运行python?GPT4科研应用与AI绘图及论文高效写作

详情点击链接&#xff1a;如何用GPT 运行python&#xff1f;GPT4科研应用与AI绘图及论文高效写作 一OpenAI 1.最新大模型GPT-4 Turbo 2.最新发布的高级数据分析&#xff0c;AI画图&#xff0c;图像识别&#xff0c;文档API 3.GPT Store 4.从0到1创建自己的GPT应用 5. 模型…

SpringBoot 统计API接口用时该使用过滤器还是拦截器?

统计请求的处理时间&#xff08;用时&#xff09;既可以使用 Servlet 过滤器&#xff08;Filter&#xff09;&#xff0c;也可以使用 Spring 拦截器&#xff08;Interceptor&#xff09;。两者都可以在请求处理前后插入自定义逻辑&#xff0c;从而实现对请求响应时间的统计。 …

【前端】vue.js从入门到项目实战笔记

文章目录 第三章3.1 插值绑定&#xff08;{{}}&#xff0c; v-html&#xff09;3.1.1 文本插值3.1.2 HTML插值 3.2 属性绑定 v-bind3.2.1 指令v-bind3.2.3 类名和样式绑定 【前端目录贴】 第三章 3.1 插值绑定&#xff08;{{}}&#xff0c; v-html&#xff09; 文本插值中的代…

vue3前端开发,感受一下组合式api和VUE2选项式的差异

vue3前端开发,感受一下组合式api和VUE2选项式的差异&#xff01;今天开始&#xff0c;正式开始&#xff0c;进入学习Vue3的内容。以后代码&#xff0c;案例分享&#xff0c;都会采用组合式api的模式为大家做展示。 今天是第一节&#xff0c;带大家感受一下&#xff0c;Vue3的组…

css-盒子等样式学习

盒子居中&#xff0c;继承外层盒子的宽高 兼容性&#xff08;border-box&#xff09;将边框收到盒子内部 初始化div 不用管box-setting content-box 还原 创建为一个类 &#xff0c;让所有需要还原的类 进行继承 padding 用法表示margin上下左右边距 body 外边距&…

线程和进程的区别(从JVM角度出发)

进程与线程的区别 线程具有许多传统进程所具有的特征&#xff0c;故又称为轻型进程(Light—Weight Process)或进程元&#xff1b;而把传统的进程称为重型进程(Heavy—Weight Process)&#xff0c;它相当于只有一个线程的任务。在引入了线程的操作系统中&#xff0c;通常一个进…

linux-nfc neard 编译、安装与运行

项目github地址&#xff1a; https://github.com/linux-nfc/neard git clone地址&#xff1a; https://github.com/linux-nfc/neard.git 1.安装依赖库 clone完源码切换到目录neard里。这个项目需要依赖一下库&#xff1a; - GCC compiler - D-Bus library - GLib library …