3年前 (2021-07-22)  微服务 |   抢沙发  426 
文章评分 0 次,平均分 0.0
[收起] 文章目录

在这篇文章中我们将学习如何创建分布式微服务,并使用springboot、Feign和Eureka服务器使这些微服务协同工作。我们将讨论如何使用springboot创建分布式微服务。为此,我们将使用包Spring Cloud NetFlixhttps://spring.io/projects/spring-cloud-netflix)。

任何微服务都应该能够定位另一个服务的不同实例,而不必在代码中定义它们的地址。

如果它需要访问另一个服务,理想情况下,您可以查询其他服务器实例运行的不同地址,因为最常见的情况是实例的数量及其地址是动态的。

为了在Spring实现这一点,我们将使用Spring Cloud NetFlix包中的Eureka服务器。我们的应用程序还将使用Ribbon和Feign来查找微服务的不同实例并平衡请求。

在本文中,我将解释如何创建一个服务来调用请求一个国家的资本。这个服务反过来调用另一个服务来定位请求的数据,因为第一个服务只是一个入口点。

使用的程序如下:

  • Project: Capitals-service Port: 8100
  • Project: countries-Service Port: 8000 and 8001
  • Project: eureka-server Port: 8761

Project: countries-service实例将有一个不同国家的数据库。这个服务的两个实例将被执行,这样我们就可以看到projectcapitals服务程序如何调用一个实例,以及这两个实例中的另一个如何执行负载平衡。

本文中的示例代码位于GitHub上:https://github.com/chuchip/springEureka

创建Eureka服务器

我们首先需要一个地方,所有的微服务在初始化时都可以注册。反过来,每当我们需要定位不同的实例时,就会咨询这个服务。在这个例子中,我们将使用一个非常容易创建的Eureka服务器。

为此,我们将使用starter eureka服务器创建一个新的Spring Boot项目。

在此项目中,我们将更改application.properties文件以包括以下内容:

spring.application.name = eureka-server
server.port = 8761
eureka.client.register-with-eureka = false
eureka.client.fetch-registry = false

使用spring.application.name,我们指定程序的名称。服务将侦听的端口是用server.port指定的。而且,最重要的是,因为上述值是可选的,所以它们是Eureka服务器的参数。

  • eureka.client.register-with-eureka=false-使其成为服务器不会尝试注册自身。
  • eureka.client.fetch-registry=false—因此,我们通知客户,他们不能将可用实例的数据存储在本地缓存中。这意味着,当他们需要访问服务时,必须咨询Eureka服务器。在生产中,这通常设置为true以加快请求。我必须说明,默认情况下,此缓存每30秒更新一次。

现在,在我们的类中,在进入Spring Boot的地方,我们放置了注释EnableEurekaServer

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

准备好了!我们的Eureka服务器已创建。要查看您的状态,我们可以使用最喜爱的浏览器并导航到http://localhost: 8761/查看我们已注册的应用程序。如下面的截图所示,仍然没有人。

使用Spring和Eureka创建微服务

在同一个屏幕里,服务器的状态如下:

使用Spring和Eureka创建微服务

请记住,运行多个Eureka服务器是正常的。在我们的示例中,我们只运行了一个,尽管这在实际用例中并不正常。

countries-service”微服务

现在我们有了服务器,让我们创建第一个客户。为此,我们将使用以下启动器创建另一个Spring Boot项目:

  • Eureka Discovery
  • Web
  • Lombok
  • H2
  • JPA

正如我前面提到的,这个微服务将拥有数据库,并由资本服务公司查询以找到一个国家的首都。

这个项目的显著之处在于Spring引导文件application.properties

spring.application.name = countries-service
eureka.client.serviceUrl.defaultZone = http://localhost:8761/eureka
server.port = 8000 
#  JPA Configuration
spring.jpa.show-sql = true
spring.h2.console.enabled = true

如您所见,通过参数eureka.client.serviceUrl.defaultZone,我们可以指定eureka服务器的位置。Spring Boot会自动检测到您有可用的Eureka发现包,并尝试向相应的服务器注册。

要使用Eclipse在端口8001上启动application countries服务的第二个实例,请转到Run菜单中的Run configurations选项,并在第一次运行应用程序时复制Eclipse为countries服务创建的内容。在tab参数中,我们添加参数--server.port=8001

使用Spring和Eureka创建微服务

在下面的屏幕截图中,您可以看到如果我们启动这个程序的两个实例,一个在端口8000上,另一个在端口8001上,我们可以看到在Eureka服务器中有多个实例。用于register的名称是application.properties文件的变量spring.application.name中声明的应用程序名称。

因此,我们看到application-countries服务有两个实例,都是在宿主端口chuchi中提出的—一个在端口8000上,另一个在端口8001上。

使用Spring和Eureka创建微服务

这个简单的应用程序将使用H2数据库进行数据持久化,我只有一个名为countries的简单表,我们将通过JPA访问它。表结构在com.profesorp.countriesservice.entities.Countries.java中定义

capitalsServiceControllert类中,定义了以下入口点。

1. 获取请求. / {country}

接收:Country code. ( 'it is', 'eu', 'in' ....)

返回:CapitalsBean类型的对象

使用Spring和Eureka创建微服务

2. 获取请求. / time/{time}

设置输入/{country}在返回结果之前暂停的时间。

capitals-service”微服务

此服务调用上述服务来请求一个国家的所有数据。它只显示呼叫的首都、国家和服务港。

使用Spring和Eureka创建微服务

我们需要以下启动器:

  • Eureka Discovery
  • Feign
  • Lombok
  • Web

首先,与前面的服务一样,application.properties文件将包含以下内容:

spring.application.name = capitals-service
eureka.client.serviceUrl.defaultZone = http://localhost:8761/eureka
server.port = 8100

也就是说,我们定义应用程序名,然后指定Eureka服务器的位置和它必须注册的位置,最后指定您将听到程序的端口。

使用RestTemplate

为了发出RESTful请求,countries-services使用org.springframework.web.client包中的类RestTemplate

@GetMapping("/template/{country}")
public CapitalsBean getCountryUsingRestTemplate(@PathVariable String country) { 
    Map<String, String> uriVariables = new HashMap<>();
    uriVariables.put("country", country);               
    ResponseEntity<CapitalsBean> responseEntity = new RestTemplate().getForEntity(
            "http://localhost:8000/{country}", 
            CapitalsBean.class, 
            uriVariables );     
    CapitalsBean response = responseEntity.getBody();       
    return response;
}

如图所示,只需将请求中发送的变量放入一个hashmap中,在本例中,该hashmap只是国家。然后它创建一个对象ResponseEntity,调用静态函数RestTemplate.getForEntity(),作为参数传递URL、存储响应的类以及请求中发送的变量。

然后我们捕获CapitalsBean对象,我们在ResponseEntityBody对象中使用它。

但是,使用这种方法有一个问题:我们编写了程序中不同微服务实例所在的URL。我们还需要编写大量的代码来进行简单的调用。

简单的请求使用Feign

一种更优雅的方法是使用假动作。Feign是Spring的一个工具,它允许我们使用声明性函数进行调用。

要使用Feign,我们必须在类中包含标签@EnableFeignClients。在本例中,我们将它放在classCapitalsServiceApplication

@SpringBootApplication
@EnableFeignClients("com.profesorp.capitalsservice")
public class CapitalsServiceApplication {
    public static void main(String[] args) {
        SpringApplication.run(CapitalsServiceApplication.class, args);
    }
}

如果没有将任何参数传递给标记@EnableFeignClients,请在主包中查找Feign的客户机。如果我们输入一个值,只在发送的包中查找客户机。因此,在这个示例中,只需查看packagecom.profesorp.capitalsservice

现在我们可以用interfaceCapitalsServiceProxy定义客户端

@FeignClient(name="simpleFeign",url="http://localhost:8000/")
public interface CapitalsServiceProxySimple {   
    @GetMapping("/{country}")
    public CapitalsBean getCountry(@PathVariable("country") String country);
}

首先,类被标记为@FeignClient,指定服务器所在的URL以及它必须调用的URL。请注意,我们只编写主机名和端口(localhost:8000)。必须设置参数名称,但其内容不重要。

然后我们定义不同的入口点。在我们的例子中,只定义了一个,但是我们可以包括对/time/{time}的调用。

要使用此客户端,我们只需在程序中输入以下代码:

@Autowired
private CapitalsServiceProxySimple simpleProxy;
@GetMapping("/feign/{country}")
public CapitalsBean getCountryUsingFeign(@PathVariable String country) {
    CapitalsBean response = simpleProxy.getCountry(country);        
    return response;
}

Spring注入变量CapitalsServiceProxySimple,然后调用函数getCountry()

干净多了,对吧?假设我们的REST服务器有许多入口点,我们将节省大量的样板代码。

但是,我们仍然存在这样一个问题:地址服务器是用我们的代码编写的,这使得我们无法访问同一服务的不同实例,并且我们的微服务将无法真正扩展。

使用Eureka服务器发出Feign请求

为了解决这个问题,我们将不输入服务器地址,而是输入应用程序的名称,Spring Boot将调用Eureka服务器,询问服务所在的地址。

为此,我们创建一个外部接口,如下所示:

@FeignClient(name="countries-service")
public interface CapitalsServiceProxy {
    @GetMapping("/{country}")
    public CapitalsBean getCountry(@PathVariable("country") String country);
}

如您所见,我们没有指定服务的地址,只是简单地输入了名称。在这种情况下,countries-service记录在Eureka应用服务器中。

这将依次对一个实例和另一个实例执行。因此,第一个请求将转到端口8000,下一个请求将转到端口8001

使用Spring和Eureka创建微服务
使用Spring和Eureka创建微服务

因此,我们的应用程序将自动使用所有服务实例。

设置RIBBON

在Feign下使用包装Ribbon,这才是真正的要求。默认情况下,Ribbon使用RoundRobinRule规则。此规则将依次选择Eureka显示的每个实例,与每个实例的响应时间无关

如果您希望使用其他三个可用规则中的任何一个,甚至定义一个新规则,那么我们必须为Ribbon创建一个配置类,如下所示:

import org.springframework.context.annotation.Bean;
import com.netflix.loadbalancer.IPing;
import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.NoOpPing;
import com.netflix.loadbalancer.WeightedResponseTimeRule;
public class RibbonConfiguration {
     @Bean
     public IPing ribbonPing() {
            return new NoOpPing();
     }   
     @Bean  
     public IRule ribbonRule() {
            return new WeightedResponseTimeRule();
     }
}

在函数ribbonRule()中,如果希望平衡逻辑考虑每个实例的响应时间,则返回对象weightedResponseTimeRules

现在,要指定要使用此类配置Ribbon,请添加标签:

@RibbonClient(name=“countries service”,configuration=RibbonConfiguration.class)到我们的class CapitalsServiceApplication

@SpringBootApplication
@EnableFeignClients 
@RibbonClient(name="countries-service", configuration = RibbonConfiguration.class)
public class CapitalsServiceApplication {
....
}

为了检查这是如何执行的,我们使用service-countries服务的call/time/{time}对监听端口8001的服务器建立了10毫秒的暂停,对监听端口8000的服务器建立了300毫秒的暂停

> curl localhost:8001/time/10
> curl localhost:8000/time/300

假设我们在Linux上工作,我们可以使用下面的Bash代码生成100个请求。

COUNTER=0; while [ $COUNTER -lt 100 ]; do 
    curl http://localhost:8100/es
    let COUNTER=COUNTER+1
done

过了一会儿,我们看到通过调用http://localhost:8100/puertos.

使用Spring和Eureka创建微服务

如您所见,对端口8001到端口8000的请求更多,考虑到端口8000的延迟为300毫秒,而8001只接收到10毫秒,这是正常的。

在本文的结尾,我要说通过直接使用restemplate,Ribbon可以毫无伪装地使用,但是关于这个案例的研究我将留到另一个时间。

另外,为了测试和平衡,我使用了Docker;可以在我的GitHub上找到的源代码:https://github.com/chuchip/springEureka

您将在countries-service项目的application.properties文件中看到以下行:

eureka.client.serviceUrl.defaultZone:http://eurekaserver:8761/eureka
server.port=${SERVER_PORT}

这还用于使用环境变量SERVER_PORT(每个实例必须侦听的端口)动态定义何时将容器释放给Docker。

原文地址:https://dzone.com/articles/microservices-in-spring-eureka

 

除特别注明外,本站所有文章均为老K的Java博客原创,转载请注明出处来自https://javakk.com/2149.html

关于

发表评论

表情 格式

暂无评论

登录

忘记密码 ?

切换登录

注册