为了账号安全,请及时绑定邮箱和手机立即绑定

JAVA分布式学习入门教程

概述

本文深入探讨了JAVA分布式学习的相关内容,涵盖分布式系统的基础概念、Java在分布式系统中的作用、常见的分布式框架,以及应用场景。文章还提供了具体的代码示例和实战操作指导,帮助读者更好地理解和掌握JAVA分布式开发技术。

分布式系统基础概念

分布式系统是指一组通过网络进行通信、相互协作的独立计算机系统,它们一起提供一个统一的功能。这些计算机系统称为节点或进程,每个节点具有独立的处理能力、本地内存和通信协议。分布式系统的一个关键特性是,系统中的每个节点都可以独立运行,而且即使某些节点出现故障,整个系统仍能继续运行。

分布式系统的特点和优势

特点

  1. 透明性:用户无需关心数据或任务分布到哪些节点上。
  2. 可靠性:通过冗余机制提高系统的可用性。
  3. 可扩展性:通过添加更多的节点来增加系统的处理能力和存储容量。
  4. 灵活性:能够根据需求动态调整资源。
  5. 高效性:利用网络结构进行任务分配和负载均衡。

优势

  1. 高可用性:通过冗余机制,即使部分节点故障,系统仍能继续提供服务。
  2. 可扩展性:可以方便地添加新的节点来扩展系统的处理能力和存储容量。
  3. 灵活性:系统可以根据需求变化动态调整资源分配。
  4. 高效性:利用网络结构进行任务分配和负载均衡,提高了整体的处理效率。
分布式系统的应用场景
  1. 大型网站和应用:如电商平台、社交网络等。
  2. 云计算和大数据处理:处理PB级别的数据,提供海量计算能力。
  3. 物联网:连接和管理大量的设备,处理各种传感器数据。
  4. 金融服务:银行系统、证券交易系统,需要高可靠性和实时性。
  5. 游戏行业:多人在线游戏,需要实时处理大量并发操作。

示例

以电商平台为例,分布式系统可以将订单处理、库存管理、支付系统等功能分布到不同的服务器上,通过网络通信进行协调,以提高系统的并发处理能力和可靠性。

Java分布式开发基础

Java在分布式系统开发中扮演着重要的角色。Java编程语言的平台无关性、丰富的API和支持广泛的开发框架使其成为构建复杂分布式应用的理想选择。

Java在分布式系统中的作用

Java提供了强大的网络编程支持,可以使用Java的套接字(Socket)和远程方法调用(RMI)等技术实现网络通信。此外,Java的反射机制、序列化机制和线程模型也使得分布式开发更加便捷。

示例代码

以下是一个简单的Java Socket客户端和服务端的示例:

服务端代码:

import java.io.*;
import java.net.*;

public class Server {
    public static void main(String[] args) throws IOException {
        ServerSocket serverSocket = new ServerSocket(8080);
        Socket socket = serverSocket.accept();
        BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        String inputLine = in.readLine();
        System.out.println("Received from client: " + inputLine);
        in.close();
        socket.close();
        serverSocket.close();
    }
}

客户端代码:

import java.io.*;
import java.net.*;

public class Client {
    public static void main(String[] args) throws IOException {
        Socket socket = new Socket("localhost", 8080);
        PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
        out.println("Hello Server");
        socket.close();
    }
}
常见的Java分布式框架简介

Spring Boot 和 Spring Cloud

Spring Boot 和 Spring Cloud 是构建微服务架构的常用框架。Spring Boot 使开发独立的、生产级别的Spring应用程序变得简单,而Spring Cloud提供了一系列微服务架构相关的工具和库,简化了服务发现、配置管理、负载均衡、断路器等功能的实现。

示例代码

以下是一个简单的Spring Boot应用示例,展示了一个简单的RESTful API:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@SpringBootApplication
public class Application {

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

@RestController
public class GreetingController {

    @GetMapping("/greeting")
    public String greeting() {
        return "Hello, World!";
    }
}

Dubbo

Dubbo 是一个高性能、轻量级的Java RPC框架,提供了服务治理、服务分发、服务路由等功能。

示例代码

以下是一个简单的Dubbo服务提供者和消费者示例:

服务提供者代码:

import com.alibaba.dubbo.config.ApplicationConfig;
import com.alibaba.dubbo.config.RegistryConfig;
import com.alibaba.dubbo.config.ServiceConfig;

public class Provider {
    public static void main(String[] args) {
        ServiceConfig<GreetingService> serviceConfig = new ServiceConfig<>();
        serviceConfig.setApplication(new ApplicationConfig("dubbo-provider"));
        serviceConfig.setRegistry(new RegistryConfig("zookeeper://127.0.0.1:2181"));
        serviceConfig.setInterface(GreetingService.class);
        serviceConfig.setRef(new GreetingServiceImpl());
        serviceConfig.export();
    }
}

服务消费者代码:

import com.alibaba.dubbo.config.ReferenceConfig;

public class Consumer {
    public static void main(String[] args) {
        ReferenceConfig<GreetingService> referenceConfig = new ReferenceConfig<>();
        referenceConfig.setApplication(new com.alibaba.dubbo.config.ApplicationConfig("dubbo-consumer"));
        referenceConfig.setRegistry(new RegistryConfig("zookeeper://127.0.0.1:2181"));
        referenceConfig.setInterface(GreetingService.class);
        GreetingService greetingService = referenceConfig.get();
        System.out.println(greetingService.greet("World"));
    }
}

RMI 示例代码

以下是一个简单的Java RMI服务提供者和服务消费者示例:

服务提供者代码:

import java.rmi.Remote;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;

public interface GreetingService extends Remote {
    String greet(String name) throws RemoteException;
}

public class GreetingServiceImpl implements GreetingService {
    @Override
    public String greet(String name) throws RemoteException {
        return "Hello, " + name;
    }
}

public class Server {
    public static void main(String[] args) {
        try {
            Registry registry = LocateRegistry.createRegistry(1099);
            registry.rebind("HelloService", new GreetingServiceImpl());
            System.out.println("Server is ready");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

服务消费者代码:

import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;

public class Client {
    public static void main(String[] args) {
        try {
            Registry registry = LocateRegistry.getRegistry("localhost", 1099);
            GreetingService greetingService = (GreetingService) registry.lookup("HelloService");
            System.out.println(greetingService.greet("World"));
        } catch (RemoteException | NotBoundException e) {
            e.printStackTrace();
        }
    }
}

JMS 示例代码

以下是一个简单的JMS示例,展示了一个简单的消息发送和接收的实现:

服务提供者代码:

import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.MessageProducer;
import javax.jms.Session;
import javax.jms.TextMessage;
import javax.jms.Topic;
import org.apache.activemq.ActiveMQConnectionFactory;

public class MessageProducer {
    private static final String BROKER_URL = "tcp://localhost:61616";
    private static final String TOPIC_NAME = "TestTopic";

    public static void main(String[] args) {
        ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(BROKER_URL);
        Connection connection = connectionFactory.createConnection();
        connection.start();
        Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
        Destination destination = session.createTopic(TOPIC_NAME);
        MessageProducer producer = session.createProducer(destination);
        TextMessage message = session.createTextMessage("Hello JMS");
        producer.send(message);
        System.out.println("Message sent: " + message.getText());
        connection.close();
    }
}

服务消费者代码:

import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.MessageListener;
import javax.jms.Session;
import javax.jms.Topic;
import org.apache.activemq.ActiveMQConnectionFactory;

public class MessageConsumer implements MessageListener {
    private static final String BROKER_URL = "tcp://localhost:61616";
    private static final String TOPIC_NAME = "TestTopic";

    public static void main(String[] args) {
        ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(BROKER_URL);
        Connection connection = connectionFactory.createConnection();
        connection.start();
        Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
        Destination destination = session.createTopic(TOPIC_NAME);
        MessageConsumer consumer = session.createConsumer(destination);
        consumer.setMessageListener(new MessageConsumer());
        System.out.println("Waiting for messages...");
        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        connection.close();
    }

    @Override
    public void onMessage(Message message) {
        if (message instanceof TextMessage) {
            try {
                System.out.println("Message received: " + ((TextMessage) message).getText());
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

Apache Thrift 示例代码

以下是一个简单的Thrift服务提供者和消费者的示例:

定义 .thrift 文件:

namespace java com.example.hello
service HelloService {
    string greet(1: string name)
}

生成Java代码并实现服务:

import com.example.hello.HelloService;
import com.example.hello.HelloServiceBlockingIF;

public class HelloServiceImpl implements HelloServiceBlockingIF {
    @Override
    public String greet(String name) {
        return "Hello, " + name;
    }
}

启动服务端:

import org.apache.thrift.server.TServer;
import org.apache.thrift.server.TSimpleServer;
import org.apache.thrift.transport.TServerSocket;
import org.apache.thrift.transport.TServerTransport;

public class HelloServer {
    public static void main(String[] args) {
        try {
            HelloService.Processor<HelloServiceImpl> processor = new HelloService.Processor<>(new HelloServiceImpl());
            TServerTransport serverTransport = new TServerSocket(9090);
            TServer server = new TSimpleServer(new TServer.Args(serverTransport).processor(processor));
            System.out.println("Starting the server...");
            server.serve();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

启动客户端:

import org.apache.thrift.protocol.TProtocol;
import org.apache.thrift.transport.TTransport;
import org.apache.thrift.transport.TSocket;

public class HelloClient {
    public static void main(String[] args) {
        try {
            TTransport transport = new TSocket("localhost", 9090);
            TProtocol protocol = new TProtocol(transport);
            HelloService.Client client = new HelloService.Client(protocol);
            transport.open();
            System.out.println(client.greet("World"));
            transport.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
Java分布式开发的基本原则

在进行Java分布式开发时,需要遵循一些基本原则,以确保系统的稳定性和可维护性:

  1. 模块化和松耦合:将系统拆分成多个独立的模块,每个模块应该尽量减少对外部模块的依赖。
  2. 服务化:将业务逻辑封装成服务,通过标准接口进行通信。
  3. 异步和非阻塞:使用异步通信和非阻塞I/O来提高系统的并发处理能力。
  4. 容错和高可用:设计时充分考虑容错机制,提高系统的高可用性。
  5. 安全性:确保通信的安全性,防止数据泄露。
  6. 可扩展性:系统设计应该易于扩展,支持动态添加和删除节点。
实战:搭建简单的Java分布式应用

选择合适的分布式框架、搭建分布式开发环境、编写第一个Java分布式应用实例。

选择合适的分布式框架

Spring Boot 和 Spring Cloud

选择Spring Boot和Spring Cloud作为分布式框架,因为它们提供了丰富的功能和强大的社区支持,适合初学者入门。

其他分布式框架选择

除了Spring Boot和Spring Cloud,还有其他框架如RMI、JMS、Dubbo和Apache Thrift。选择合适的框架时,需要根据具体的应用场景和需求来决定。

详细案例分析

选择合适的框架时,需要考虑以下几个方面:

  1. 功能需求:框架是否提供了所需的功能,如服务发现、负载均衡、配置管理等。
  2. 社区支持:框架是否有活跃的社区支持和丰富的文档。
  3. 性能需求:框架在处理高并发和大数据量时的表现。
  4. 学习曲线:框架的学习难度和上手速度。
在本地环境中搭建分布式开发环境

安装JDK

  1. 下载最新版本的JDK。
  2. 安装JDK,并设置环境变量。
export JAVA_HOME=/path/to/jdk
export PATH=$JAVA_HOME/bin:$PATH

安装Maven

  1. 下载Maven安装包。
  2. 解压到指定目录。
  3. 设置Maven环境变量。
export MAVEN_HOME=/path/to/maven
export PATH=$MAVEN_HOME/bin:$PATH
  1. 配置Maven的本地仓库路径。
<localRepository>/path/to/localrepo</localRepository>

安装IDE

推荐使用IntelliJ IDEA或Eclipse等IDE,方便开发和调试。

编写第一个Java分布式应用实例

示例代码

以下是一个简单的Spring Boot和Spring Cloud应用示例,展示了一个简单的服务提供者和服务消费者:

服务提供者代码:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

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

@RestController
public class GreetingController {

    @GetMapping("/greeting")
    public String greeting() {
        return "Hello, World!";
    }
}

服务消费者代码:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

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

@RestController
public class GreetingClient {

    @GetMapping("/greeting")
    public String greeting() {
        return "Hello, World!";
    }
}

搭建Eureka服务发现

  1. 在服务提供者和消费者中添加Eureka依赖。
  2. 配置Eureka服务器地址。
  3. 启动Eureka服务器,服务提供者和服务消费者自动注册到Eureka服务器。

测试应用

启动服务提供者和服务消费者,访问服务消费者中的接口,验证服务提供者是否正常提供服务。

Java分布式应用中的常用技术

分布式应用中常用的几个关键技术包括远程过程调用(RPC)、分布式缓存、分布式事务处理等。

RPC远程过程调用

远程过程调用(Remote Procedure Call, RPC)是一种通过网络传输数据和调用远程服务的技术。它允许一个程序调用另一个不同地址空间中的程序的过程,就像调用本地过程一样的方式。

示例代码

以下是一个简单的RPC服务提供者和服务消费者的示例:

服务提供者代码:

import com.example.hello.HelloService;
import com.example.hello.HelloService.Iface;

public class HelloServiceImpl implements Iface {
    @Override
    public String greet(String name) {
        return "Hello, " + name;
    }
}

服务消费者代码:

import com.example.hello.HelloService;
import com.example.hello.HelloService.Iface;
import com.example.hello.HelloService.Client;
import org.apache.thrift.protocol.TBinaryProtocol;
import org.apache.thrift.protocol.TProtocol;
import org.apache.thrift.transport.TSocket;
import org.apache.thrift.transport.TTransport;
import org.apache.thrift.transport.TTransportException;

public class HelloClient {
    public static void main(String[] args) {
        try {
            TTransport transport = new TSocket("localhost", 9090);
            TProtocol protocol = new TBinaryProtocol(transport);
            Client client = new Client(protocol);
            transport.open();
            System.out.println(client.greet("World"));
            transport.close();
        } catch (TTransportException e) {
            e.printStackTrace();
        }
    }
}
分布式缓存技术

分布式缓存技术可以提高应用的性能和可伸缩性,常见的分布式缓存技术有Redis、Memcached等。

示例代码

以下是一个简单的Redis缓存示例:

import redis.clients.jedis.Jedis;

public class RedisCacheExample {
    public static void main(String[] args) {
        Jedis jedis = new Jedis("localhost");
        jedis.set("key", "value");
        String value = jedis.get("key");
        System.out.println("Value from cache: " + value);
        jedis.close();
    }
}

Memcached 示例代码

以下是一个简单的Memcached缓存示例:

import net.spy.memcached.AddrUtil;
import net.spy.memcached.MemcachedClient;

public class MemcachedExample {
    public static void main(String[] args) {
        try {
            MemcachedClient client = new MemcachedClient(AddrUtil.getAddresses("localhost:11211"));
            client.set("key", 0, "value");
            String value = client.get("key").toString();
            System.out.println("Value from cache: " + value);
            client.shutdown();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
分布式事务处理

分布式事务处理确保在分布式系统中的一系列操作要么全部成功,要么全部失败,以保持数据的一致性。

示例代码

以下是一个简单的XA事务示例:

import javax.transaction.xa.XAException;
import javax.transaction.xa.XAResource;
import javax.transaction.xa.Xid;

public class XATransactionExample {
    public static void main(String[] args) throws XAException {
        XADataSource xaDataSource = new com.mysql.jdbc.jdbc2.optional.MysqlXADataSource();
        xaDataSource.setUrl("jdbc:mysql://localhost:3306/test");
        xaDataSource.setUser("root");
        xaDataSource.setPassword("password");

        XAConnection xaConnection = xaDataSource.getXAConnection();
        XAResource xaResource = xaConnection.getXAResource();
        Connection connection = xaConnection.getConnection();

        Xid xid = new Xid(new byte[]{1, 2, 3}, new byte[]{4, 5}, new byte[]{6, 7, 8});
        xaResource.start(xid, XAResource.TMNOFLAGS);

        PreparedStatement preparedStatement = connection.prepareStatement("INSERT INTO test_table (column1) VALUES (?)");
        preparedStatement.setString(1, "test");
        preparedStatement.executeUpdate();

        xaResource.end(xid, XAResource.TMSUCCESS);
        xaResource.commit(xid, false);

        xaConnection.close();
    }
}

SAGA 事务示例代码

以下是一个简单的SAGA事务示例:

public class SagaTransactionExample {
    public static void main(String[] args) {
        // 业务操作1
        try {
            // 执行业务操作1
            System.out.println("Business operation 1 executed successfully");
        } catch (Exception e) {
            // 回滚操作1
            System.out.println("Rolling back operation 1");
            return;
        }

        // 业务操作2
        try {
            // 执行业务操作2
            System.out.println("Business operation 2 executed successfully");
        } catch (Exception e) {
            // 回滚操作2
            System.out.println("Rolling back operation 2");
            return;
        }

        // 业务操作3
        try {
            // 执行业务操作3
            System.out.println("Business operation 3 executed successfully");
        } catch (Exception e) {
            // 回滚操作3
            System.out.println("Rolling back operation 3");
            return;
        }

        // 如果所有业务操作成功,则提交事务
        System.out.println("All operations executed successfully");
    }
}
常见问题与解决方案

在分布式系统中,常见的问题包括网络延迟、数据一致性等,这些都需要通过特定的机制和策略来解决。

分布式系统中的网络延迟问题

网络延迟是分布式系统中的常见问题,可以通过增加冗余、优化网络配置和使用负载均衡器等方法来解决。

示例代码

以下是一个简单的负载均衡器示例,使用Nginx配置负载均衡:

http {
    upstream backend {
        server backend1.example.com;
        server backend2.example.com;
        server backend3.example.com;
    }

    server {
        listen 80;
        location / {
            proxy_pass http://backend;
        }
    }
}

其他负载均衡器示例

以下是一个使用HAProxy配置负载均衡的示例:

global
    log /dev/log local0
    log /dev/log local1 notice
    maxconn 4096

defaults
    mode http
    option httplog
    option dontlognull
    timeout connect 5000ms
    timeout client 50000ms
    timeout server 50000ms

frontend http_front
    bind *:80
    default_backend http_back

backend http_back
    server web1 127.0.0.1:8080 check
    server web2 127.0.0.2:8080 check
数据一致性问题及解决方案

数据一致性是分布式系统中的重要问题,可以使用两阶段提交(2PC)、三阶段提交(3PC)等协议来解决。

示例代码

以下是一个简单的两阶段提交示例:

import javax.transaction.xa.XAException;
import javax.transaction.xa.XAResource;
import javax.transaction.xa.Xid;

public class TwoPhaseCommitExample {
    public static void main(String[] args) throws XAException {
        XAResource xaResource = ...; // 初始化XAResource
        Xid xid = new Xid(new byte[]{1, 2, 3}, new byte[]{4, 5}, new byte[]{6, 7, 8});

        xaResource.start(xid, XAResource.TMNOFLAGS);
        try {
            // 执行本地事务
            ...
        } catch (Exception e) {
            // 处理异常
            xaResource.rollback(xid);
            return;
        }

        xaResource.end(xid, XAResource.TMSUCCESS);
        xaResource.prepare(xid);
        xaResource.commit(xid, false);
    }
}

SAGA 事务示例代码

以下是一个简单的SAGA事务示例:

public class SagaTransactionExample {
    public static void main(String[] args) {
        // 业务操作1
        try {
            // 执行业务操作1
            System.out.println("Business operation 1 executed successfully");
        } catch (Exception e) {
            // 回滚操作1
            System.out.println("Rolling back operation 1");
            return;
        }

        // 业务操作2
        try {
            // 执行业务操作2
            System.out.println("Business operation 2 executed successfully");
        } catch (Exception e) {
            // 回滚操作2
            System.out.println("Rolling back operation 2");
            return;
        }

        // 业务操作3
        try {
            // 执行业务操作3
            System.out.println("Business operation 3 executed successfully");
        } catch (Exception e) {
            // 回滚操作3
            System.out.println("Rolling back operation 3");
            return;
        }

        // 如果所有业务操作成功,则提交事务
        System.out.println("All operations executed successfully");
    }
}
分布式系统的可扩展性和性能优化

分布式系统的可扩展性可以通过水平扩展和垂直扩展来实现,性能优化可以通过缓存技术、数据库优化和代码优化等方法来实现。

示例代码

以下是一个简单的数据库优化示例,使用索引优化查询性能:

CREATE INDEX idx_column1 ON test_table (column1);

其他性能优化策略

  1. 缓存策略:使用分布式缓存如Redis、Memcached。
  2. 数据分片:将数据分布在多台服务器上,提高读写性能。
  3. 异步处理:使用消息队列进行异步处理,避免同步操作带来的延迟。
  4. 负载均衡:合理分配流量,避免单点过载。
总结与进阶资源推荐

在学习Java分布式开发的过程中,需要不断实践和积累经验,以提高自己的技能水平。

Java分布式学习的下一步

可以深入学习Spring Boot和Spring Cloud相关技术,了解微服务架构的更多细节和最佳实践。还可以学习其他分布式框架如Dubbo、Apache Thrift等,以拓宽自己的技术视野。

推荐书籍和在线课程

推荐在线学习网站:慕课网 提供了大量的Java分布式开发课程,适合不同水平的学习者。此外,还可以关注一些技术博客和社区,如CSDN等,获取最新的技术和实践经验。

分布式技术社区和资源分享

可以加入一些分布式系统的技术社区,如Stack Overflow、GitHub等,与其他开发者交流和分享经验。此外,还可以关注一些技术博客和论坛,获取最新的技术和实践经验。

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消