Spring Cloud 学习笔记(一)——Eureka服务治理

服务治理

所谓服务治理就是用来实现各个微服务实例的自动化注册与发现,在这种模式下,服务间的调用不再通过指定具体的实例地址来实现,而是通过向服务注册中心获取服务名并发起请求调用实现。

Eureka是由Netflix开发的一款服务治理开源框架。Eureka服务端是一个服务注册中心(Eureka Server),提供服务的注册和发现,Eureka客户端为服务提供者(Server Provider),它将自己提供的服务注册到Eureka服务端,并周期性地发送心跳来更新它的服务租约,同时也能从服务端查询当前注册的服务信息并把它们缓存到本地并周期性地刷新服务状态。这样服务消费者(Server Consumer)便可以从服务注册中心获取服务名称,并消费服务。


不使用Eureka时内部服务之间的调用

方式一

A服务将服务实例的内网ip给消费者B,B在Nginx上配置A服务的upstream,即将A服务的三个实例配置进去。
    ##B服务Nginx配置
    upstream servicea_api_servers{
        server 192.168.99.100:80 weight=3 max_fails=3 fail_timeout=20s;
        server 192.168.99.101:80 weight=1 max_fails=3 fail_timeout=20s;
        server 192.168.99.102:80 weight=4 max_fails=3 fail_timeout=20s;
    }
    ##...
    server{
        listen 80 default_server;
        server_name serviceb.com.cn;
        location /api/servicea/ {
            proxy_pass http://servicea_api_servers/api/;
        }
    }

通过B服务自己的Nginx来维护A服务的具体实例IP,当A服务的实例IP发生变化时,其下游的消费者都需要修改配置文件

方式二

A服务自身维护自己的实例,只提供给消费者一个统一的接口。

    ## B服务只需配置一个代理
    server{
        listen 80 default_server;
        server_name serviceb.com.cn;
        location /api/servicea/ {
            proxy_pass http://servicea.com.cn/api/;
        }
    }

A服务维护自身实例

    ##A服务配置自身内网到实例的配置
    upstream servicea_api_servers{
        server 192.168.99.100:80 weight=3 max_fails=3 fail_timeout=20s;
        server 192.168.99.101:80 weight=1 max_fails=3 fail_timeout=20s;
        server 192.168.99.102:80 weight=4 max_fails=3 fail_timeout=20s;
    }
    ##...
    server{
        listen 80 default_server;
        server_name servicea.com.cn;
        location /api/ {
            proxy_pass http://servicea_api_servers/api/;
        }
    }

Eureka使用

1.搭建Eureka-Server服务注册中心

新建一个Spring Boot项目,引入依赖包

		<dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
        </dependency>

	<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>

在启动类上添加@EnableEurekaServer注解,表明这是一个Eureka服务端:

@EnableEurekaServer
@SpringBootApplication
public class EurekademoApplication {

接着在application.yml中添加一些配置:

server:
  port: 8080
  
eureka:
  instance:
    hostname: localhost
  client:
    register-with-eureka: false
    fetch-registry: false
    serviceUrl:
      defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
  1. eureka.instance.hostname指定了Eureka服务端的IP;
  2. eureka.client.register-with-eureka表示是否将服务注册到Eureka服务端,由于自身就是Eureka服务端,所以设置为false;
  3. eureka.client.fetch-registry表示是否从Eureka服务端获取服务信息,因为这里只搭建了一个Eureka服务端,并不需要从别的Eureka服务端同步服务信息,所以这里设置为false;
  4. eureka.client.serviceUrl.defaultZone指定Eureka服务端的地址,默认值为http://localhost:8761/eureka。

配置完毕后启动服务,访问http://localhost:8080/,可以看到Eureka服务管理页面。

搭建Eureka-Client服务提供者

新建一个Spring Boot项目,然后引入以下依赖:

		<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>
        

接着编写一个TestController,对外提供一些REST服务:

@RestController
public class TestController {
    private Logger log = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private DiscoveryClient client;

    @GetMapping("/info")
    public String info() {
        ServiceInstance instance = client.getInstances(client.getServices().get(0)).get(0);
        String info = "host:" + instance.getHost() + ",service_id:" + instance.getServiceId();
        logger.info(info);
        return info;
    }
    @GetMapping("/hello")
    public String hello() {
        return "hello world";
    }
}

上面代码注入了org.springframework.cloud.client.discovery.DiscoveryClient对象,可以获取当前服务的一些信息。

编写启动类,在启动类上加@EnableDiscoveryClient注解,表明这是一个Eureka客户端:

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

最后配置

server:
  port: 8082
  
spring:
  application:
    name: Server-Provider
    
eureka:
  client:
    register-with-eureka: true
    fetch-registry: true
    serviceUrl:
      defaultZone: http://localhost:8080/eureka/

Spring cloud 默认开启了保护模式,会出现客户端挂掉却不被剔除的情况,因此在服务开发时,建议关闭这个配置。

eureka:
  server:
    enable-self-preservation: false

EMERGENCY! EUREKA MAY BE INCORRECTLY CLAIMING INSTANCES ARE UP WHEN THEY’RE NOT. RENEWALS ARE LESSER THAN THRESHOLD AND HENCE THE INSTANCES ARE NOT BEING EXPIRED JUST TO BE SAFE.

大致意思是Eureka已经进入了保护模式。微服务在部署之后可能由于网络问题造成Eureka客户端无法成功的发送心跳给Eureka服务端,这时候Eureka服务端认定Eureka客户端已经挂掉了,虽然实际上Eureka客户端还在正常的运行着。而保护模式就是为了解决这个问题,即当Eureka服务端在短时间内同时丢失了过多的Eureka客户端时,Eureka服务端会进入保护模式,不去剔除这些客户端。因为我们这里只部署了一个Eureka客户端服务,所以关闭客户端后满足“短时间内丢失过多Eureka客户端”的条件。

Eureka-Server集群

如果单节点的Eureka服务端宕机了,那么所有服务都无法正常的访问,这必将是灾难性的。为了提高Eureka服务端的可用性,我们一般会对其集群部署,即同时部署多个Eureka服务端,并且可以相互间同步服务。

此时,我们需要打开服务端的相互注册发现,这样我们可以做到服务之间的同步。

eureka:
  client:
    register-with-eureka: false
    fetch-registry: false

在服务端新增两个profile配置

server:
  port: 8080

spring:
  application:
    name: Eureka-Server

eureka:
  instance:
    hostname: peer1
  client:
    serviceUrl:
      defaultZone: http://peer2:8081/eureka/
  server:
    enable-self-preservation: false
server:
  port: 8081

spring:
  application:
    name: Eureka-Server

eureka:
  instance:
    hostname: peer2
  client:
    serviceUrl:
      defaultZone: http://peer1:8080/eureka/
  server:
    enable-self-preservation: false

因为Eureka服务端做了集群处理,所以Eureka客户端指定的服务端地址也要进行修改:

eureka:
  client:
    serviceUrl:
      defaultZone: http://peer1:8080/eureka/,http://peer2:8081/eureka/

搭建Server-Consumer服务消费者

新建一个Spring Boot项目,artifactId填Server-Consumer,其主要的任务就是将自身的服务注册到Eureka服务端,并且获取Eureka服务端提供的服务并进行消费。这里服务的消费我们用Ribbon来完成,Ribbon是一款实现服务负载均衡的开源软件。

在入口类中加入@EnableDiscoveryClient注解用于发现服务和注册服务,并配置一个RestTemplate Bean,然后加上@LoadBalanced注解来开启负载均衡:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;

@EnableDiscoveryClient
@SpringBootApplication
public class DemoApplication {
    @Bean
    @LoadBalanced
    RestTemplate restTemplate() {
        return new RestTemplate();
    }

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
}

接着编写一个TestController,用于消费服务:

@RestController
public class TestController {
    @Autowired
    private RestTemplate restTemplate;

    @GetMapping("/info")
    public String getInfo() {
        return this.restTemplate.getForEntity("http://Server-Provider/info", String.class).getBody();
    }
}

上面代码注入了RestTemplate,getInfo中使用RestTemplate对象均衡的去获取服务并消费。可以看到我们使用服务名称(Server-Provider)去获取服务的,而不是使用传统的IP加端口的形式。这就体现了使用Eureka去获取服务的好处,我们只要保证这个服务名称不变即可,IP和端口不再是我们关心的点。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值