实战前先做一个背景了解。
单体架构:近几年技术的飞速发展,各种各样的服务已经进入到网络化。单体架构发布时只需要打成一个war或jar包发布即可;而随着业务量激增或网站流量的增加,必会暴露致命缺陷。
SOA:Service Oriented Architecture 面向服务的体系结构。旨在提升代码复用性及扩展性,降低耦合等。 如一个外卖流程,分配送餐是一个服务,短信通知也是一个服务。这些服务独立部署,通过网络互相调用(HTTP等方式),形成完整的服务系统。
微服务:微服务是由多个功能单一的小服务组成的,服务可以根据业务进行拆分;这些服务独立部署;不同的服务可以采用不同的技术(不同的变成语言或数据库等);服务之间采用HTTP等轻量协议进行交互传输数据,可看成是更细粒度的SOA架构。
优点:
代码复杂度低
:根据业务细粒度划分,业务功能明确清晰,体积小,便于理解和维护独立部署
:部署的影响范围小错误隔离
:多服务中,一个服务的宕机不会影响整个系统的运行缺点:
数据一致性问题:典型的分布式事务的问题
那为了更好的管理微服务,SpringCloud技术诞生了。常用技术栈实现:
技术栈 | 技术栈落地实现 |
---|---|
服务注册和发现 | Eureka、Zookeeper、Consul、Nacos |
熔断、降级、限流 | Hystrix、Sentinel |
服务调用 | Ribbon、LoadBalancer、Feign、OpenFeign、Dubbo |
配置 | Config、Zookeeper、Consul、Nacos |
网关 | Zuul、Gateway |
消息总线 | Bus、Nacos |
以上的技术实现方案有SpringCloudNetflix的也有SpringCloudAlibaba的。此系列我们只使用Alibaba的。
以下技术栈:
在实战前先确保我们的开发环境:
注意:IDEA中如果和Maven的版本不匹配会报错,Unable to import maven project,自己调整下版本吧
在创建一个项目时,首先要注意的就是和SpringCloud和Alibaba的版本是否兼容,看一下SpringBoot和cloud的版本兼容
到spring官网或者阿里云的网页创建项目都可以。先创建一个项目导入到IDEA中吧
导入后将SpringBoot版本改为2.6.11的即可
然后再创建子module(服务者和消费者),在父工程主要做版本依赖管理:
<properties>
<java.version>8java.version>
<boot.version>2.6.11boot.version>
<cloud.version>2021.0.4cloud.version>
<cloud.alibaba.version>2021.0.4.0cloud.alibaba.version>
properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-dependenciesartifactId>
<version>${boot.version}version>
<type>pomtype>
<scope>importscope>
dependency>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-dependenciesartifactId>
<version>${cloud.version}version>
<type>pomtype>
<scope>importscope>
dependency>
<dependency>
<groupId>com.alibaba.cloudgroupId>
<artifactId>spring-cloud-alibaba-dependenciesartifactId>
<version>${cloud.alibaba.version}version>
<type>pomtype>
<scope>importscope>
dependency>
dependencies>
dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.pluginsgroupId>
<artifactId>maven-compiler-pluginartifactId>
<version>3.7.0version>
<configuration>
<source>1.8source>
<target>1.8target>
<encoding>UTF-8encoding>
configuration>
plugin>
plugins>
build>
注意:nacos需要依赖jdk环境,必须是1.8及以上的版本
nacos的下载页面:https://github.com/alibaba/nacos/releases
瞅好对应的版本关系下载即可。
下载完毕后,cmd命令窗口启动即可。
注:如果下载的时2.2.1及以上版本的,nacos把默认的密钥给设置为空了,需要我们手动给添加上,然后在启动
在nacos的配置文件application.properties中
nacos.core.auth.plugin.nacos.token.secret.key=SecretKey012345678901234567890123456789012345678901234567890123456789
启动nacos
startup.cmd -m standalone
启动完成后,登录nacos的网址看下http://localhost:8848/nacos,默认的用户名和密码都是nacos。
创建三个子工程,分别是provider8001
、provicer-8002
和consumer9001
,然后注册进入nacos后,通过Ribbon实现远程调用。
工程结构如图,3个工程都引入健康监控和nacos的服务注册发现
以consumer项目为例的配置文件
server:
port: 8001
spring:
application:
name: provider # 应用名
cloud:
nacos:
discovery:
server-addr: localhost:8848 # nacos服务地址
图例:
启动类及注解:
@SpringBootApplication
@EnableDiscoveryClient
public class ProviderApplication {
public static void main(String[] args) {
SpringApplication.run(ProviderApplication.class, args);
}
}
服务已经注册,且provider的实例是两个,莫得问题~
采用RestTemplate+Ribbon实现简单远程调用
服务提供者提供接口(两个提供者都写上)
@RestController // @RestController注解是@Controller+@ResponseBody
public class TestController {
@Value("${server.port}")
private String port; // 获取配置文件中写的程序端口号
@RequestMapping("/test") // 标记是该方法的请求
public String test() {
return "hello world test " + port; // 返回值是一个字符串,因为用了@RestController所以不必额外加@ResponseBody了
}
}
消费者还需要引入loadbalancer的依赖,高版本中需要自己手动引入
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-loadbalancerartifactId>
dependency>
服务消费者采用JavaConfig的方式将配置类做好,代码如下:
@Configuration
public class GenericConfiguration { // 常规配置类
@LoadBalanced // 标注此注解后,RestTemplate就具有了客户端负载均衡能力
@Bean
public RestTemplate restTemplate(){ // 创建RestTemplate,并交个Spring容器管理
return new RestTemplate();
}
}
消费者调用接口
@RestController
public class TestController {
private final String SERVER_URL = "http://provider"; // 这里的服务地址填写注册到Nacos的应用名称
@Resource
private RestTemplate restTemplate;
@RequestMapping("/test") // 标记是该方法的请求
public String test() {
return restTemplate.getForObject(SERVER_URL + "/test", String.class);//调用提供者/test接口
}
}
启动项目测试调用执行:
curl localhost:9001/test
可看到远程调用以及简单的负载实现效果。