最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

深入探討Java應(yīng)用性能監(jiān)控與調(diào)優(yōu)的工具鏈構(gòu)建

 更新時(shí)間:2025年06月10日 09:40:57   作者:天天進(jìn)步2015  
這篇文章主要來和大家將深入探討Java應(yīng)用性能監(jiān)控與調(diào)優(yōu)的完整工具鏈,從傳統(tǒng)的單機(jī)分析工具JProfiler到現(xiàn)代化的分布式監(jiān)控系統(tǒng)Prometheus,希望能幫助開發(fā)者和運(yùn)維人員構(gòu)建全方位的性能監(jiān)控體系

引言

在當(dāng)今高度競(jìng)爭(zhēng)的數(shù)字環(huán)境中,Java應(yīng)用程序的性能直接影響用戶體驗(yàn)和業(yè)務(wù)成功。隨著系統(tǒng)規(guī)模和復(fù)雜性的增長(zhǎng),性能問題變得越來越難以預(yù)測(cè)和解決。本文將深入探討Java應(yīng)用性能監(jiān)控與調(diào)優(yōu)的完整工具鏈,從傳統(tǒng)的單機(jī)分析工具JProfiler到現(xiàn)代化的分布式監(jiān)控系統(tǒng)Prometheus,幫助開發(fā)者和運(yùn)維人員構(gòu)建全方位的性能監(jiān)控體系。

Java性能監(jiān)控的挑戰(zhàn)與策略

Java應(yīng)用性能監(jiān)控面臨著諸多挑戰(zhàn):分布式系統(tǒng)的復(fù)雜性、微服務(wù)架構(gòu)帶來的調(diào)用鏈追蹤難題、容器化環(huán)境下的資源監(jiān)控、高并發(fā)場(chǎng)景的性能瓶頸識(shí)別等。這些挑戰(zhàn)要求我們建立多層次、全方位的監(jiān)控策略。

有效的Java性能監(jiān)控策略應(yīng)包括以下幾個(gè)層面:

  • JVM層面:監(jiān)控堆內(nèi)存使用、垃圾回收、線程狀態(tài)等JVM內(nèi)部指標(biāo)
  • 應(yīng)用層面:監(jiān)控方法調(diào)用、SQL執(zhí)行、外部服務(wù)調(diào)用等應(yīng)用行為
  • 系統(tǒng)層面:監(jiān)控CPU、內(nèi)存、磁盤I/O、網(wǎng)絡(luò)等系統(tǒng)資源使用情況
  • 業(yè)務(wù)層面:監(jiān)控關(guān)鍵業(yè)務(wù)指標(biāo),如交易量、響應(yīng)時(shí)間、錯(cuò)誤率等

為了實(shí)現(xiàn)這一策略,我們需要構(gòu)建一個(gè)完整的工具鏈,覆蓋從開發(fā)環(huán)境到生產(chǎn)環(huán)境的全生命周期監(jiān)控需求。接下來,我們將詳細(xì)介紹這一工具鏈的各個(gè)組成部分。

本地性能分析工具

1.JProfiler深度解析

JProfiler是Java領(lǐng)域最強(qiáng)大的本地性能分析工具之一,它提供了豐富的功能來分析Java應(yīng)用的性能問題。

主要功能

CPU分析:JProfiler可以記錄方法調(diào)用的執(zhí)行時(shí)間,幫助開發(fā)者找出性能熱點(diǎn)。它支持兩種模式:

  • 采樣模式:低開銷,適合長(zhǎng)時(shí)間運(yùn)行的應(yīng)用
  • 插樁模式:高精度,適合短時(shí)間精確分析

內(nèi)存分析:

  • 堆遍歷:展示堆內(nèi)存中對(duì)象的分布情況
  • 對(duì)象引用分析:查找內(nèi)存泄漏的根源
  • GC活動(dòng)監(jiān)控:分析垃圾回收對(duì)性能的影響

線程分析:

  • 線程狀態(tài)監(jiān)控:查看線程的活動(dòng)狀態(tài)
  • 線程轉(zhuǎn)儲(chǔ):分析死鎖和線程阻塞問題
  • 線程歷史記錄:了解線程隨時(shí)間的行為變化

數(shù)據(jù)庫分析:

  • JDBC調(diào)用監(jiān)控:分析SQL語句執(zhí)行時(shí)間
  • 連接池使用情況:監(jiān)控?cái)?shù)據(jù)庫連接的使用

實(shí)戰(zhàn)應(yīng)用

以下是使用JProfiler分析內(nèi)存泄漏的典型步驟:

  • 啟動(dòng)JProfiler并連接到目標(biāo)Java應(yīng)用
  • 在"內(nèi)存"視圖中執(zhí)行堆快照
  • 分析對(duì)象實(shí)例數(shù)量,找出異常增長(zhǎng)的對(duì)象類型
  • 使用"最短GC根路徑"功能找出這些對(duì)象被引用的路徑
  • 根據(jù)引用路徑定位代碼中的內(nèi)存泄漏點(diǎn)
// 內(nèi)存泄漏示例
public class CacheManager {
    // 使用靜態(tài)HashMap可能導(dǎo)致內(nèi)存泄漏
    private static final Map<String, Object> cache = new HashMap<>();
    
    public static void addToCache(String key, Object value) {
        cache.put(key, value);  // 對(duì)象被永久引用,無法被GC回收
    }
    
    // 缺少清理機(jī)制
}

JProfiler可以清晰地顯示這種情況下HashMap對(duì)象不斷增長(zhǎng),并通過引用圖指出CacheManager類是問題根源。

2.VisualVM實(shí)戰(zhàn)應(yīng)用

VisualVM是JDK自帶的性能分析工具,雖然功能不如JProfiler全面,但作為免費(fèi)工具,它提供了足夠強(qiáng)大的分析能力。

主要功能

  • 應(yīng)用概覽:顯示JVM參數(shù)、系統(tǒng)屬性等基本信息
  • 監(jiān)視器:實(shí)時(shí)監(jiān)控CPU、堆內(nèi)存、類加載、線程數(shù)等指標(biāo)
  • 線程分析:查看線程狀態(tài)、線程轉(zhuǎn)儲(chǔ)、死鎖檢測(cè)
  • 采樣器:CPU和內(nèi)存使用情況采樣分析
  • 性能分析器:通過插樁方式進(jìn)行CPU和內(nèi)存分析

實(shí)戰(zhàn)應(yīng)用

VisualVM在排查高CPU使用率問題時(shí)特別有效:

  • 啟動(dòng)VisualVM并連接到目標(biāo)應(yīng)用
  • 在"采樣器"標(biāo)簽中啟動(dòng)CPU采樣
  • 等待應(yīng)用執(zhí)行高CPU負(fù)載的操作
  • 停止采樣并分析熱點(diǎn)方法
// CPU密集型操作示例
public class PrimeCalculator {
    public static List<Integer> findPrimes(int max) {
        List<Integer> primes = new ArrayList<>();
        for (int i = 2; i <= max; i++) {
            boolean isPrime = true;
            for (int j = 2; j < i; j++) {  // 低效算法
                if (i % j == 0) {
                    isPrime = false;
                    break;
                }
            }
            if (isPrime) {
                primes.add(i);
            }
        }
        return primes;
    }
}

VisualVM會(huì)顯示findPrimes方法占用了大量CPU時(shí)間,幫助開發(fā)者識(shí)別需要優(yōu)化的代碼。

3.Java Mission Control與Flight Recorder

Java Mission Control (JMC)和Flight Recorder (JFR)是Oracle提供的低開銷監(jiān)控工具,特別適合在生產(chǎn)環(huán)境中使用。

主要功能

  • 低開銷監(jiān)控:JFR的性能開銷通常低于2%,適合生產(chǎn)環(huán)境
  • 事件記錄:記錄JVM內(nèi)部事件,如GC、JIT編譯、線程事件等
  • 規(guī)則引擎:自動(dòng)分析記錄數(shù)據(jù),提供優(yōu)化建議
  • 詳細(xì)的GC分析:提供垃圾回收詳細(xì)信息和性能影響

實(shí)戰(zhàn)應(yīng)用

使用JMC和JFR分析GC問題:

  • 啟動(dòng)應(yīng)用時(shí)添加JFR參數(shù):-XX:+FlightRecorder
  • 在JMC中連接到應(yīng)用并啟動(dòng)記錄
  • 設(shè)置記錄時(shí)長(zhǎng)和事件詳細(xì)程度
  • 分析記錄結(jié)果,特別關(guān)注GC相關(guān)事件

JFR記錄可以顯示Full GC的頻率、持續(xù)時(shí)間和原因,幫助識(shí)別內(nèi)存配置問題或內(nèi)存泄漏。

APM工具與服務(wù)

隨著應(yīng)用架構(gòu)向分布式和微服務(wù)方向演進(jìn),傳統(tǒng)的單機(jī)性能分析工具已經(jīng)不足以應(yīng)對(duì)復(fù)雜系統(tǒng)的監(jiān)控需求。應(yīng)用性能管理(APM)工具應(yīng)運(yùn)而生,它們提供了全方位的分布式系統(tǒng)性能監(jiān)控能力。

Pinpoint全鏈路追蹤

Pinpoint是一款開源的APM工具,專注于分布式應(yīng)用的性能分析和事務(wù)追蹤,特別適合微服務(wù)架構(gòu)。

主要功能

1.分布式事務(wù)追蹤:

  • 端到端的請(qǐng)求跟蹤,可視化展示調(diào)用鏈
  • 精確定位每個(gè)服務(wù)節(jié)點(diǎn)的性能問題
  • 支持跨進(jìn)程、跨服務(wù)器的調(diào)用追蹤

2.實(shí)時(shí)監(jiān)控:

  • 服務(wù)器地圖:直觀展示系統(tǒng)拓?fù)浣Y(jié)構(gòu)
  • 實(shí)時(shí)活動(dòng)線程監(jiān)控
  • JVM資源使用情況監(jiān)控

3.代碼級(jí)分析:

  • 方法級(jí)調(diào)用分析
  • SQL查詢分析
  • 外部調(diào)用(HTTP, Redis, MongoDB等)分析

實(shí)戰(zhàn)應(yīng)用

Pinpoint的部署架構(gòu)包括三個(gè)主要組件:

  • Pinpoint Agent:附加到Java應(yīng)用上的代理,收集性能數(shù)據(jù)
  • Pinpoint Collector:接收和處理Agent發(fā)送的數(shù)據(jù)
  • Pinpoint Web:提供Web界面展示分析結(jié)果

部署示例:

# docker-compose.yml示例
version: '3.6'
services:
  pinpoint-hbase:
    container_name: pinpoint-hbase
    image: pinpointdocker/pinpoint-hbase:2.3.3
    restart: always
    ports:
      - "2181:2181"
      - "16010:16010"
    environment:
      - JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64
      - HBASE_MANAGES_ZK=true
    volumes:
      - /path/to/hbase-data:/home/pinpoint/hbase

  pinpoint-collector:
    container_name: pinpoint-collector
    image: pinpointdocker/pinpoint-collector:2.3.3
    restart: always
    ports:
      - "9994:9994"
      - "9995:9995"
      - "9996:9996"
    environment:
      - HBASE_HOST=pinpoint-hbase
      - HBASE_PORT=2181
      - DEBUG_LEVEL=INFO

???????  pinpoint-web:
    container_name: pinpoint-web
    image: pinpointdocker/pinpoint-web:2.3.3
    restart: always
    ports:
      - "8080:8080"
    environment:
      - HBASE_HOST=pinpoint-hbase
      - HBASE_PORT=2181
      - DEBUG_LEVEL=INFO

Java應(yīng)用集成Pinpoint的配置示例:

# 添加Pinpoint Agent到Java啟動(dòng)參數(shù)
java -javaagent:/path/to/pinpoint-agent/pinpoint-bootstrap-2.3.3.jar \
     -Dpinpoint.agentId=my-application \
     -Dpinpoint.applicationName=MyApplication \
     -jar my-application.jar

SkyWalking分布式系統(tǒng)性能監(jiān)控

Apache SkyWalking是另一款優(yōu)秀的開源APM系統(tǒng),它提供了分布式系統(tǒng)的監(jiān)控、追蹤和診斷能力。相比Pinpoint,SkyWalking在國(guó)內(nèi)社區(qū)更為活躍,且提供了更豐富的語言支持。

主要功能

1.服務(wù)、服務(wù)實(shí)例和端點(diǎn)指標(biāo):

  • 服務(wù)級(jí)別的性能指標(biāo)
  • 服務(wù)實(shí)例(單個(gè)節(jié)點(diǎn))的健康狀況
  • 端點(diǎn)(API)級(jí)別的響應(yīng)時(shí)間分析

2.拓?fù)鋱D分析:

  • 自動(dòng)發(fā)現(xiàn)服務(wù)依賴關(guān)系
  • 可視化展示系統(tǒng)架構(gòu)
  • 識(shí)別服務(wù)間的調(diào)用瓶頸

3.分布式追蹤:

  • 完整的分布式追蹤能力
  • 方法棧分析
  • 異常捕獲和分析

4.告警系統(tǒng):

  • 基于規(guī)則的告警機(jī)制
  • 支持多種通知渠道
  • 自定義告警閾值

實(shí)戰(zhàn)應(yīng)用

SkyWalking的核心組件包括:

  • Agent:收集應(yīng)用性能數(shù)據(jù)
  • OAP(Observability Analysis Platform):數(shù)據(jù)分析平臺(tái)
  • UI:可視化界面

Spring Boot應(yīng)用集成SkyWalking的示例:

# 添加SkyWalking Agent到Java啟動(dòng)參數(shù)
java -javaagent:/path/to/skywalking-agent/skywalking-agent.jar \
     -Dskywalking.agent.service_name=my-service \
     -Dskywalking.collector.backend_service=oap-server:11800 \
     -jar my-application.jar

SkyWalking的一個(gè)典型應(yīng)用場(chǎng)景是識(shí)別慢SQL查詢:

// 可能導(dǎo)致性能問題的數(shù)據(jù)庫操作
@Service
public class ProductService {
    @Autowired
    private JdbcTemplate jdbcTemplate;
    
    public List<Product> findProductsByCategory(String category) {
        // 未優(yōu)化的SQL查詢,可能導(dǎo)致全表掃描
        String sql = "SELECT * FROM products WHERE category LIKE '%" + category + "%'";
        return jdbcTemplate.query(sql, new ProductRowMapper());
    }
}

SkyWalking可以識(shí)別這種慢查詢,并在追蹤視圖中顯示其執(zhí)行時(shí)間和SQL語句,幫助開發(fā)者定位問題。

基于Prometheus的監(jiān)控體系

在現(xiàn)代云原生架構(gòu)中,Prometheus已經(jīng)成為事實(shí)上的監(jiān)控標(biāo)準(zhǔn)。它是一個(gè)開源的系統(tǒng)監(jiān)控和告警工具包,特別適合容器化環(huán)境和動(dòng)態(tài)服務(wù)編排平臺(tái)。

Prometheus架構(gòu)與工作原理

Prometheus采用拉取(Pull)模式收集指標(biāo)數(shù)據(jù),這種設(shè)計(jì)使其特別適合動(dòng)態(tài)變化的環(huán)境。

核心組件

Prometheus Server:

  • 時(shí)序數(shù)據(jù)庫:存儲(chǔ)所有收集的指標(biāo)數(shù)據(jù)
  • 數(shù)據(jù)抓?。憾ㄆ趶哪繕?biāo)服務(wù)拉取指標(biāo)
  • PromQL查詢引擎:提供強(qiáng)大的查詢語言

Exporters:

  • 將各種系統(tǒng)和服務(wù)的指標(biāo)暴露為Prometheus可以抓取的格式
  • 常見的Exporters包括Node Exporter(系統(tǒng)指標(biāo))、JMX Exporter(Java應(yīng)用指標(biāo))等

Alertmanager:

  • 處理告警:根據(jù)規(guī)則觸發(fā)告警
  • 分組和抑制:減少告警風(fēng)暴
  • 路由:將告警發(fā)送到不同的通知渠道

Pushgateway:

  • 允許短期作業(yè)推送指標(biāo)
  • 適用于不適合拉取模式的場(chǎng)景

工作流程

  • Prometheus服務(wù)器定期從配置的目標(biāo)(targets)抓取指標(biāo)
  • 收集的指標(biāo)存儲(chǔ)在本地時(shí)序數(shù)據(jù)庫中
  • 根據(jù)規(guī)則評(píng)估數(shù)據(jù),生成新的時(shí)間序列或觸發(fā)告警
  • Grafana或其他可視化工具查詢Prometheus數(shù)據(jù)并展示

Java應(yīng)用集成Prometheus

Java應(yīng)用可以通過多種方式與Prometheus集成,最常見的是使用Micrometer框架。

使用Micrometer和Spring Boot

Micrometer是一個(gè)應(yīng)用指標(biāo)門面,提供了一個(gè)與供應(yīng)商無關(guān)的指標(biāo)收集API。Spring Boot 2.x已經(jīng)集成了Micrometer。

配置示例:

<!-- Maven依賴 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
    <groupId>io.micrometer</groupId>
    <artifactId>micrometer-registry-prometheus</artifactId>
</dependency>
# application.properties
# 啟用Prometheus端點(diǎn)
management.endpoints.web.exposure.include=prometheus,health,info
# 啟用所有指標(biāo)
management.metrics.enable.all=true

自定義指標(biāo)示例:

@RestController
public class OrderController {
    private final Counter orderCounter;
    private final Timer orderProcessingTimer;
    
    public OrderController(MeterRegistry registry) {
        this.orderCounter = Counter.builder("app.orders.total")
                .description("Total number of orders processed")
                .register(registry);
                
        this.orderProcessingTimer = Timer.builder("app.orders.processing.time")
                .description("Order processing time")
                .register(registry);
    }
    
    @PostMapping("/orders")
    public ResponseEntity<Order> createOrder(@RequestBody Order order) {
        return orderProcessingTimer.record(() -> {
            // 處理訂單邏輯
            orderCounter.increment();
            return ResponseEntity.ok(orderService.createOrder(order));
        });
    }
}

Prometheus配置

Prometheus服務(wù)器配置示例:

# prometheus.yml
global:
  scrape_interval: 15s
  evaluation_interval: 15s

scrape_configs:
  - job_name: 'spring-boot-app'
    metrics_path: '/actuator/prometheus'
    static_configs:
      - targets: ['app-server:8080']

Grafana可視化面板構(gòu)建

Grafana是一個(gè)開源的可視化和分析平臺(tái),可以與Prometheus無縫集成,提供強(qiáng)大的數(shù)據(jù)可視化能力。

關(guān)鍵功能

數(shù)據(jù)源集成:支持多種數(shù)據(jù)源,包括Prometheus、Elasticsearch、InfluxDB等

豐富的可視化選項(xiàng):圖表、儀表盤、熱力圖、表格等

告警功能:基于可視化面板設(shè)置告警規(guī)則

用戶權(quán)限管理:控制面板的訪問權(quán)限

JVM監(jiān)控面板

為Java應(yīng)用創(chuàng)建JVM監(jiān)控面板是最基本的需求。以下是一個(gè)典型的JVM監(jiān)控面板包含的指標(biāo):

1.內(nèi)存使用情況:

  • 堆內(nèi)存使用量
  • 非堆內(nèi)存使用量
  • 各代內(nèi)存使用情況

2.垃圾回收:

  • GC次數(shù)
  • GC暫停時(shí)間
  • 各代GC活動(dòng)

3.線程:

  • 活動(dòng)線程數(shù)
  • 守護(hù)線程數(shù)
  • 阻塞線程數(shù)

4.類加載:

  • 已加載類數(shù)量
  • 卸載類數(shù)量

PromQL查詢示例:

# 堆內(nèi)存使用率
sum(jvm_memory_used_bytes{area="heap"}) / sum(jvm_memory_max_bytes{area="heap"})

# GC暫停時(shí)間
rate(jvm_gc_pause_seconds_sum[5m])

# 線程數(shù)
jvm_threads_live_threads

常見指標(biāo)與告警策略

有效的監(jiān)控不僅僅是收集數(shù)據(jù),還需要設(shè)置合理的告警策略,以便及時(shí)發(fā)現(xiàn)和解決問題。

核心指標(biāo)

1.RED指標(biāo):適用于服務(wù)監(jiān)控

  • Rate (請(qǐng)求率):每秒請(qǐng)求數(shù)
  • Error (錯(cuò)誤率):失敗請(qǐng)求的比例
  • Duration (持續(xù)時(shí)間):請(qǐng)求處理時(shí)間

2.USE指標(biāo):適用于資源監(jiān)控

  • Utilization (使用率):資源忙碌的時(shí)間比例
  • Saturation (飽和度):資源的額外工作量
  • Errors (錯(cuò)誤):錯(cuò)誤事件計(jì)數(shù)

告警規(guī)則示例

# Prometheus告警規(guī)則
groups:
- name: jvm-alerts
  rules:
  - alert: HighHeapUsage
    expr: sum(jvm_memory_used_bytes{area="heap"}) / sum(jvm_memory_max_bytes{area="heap"}) > 0.9
    for: 5m
    labels:
      severity: warning
    annotations:
      summary: "High Heap Memory Usage"
      description: "JVM heap usage is above 90% for 5 minutes on {{ $labels.instance }}"
      
  - alert: HighGCPauseTime
    expr: rate(jvm_gc_pause_seconds_sum[5m]) > 0.5
    for: 2m
    labels:
      severity: critical
    annotations:
      summary: "High GC Pause Time"
      description: "GC pause time is too high on {{ $labels.instance }}"
      
  - alert: HighCPUUsage
    expr: process_cpu_usage > 0.8
    for: 5m
    labels:
      severity: warning
    annotations:
      summary: "High CPU Usage"
      description: "CPU usage is above 80% for 5 minutes on {{ $labels.instance }}"

性能調(diào)優(yōu)最佳實(shí)踐

監(jiān)控系統(tǒng)能夠幫助我們發(fā)現(xiàn)性能問題,但解決這些問題還需要有效的調(diào)優(yōu)策略。本節(jié)將介紹Java應(yīng)用性能調(diào)優(yōu)的最佳實(shí)踐。

JVM參數(shù)優(yōu)化

JVM參數(shù)配置對(duì)Java應(yīng)用的性能有著至關(guān)重要的影響。合理的JVM參數(shù)可以顯著提升應(yīng)用性能。

內(nèi)存配置

堆內(nèi)存設(shè)置:

  • -Xms和-Xmx:設(shè)置初始和最大堆大小
  • 建議將兩者設(shè)置為相同值,避免堆大小動(dòng)態(tài)調(diào)整帶來的性能波動(dòng)
  • 通常設(shè)置為可用物理內(nèi)存的50%-70%

新生代和老年代比例:

  • -XX:NewRatio:設(shè)置老年代與新生代的比例
  • -XX:SurvivorRatio:設(shè)置Eden區(qū)與Survivor區(qū)的比例
  • 對(duì)于高并發(fā)應(yīng)用,可以增大新生代比例,減少Full GC頻率

元空間配置:

  • -XX:MetaspaceSize和-XX:MaxMetaspaceSize:設(shè)置元空間初始和最大大小
  • 對(duì)于使用大量動(dòng)態(tài)類加載的應(yīng)用,需要適當(dāng)增加元空間大小

垃圾回收器選擇

常用垃圾回收器:

  • Parallel GC:注重吞吐量,適合批處理應(yīng)用
  • CMS:低延遲,適合交互式應(yīng)用,但已被標(biāo)記為廢棄
  • G1:平衡吞吐量和延遲,適合大內(nèi)存應(yīng)用
  • ZGC:超低延遲,適合對(duì)GC停頓時(shí)間要求極高的應(yīng)用

G1垃圾回收器配置:

-XX:+UseG1GC
-XX:MaxGCPauseMillis=200
-XX:InitiatingHeapOccupancyPercent=45

ZGC配置示例(JDK 11+):

-XX:+UnlockExperimentalVMOptions
-XX:+UseZGC
-XX:ZCollectionInterval=120

JIT編譯器優(yōu)化

分層編譯:

  • -XX:+TieredCompilation:?jiǎn)⒂梅謱泳幾g
  • 結(jié)合解釋執(zhí)行和不同級(jí)別的JIT編譯,提供最佳性能

編譯閾值調(diào)整:

  • -XX:CompileThreshold:方法調(diào)用多少次后觸發(fā)編譯
  • 降低閾值可以更快進(jìn)入編譯狀態(tài),但會(huì)增加編譯開銷

代碼緩存大?。?/p>

  • -XX:ReservedCodeCacheSize:設(shè)置JIT編譯代碼的緩存大小
  • 對(duì)于大型應(yīng)用,可能需要增加默認(rèn)值

實(shí)戰(zhàn)配置示例

以下是一個(gè)面向微服務(wù)應(yīng)用的JVM配置示例:

java -server \
     -Xms2g -Xmx2g \
     -XX:+UseG1GC \
     -XX:MaxGCPauseMillis=100 \
     -XX:+ParallelRefProcEnabled \
     -XX:ErrorFile=/var/log/java_error.log \
     -XX:+HeapDumpOnOutOfMemoryError \
     -XX:HeapDumpPath=/var/log/java_heapdump.hprof \
     -Xlog:gc*:file=/var/log/gc.log:time,uptime,level,tags:filecount=5,filesize=100m \
     -jar my-application.jar

代碼級(jí)優(yōu)化技巧

除了JVM級(jí)別的調(diào)優(yōu),代碼級(jí)別的優(yōu)化也是提升應(yīng)用性能的關(guān)鍵。

集合類優(yōu)化

選擇合適的集合類:

  • 隨機(jī)訪問優(yōu)先使用ArrayList,而不是LinkedList
  • 頻繁插入刪除操作優(yōu)先使用LinkedList
  • 對(duì)于高并發(fā)場(chǎng)景,考慮使用ConcurrentHashMap而不是HashMap

預(yù)設(shè)集合初始容量:

// 優(yōu)化前
List<Customer> customers = new ArrayList<>();  // 默認(rèn)容量為10

// 優(yōu)化后
List<Customer> customers = new ArrayList<>(10000);  // 預(yù)設(shè)合適的容量

避免頻繁擴(kuò)容:

// 優(yōu)化前
Map<String, Object> cache = new HashMap<>();  // 負(fù)載因子0.75,容量16

// 優(yōu)化后
Map<String, Object> cache = new HashMap<>(1024, 0.9f);  // 更大的容量和負(fù)載因子

并發(fā)編程優(yōu)化

線程池配置:

// 優(yōu)化前:創(chuàng)建無限制的線程
ExecutorService executor = Executors.newCachedThreadPool();

// 優(yōu)化后:創(chuàng)建有界線程池
ExecutorService executor = new ThreadPoolExecutor(
    10,                 // 核心線程數(shù)
    20,                 // 最大線程數(shù)
    60, TimeUnit.SECONDS, // 空閑線程存活時(shí)間
    new ArrayBlockingQueue<>(500), // 工作隊(duì)列
    new ThreadPoolExecutor.CallerRunsPolicy() // 拒絕策略
);

避免鎖競(jìng)爭(zhēng):

// 優(yōu)化前:粗粒度鎖
public synchronized void updateStats(String key, int value) {
    // 更新統(tǒng)計(jì)信息
}

// 優(yōu)化后:細(xì)粒度鎖
private final Map<String, Object> lockMap = new ConcurrentHashMap<>();

public void updateStats(String key, int value) {
    Object lock = lockMap.computeIfAbsent(key, k -> new Object());
    synchronized(lock) {
        // 更新特定key的統(tǒng)計(jì)信息
    }
}

使用并發(fā)工具類:

  • 使用ConcurrentHashMap代替synchronized的HashMap
  • 使用AtomicInteger代替synchronized的計(jì)數(shù)器
  • 使用CopyOnWriteArrayList代替synchronized的ArrayList

數(shù)據(jù)結(jié)構(gòu)和算法優(yōu)化

緩存計(jì)算結(jié)果:

// 使用Guava緩存
LoadingCache<Key, Graph> graphs = CacheBuilder.newBuilder()
    .maximumSize(1000)
    .expireAfterWrite(10, TimeUnit.MINUTES)
    .recordStats()
    .build(
        new CacheLoader<Key, Graph>() {
            public Graph load(Key key) throws Exception {
                return createExpensiveGraph(key);
            }
        });

避免不必要的對(duì)象創(chuàng)建:

// 優(yōu)化前:每次調(diào)用都創(chuàng)建新對(duì)象
public String formatDate(Date date) {
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
    return sdf.format(date);
}

// 優(yōu)化后:使用ThreadLocal避免重復(fù)創(chuàng)建
private static final ThreadLocal<SimpleDateFormat> dateFormatter = 
    ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyy-MM-dd"));
    
public String formatDate(Date date) {
    return dateFormatter.get().format(date);
}

使用更高效的算法:

  • 使用二分查找代替線性查找
  • 使用HashMap進(jìn)行O(1)查找而不是列表的O(n)查找
  • 避免嵌套循環(huán),降低算法復(fù)雜度

數(shù)據(jù)庫交互優(yōu)化

數(shù)據(jù)庫操作通常是Java應(yīng)用的性能瓶頸,優(yōu)化數(shù)據(jù)庫交互可以顯著提升應(yīng)用性能。

連接池優(yōu)化

HikariCP配置:

# 連接池大小配置
spring.datasource.hikari.maximum-pool-size=10
spring.datasource.hikari.minimum-idle=5

# 連接超時(shí)配置
spring.datasource.hikari.connection-timeout=30000
spring.datasource.hikari.idle-timeout=600000
spring.datasource.hikari.max-lifetime=1800000

監(jiān)控連接池:

@Bean
public HikariDataSource dataSource() {
    HikariConfig config = new HikariConfig();
    // 基本配置
    config.setJdbcUrl("jdbc:mysql://localhost:3306/mydb");
    config.setUsername("user");
    config.setPassword("password");
    
    // 連接池配置
    config.setMaximumPoolSize(10);
    config.setMinimumIdle(5);
    
    // 添加指標(biāo)收集
    config.setMetricRegistry(metricRegistry);
    
    return new HikariDataSource(config);
}

SQL查詢優(yōu)化

使用索引:

-- 優(yōu)化前:無索引查詢
SELECT * FROM orders WHERE customer_id = ?

-- 優(yōu)化后:添加索引
CREATE INDEX idx_customer_id ON orders(customer_id);

避免N+1查詢問題:

// 優(yōu)化前:N+1查詢問題
List<Order> orders = orderRepository.findAll();
for (Order order : orders) {
    Customer customer = customerRepository.findById(order.getCustomerId());
    // 處理訂單和客戶
}

// 優(yōu)化后:使用JOIN查詢
List<OrderWithCustomer> results = orderRepository.findAllOrdersWithCustomers();

分頁查詢:

// 優(yōu)化前:一次性加載所有數(shù)據(jù)
List<Product> products = productRepository.findAll();

// 優(yōu)化后:使用分頁查詢
Page<Product> productPage = productRepository.findAll(
    PageRequest.of(0, 100, Sort.by("name"))
);

批處理操作

批量插入:

// 優(yōu)化前:?jiǎn)螚l插入
for (Order order : orders) {
    jdbcTemplate.update("INSERT INTO orders VALUES (?, ?, ?)", 
        order.getId(), order.getCustomerId(), order.getAmount());
}

???????// 優(yōu)化后:批量插入
jdbcTemplate.batchUpdate("INSERT INTO orders VALUES (?, ?, ?)",
    new BatchPreparedStatementSetter() {
        @Override
        public void setValues(PreparedStatement ps, int i) throws SQLException {
            Order order = orders.get(i);
            ps.setLong(1, order.getId());
            ps.setLong(2, order.getCustomerId());
            ps.setBigDecimal(3, order.getAmount());
        }
        
        @Override
        public int getBatchSize() {
            return orders.size();
        }
    });

使用JPA批處理:

# 啟用JPA批處理
spring.jpa.properties.hibernate.jdbc.batch_size=50
spring.jpa.properties.hibernate.order_inserts=true
spring.jpa.properties.hibernate.order_updates=true

工具鏈整合策略

構(gòu)建一個(gè)完整的性能監(jiān)控與調(diào)優(yōu)工具鏈,需要將前面介紹的各種工具有機(jī)地整合起來,形成覆蓋開發(fā)、測(cè)試和生產(chǎn)環(huán)境的全生命周期監(jiān)控體系。

從開發(fā)到生產(chǎn)的監(jiān)控體系

不同的環(huán)境有不同的監(jiān)控需求,需要選擇合適的工具組合。

開發(fā)環(huán)境

開發(fā)環(huán)境的監(jiān)控主要關(guān)注代碼質(zhì)量和性能問題的早期發(fā)現(xiàn)。

IDE集成工具:

  • JProfiler或YourKit的IDE插件
  • Eclipse Memory Analyzer Tool (MAT)
  • IntelliJ IDEA內(nèi)置的性能分析器

代碼質(zhì)量工具:

  • SonarQube:靜態(tài)代碼分析,發(fā)現(xiàn)潛在性能問題
  • JaCoCo:代碼覆蓋率分析,確保性能測(cè)試的充分性

單元測(cè)試性能框架:

JMH (Java Microbenchmark Harness):微基準(zhǔn)測(cè)試框架

示例:

@Benchmark
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.MICROSECONDS)
public void testStringConcatenation() {
    String result = "";
    for (int i = 0; i < 100; i++) {
        result += i;  // 低效的字符串拼接
    }
}

???????@Benchmark
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.MICROSECONDS)
public void testStringBuilder() {
    StringBuilder sb = new StringBuilder();
    for (int i = 0; i < 100; i++) {
        sb.append(i);  // 高效的字符串拼接
    }
    String result = sb.toString();
}

測(cè)試環(huán)境

測(cè)試環(huán)境的監(jiān)控需要更全面,模擬生產(chǎn)環(huán)境的負(fù)載情況。

負(fù)載測(cè)試工具:

  • JMeter:創(chuàng)建復(fù)雜的負(fù)載測(cè)試場(chǎng)景
  • Gatling:基于Scala的高性能負(fù)載測(cè)試工具
  • 配合APM工具分析系統(tǒng)在負(fù)載下的性能瓶頸

環(huán)境監(jiān)控:

  • Prometheus + Grafana:監(jiān)控系統(tǒng)資源和應(yīng)用指標(biāo)
  • ELK Stack:收集和分析日志數(shù)據(jù)

持續(xù)集成/持續(xù)部署(CI/CD)集成:

  • 在CI/CD流程中集成性能測(cè)試
  • 設(shè)置性能基準(zhǔn),自動(dòng)對(duì)比性能變化
  • 性能退化時(shí)自動(dòng)告警

生產(chǎn)環(huán)境

生產(chǎn)環(huán)境的監(jiān)控需要輕量級(jí)、高可靠性,并且不影響系統(tǒng)性能。

輕量級(jí)JVM監(jiān)控:

  • JMX + Prometheus JMX Exporter:低開銷的JVM指標(biāo)收集
  • Java Flight Recorder:生產(chǎn)環(huán)境性能數(shù)據(jù)記錄

分布式追蹤:

  • SkyWalking或Pinpoint:全鏈路追蹤
  • Spring Cloud Sleuth + Zipkin:微服務(wù)架構(gòu)的分布式追蹤

日志和指標(biāo)聚合:

  • ELK Stack (Elasticsearch, Logstash, Kibana):日志聚合和分析
  • Prometheus + Grafana:指標(biāo)收集和可視化
  • Alertmanager:告警管理和通知

自動(dòng)化運(yùn)維:

  • 自動(dòng)擴(kuò)縮容策略
  • 基于監(jiān)控指標(biāo)的自動(dòng)恢復(fù)機(jī)制

性能問題排查流程

當(dāng)監(jiān)控系統(tǒng)檢測(cè)到性能問題時(shí),需要有一個(gè)系統(tǒng)化的排查流程。

問題識(shí)別

1.確認(rèn)問題的范圍和影響:

  • 是系統(tǒng)級(jí)問題還是特定服務(wù)問題?
  • 影響了多少用戶?
  • 問題是持續(xù)的還是間歇性的?

2.收集關(guān)鍵指標(biāo):

  • 系統(tǒng)資源使用情況:CPU、內(nèi)存、磁盤I/O、網(wǎng)絡(luò)
  • JVM指標(biāo):堆內(nèi)存使用、GC活動(dòng)、線程狀態(tài)
  • 應(yīng)用指標(biāo):請(qǐng)求率、錯(cuò)誤率、響應(yīng)時(shí)間
  • 數(shù)據(jù)庫指標(biāo):連接數(shù)、查詢執(zhí)行時(shí)間、鎖等待

問題分析

自頂向下分析:

  • 從用戶體驗(yàn)問題開始
  • 通過分布式追蹤定位問題服務(wù)
  • 分析服務(wù)內(nèi)部的方法調(diào)用和資源使用

常見性能問題模式:

  • CPU密集型問題:算法效率低、無限循環(huán)
  • 內(nèi)存問題:內(nèi)存泄漏、過度分配
  • I/O問題:阻塞I/O、資源等待
  • 并發(fā)問題:鎖競(jìng)爭(zhēng)、線程池配置不當(dāng)

工具組合使用:

  • 使用APM工具定位問題服務(wù)和端點(diǎn)
  • 使用JProfiler或Flight Recorder深入分析JVM行為
  • 使用數(shù)據(jù)庫監(jiān)控工具分析SQL性能

問題解決

短期解決方案:

  • 增加資源:擴(kuò)展實(shí)例數(shù)、增加內(nèi)存
  • 調(diào)整配置:優(yōu)化JVM參數(shù)、連接池設(shè)置
  • 重啟服務(wù):清除內(nèi)存泄漏或資源耗盡問題

長(zhǎng)期解決方案:

  • 代碼重構(gòu):優(yōu)化算法、修復(fù)內(nèi)存泄漏
  • 架構(gòu)調(diào)整:拆分服務(wù)、優(yōu)化數(shù)據(jù)模型
  • 緩存策略:引入或優(yōu)化緩存機(jī)制

驗(yàn)證解決方案:

  • 在測(cè)試環(huán)境復(fù)現(xiàn)并驗(yàn)證修復(fù)
  • 使用負(fù)載測(cè)試工具驗(yàn)證性能改進(jìn)
  • 在生產(chǎn)環(huán)境部署并密切監(jiān)控

案例分析:內(nèi)存泄漏排查

以下是一個(gè)典型的內(nèi)存泄漏排查流程:

問題識(shí)別:

  • Prometheus告警顯示堆內(nèi)存使用率持續(xù)增長(zhǎng)
  • GC頻率增加,但無法釋放足夠內(nèi)存
  • 應(yīng)用響應(yīng)時(shí)間逐漸增加

問題分析:

  • 使用JMX查看內(nèi)存使用趨勢(shì),確認(rèn)是內(nèi)存泄漏而非內(nèi)存配置不足
  • 使用Java Flight Recorder收集堆轉(zhuǎn)儲(chǔ)
  • 使用Eclipse MAT分析堆轉(zhuǎn)儲(chǔ),找出占用內(nèi)存最多的對(duì)象
  • 發(fā)現(xiàn)大量HashMap實(shí)例被靜態(tài)引用持有

問題解決:

定位到使用靜態(tài)HashMap作為緩存但沒有大小限制的代碼

修改為使用LRU緩存,限制最大條目數(shù)

或者使用WeakHashMap,允許不再使用的鍵值被GC回收

// 優(yōu)化前:無限制的緩存,可能導(dǎo)致內(nèi)存泄漏
private static final Map<String, Object> cache = new HashMap<>();

// 優(yōu)化后:使用Guava緩存,限制大小和過期時(shí)間
private static final Cache<String, Object> cache = CacheBuilder.newBuilder()
    .maximumSize(1000)
    .expireAfterWrite(10, TimeUnit.MINUTES)
    .build();

結(jié)論與展望

本文詳細(xì)介紹了Java應(yīng)用性能監(jiān)控與調(diào)優(yōu)的完整工具鏈,從單機(jī)分析工具JProfiler到分布式監(jiān)控系統(tǒng)Prometheus,覆蓋了開發(fā)、測(cè)試和生產(chǎn)環(huán)境的全生命周期監(jiān)控需求。

關(guān)鍵要點(diǎn)總結(jié)

性能監(jiān)控是持續(xù)過程:性能監(jiān)控不是一次性工作,而是需要貫穿應(yīng)用生命周期的持續(xù)活動(dòng)。

多層次監(jiān)控體系:有效的監(jiān)控需要覆蓋JVM層面、應(yīng)用層面、系統(tǒng)層面和業(yè)務(wù)層面。

工具選擇要適合場(chǎng)景:

  • 開發(fā)環(huán)境:JProfiler、VisualVM等詳細(xì)分析工具
  • 測(cè)試環(huán)境:JMeter、APM工具等全面監(jiān)控工具
  • 生產(chǎn)環(huán)境:Prometheus、SkyWalking等輕量級(jí)監(jiān)控工具

性能調(diào)優(yōu)的系統(tǒng)方法:

  • JVM參數(shù)優(yōu)化:內(nèi)存配置、垃圾回收器選擇
  • 代碼級(jí)優(yōu)化:數(shù)據(jù)結(jié)構(gòu)、算法、并發(fā)處理
  • 數(shù)據(jù)庫交互優(yōu)化:連接池、SQL查詢、批處理
  • 問題排查的結(jié)構(gòu)化流程:?jiǎn)栴}識(shí)別、分析和解決的系統(tǒng)化方法

未來趨勢(shì)

AIOps的興起:

  • 人工智能輔助的運(yùn)維將成為趨勢(shì)
  • 基于機(jī)器學(xué)習(xí)的異常檢測(cè)和根因分析
  • 自動(dòng)化的性能優(yōu)化建議

云原生監(jiān)控:

  • 容器和Kubernetes環(huán)境的專用監(jiān)控工具
  • 服務(wù)網(wǎng)格(Service Mesh)的可觀測(cè)性
  • 無服務(wù)器(Serverless)架構(gòu)的性能監(jiān)控

實(shí)時(shí)分析與預(yù)測(cè):

  • 實(shí)時(shí)流處理的性能數(shù)據(jù)分析
  • 預(yù)測(cè)性分析,提前發(fā)現(xiàn)潛在問題
  • 自動(dòng)化的容量規(guī)劃

更深入的代碼級(jí)優(yōu)化:

  • JVM即時(shí)編譯器(JIT)的更多優(yōu)化
  • 更智能的垃圾回收算法
  • 更高效的并發(fā)編程模型

通過構(gòu)建完整的性能監(jiān)控與調(diào)優(yōu)工具鏈,我們可以更好地理解和優(yōu)化Java應(yīng)用的性能,提供更好的用戶體驗(yàn),同時(shí)降低運(yùn)維成本。隨著技術(shù)的不斷發(fā)展,性能監(jiān)控與調(diào)優(yōu)的工具和方法也將不斷演進(jìn),為我們提供更強(qiáng)大的能力來應(yīng)對(duì)日益復(fù)雜的應(yīng)用場(chǎng)景。

以上就是深入探討Java應(yīng)用性能監(jiān)控與調(diào)優(yōu)的工具鏈構(gòu)建的詳細(xì)內(nèi)容,更多關(guān)于Java性能監(jiān)控與調(diào)優(yōu)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • JAVA多線程和并發(fā)基礎(chǔ)面試問答(翻譯)

    JAVA多線程和并發(fā)基礎(chǔ)面試問答(翻譯)

    多線程和并發(fā)問題是Java技術(shù)面試中面試官比較喜歡問的問題之一。在這里,從面試的角度列出了大部分重要的問題,但是你仍然應(yīng)該牢固的掌握J(rèn)ava多線程基礎(chǔ)知識(shí)來對(duì)應(yīng)日后碰到的問題
    2014-09-09
  • java 字符串截取的實(shí)例詳解

    java 字符串截取的實(shí)例詳解

    這篇文章主要介紹了java 字符串截取的實(shí)例詳解的相關(guān)資料,這里提供了實(shí)例代碼幫助大家實(shí)現(xiàn)這樣的功能,需要的朋友可以參考下
    2017-08-08
  • SpringMvc靜態(tài)資源訪問實(shí)現(xiàn)方法代碼實(shí)例

    SpringMvc靜態(tài)資源訪問實(shí)現(xiàn)方法代碼實(shí)例

    這篇文章主要介紹了SpringMvc靜態(tài)資源訪問實(shí)現(xiàn)方法代碼實(shí)例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-08-08
  • Java中直接初始化HashMap的方法實(shí)現(xiàn)

    Java中直接初始化HashMap的方法實(shí)現(xiàn)

    在Java編程中,HashMap 是常用的數(shù)據(jù)結(jié)構(gòu),用于存儲(chǔ)鍵值對(duì),有時(shí)我們需要在創(chuàng)建 HashMap 的同時(shí)就初始化一些固定的、不會(huì)改變的值,然而,Java并沒有像某些動(dòng)態(tài)語言那樣的直接字面量初始化語法,所以本文給大家介紹了Java中直接初始化HashMap的方法,需要的朋友可以參考下
    2025-06-06
  • 超詳細(xì)介紹idea中java程序打jar包的兩種方式

    超詳細(xì)介紹idea中java程序打jar包的兩種方式

    這篇文章主要介紹了超詳細(xì)介紹idea中java程序打jar包的兩種方式一種是可直接執(zhí)行的runnable jar文件,另一種是包含多個(gè)主類,運(yùn)行時(shí)需要指定主類全類名的jar包,感興趣的可以了解一下
    2020-07-07
  • 詳解SpringBoot實(shí)現(xiàn)fastdfs防盜鏈功能的示例代碼

    詳解SpringBoot實(shí)現(xiàn)fastdfs防盜鏈功能的示例代碼

    我們可以通過fastdfs實(shí)現(xiàn)一個(gè)分布式文件系統(tǒng),如果fastdfs部署在外網(wǎng),那么任何一個(gè)人知道了上傳接口,就可以實(shí)現(xiàn)文件的上傳和訪問。那么如何阻止他人訪問我們fastdfs服務(wù)器上的文件呢?此處就需要使用fastdfs的防盜鏈功能,本文就來講講如何實(shí)現(xiàn)這一功能
    2022-10-10
  • SpringMVC中請(qǐng)求參數(shù)的獲取方式

    SpringMVC中請(qǐng)求參數(shù)的獲取方式

    這篇文章主要為大家介紹了SpringMVC中請(qǐng)求參數(shù)的獲取方式,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-05-05
  • Java日期處理之字符串轉(zhuǎn)換為日期的方法詳解

    Java日期處理之字符串轉(zhuǎn)換為日期的方法詳解

    在Java編程中,日期和時(shí)間的處理是一個(gè)常見的需求,下面我們就來聊聊如何將日期字符串轉(zhuǎn)換為日期對(duì)象,并從中提取有用的信息,如星期幾和一年中的第幾天
    2025-05-05
  • IntelliJ Idea 2017注冊(cè)碼免費(fèi)激活方法

    IntelliJ Idea 2017注冊(cè)碼免費(fèi)激活方法

    IDEA 全稱 IntelliJ IDEA,是Java語言開發(fā)的集成環(huán)境,IntelliJ在業(yè)界被公認(rèn)為最好的java開發(fā)工具之一。下面給大家介紹IntelliJ Idea 2017注冊(cè)碼免費(fèi)激活方法,需要的朋友參考下
    2018-01-01
  • Java Calendar日歷與Date日期的相互轉(zhuǎn)換詳解

    Java Calendar日歷與Date日期的相互轉(zhuǎn)換詳解

    這篇文章主要介紹了Java Calendar日歷與Date日期的相互轉(zhuǎn)換詳解,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-08-08

最新評(píng)論

沛县| 阿拉善左旗| 周口市| 临夏县| 寿光市| 兴国县| 西林县| 旬阳县| 澳门| 永新县| 鸡西市| 遂昌县| 修水县| 睢宁县| 喜德县| 定陶县| 万年县| 本溪市| 措勤县| 苍梧县| 定兴县| 毕节市| 梧州市| 甘洛县| 易门县| 芮城县| 马公市| 郎溪县| 上饶市| 方正县| 象山县| 汝城县| 黑河市| 札达县| 兴安县| 平邑县| 洛隆县| 南宁市| 凤台县| 谢通门县| 瓮安县|