微服务间的互相调用和负载均衡实现

    技术2022-07-11  144

    微服务间的互相调用和负载均衡实现

    一、Eureka作为服务注册中心二、feign实现微服务的之间的调用三、在模块中添加Feign依赖,在主启动类中添加扫描注解四、编写测试demo五、启动访问测试,会发现访问时带有轮询机制的负载均衡。

    一、Eureka作为服务注册中心

    服务注册中心对整个微服务架构起着最核心的整合作用,因此对Eureka还是有很大的必要进行深入研究。 Eureka与zookeeper的区别:

    著名的CAP理论指出,一个分布式系统不可能同时满足C(一致性)、A(可用性)和P(分区容错性)。由于分区容错性在是分布式系统中必须要保证的,因此我们只能在A和C之间进行权衡。在此Zookeeper保证的是CP, 而Eureka则是AP。Zookeeper保证CP

    Eureka保证AP

    Eureka看明白了这一点,因此在设计时就优先保证可用性。Eureka各个节点都是平等的,几个节点挂掉不会影响正常节点的工作,剩余的节点依然可以提供注册和查询服务。而Eureka的客户端在向某个Eureka注册或时如果发现连接失败,则会自动切换至其它节点,只要有一台Eureka还在,就能保证注册服务可用(保证可用性),只不过查到的信息可能不是最新的(不保证强一致性)。除此之外,Eureka还有一种自我保护机制,如果在15分钟内超过85%的节点都没有正常的心跳,那么Eureka就认为客户端与注册中心出现了网络故障,此时会出现以下几种情况:

    Eureka不再从注册列表中移除因为长时间没收到心跳而应该过期的服务Eureka仍然能够接受新服务的注册和查询请求,但是不会被同步到其它节点上(即保证当前节点依然可用)当网络稳定时,当前实例新的注册信息会被同步到其它节点中

    Eureka具体设置流程

    一、改造工作 在eureka-server工程中resources文件夹下,创建配置文件application-peer1.yml: server: port: 8761 spring: profiles: peer1 eureka: instance: hostname: peer1 client: serviceUrl: defaultZone: http://peer2:8769/eureka/

    并且创建另外一个配置文件application-peer2.yml:

    server: port: 8769 spring: profiles: peer2 eureka: instance: hostname: peer2 client: serviceUrl: defaultZone: http://peer1:8761/eureka/

    这时eureka-server就已经改造完毕。

    按照官方文档的指示,需要改变etc/hosts,linux系统通过vim /etc/hosts ,加上:

    127.0.0.1 peer1 127.0.0.1 peer2

    windows电脑,在c:/windows/systems/drivers/etc/hosts 修改。

    这时需要改造下service-hi:

    eureka: client: serviceUrl: defaultZone: http://peer1:8761/eureka/ server: port: 8762 spring: application: name: service-hi 二、启动工程 启动eureka-server: java -jar eureka-server-0.0.1-SNAPSHOT.jar - -spring.profiles.active=peer1 java -jar eureka-server-0.0.1-SNAPSHOT.jar - -spring.profiles.active=peer2

    启动service-hi:

    java -jar service-hi-0.0.1-SNAPSHOT.jar

    访问:localhost:8761,如图:

    你会发现注册了service-hi,并且有个peer2节点,同理访问localhost:8769你会发现有个peer1节点。

    client只向8761注册,但是你打开8769,你也会发现,8769也有 client的注册信息。

    二、feign实现微服务的之间的调用

    Feign简介 Feign是一个声明式的伪Http客户端,它使得写Http客户端变得更简单。使用Feign,只需要创建一个接口并注解。它具有可插拔的注解特性,可使用Feign 注解和JAX-RS注解。Feign支持可插拔的编码器和解码器。Feign默认集成了Ribbon,并和Eureka结合,默认实现了负载均衡的效果。

    简而言之:

    Feign 采用的是基于接口的注解Feign 整合了ribbon

    Feign解决了什么问题 封装了Http调用流程,更适合面向接口化的变成习惯 在服务调用的场景中,我们经常调用基于Http协议的服务,而我们经常使用到的框架可能有HttpURLConnection、Apache HttpComponnets、OkHttp3 、Netty等等,这些框架在基于自身的专注点提供了自身特性。而从角色划分上来看,他们的职能是一致的提供Http调用服务。具体流程如下:

    三、在模块中添加Feign依赖,在主启动类中添加扫描注解

    添加Feign依赖 新建一个spring-boot工程,取名为serice-feign,在它的pom文件引入Feign的起步依赖spring-cloud-starter-feign、Eureka的起步依赖spring-cloud-starter-eureka、Web的起步依赖spring-boot-starter-web,代码如下:

    <?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 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.forezp</groupId> <artifactId>service-feign</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>service-feign</name> <description>Demo project for Spring Boot</description> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.2.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-feign</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</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>Dalston.RC1</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> <repositories> <repository> <id>spring-milestones</id> <name>Spring Milestones</name> <url>https://repo.spring.io/milestone</url> <snapshots> <enabled>false</enabled> </snapshots> </repository> </repositories> </project>

    在主启动类中添加扫描注解 在程序的启动类ServiceFeignApplication ,加上@EnableFeignClients注解开启Feign的功能:

    @SpringBootApplication @EnableDiscoveryClient @EnableFeignClients public class ServiceFeignApplication { public static void main(String[] args) { SpringApplication.run(ServiceFeignApplication.class, args); } }

    四、编写测试demo

    在工程的配置文件application.yml文件,指定程序名为service-feign,端口号为8765,服务注册地址为http://localhost:8761/eureka/ ,代码如下:

    eureka: client: serviceUrl: defaultZone: http://localhost:8761/eureka/ server: port: 8765 spring: application: name: service-feign

    定义一个feign接口,通过@ FeignClient(“服务名”),来指定调用哪个服务。比如在代码中调用了service-hi服务的“/hi”接口,代码如下:

    /** * Created by fangzhipeng on 2017/4/6. */ @FeignClient(value = "service-hi") public interface SchedualServiceHi { @RequestMapping(value = "/hi",method = RequestMethod.GET) String sayHiFromClientOne(@RequestParam(value = "name") String name); }

    在Web层的controller层,对外暴露一个"/hi"的API接口,通过上面定义的Feign客户端SchedualServiceHi 来消费服务。代码如下:

    @RestController public class HiController { @Autowired SchedualServiceHi schedualServiceHi; @RequestMapping(value = "/hi",method = RequestMethod.GET) public String sayHi(@RequestParam String name){ return schedualServiceHi.sayHiFromClientOne(name); } }

    五、启动访问测试,会发现访问时带有轮询机制的负载均衡。

    启动程序,多次访问http://localhost:8765/hi?name=forezp,浏览器交替显示:

    hi forezp,i am from port:8762 hi forezp,i am from port:8763
    Processed: 0.031, SQL: 9