欢迎您访问365答案网,请分享给你的朋友!
生活常识 学习资料

一.搭建简单的微服务工程

时间:2023-06-14
一、搭建简单的微服务工程 1、从单体架构到微服务架构的演变

我们最先接触的单体架构,整个系统就只有一个工程,打包往往是打成了 war 包,然后部署 到单一 tomcat 上面,这种就是单体架构,如图:

单体架构优点

1、结构简单,部署简单

2、所需的硬件资源少

3、节省成本

缺点

1、版本迭代慢,往往改动一个代码会影响全局

2、不能满足一定并发的访问

3、代码维护困难,所有代码在一个工程里面,存在被其他人修改的风险

随着业务的拓展,公司的发展,单体架构慢慢的不能满足我们的需求,我们需要对架构进行 变动,我们能够想到的最简单的办法就是加机器,对应用横向扩展。 如图:

这种架构貌似暂时解决了我们的问题,但是用户量慢慢增加后,我们只能通过横向加机器来解决,还是会存在版本迭代慢,代码维护困难的问题。而且用户请求往往是读多写少的情况, 所以可能真正需要扩容的只是业务量大的模块而已,而现在是整个工程都扩容了,这无形中是一种资源的浪费,因为其他模块可能根本不需要扩容就可以满足需求。所以我们有必要对整个工 程按照模块进行拆分,拆分后的架构图如下:

模块拆分后,模块和模块之间是需要通过接口调用的方式进行通信,模块和模块之间通过分流软件进行负载均衡。这个架构解决前面的资源浪费问题和代码管理问题,因为我们是对系统拆分了,各个模块都有单独的工程,比如我修改商品模块,就不需要担心会不会影响购物车模块。但是这种架构扩展非常麻烦,一旦需要横向加机器,或者减机器都需要修改 nginx 配置,一旦机器变多了以后,nginx 的配置量就是一个不能完成的工作。OK,这时候 SOA 服 务治理框架就应运而生,架构图如下:

基于注册中心的 SOA 框架,扩展是非常方便的,因为不需要维护分流工具,但我们启动应 用的时候就会把服务通过 http 的方式注册到注册中心。

在 SOA 框架中一般会有三种角色:1、注册中心 2、服务提供方 3、服务消费方

1、注册中心

​ 在注册中心维护了服务列表

2、服务提供方

​ 服务提供方启动的时候会把自己注册到注册中心

3、服务消费方

​ 服务消费方启动的时候,把获取注册中心的服务列表,然后调用的时候从这个服务列表中选择某一个去调用。

微服务工程的特点:

1、扩展灵活

2、每个应用都规模不大

3、服务边界清晰,各司其职

4、打包应用变多,往往需要借助 CI 持续集成工具

2、简单的微服务工程搭建 1、注册中心搭建(eureka服务端: netflix-eureka-server)

Springcloud 中,我们选择 eureka 作为注册中心,springcloud 工程是基于 springboot 工程的。 pom.xml 中 jar 包依赖:

org.springframework.boot spring-boot-starter-parent 2.2.2.RELEASE 1.8 Hoxton.SR1 org.springframework.cloud spring-cloud-starter-netflix-eureka-server org.springframework.cloud spring-cloud-dependencies ${spring-cloud.version} pom import

application.properties 配置文件(不能叫bootstrap.properties)

server.port=8763eureka.instance.hostname=localhost#是否注册到eurekaeureka.client.registerWithEureka=false#是否从eureka中拉取注册信息eureka.client.fetchRegistry=false##暴露eureka服务的地址# http://localhost:8763/eureka/eureka.client.serviceUrl.defaultZone=http://${eureka.instance.hostname}:${server.port}/eureka/#自我保护模式,当出现出现网络分区、eureka在短时间内丢失过多客户端时,会进入自我保护模式,即一个服务长时间没有发送心跳,eureka也不会将其删除,默认为trueeureka.server.enable-self-preservation=true#eureka server清理无效节点的时间间隔,默认60000毫秒,即60秒eureka.server.eviction-interval-timer-in-ms=60000#服务手动下线 delete请求 http://localhost:8763/eureka/apps/MICRO-ORDER/localhost:xxx:8084

启动类

package len.hgy;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;@SpringBootApplication@EnableEurekaServerpublic interface EurekaApplication { public static void main(String[] args) { SpringApplication.run(EurekaApplication.class,args); }}

查看

http://localhost:8763/

2、服务提供方(eureka 客户端: netflix-eureka-client)

Pom 的 jar 包依赖,其他都跟 eureka 服务端是一样的,只是服务提供方要把服务注册到 eureka 服务端,所以服务提供方就是 eureka 的客户端,所以需要导入 eureka 客户端的启动器。

org.springframework.cloud spring-cloud-starter-netflix-eureka-client

bootstrap.properties

spring.application.name=micro-orderserver.port=8084eureka.client.serviceUrl.defaultZone=http://localhost:8763/eureka/# 一下有默认配置#服务续约,心跳的时间间隔eureka.instance.lease-renewal-interval-in-seconds=30#如果从前一次发送心跳时间起,90秒没接受到新的心跳,讲剔除服务eureka.instance.lease-expiration-duration-in-seconds=90#表示eureka client间隔多久去拉取服务注册信息,默认为30秒eureka.client.registry-fetch-interval-seconds=30

启动类

package len.hgy;import org.mybatis.spring.annotation.MapperScan;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.cloud.netflix.eureka.EnableEurekaClient;@SpringBootApplication(scanbasePackages = {"len.hgy"})// 注册到eureka@EnableEurekaClient@MapperScan("len.hgy.dao")public class MicroOrderApplication { public static void main(String[] args) { SpringApplication.run(MicroOrderApplication.class, args); }}

3、服务消费方(eureka 客户端: netflix-eureka-client)

pom 和属性配置文件基本上差不多,消费要负责调用服务提供方,所以需要调用客户端

依赖

org.springframework.cloud spring-cloud-starter-netflix-eureka-client

bootstrap.properties

#是否注册到eurekaeureka.client.registerWithEureka=true#是否从eureka中拉取注册信息eureka.client.fetchRegistry=trueeureka.client.serviceUrl.defaultZone=http://localhost:8763/eureka/

启动类

package len.hgy;import len.hgy.service.feign.StudentService;import len.hgy.service.feign.TeacherServiceFeign;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;import org.springframework.cloud.client.loadbalancer.LoadBalanced;import org.springframework.cloud.netflix.eureka.EnableEurekaClient;import org.springframework.cloud.openfeign.EnableFeignClients;import org.springframework.context.annotation.Bean;import org.springframework.web.client.RestTemplate;@SpringBootApplication(scanbasePackages = {"len.hgy"})//注册到eureka@EnableEurekaClient//开启断路器功能//@EnableCircuitBreaker//开启feign支持,clients指定哪个类开启feign//@EnableFeignClients(clients = {StudentService.class,TeacherServiceFeign.class})public class MicroWebApplication { @Bean // 负载均衡注解 @LoadBalanced RestTemplate restTemplate() { return new RestTemplate(); // 使用这个bean实例才能负载均衡 } public static void main(String[] args) { SpringApplication.run(MicroWebApplication.class,args); }}

服务调用的时候就根据服务提供方的服务名称来调用的

public static String SERVIER_NAME = "micro-order";@Overridepublic List queryContents() { s.incrementAndGet(); List results = restTemplate.getForObject("http://" + SERVIER_NAME + "/user/queryContent", List.class); return results;}

服务提供方的名称,再加上服务提供方的接口名就可以完成调用了。 服务提供方和服务消费启动的时候都会往服务注册中心注册服务,eureka 服务端也可以通过 界面查看到服务注册情况:

http://localhost:8763/

调用web接口测试看看

// controllerpackage len.hgy.controller;import len.hgy.bean.ConsultContent;import len.hgy.service.UserService;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;import java.util.List;@RestController@RequestMapping("/user")public class UserController { @Autowired private UserService userService; @RequestMapping("/queryUser") public List queryUser() { return userService.queryContents(); } @RequestMapping("/queryMonitor") public String queryMonitor() { return userService.queryMonitor(); }}

http://localhost:8083/user/queryUser

3、Eureka 用户认证

连接到 eureka 的时候需要带上连接的用户名和密码

Eureka 服务端改造

添加security启动器

org.springframework.boot spring-boot-starter-security // spring-boot

关闭 csrf 验证

package hgy.security;import org.springframework.security.config.annotation.web.builders.HttpSecurity;import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;@EnableWebSecuritypublic class WebSecurityConfigurer extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { //关闭csrf http.csrf().disable(); //开启认证:URL格式登录必须是httpBasic http.authorizeRequests().anyRequest().authenticated().and().httpBasic(); }}

application.properties 配置

# 开启 basic 校验,设置登录用户名密码security.basic.enabled=truespring.security.user.name=adminspring.security.user.password=admin

Eureka 客户端改造

跟 eureka 连接的时候要带上用户名密码

#eureka.client.serviceUrl.defaultZone=http://localhost:9876/eureka/eureka.client.serviceUrl.defaultZone=http://admin:admin@localhost:9876/eureka/

此时登录页需要输入用户密码

http://localhost:9876/

4、服务续约保活

当客户端启动想 eureka 注册了本身服务列表后,需要隔段时间发送一次心跳给 eureka 服务 端来证明自己还活着,当 eureka 收到这个心跳请求后才会知道客户端还活着,才会维护该 客户端的服务列表信息。一旦因为某些原因导致客户端没有按时发送心跳给 eureka 服务端, 这时候 eureka 可能会认为你这个客户端已经挂了,它就有可能把该服务从服务列表中删除 掉。

有关续约保活的配置

客户端配置

# 客户端配置#服务续约,心跳的时间间隔 eureka.instance.lease-renewal-interval-in-seconds=30#如果从前一次发送心跳时间起,90 秒没接受到新的心跳,将剔除服务 eureka.instance.lease-expiration-duration-in-seconds=90#表示 eureka client 间隔多久去拉取服务注册信息,默认为 30 秒 eureka.client.registry-fetch-interval-seconds=30

服务端配置

# 服务端配置#自我保护模式,当出现出现网络分区、eureka 在短时间内丢失过多客户端时, 会进入自我保护模式,即一个服务长时间没有发送心跳,eureka 也不会将其删 除,默认为 trueeureka.server.enable-self-preservation=true#Eureka Server 在运行期间会去统计心跳失败比例在 15 分钟之内是否低 于 85%,如果低于 85%,Eureka Server 会将这些实例保护起来eureka.server.renewal-percent-threshold=0.85#eureka server 清理无效节点的时间间隔,默认 60000 毫秒,即 60 秒 eureka.server.eviction-interval-timer-in-ms=60000

5、Eureka 健康检测

Eureka 默认的健康检测只是你校验服务连接是否是 UP 还是 DOWN 的,然后客户端只会调用 状态为 UP 状态的服务,但是有的情况下,虽然服务连接是好的,但是有可能这个服务的某 些接口不是正常的,可能由于需要连接 Redis,mongodb 或者 DB 有问题导致接口调用失败, 所以理论上服务虽然能够正常调用,但是它不是一个健康的服务。所以我们就有必要对这种 情况做自定义健康检测。

application.properties 配置

开启健康检测

#健康检测eureka.client.healthcheck.enabled=true

自定义健康检测代码

@Configurationpublic class MicroWebHealthIndicator implements HealthIndicator { @Override public Health health() { //这个状态就是数据库是否连接OK if(UserController.canVisitDb) { // 业务标识, 更具db,redis, mysql等的连接情况得出一个标识 return new Health.Builder(Status.UP).build(); } else { return new Health.Builder(Status.DOWN).build(); } }}

jar

org.springframework.boot spring-boot-starter-actuator

6、服务下线

比如有些情况是服务主机意外宕机了,也就意味着服务没办法给 eureka 心跳信息了,但是 eureka 在没有接受到心跳的情况下依赖维护该服务 90s,在这 90s 之内可能会有客户端调用 到该服务,这就可能会导致调用失败。所以我们必须要有一个机制能手动的立马把宕机的服 务从 eureka 服务列表中清除掉,避免被服务调用方调用到。

调用服务下线的接口: 这个接口是调用 eureka 服务端的接口

http://localhost:9876/eureka/apps/micro-order/localhost:micro-order:8765

delete请求

注意:

测试时候如果服务没有关闭, 会一直有心跳, 导致手动下线失败

另外手动停止idea的服务会直接移除掉服务, 不会保活90s, 因为是正常停机, 客户端自动服务下线了

可以通过如下命令自己模拟异常宕机

windows

netstat -nao | findstr 8765taskkill /f /pid 19016 # 此时eureka的服务列表中还是有服务, 到保活时间过去, eureka也会将其删除掉

linux

ps -aux | grep 8765kill -9 19016

暂停服务接口

PUT http://localhost:9876/eureka/apps/micro-order/localhost:micro-order:8765?value=OUT_OF_SERVICE

上线服务

PUT http://localhost:9876/eureka/apps/micro-order/localhost:micro-order:8765?value=UP

7、Eureka 高可用

Eureka 热备份的架构图如下:

整个微服务中存在多个 eureka 服务,每个 eureka 服务都是相互复制的,会把客户端注册进 来的服务复制到 eureka 集群中的其他节点里面来。其实简单来说就是 eureka 每个节点相互 复制。

具体配置如下:

端口为 9878 的 eureka 服务端把自己注册到 9877 的 eureka 服务端

# 多个使用逗号分隔server.port=9877eureka.client.serviceUrl.defaultZone=http://localhost:9878/eureka/

端口为 9877 的 eureka 服务端把自己注册到 9878 的 eureka 服务端

# 多个使用逗号分隔server.port=9878eureka.client.serviceUrl.defaultZone=http://localhost:9877/eureka/

配置文件

application-9877.properties

application-9878.properties

启动的时候按照指定配置文件启动

java -jar netflix-eureka-server-1.0-SNAPSHOT.jar --spring.profiles.active=9877 --server.port=9877

java -jar netflix-eureka-server-1.0-SNAPSHOT.jar --spring.profiles.active=9878 --server.port=9878

配置就是这样的了

eureka.client.serviceUrl.defaultZone=http://admin:admin@localhost:9877/eureka/

Copyright © 2016-2020 www.365daan.com All Rights Reserved. 365答案网 版权所有 备案号:

部分内容来自互联网,版权归原作者所有,如有冒犯请联系我们,我们将在三个工作时内妥善处理。