初识微服务
微服务体系结构风格是一种将单个应用程序开发为一套小型服务的方法,每个服务都在各自的进程中运行,并且与轻量级(通常是HTTP资源API)通信。当然这些服务都是围绕业务能力来构建的,可通过完全自动化的部署机制独立部署,这些服务的集中管理器是最低限度的,可以用不同的编程语言编写,并且使用不同的数据存储技术,我想下面这个图可以让大家更好的立即一下何为微服务
简单解释一下,这就是将一个完全成熟的应用程序在疯狂解耦的情况下,使之真正的一个模块做一种业务,而不是全部堆积在一起,这样,如果某个模块出现错误,进行调试时,也会因为耦合度过高的原因而导致过于麻烦,进行微服务架构之后的项目可以做到耦合度低,极大的方便了我们对于代码的管控以及调试。
说到微服务,就不得不说到我们今天的主角了,那就是SpringCloud了,那么什么时SpringCloud呢,这是一个微服务架构的落地技术栈,其中大概包含了三十多个技术(大家能体会到微服务的强大了嘛!!)那么就先说说我们的第一个技术啦:
Eureka:
Eureka的主要操作就是服务的注册与发现,这个技术解决了,服务之间调用时,调用方需要记录提供方的地址信息,从而造成耦合过高的问题了,Eureka的解决方式也很简单,既然调用方和提供方之间非得互相交互,那我就给你们一个中间件,调用方需要什么就来中间件自己找,提供方把信息直接传到中间件,避免了,二者的耦合性,大概就是这么一个图:
大概解释一下,服务调用方需要地址信息从而通知服务提供方,但是地址信息已经被服务提供方上传到了我们的中间件也就是Eureka,那么第一步之间的直接交互也就避免了,也就意味着效率提供了一丢丢,当调用方获得地址后就会对提供发发送请求,再加上这之间是异步的,所以提供发收到请求,进行操作后将数据上传到Eureka,调用方便可从中间件获得所需信息,因为有了中间件,二者的直接联系被大大减少了,也就意味了,不会发生调用方死等提供方消息而发生效率低下的问题了。
实际操作
理论大概就是这样了,那么接下来就是实战啦!!更方便大家的理解
首先我们的Eureka是部署在微服务架构上的产物,则第一步就是导入依赖啦,首先创建SpingCloud项目,而SpringCloud又是已SpringBoot为基础的,所以我们的依赖就变成这样啦:
父依赖:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.6.RELEASE</version>
<relativePath />
</parent>
项目的本身依赖
然后就是我们的jdk1.8的依赖啦,当然推荐大家还是导入的,毕竟有些错误出现可是很不好解决的啦
<properties>
<java.version>1.8</java.version>
</properties>
接下来就是SpringBoot的人上人SpringCloud了,维护了SpringCloud版本,就是Greenwich.SR6
<properties>
<spring.coud-version>
Greenwich.SR6
<spring.coud-version>
</properties>
接下来就是维护版本了,大可不用记毕竟外面文档一大推滴
<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>
插件千万别忘了
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
完成上面所有的步骤之后我们的微服务架构就可以说完成一大部分了,接下来创建中间件EurekaServer,在pom.xml中导入新的依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
接下来就到了编写配置文件的步骤
# Eureka默认是集群配置,单机版的Eureka,集群需要Eureka之间相互通讯
eureka:
client:
fetch-registry: false # 将集群版配置为单机版,是否拉取其他服务(EurekaServer)信息
register-with-eureka: false # 将集群版配置为单机版,是否注册到其他服务(EurekaServer)上
service-url:
defaultZone: http://localhost:8761/eureka/ # 针对EurekaServer节点来说,一般是集群配置时,找其他的EurekaServer
# 端口号
server:
port: 8761
接下来就是SpringBoot的启动类了,但是这次不单单是一个@SpringBootApplication了,还多了一个Eureka的专属注解@EnableEurekaServer,
当然在配置文件里有个坑,就是我们的defaulZone的路径了,这个路径的默认就是这个,所以我们项目的端口号也得跟着改,但是这样也不麻烦,所以大家就不要整花活了哈哈
接下来正常测试,访问我们的路径 http://localhost:8761/ 这样就可正常访问SpringErueka的官网了
那么既然是微服务我们当然拆解代码,避免耦合了,首先创建一个服务提供者我们就叫做 eureka-search 首先就是导入依赖了,在步骤这方面不必犹豫也不可犹豫,第一步永远是先导依赖了,当然这些依赖就是官方文档的,你要问我记住了嘛,那答案肯定是记不住啦,不过呀,忘记了轮子理论了嘛哈哈!!
<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-web</artifactId>
</dependency>
第二步,那就是编写配置文件了,
# 是eurekaClient,需要拉取eureka信息,注册到eureka上,配置eureka-server的地址
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka/
# 服务名
spring:
application:
name: search
#给这个服务提供者分配个端口
server:
port: 9200
第三步,那就是创建启动类了
顺便给我们的search写一个方法
@RestController
public class SearchController(){
@PostMapping("/search/test")
pubic void test(){
return "search被调用了"
}
}
当然这个也就是两个注解的事情了。接下来启动,我们就可以去看效果啦。
我们的服务提供者有了,怎么能没有服务调用者呢,接下来我们创建 eureka-core 操作和上面一模一样,第一步导入依赖,第二部编写配置文件,第三步创建启动类。
接下来就到重头戏了,我们有了调用者和提供者,那么他们到底是怎么用的呢?
@RestController
public class CoreController {
#这都是到了,依赖和springBoot自带的了
@Autowired
private RestTemplate restTemplate;
@Resource
private EurekaClient eurekaClient;
@GetMapping("/core/test")
public String test(){
// 通过Eureka获取SEARCH服务的ip和端口
InstanceInfo searchInfo = eurekaClient.getNextServerFromEureka("search", false);
String ip = searchInfo.getIPAddr();
int port = searchInfo.getPort();
// 调用search服务中的接口,/search/test
String result = restTemplate.getForObject("http://"+ip+":"+port+"/search/test", String.class);
return result;
}
}
Erueka的安全性
我们不能光会使用,还得了解深层滴,那么我们就来聊聊Erueka的安全性
我们上面说过,server保存了search的地址信息,那是不是就是说任何人都可以来获取这个地址信息呀,那这样不就不安全了么,所以,我们就需要设置一个用户名和密码了,那么该怎么做呢,其实我们的文档什么都告诉我们了,首先导入依赖,当然是在我们的server哦
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
接下来,除了启动类就需要添加配置类了(@EnableWebSecurity)
@EnableWebSecurity
class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
#这步就是告诉我们的系统erueka的路径不做csrf操作
http.csrf().ignoringAntMatchers("/eureka/**");
super.configure(http);
}
}
在下一步就是配置文件
# 设置username,password
spring:
security:
user:
name: admin
password: admin
好了,我们现在有了用户名和密码了,那么我们配置文件中的路径也得需要了呀,否则谁都进不去,这不是完蛋了嘛,
eureka:
client:
service-url:
defaultZone: http://用户名:密码@localhost:8761/eureka
自我保护机制
接下来我们来聊赖Eureka的自我保护机制,当然我们为什么聊到自我保护机制呢,如果小伙伴们上述操作都没问题的话,进入到Eureka的界面中,屏幕中会出现一句长长的红色字体,当然,这是没有任何影响的,这只是纯粹的为了吓唬你,哈哈,开玩笑的啦,这就是Erueka的自我保护机制了,那么为什么会出现这个呢,是因为,Erueka的自我保护机制是默认开启的,我们的server注册成功后,会每隔一段时间发送一次心跳,也就是http请求,Erueka在接收时,如果在15分钟内,心跳超过了85%,那么就会默认认为,自己的系统出问题了,就会开启,默认保护注册到server上的cliert
在此期间:
1.不会删除任何注册在server上的client
2. 会正常的提供服务,就算是错误的
当心跳回复正常之后,就会赶紧去找其他的服务节点是同步数据,同时也说出了,Erueka是可以部署集群的,那么我们就来聊聊
Erueka的集群
那么第一步就是为什么要部署集群呢?
当然是为了避免单点故障了,说到单点故障,大家也可以去看看redis的集群哦,大同小异的,就是部署多台Erueka,而且,他们之间应该互相通信,和redis不同的是Erueka的集群中节点不存在主从。
那么如何创建呢,那就是创建多个server,在配置文件中多分配几个服务名就好啦
eureka:
client:
#切记要把flase改为true不然就还是单机的啦
register-with-eureka: true # 在集群模式下代表注册到其他的Eureka上
fetch-registry: true # 拉取其他eureka上的注册列表信息
service-url:
defaultZone: http://host:port/eureka,http://host:port/eureka,http://host:port/eureka...
spring:
application:
name: 服务名
我们来说说Erueka的其他细节
第一个:Erueka的心跳
eureka:
instance:
lease-renewal-interval-in-seconds: 30 # 默认心跳间隔30s
第二个:EruekaServer什么时候会认为EruekaClient宕机
eureka:
instance:
lease-expiration-duration-in-seconds: 90 # 认定宕机时间为90s
第三个:EruekaClient更新注册表的时间
eureka:
client:
registry-fetch-interval-seconds: 30 # 没30s拉取一次最新的注册表信息
第四个:cap(大家可以着重的看一看这一块)
CAP定理:
C:Consistency 一致性
A: Availability 可用性
P:Partition tolerance 分区容错性
这三者,分区容错性没有选择行,必须保证,接下来就是在一致性和可用性之间权衡了,是保障效率还是稳定就看具体情况了