1.项目架构的发展过程
1.1. 单一应用架构(单体架构)
- 当网站流量很小时,只需一个应用,将所有功能都部署在一起,以减少部署节点和成本。此 时,用于简化增删改查工作量的数据访问框架(ORM)是关键。
- 适用于小型网站,小型管理系统,将所有功能都部署到一个功能里,简单易用。
- 缺点:1、性能扩展比较难 2、协同开发问题 3、不利于升级维护
1.2. 垂直应用架构
- 当访问量逐渐增大,单一应用增加机器带来的加速度越来越小,将应用拆成互不相干的几个 应用,以提升效率。此时,用于加速前端页面开发的Web框架(MVC)是关键。
- 通过切分业务来实现各个模块独立部署,降低了维护和部署的难度,团队各司其职更易管 理,性能扩展也更方便,更有针对性。
- 缺点:公用模块无法重复利用,开发性的浪费
1.3. 分布式服务架构
- 当垂直应用越来越多,应用之间交互不可避免,将核心业务抽取出来,作为独立的服务,逐渐形成稳定的服务中心,使前端应用能更快速的响应多变的市场需求。此时,用于提高业务 复用及整合的分布式服务框架是关键。
1.4. 流动计算架构(SOA架构)
- 当服务越来越多,容量的评估,小服务资源的浪费等问题逐渐显现,此时需增加一个调度中 心基于访问压力实时管理集群容量,提高集群利用率。此时,用于提高机器利用率的资源调 度和治理中心(SOA)[ Service Oriented Architecture]是关键。
1.5. 微服务架构
2. 微服务架构的特点
-
单一职责:微服务架构中每一个服务(模块项目)都对应唯一的业务能力,做到单一职责
-
微:微服务的服务拆分粒度很小,例如一个用户管理就可以作为一个服务。每个服务虽小, 但“五脏俱全”。
-
面向服务:面向服务是说每个服务都要对外暴露Restful风格服务接口API。并不关心服务的 技术实现,做到与平台和语言无关,也不限定用什么技术实现,只要提供Restful的接口即可。
-
自治:自治是说服务间互相独立,互不干扰
-
团队独立:每个服务都是一个独立的开发团队,人数不能过多。
-
技术独立:因为是面向服务,提供Restfule接口,使用什么技术没有别人干涉
-
前后端分离:采用前后端分离开发,提供统一Rest接口,后端不用再为PC、移动段开发不同接口
-
数据库分离:每个服务都使用自己的数据源
-
部署独立,服务间虽然有调用,但要做到服务重启不影响其它服务。有利于持续集成和 持续交付。每个服务都是独立的组件,可复用,可替换,降低耦合,易维护
-
3. 服务的调用方式
- RPC:Remote Produce Call远程过程调用,类似的还有RMI。自定义数据格式,基于原生 TCP通信,速度快,效率高。早期的webservice,现在热门的dubbo,都是RPC的典型代表
- Http:http其实是一种网络传输协议,基于TCP,规定了数据传输的格式。现在客户端浏览 器与服务端通信基本都是采用Http协议,也可以用来进行远程服务调用。缺点是消息封装臃 肿,优势是对服务的提供和调用方没有任何技术限定,自由灵活,更符合微服务理念。
- 如果你们公司全部采用Java技术栈,那么使用Dubbo作为微服务架构是一个不错的选择。
- 如果公司的技术栈多样化,而且你更青睐Spring家族,那么SpringCloud搭建微服务是不二之选。在我们的项目中,我们会选择SpringCloud套件,因此我们会使用Http方式来实现服务间调用。
4. Http客户端工具
4.1. http客户端工具有哪些
- HttpClient
- OKHttp
- URLConnection
4.2. 使用httpclient客户端测试百度
- 引入相关jar
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
</dependency>
2.编写客户端代码
public class HttpClientTest {
public static void main(String[] args) throws IOException {
//获取HttpClient客户端
CloseableHttpClient httpClient = HttpClientBuilder.create().build();
//创建Get请求
HttpGet httpGet = new HttpGet("http://www.baidu.com");
//由客户端发送get请求
CloseableHttpResponse httpResponse = httpClient.execute(httpGet);
System.out.println("响应状态码:" + httpResponse.getStatusLine());
//获取响应结果
HttpEntity entity = httpResponse.getEntity();
String s = EntityUtils.toString(entity);
System.out.println("内容为:" + s);
}
}
4.3. 使用http客户端测试相应实体类
1.创建Springboot项目springcloud-httptest-entity,引入依赖,application.yml配置文件中 配置tomcat端口
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
server:
port: 8081
2.创建实体类
package com.example.entiy;
import java.io.Serializable;
public class User implements Serializable {
private Integer id;
private String name;
public User() {
}
public User(Integer id, String name) {
this.id = id;
this.name = name;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "User{" +
"id=" + id + ", name='" + name + '\'' +
'}';
}
}
3.编写controller类
@RestController
public class UserController {
@RequestMapping("/findUser")
public User findUser() {
return new User(1, "张三");
}
}
4.在另一个Springboot项目springcloud-httptest中,引入相关依赖
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.58</version>
</dependency>
5.在另一个Springboot项目springcloud-httptest中,创建实体类
package com.example.entiy;
import java.io.Serializable;
public class User implements Serializable {
private Integer id;
private String name;
public User() {
}
public User(Integer id, String name) {
this.id = id;
this.name = name;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "User{" +
"id=" + id + ", name='" + name + '\'' +
'}';
}
}
6.在另一个Springboot项目springcloud-httptest中,编写测试Controller
@RestController
public class UserController {
@RequestMapping("/findUser")
public User findUser() throws IOException {
CloseableHttpClient httpClient = HttpClientBuilder.create().build();
HttpGet httpGet = new HttpGet("http://127.0.0.1:8081/findUser");
CloseableHttpResponse response = httpClient.execute(httpGet);
System.out.println("状态码" + response.getStatusLine());
HttpEntity entity = response.getEntity();
String s = EntityUtils.toString(entity, "UTF-8");
User user = JSONObject.parseObject(s, User.class);
return user;
}
}
4.4. springboot默认整合http客户端工具
Spring提供了一个RestTemplate模板工具类,对基于Http的客户端进行了封装,并且实现了对象与json的序列化和反序列化,非常方便。RestTemplate并没有限定Http的客户端类 型,而是进行了抽象,目前常用的3种都有支持
1.在springcloud-httptest项目中,使用RestTemplate访问百度
@Configuration
public class MyConfiguration {
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
@RestController
public class RestTemplateController {
@Autowired
private RestTemplate restTemplate;
@RequestMapping("/pingBD")
public String pingBaidu() {
String message = restTemplate.getForObject("http://www.baidu.com", String.class);
System.out.println(message);
return message;
}
}
2.在springcloud-httptest中,使用RestTemplate测试实体类
@RequestMapping("/restGetUser")
public User getUser(){
User user = restTemplate.getForObject("http://127.0.0.1:8081/findUser", User.class);
return user;
}
4.5. 问题?
- 在consumer中,我们把url地址硬编码到了代码中,不方便后期维护
- consumer需要记忆provider的地址,如果出现变更,可能得不到通知,地址将失效
- consumer不清楚provider的状态,服务宕机也不知道
- provider只有1台服务,不具备高可用性
- 即便provider形成集群,consumer还需自己实现负载均衡
5. SpringCloud
5.1. 初识SpringCloud
微服务是一种架构方式,最终肯定需要技术架构去实施。
微服务的实现方式很多,但是最火的莫过于Spring Cloud了。为什么?
- 后台硬:作为Spring家族的一员,有整个Spring全家桶靠山,背景十分强大。
- 技术强:Spring作为Java领域的前辈,可以说是功力深厚。有强力的技术团队支撑,一般人还真比不了
- 群众基础好:可以说大多数程序员的成长都伴随着Spring框架,试问:现在有几家公司开发 不用Spring?SpringCloud与Spring的各个框架无缝整合,对大家来说一切都是熟悉的配方,熟悉的味道。
- 使用方便:相信大家都体会到了SpringBoot给我们开发带来的便利,而SpringCloud完全支持SpringBoot的开发,用很少的配置就能完成微服务框架的搭建
5.2. SpringCloud的简介
5.2. SpringCloud的简介
- SpringCloud是Spring旗下的项目之一,官网地址:http://projects.spring.io/spring-cloud/
- Spring最擅长的就是集成,把世界上最好的框架拿过来,集成到自己的项目中。
- SpringCloud也是一样,它将现在非常流行的一些技术整合到一起,实现了诸如:配置管 理,服务发现,智能路由,负载均衡,熔断器,控制总线,集群状态等等功能。
5.2.2. SpringCloud相关组件(框架)
- Eureka:服务治理组件,包含服务注册中心,服务注册与发现机制的实现。(服务治理, 服务注册/发现) ,类似的产品还有Consul、Nacos
- Zuul:网关组件,提供智能路由,访问过滤功能 ,类似产品还有Spring Cloud GateWay Ribbon:客户端负载均衡的服务调用组件(客户端负载均衡)
- Feign:服务调用,给予Ribbon和Hystrix的声明式服务调用组件 (声明式服务调用) (发 送Http请求访问)
- Hystrix:容错管理组件,实现断路器模式,帮助服务依赖中出现的延迟和故障提供强大的 容错能力。(熔断、断路器,容错)
5.3. SpringCloud微服务场景模拟
5.3.1. 创建Eureka注册中心工程
1.引入相关依赖
注意:spring-cloud的2020.0.2版本,需要springboot的2.4.4版本支持。
<properties>
<java.version>1.8</java.version>
<spring-cloud.version>2021.0.7</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<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>
2.配置yml文件
#tomcat端口
server:
port: 8081
#设置项目的名称
spring:
application:
name: eureka-server # 名称会在eureka注册中心中体现
#设置eureka相关的配置
eureka:
client:
service-url:
# 单个eureka使用时,表示eureka注册中心访问地址,表示将来客户端使用该地址和eureka注册中心进行通信
# 多个eureka集群时,写成其他eureka注册中心的地址,表示当前eureka注册中心要连接其他eureka注册中心。
defaultZone: http://127.0.0.1:8081/eureka # http://eureka注册中心访问地址:端口/eureka
# 是否将自己的路径注册到eureka注册中心上。
# 单个eureka注册中心使用时配置为false,表示自己作为注册中心,自己不注册自己;
# 多个eureka注册中心集群时配置为true,表示当前的eureka注册中心需要将自己的地方注册到其他eureka注册中心中
register-with-eureka: false # 默认值为true
# 是否需要从当前eureka注册中心中抓取其他eureka注册中心地址。
# 单个eureka注册中心使用时配置为false,不需要从自己这抓取路径。
# 多个eureka注册中心集群时配置为true,可用从自己这抓取其他eureka注册中心的路径
fetch-registry: false #默认值为true
3.引导类中配置@EnableEurekaServer
@SpringBootApplication
@EnableEurekaServer //开启eureka服务
public class SpringcloudDay01EurekaApplication {
public static void main(String[] args) {
SpringApplication.run(SpringcloudDay01EurekaApplication.class, args);
}
}
4.启动测试
5.3.2. 创建服务提供方工程
1.引入相关依赖
<properties>
<java.version>1.8</java.version>
<spring-cloud.version>2021.0.7</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 引入eureka-client起步依赖,此依赖需要spring-boot-starter-web依赖
辅助 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
<version>3.1.1</version>
</dependency>
</dependencies>
<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>
2.编写配置文件
server:
port: 8082
spring:
application:
name: eureka-provider
eureka:
client:
service-url:
defaultZone: http://127.0.0.1:8081/eureka
3.编写controller
@RestController
public class TestController {
@RequestMapping("/test")
public String test() {
return "Hello Eureka Consumer";
}
}
4.给启动类添加注解
@SpringBootApplication
@EnableEurekaClient //开启eureka客户端操作
public class SpringcloudDay01ProviderApplication {
public static void main(String[] args) {
SpringApplication.run(SpringcloudDay01ProviderApplication.class, args);
}
}
5.启动之后,会在eureka注册中心中看到注册的信息
5.3.3. 创建服务消费方工程
1.引入相关依赖
<properties>
<java.version>1.8</java.version>
<spring-cloud.version>2021.0.7</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<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>
2.编写配置文件
server:
port: 8083
spring:
application:
name: eureka-consumer
eureka:
client:
service-url:
defaultZone: http://127.0.0.1:8081/eureka
3.编写Config配置类
@Configuration
public class MyConfiguration {
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
4.编写Controller测试类
@RestController
public class TestController {
@Autowired
private RestTemplate restTemplate;
@Autowired
private DiscoveryClient discoveryClient;
@RequestMapping("/test")
public String test() {
List<ServiceInstance> instances = discoveryClient.getInstances("EUREKA-PROVIDER");//参数:服务提供方在eureka中的名称
ServiceInstance serviceInstance = instances.get(0);
String host = serviceInstance.getHost(); //获取服务提供方主机地址
int port = serviceInstance.getPort();//获取服务提供方端口
String url = "http://" + host + ":" + port + "/test"; //拼接服务提供方访问路径
String s = restTemplate.getForObject(url, String.class);//访问服务提供方接口。
return s;
}
}
5.给启动类添加注解
@SpringBootApplication
@EnableEurekaClient //开启eureka客户端操作
@EnableDiscoveryClient //开启discoveryclient支持
public class SpringcloudDay01ConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(SpringcloudDay01ConsumerApplication.class, args);
}
}
5.4. Eureka配置文件配置解释
-
eureka-server配置
- eureka.client.register-with-eureka 是否注册到eureka服务中
- fetch-registry 是否拉取其他的服务
- enable-self-preservation false # 关闭自我保护模式(缺省为打开)
- eviction-interval-timer-in-ms: 1000 # 扫描失效服务的间隔时间(缺省为 60*1000ms)
-
eureka-client配置
- lease-renewal-interval-in-seconds:服务续约(renew)的间隔,默认为30秒
- lease-expiration-duration-in-seconds:服务失效时间,默认值90秒
6. Nacos注册中心
6.1. Nacos概述
- Nacos(Dynamic Naming and Configuration Service) 是阿里巴巴2018年7月开源的项目。
- 它专注于服务发现和配置管理领域 致力于帮助您发现、配置和管理微服务。 Nacos 支持几乎所有主流类型的“服务”的发现、配置和管理。
- 一句话概括就是Nacos = Spring Cloud注册中心 + Spring Cloud配置中心。
- 官网: https://nacos.io/
6.2. Nacos下载、安装、运行、访问管理界面
下载
下载地址: https://github.com/alibaba/nacos/releases
安装
Nacos是绿色版免安装的,直接解压出来就可以使用。
运行
nacos高版本默认是按照集群方式启动的,如果要单机启动通过cmd命令提示窗口输入指令
startup.cmd -m standalone
访问控制台
浏览器输入地址:http://localhost:8848/nacos,即可打开Nacos控制台,第一次登陆需要输入 用户名(nacos)和密码(nacos)。
6.3. Nacos入门案例
6.3.1. 构建服务提供者
1.创建springboot项目,名称为springcloud-day01-nacosprovider
2.在项目的pom.xml文件中引入起步依赖
<properties>
<java.version>8</java.version>
<!--spring cloud 版本-->
<spring-cloud.version>2021.0.7</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--nacos起步依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
<version>0.2.2.RELEASE</version>
</dependency>
<dependency>
<groupId>com.alibaba.nacos</groupId>
<artifactId>nacos-client</artifactId>
<version>2.2.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<!--引入Spring Cloud 依赖-->
<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>
3.在application.yml中配置nacos连接
server:
port: 8081
spring:
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
application:
name: nacos-provider
4.创建controller,作为consumer服务消费者调用
@RestController
public class ProviderController {
@RequestMapping("/provider")
public String provider() {
return "Hello Nacos Consumer";
}
}
6.3.2. 构建服务消费者
1.创建springboot项目,名称为springcloud-day01-nacosconsumer
2.在项目的pom.xml文件中引入起步依赖
<properties>
<java.version>8</java.version>
<!--spring cloud 版本-->
<spring-cloud.version>2021.0.7</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--nacos起步依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
<version>0.2.2.RELEASE</version>
</dependency>
<dependency>
<groupId>com.alibaba.nacos</groupId>
<artifactId>nacos-client</artifactId>
<version>2.2.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<!--引入Spring Cloud 依赖-->
<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>
3.在application.yml中配置nacos连接
server:
port: 8082
spring:
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
application:
name: nacos-consumer
4.在引导类中配置注解
@EnableDiscoveryClient
@SpringBootApplication
public class SpringcloudDay01NacosConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(SpringcloudDay01NacosConsumerApplication.class, args);
}
}
5.创建RestTemplate配置类
@Configuration
public class RestTemplateConfig {
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
6.创建Controller调用服务提供方的Controller
@RestController
public class ConsumerController {
@Autowired
private RestTemplate restTemplate;
@Autowired
private DiscoveryClient discoveryClient;
@RequestMapping("/consumer")
public String consumer() {
//演示discoveryClient 使用
List<ServiceInstance> instances =
discoveryClient.getInstances("nacos-provider");
//判断集合是否有数据
if (instances == null || instances.size() == 0) {
//集合没有数据
return null;
}
ServiceInstance instance = instances.get(0);
String host = instance.getHost();//获取ip
int port = instance.getPort();//获取端口
System.out.println(host);
System.out.println(port);
String url = "http://" + host + ":" + port + "/provider";
// 3. 调用方法
String str = restTemplate.getForObject(url, String.class);
return str;
}
}
7.运行测试
标签:服务,String,spring,eureka,cloud,public,SpringCloud01 From: https://www.cnblogs.com/jiabaolatiao/p/17506775.html