13、微服务安全、监控与可观测性实践

微服务安全、监控与可观测性实践

1. 安全相关

在微服务架构中,安全是至关重要的一个方面,下面从几个关键部分来介绍相关的安全措施和实践。

1.1 配置 AWS 凭证读取

在 Java 应用里,我们可以借助 Spring Boot 来配置从 Vault 读取 AWS 凭证。以下是示例代码:

import com.packtpub.microservices.ch06.attachment.config.Configuration;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;

@SpringBootApplication
@EnableConfigurationProperties(Configuration.class)
public class Application {
    private final Configuration config;

    public Application(Configuration config) {
        this.config = config;
    }

    @Bean
    public AmazonS3 getS3Client() {
        AmazonS3ClientBuilder client = AmazonS3ClientBuilder.standard();
        AWSCredentials credentials = new BasicAWSCredentials(config.getAwsAccessKeyId(), config.getAwsSecretAccessKey());
        return client.withCredentials(new AWSStaticCredentialsProvider(credentials)).withRegion(Regions.US_WEST_2).build();
    }

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

这段代码通过 Spring Boot 应用,从配置类 Configuration 中获取 AWS 凭证,进而创建 Amazon S3 客户端。

1.2 安全日志记录

日志是可观测系统的关键组成部分,不过在微服务架构下,日志也可能带来隐私和安全风险。过多的日志信息可能会泄露系统用户信息或者敏感的令牌、密钥等。所以,需要精心规划服务的日志记录策略。
日志通常按照级别进行组织,开发者可以根据需求调整日志的详细程度。例如,在生产环境中测试服务应对故障场景时,可以提高日志级别以获取更多系统事件的详细信息。

1.3 基础设施即代码(Infrastructure as Code)

微服务架构常常需要频繁地调配计算资源,系统中节点数量的增加会扩大攻击面。传统的配置管理方式,如使用自定义 shell 脚本,随着系统需求的增长,会变得难以维护,容易导致配置漂移,使系统的遗留部分面临攻击风险。

而基础设施即代码(Infrastructure as Code)通过机器可读的代码文件来管理基础设施的调配和维护。以 Terraform 为例,它是 HashiCorp 开发的开源工具,下面介绍使用 Terraform 调配 AWS 资源的步骤:
1. 安装 Terraform :如果你使用的是 macOS X 并且使用 HomeBrew,可以使用以下命令进行安装:

$ brew install terraform
  1. 创建配置文件 :创建一个名为 example.tf 的文件,其中包含 EC2 实例和 ElastiCache 实例的配置信息,示例如下:
provider "aws" {
    access_key = "ACCESS_KEY"
    secret_key = "SECRET_KEY"
    region = "us-east-1"
}

resource "aws_instance" "example" {
    ami           = "ami-b374d5a5"
    instance_type = "t2.micro"
}

resource "aws_elasticache_cluster" "example" {
    cluster_id           = "cluster-example"
    engine               = "redis"
    node_type            = "cache.m3.medium"
    num_cache_nodes      = 1
    parameter_group_name = "default.redis3.2"
    port                 = 6379
    snapshot_window      = "05:00-09:00"
    snapshot_retention_limit = 5
}

请将 ACCESS_KEY SECRET_KEY 替换为有效的 AWS 访问密钥对。
3. 初始化 Terraform :执行以下命令初始化 Terraform,这将安装配置文件中引用的 AWS 提供程序:

$ terraform init
  1. 应用配置 :运行以下命令并在提示时输入 yes 来应用配置:
$ terraform apply
  1. 销毁资源 :如果需要销毁创建的资源,可以运行以下命令并在提示时输入 yes
$ terraform destroy
2. 监控与可观测性

在微服务架构中,监控和可观测性是非常重要的,它有助于我们及时发现系统中的问题并进行处理。下面介绍几个关键的监控和可观测性实践。

2.1 结构化 JSON 日志记录

输出有用的日志是构建可观测服务的关键部分。在微服务架构中,多个服务可能会将事件日志发送到集中式日志存储,因此输出结构化日志是非常有用的。JSON 是一种常见的消息传递标准,它轻量级且结构化,适合用于事件日志。

以下是使用 Logback 库将 Java 应用的日志输出为 JSON 格式的步骤:
1. 添加依赖 :在 build.gradle 文件中添加 Logback 库的依赖:

group 'com.packtpub.microservices'
version '1.0-SNAPSHOT'

buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath group: 'org.springframework.boot', name: 'spring-boot-gradle-plugin', version: '1.5.9.RELEASE'
    }
}

apply plugin: 'java'
apply plugin: 'org.springframework.boot'

sourceCompatibility = 1.8

repositories {
    mavenCentral()
}

dependencies {
    compile group: 'org.springframework.boot', name: 'spring-boot-starter-web'
    compile group: 'io.github.resilience4j', name: 'resilience4j-circuitbreaker', version: '0.11.0'
    compile group: 'net.logstash.logback', name: 'logstash-logback-encoder', version: '4.7'
    testCompile group: 'junit', name: 'junit', version: '4.12'
}
  1. 创建配置文件 :创建 logback.xml 配置文件,示例如下:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
    <appender name="consoleAppender" class="ch.qos.logback.core.ConsoleAppender">
        <encoder class="net.logstash.logback.encoder.LogstashEncoder"/>
    </appender>
    <logger name="jsonLogger" additivity="false" level="DEBUG">
        <appender-ref ref="consoleAppender"/>
    </logger>
    <root level="INFO">
        <appender-ref ref="consoleAppender"/>
    </root>
</configuration>
  1. 添加测试日志 :在 Application.java 中添加一个测试日志消息:
package com.packtpub.microservices.ch07.message;

import com.packtpub.microservices.ch07.message.clients.SocialGraphClient;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import java.util.concurrent.Executor;

@SpringBootApplication
@EnableAsync
public class Application {
    private Logger logger = LogManager.getLogger(Application.class);

    @Bean
    public MessageRepository messageRepository() {
        return new MessageRepository();
    }

    @Bean
    public SocialGraphClient socialGraphClient() {
        return new SocialGraphClient("http://localhost:4567");
    }

    public static void main(String[] args) {
        logger.info("Starting application");
        SpringApplication.run(Application.class, args);
    }

    @Bean
    public Executor asyncExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(2);
        executor.setMaxPoolSize(2);
        executor.setQueueCapacity(500);
        executor.setThreadNamePrefix("SocialServiceCall-");
        executor.initialize();
        return executor;
    }
}
  1. 运行应用 :运行应用程序,你会看到日志消息以 JSON 格式输出:
$ ./gradlew bootRun
2.2 使用 StatsD 和 Graphite 收集指标

指标是随时间变化的数值测量,常见的指标类型有计数器、计时器和仪表。StatsD 是一个开源的网络守护进程,它将指标数据推送到服务器进行聚合,然后发送到持久化后端,Graphite 是常用的后端之一。

下面是使用 Spring Boot Actuator 和 Micrometer 结合 StatsD 和 Graphite 收集指标的步骤:
1. 更新依赖 :在 build.gradle 文件中更新 Spring Boot 版本并添加 Actuator 和 Micrometer 的依赖:

group 'com.packtpub.microservices'
version '1.0-SNAPSHOT'

buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath group: 'org.springframework.boot', name: 'spring-boot-gradle-plugin', version: '2.0.4.RELEASE'
    }
}

apply plugin: 'java'
apply plugin: 'org.springframework.boot'

sourceCompatibility = 1.8

repositories {
    mavenCentral()
}

dependencies {
    compile group: 'org.springframework.boot', name: 'spring-boot-starter-web', version: '2.0.4.RELEASE'
    compile group: 'org.springframework.boot', name: 'spring-boot-starter-actuator', version: '2.0.4.RELEASE'
    compile group: 'io.micrometer', name: 'micrometer-core', version: '1.0.6'
    compile group: 'io.micrometer', name: 'micrometer-registry-statsd', version: '1.0.6'
    compile group: 'io.github.resilience4j', name: 'resilience4j-circuitbreaker', version: '0.11.0'
    compile group: 'log4j', name: 'log4j', version: '1.2.17'
    compile group: 'net.logstash.logback', name: 'logstash-logback-encoder', version: '5.2'
    testCompile group: 'junit', name: 'junit', version: '4.12'
}
  1. 配置应用 :在 application.yml 文件中添加以下配置:
server:
  port: 8082
management:
  metrics:
    export:
      statsd:
        enabled: true
        flavor: "etsy"
        host: 0.0.0.0
        port: 8125
  1. 添加注解 :在 MessageController.java 中添加 Timed 注解:
package com.packtpub.microservices.ch07.message.controllers;

import com.packtpub.microservices.ch07.message.MessageRepository;
import com.packtpub.microservices.ch07.message.clients.SocialGraphClient;
import com.packtpub.microservices.ch07.message.exceptions.MessageNotFoundException;
import com.packtpub.microservices.ch07.message.exceptions.MessageSendForbiddenException;
import com.packtpub.microservices.ch07.message.models.Message;
import com.packtpub.microservices.ch07.message.models.UserFriendships;
import io.micrometer.core.annotation.Timed;
import io.micrometer.statsd.StatsdMeterRegistry;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.scheduling.annotation.Async;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.servlet.support.ServletUriComponentsBuilder;
import java.net.URI;
import java.util.List;
import java.util.concurrent.CompletableFuture;

@RestController
@Timed
public class MessageController {
    @Autowired
    private MessageRepository messagesStore;
    @Autowired
    private SocialGraphClient socialGraphClient;
    @Autowired
    private StatsdMeterRegistry registry;

    @Timed(value="get.messages")
    @RequestMapping(path = "/{id}", method = RequestMethod.GET, produces = "application/json")
    public Message get(@PathVariable("id") String id) throws MessageNotFoundException {
        registry.counter("get_messages").increment();
        return messagesStore.get(id);
    }

    @RequestMapping(path = "/", method = RequestMethod.POST, produces = "application/json")
    public ResponseEntity<Message> send(@RequestBody Message message) throws MessageSendForbiddenException {
        List<String> friendships = socialGraphClient.getFriendships(message.getSender());
        if (!friendships.contains(message.getRecipient())) {
            throw new MessageSendForbiddenException("Must be friends to send message");
        }
        Message saved = messagesStore.save(message);
        URI location = ServletUriComponentsBuilder
              .fromCurrentRequest().path("/{id}")
              .buildAndExpand(saved.getId()).toUri();
        return ResponseEntity.created(location).build();
    }

    @Async
    public CompletableFuture<Boolean> isFollowing(String fromUser, String toUser) {
        // 方法体
    }
}

通过以上的安全和监控实践,可以提高微服务架构的安全性和可观测性,帮助我们更好地管理和维护系统。

微服务安全、监控与可观测性实践(续)

2.3 使用 Prometheus 收集指标

Prometheus 是一个开源的系统监控和警报工具包,它以时间序列数据的形式收集和存储指标。与 StatsD 和 Graphite 不同,Prometheus 采用拉取模型,即主动从目标服务中拉取指标数据。

以下是使用 Spring Boot 和 Micrometer 集成 Prometheus 收集指标的步骤:
1. 添加依赖 :在 build.gradle 文件中添加 Prometheus 相关依赖:

group 'com.packtpub.microservices'
version '1.0-SNAPSHOT'

buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath group: 'org.springframework.boot', name: 'spring-boot-gradle-plugin', version: '2.0.4.RELEASE'
    }
}

apply plugin: 'java'
apply plugin: 'org.springframework.boot'

sourceCompatibility = 1.8

repositories {
    mavenCentral()
}

dependencies {
    compile group: 'org.springframework.boot', name: 'spring-boot-starter-web', version: '2.0.4.RELEASE'
    compile group: 'org.springframework.boot', name: 'spring-boot-starter-actuator', version: '2.0.4.RELEASE'
    compile group: 'io.micrometer', name: 'micrometer-core', version: '1.0.6'
    compile group: 'io.micrometer', name: 'micrometer-registry-prometheus', version: '1.0.6'
    compile group: 'io.github.resilience4j', name: 'resilience4j-circuitbreaker', version: '0.11.0'
    compile group: 'log4j', name: 'log4j', version: '1.2.17'
    compile group: 'net.logstash.logback', name: 'logstash-logback-encoder', version: '5.2'
    testCompile group: 'junit', name: 'junit', version: '4.12'
}
  1. 配置应用 :在 application.yml 文件中添加以下配置,启用 Prometheus 端点:
management:
  endpoints:
    web:
      exposure:
        include: prometheus
  1. 访问指标 :启动应用后,可以通过访问 /actuator/prometheus 端点查看收集到的指标数据。
2.4 利用追踪简化调试

在微服务架构中,请求可能会经过多个服务和组件,当出现问题时,很难确定问题出在哪里。追踪(Tracing)可以帮助我们跟踪请求在系统中的流动,识别性能瓶颈和错误。

常见的追踪系统有 Jaeger、Zipkin 等。以下是一个简单的使用 Spring Cloud Sleuth 和 Zipkin 进行追踪的示例:
1. 添加依赖 :在 build.gradle 文件中添加相关依赖:

group 'com.packtpub.microservices'
version '1.0-SNAPSHOT'

buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath group: 'org.springframework.boot', name: 'spring-boot-gradle-plugin', version: '2.0.4.RELEASE'
    }
}

apply plugin: 'java'
apply plugin: 'org.springframework.boot'

sourceCompatibility = 1.8

repositories {
    mavenCentral()
}

dependencies {
    compile group: 'org.springframework.boot', name: 'spring-boot-starter-web', version: '2.0.4.RELEASE'
    compile group: 'org.springframework.cloud', name: 'spring-cloud-starter-sleuth', version: '2.0.2.RELEASE'
    compile group: 'org.springframework.cloud', name: 'spring-cloud-starter-zipkin', version: '2.0.2.RELEASE'
    compile group: 'io.github.resilience4j', name: 'resilience4j-circuitbreaker', version: '0.11.0'
    compile group: 'log4j', name: 'log4j', version: '1.2.17'
    compile group: 'net.logstash.logback', name: 'logstash-logback-encoder', version: '5.2'
    testCompile group: 'junit', name: 'junit', version: '4.12'
}
  1. 配置应用 :在 application.yml 文件中配置 Zipkin 服务器地址:
spring:
  zipkin:
    base-url: http://localhost:9411
  1. 查看追踪信息 :启动 Zipkin 服务器和应用后,可以通过访问 Zipkin 的 Web 界面(通常是 http://localhost:9411 )查看请求的追踪信息。
2.5 异常告警

当系统出现问题时,及时的告警可以帮助我们快速响应并解决问题。常见的告警系统有 Grafana、Alertmanager 等。

以下是一个使用 Spring Boot Actuator 和 Prometheus 结合 Alertmanager 进行告警的示例:
1. 配置 Prometheus 规则 :在 Prometheus 的配置文件中添加告警规则,例如:

groups:
- name: example-rules
  rules:
  - alert: HighRequestLatency
    expr: http_request_duration_seconds_sum / http_request_duration_seconds_count > 1
    for: 5m
    labels:
      severity: page
    annotations:
      summary: High request latency
      description: The average request latency is above 1 second for 5 minutes.
  1. 配置 Alertmanager :在 Alertmanager 的配置文件中配置告警接收方式,如邮件、Slack 等。
  2. 启动服务 :启动 Prometheus、Alertmanager 和应用,当满足告警规则时,Alertmanager 会发送告警通知。

总结

微服务架构的安全、监控和可观测性是保障系统稳定运行的关键。通过合理配置安全措施,如安全日志记录和基础设施即代码,可以降低系统的安全风险;利用结构化日志、指标收集和追踪技术,可以更好地了解系统的运行状态,及时发现和解决问题;而异常告警则可以在系统出现问题时及时通知相关人员,减少故障对业务的影响。

以下是本文介绍的各项技术的对比表格:
| 技术 | 作用 | 特点 |
| ---- | ---- | ---- |
| 安全日志记录 | 记录系统事件,帮助排查问题,但需注意隐私和安全风险 | 可配置日志级别,按需调整详细程度 |
| 基础设施即代码(Terraform) | 通过代码管理基础设施的调配和维护 | 支持版本控制、审查和回滚,减少配置漂移 |
| 结构化 JSON 日志记录 | 输出结构化日志,便于分析和查询 | 采用 JSON 格式,易于集成到集中式日志存储 |
| StatsD 和 Graphite | 收集和可视化指标数据 | 开源,社区活跃,易于上手 |
| Prometheus | 收集和存储时间序列指标数据 | 采用拉取模型,支持告警规则配置 |
| 追踪(Spring Cloud Sleuth 和 Zipkin) | 跟踪请求在系统中的流动,简化调试 | 帮助定位性能瓶颈和错误 |
| 异常告警(Prometheus 和 Alertmanager) | 在系统出现问题时及时通知 | 可配置告警规则和接收方式 |

下面是一个简单的 mermaid 流程图,展示了微服务架构中监控和可观测性的整体流程:

graph LR
    A[服务运行] --> B[日志记录]
    A --> C[指标收集]
    A --> D[请求追踪]
    B --> E[集中式日志存储]
    C --> F[指标存储]
    D --> G[追踪系统]
    E --> H[日志分析]
    F --> I[指标可视化]
    G --> J[追踪分析]
    H --> K[问题排查]
    I --> K
    J --> K
    K --> L[异常告警]

通过以上的实践和技术,我们可以构建一个更加安全、稳定和可观测的微服务架构。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值