4年前 (2021-03-02)  微服务 |   抢沙发  315 
文章评分 0 次,平均分 0.0

 

 

使用Spring搭建微服务框架系列二

上一节中讲了使用Spring搭建的微服务如何实现服务发现注册以及配置,这节继续介绍其他内容。

封装微服务访问

以下是我的客户端应用程序的WebAccountService的一部分:

@Service
public class WebAccountsService {

    @Autowired        // NO LONGER auto-created by Spring Cloud (see below)
    @LoadBalanced     // Explicitly request the load-balanced template
                      // with Ribbon built-in
    protected RestTemplate restTemplate; 

    protected String serviceUrl;

    public WebAccountsService(String serviceUrl) {
        this.serviceUrl = serviceUrl.startsWith("http") ?
               serviceUrl : "http://" + serviceUrl;
    }

    public Account getByNumber(String accountNumber) {
        Account account = restTemplate.getForObject(serviceUrl
                + "/accounts/{number}", Account.class, accountNumber);

        if (account == null)
            throw new AccountNotFoundException(accountNumber);
        else
            return account;
    }
    ...
}

注意,我的WebAccountService只是restemplatemicroservice获取数据的包装器。有趣的部分是serviceUrlrest模板。

访问微服务

如下所示,serviceUrl由主程序提供给WebAccountController(后者将其传递给WebAccountService):

@SpringBootApplication
@EnableDiscoveryClient
@ComponentScan(useDefaultFilters=false)  // Disable component scanner
public class WebServer {

    // Case insensitive: could also use: http://accounts-service
    public static final String ACCOUNTS_SERVICE_URL
                                        = "http://ACCOUNTS-SERVICE";

    public static void main(String[] args) {
        // Will configure using web-server.yml
        System.setProperty("spring.config.name", "web-server");
        SpringApplication.run(WebServer.class, args);
    }

    @LoadBalanced    // Make sure to create the load-balanced template
    @Bean
    RestTemplate restTemplate() {
        return new RestTemplate();
    }

    /**
     * Account service calls microservice internally using provided URL.
     */
    @Bean
    public WebAccountsService accountsService() {
        return new WebAccountsService(ACCOUNTS_SERVICE_URL);
    }

    @Bean
    public WebAccountsController accountsController() {
         return new WebAccountsController
                       (accountsService());  // plug in account-service
    }
}

需要注意的几点:

1. WebController是一个典型的基于springmvc视图的返回HTML的控制器。应用程序使用Thymeleaf作为视图技术(用于生成动态HTML)

2. WebServer也是一个@EnableDiscoveryClient,但在本例中,除了向发现服务器注册自身(这是不必要的,因为它不提供自己的服务)之外,它还使用Eureka来定位帐户服务。

3. 从Spring Boot继承的默认组件扫描程序安装程序查找@component类,在本例中,找到我的WebAccountController并尝试创建它。但是,我想自己创建它,所以我禁用了这个@ComponentScan(usefaultfilters=false)这样的扫描器。

4. 我传递给WebAccountController的服务url是用于向发现服务器注册自身的服务的名称—默认情况下,这与spring.application.name有关帐户服务的流程-请参阅account-service.yml上面。不需要使用大写,但它确实有助于强调ACCOUNTS-SERVICE是一个逻辑主机(将通过发现获得),而不是实际主机。

负载均衡RestTemplate

RestTemplate bean将被springcloud截获并自动配置(由于@LoadBalanced注释),以使用使用Netflix功能区进行微服务查找的定制HttpRequestClient。Ribbon也是一个负载平衡器,因此如果您有多个可用的服务实例,它会为您选择一个。(Eureka和Consul都不自己执行负载平衡,所以我们使用Ribbon来代替)。

注意:在Brixton发布系列(springcloud1.1.0.Release)中,RestTemplate不再自动创建。最初它是为您创建的,这会导致混乱和潜在的冲突(有时Spring可能太有用了!)。

注意,这个实例是使用@LoadBalanced限定的。(注释本身用@Qualifier进行了注释-有关详细信息,请参见此处)。因此,如果您有多个RestTemplate bean,可以确保注入正确的一个,如下所示:

@Autowired
    @LoadBalanced     // Make sure to inject the load-balanced template
    protected RestTemplate restTemplate;

如果查看RibbonClientHttpRequestFactory,您将看到以下代码:

String serviceId = originalUri.getHost();
    ServiceInstance instance =
             loadBalancer.choose(serviceId);  // loadBalancer uses Ribbon
    ... if instance non-null (service exists) ...
    URI uri = loadBalancer.reconstructURI(instance, originalUri);

loadBalancer获取逻辑服务名称(在发现服务器中注册的名称),并将其转换为所选微服务的实际主机名。

RestTemplate实例是线程安全的,可以用于访问应用程序不同部分中的任意数量的服务(例如,我可能让CustomerService包装访问customer data microservice的同一restemplate实例)。

配置

下面是来自web的相关web-server.yml. 用于:

1. 设置应用程序名称

2. 定义用于访问发现服务器的URL

3. 将Tomcat端口设置为3333

# Spring Properties
spring:
  application:
     name: web-service

# Discovery Server Access
eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:1111/eureka/

# HTTP Server
server:
  port: 3333   # HTTP (Tomcat) portCOPY

如何运行Demo

这个系统的一个小演示在http://github.com/paulc4/microservices-demo。克隆它,或者加载到您喜爱的IDE中,或者直接使用maven。关于如何运行演示的建议包含在项目主页的自述文件中。

视图模板引擎

Eureka仪表板(RegistrationServer内部)使用FreeMarker模板实现,但其他两个应用程序使用Thymeleaf。为了确保每个使用正确的视图引擎,在每个YML文件中都有额外的配置。

这是在registration-server.yml禁用Thymeleaf。

...
# Discovery Server Dashboard uses FreeMarker.  Don't want Thymeleaf templates
spring:
  thymeleaf:
    enabled: false     # Disable Thymeleaf spring:

因为AccountServiceWebService都使用thymeleaf,所以我们还需要分别指向它们自己的模板。这是account-server.yml的一部分:

# Spring properties
spring:
  application:
     name: accounts-service  # Service registers under this name
  freemarker:
    enabled: false      # Ignore Eureka dashboard FreeMarker templates
  thymeleaf:
    cache: false        # Allow Thymeleaf templates to be reloaded at runtime
    prefix: classpath:/accounts-server/templates/
                        # Template location for this application only
...

web-server.yml类似,但其模板由

prefix: classpath:/web-server/templates/

记下每一页末尾的“/spring.thymeleaf.prefix前缀类路径-这是至关重要的。

命令行执行

jar被编译为自动运行io.pivotal.microservices.services.Main。主要从命令行调用时-请参阅Main.java.

可以在POM中看到设置start-class的Spring Boot选项:

<properties>
        <!-- Stand-alone RESTFul application for testing only -->
        <start-class>io.pivotal.microservices.services.Main</start-class>
    </properties>

AccountsConfiguration类

@SpringBootApplication
@EntityScan("io.pivotal.microservices.accounts")
@EnableJpaRepositories("io.pivotal.microservices.accounts")
@PropertySource("classpath:db-config.properties")
public class AccountsWebApplication {
...
}

这是AccountService的主要配置类,AccountService是使用Spring数据的经典Spring Boot application。注释完成了大部分工作:

1. @SpringBootApplication-将其定义为SpringBoot应用程序。这个方便的注释结合了@EnableAutoConfiguration@Configuration@ComponentScan(默认情况下,这会导致Spring在包含此类的包及其子包中搜索组件——潜在的springbean:AccountControllerAccountRepository)。

2. @EntityScan("io.pivotal.microservices.accounts")—因为我使用的是JPA,所以需要指定@Entity类的位置。通常这是您在JPA中指定的选项persistence.xml或者在创建LocalContainerEntityManagerFactoryBean时。springboot将为我创建这个工厂bean,因为springbootstarter数据jpa依赖关系位于类路径上。因此,指定在何处查找@Entity类的另一种方法是使用@EntityScan。这将找到帐户。

3. @EnableJpaRepositories("io.pivotal.microservices.accounts")—查找扩展SpringData的Repository标记接口的类,并使用JPA自动实现它们。

4. @PropertySource("classpath:db-config.properties")-properties来配置我的数据源。

配置属性

如上所述,Spring Boot applications寻找应用程序属性或者application.yml配置自己。由于此应用程序中使用的所有三个服务器都在同一个项目中,因此它们将自动使用相同的配置。

为了避免这种情况,每个文件都通过设置spring.config.name属性。

例如,这里是WebServer.java.

public static void main(String[] args) {
  // Tell server to look for web-server.properties or web-server.yml
  System.setProperty("spring.config.name", "web-server");
  SpringApplication.run(WebServer.class, args);
}

在运行时,应用程序将查找并使用web-server.ymlsrc/main/resources中。

登录中

springboot默认为Spring设置info级日志记录。因为我们需要检查日志以找到我们的微服务工作的证据,所以我提高了警告级别以减少日志记录的数量。

为此,需要在每个xxxx中指定日志记录级别-xxxx-server.yml配置文件。这通常是定义它们的最佳位置,因为不能在属性文件中指定日志属性(在处理@PropertySource指令之前,日志已经初始化)。在SpringBoot手册中有一个关于这个的注释,但是很容易错过。

我没有在每个YAML文件中复制日志配置,而是选择将其放在logback配置文件中,因为Spring引导使用logback—请参阅src/main/resources/logback.xml文件. 这三项服务将共享相同的服务logback.xml文件.

 

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

关于

发表评论

表情 格式

暂无评论

登录

忘记密码 ?

切换登录

注册