本文详细介绍了Java分布式编程的基础知识,包括分布式系统的基本概念、Java在网络编程中的优势和常用库,以及常见的Java分布式框架和通信协议。此外,文章还提供了实战案例和调试技巧,帮助读者更好地理解和掌握Java分布式编程。
分布式系统简介 分布式系统的定义分布式系统是一类系统,由多台计算机组成,通过网络连接协同工作,以完成共同任务。每个计算机可以独立运行,也可以与其他计算机进行通信和协作。分布式系统的设计目标是提供高可用性、可伸缩性和容错性,以应对大型和复杂的应用需求。
分布式系统的特点和优势特点
- 独立性:每个节点可以独立运行,不受其他节点状态的影响。
- 并行性:节点之间可以并行处理任务,提高系统性能。
- 可伸缩性:分布式系统可以灵活地添加或删除节点,以适应业务规模的变化。
- 容错性:即使某些节点发生故障,整个系统仍能继续运行,确保业务连续性。
- 负载均衡:通过合理分配任务,避免某些节点过载而其他节点闲置。
优势
- 高可用性:分布式系统可以设计为在某些节点故障时仍能提供服务,提高系统的稳定性。
- 可伸缩性:通过增加节点数量,可以提高系统的处理能力和吞吐量。
- 资源利用率:通过合理分配任务,可以提高资源利用率,降低成本。
- 灵活性:分布式系统可以根据业务需求灵活调整架构,适应变化。
电子商务
在电子商务应用中,分布式系统可用于处理大规模的用户请求和商品交易。例如,阿里巴巴的电商平台使用分布式系统来处理订单、支付、物流等业务操作,确保高并发下的稳定和高效。
云计算
在云计算领域,分布式系统被用于提供弹性的计算资源和服务。例如,阿里云的ECS(Elastic Compute Service)提供了基于分布式架构的弹性计算能力,用户可以根据需要动态调整计算资源。
社交媒体
社交媒体应用需要处理大量用户请求和数据存储。例如,微博和微信等应用使用分布式系统来存储用户数据、处理消息推送和社交互动,确保系统的高效和稳定。
示例代码:简单的客户端-服务器模式客户端代码
import java.io.*;
import java.net.*;
public class SimpleClient {
public static void main(String[] args) throws IOException {
Socket socket = new Socket("localhost", 8080);
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String message = "Hello, Server!";
out.println(message);
String response = in.readLine();
System.out.println("服务器响应:" + response);
socket.close();
}
}
服务器代码
import java.io.*;
import java.net.*;
public class SimpleServer {
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = new ServerSocket(8080);
Socket socket = serverSocket.accept();
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String inputLine;
while ((inputLine = in.readLine()) != null) {
System.out.println("客户端发送:" + inputLine);
out.println("服务器收到:" + inputLine);
}
}
}
Java分布式编程基础
Java在网络编程中的优势
Java在网络编程中具有以下优势:
- 跨平台性:Java代码可以在任何支持Java虚拟机(JVM)的平台上运行,无需重新编译。
- 丰富的网络库:Java提供了强大的网络编程库,如Socket API和HTTP客户端库,简化了网络通信的实现。
- 并发支持: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);
System.out.println("服务器启动,监听端口: 8080");
while (true) {
Socket socket = serverSocket.accept();
System.out.println("客户端连接成功");
new Thread(new ClientHandler(socket)).start();
}
}
static class ClientHandler implements Runnable {
private Socket socket;
public ClientHandler(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
try (
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()))
) {
String inputLine;
while ((inputLine = in.readLine()) != null) {
System.out.println("客户端发送:" + inputLine);
out.println("服务器收到:" + inputLine);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
客户端代码
import java.io.*;
import java.net.*;
public class Client {
public static void main(String[] args) throws IOException {
Socket socket = new Socket("localhost", 8080);
System.out.println("客户端连接服务器成功");
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
String message = "Hello, Server!";
out.println(message);
String response = in.readLine();
System.out.println("服务器响应:" + response);
socket.close();
}
}
Java线程和并发编程基础
线程的基本概念
线程是程序中执行的一个执行路径,每个线程拥有自己的执行栈和程序计数器。Java中可以通过Runnable接口或继承Thread类来创建线程。
同步和锁
在多线程环境中,需要使用同步机制来确保资源的正确访问。Java提供了synchronized
关键字和Lock
接口来实现同步。
示例代码:使用synchronized
关键字的生产者-消费者问题
import java.util.concurrent.locks.ReentrantLock;
public class ProducerConsumer {
private int value;
private boolean valueSet = false;
private final ReentrantLock lock = new ReentrantLock();
private final Condition notFull = lock.newCondition();
private final Condition notEmpty = lock.newCondition();
public void produce(int num) throws InterruptedException {
lock.lock();
try {
while (valueSet) {
notFull.await();
}
value = num;
valueSet = true;
notEmpty.signal();
} finally {
lock.unlock();
}
}
public int consume() throws InterruptedException {
lock.lock();
try {
while (!valueSet) {
notEmpty.await();
}
valueSet = false;
return value;
} finally {
lock.unlock();
}
}
}
public class Producer extends Thread {
private ProducerConsumer pc;
public Producer(ProducerConsumer pc) {
this.pc = pc;
}
@Override
public void run() {
try {
while (true) {
pc.produce(new Random().nextInt());
sleep(1000);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public class Consumer extends Thread {
private ProducerConsumer pc;
public Consumer(ProducerConsumer pc) {
this.pc = pc;
}
@Override
public void run() {
try {
while (true) {
System.out.println(pc.consume());
sleep(1000);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
示例代码:使用Lock
接口的简单并发示例
public class SimpleConcurrentExample {
private int counter = 0;
private final ReentrantLock lock = new ReentrantLock();
private final Condition condition = lock.newCondition();
public void increment() {
lock.lock();
try {
counter++;
condition.signal();
} finally {
lock.unlock();
}
}
public int getCounter() {
lock.lock();
try {
return counter;
} finally {
lock.unlock();
}
}
public static void main(String[] args) {
SimpleConcurrentExample example = new SimpleConcurrentExample();
Thread t1 = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
example.increment();
}
});
Thread t2 = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
example.increment();
}
});
t1.start();
t2.start();
try {
t1.join();
t2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Final counter value: " + example.getCounter());
}
}
常用的Java网络库介绍
Socket API
Java的Socket API是实现网络通信的基础库,支持TCP/IP协议。Socket API提供了Socket和ServerSocket类,用于实现客户端和服务器端的连接和通信。
Java NIO(New IO)
Java NIO是Java 1.4引入的新I/O模型,支持面向缓冲区(Buffered I/O)、非阻塞I/O和选择器(Selector),适用于高并发场景。
Akka
Akka是一个基于Actor模型的并发编程框架,适用于构建分布式、高并发的应用。它提供了强大的消息传递和异步编程支持。
Netty
Netty是一个高性能的事件驱动的网络应用框架,广泛用于开发高性能、高可靠性的网络服务器和客户端。Netty支持多种协议,如HTTP、WebSocket、TCP和UDP。
分布式架构模式 分布式架构的基本模式分布式系统常见的架构模式包括客户端-服务器模式、分布式对象模型、微服务架构等。这些模式旨在解决不同层次的分布式系统设计问题。
客户端-服务器模式客户端-服务器模式是一种常见的分布式系统架构模式,其中客户端负责发起请求,服务器负责处理请求并返回响应。这种模式可以扩展性强,易于维护。
示例代码:简单的客户端-服务器模式
客户端代码
import java.io.*;
import java.net.*;
public class SimpleClient {
public static void main(String[] args) throws IOException {
Socket socket = new Socket("localhost", 8080);
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String message = "Hello, Server!";
out.println(message);
String response = in.readLine();
System.out.println("服务器响应:" + response);
socket.close();
}
}
服务器代码
import java.io.*;
import java.net.*;
public class SimpleServer {
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = new ServerSocket(8080);
Socket socket = serverSocket.accept();
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String inputLine;
while ((inputLine = in.readLine()) != null) {
System.out.println("客户端发送:" + inputLine);
out.println("服务器收到:" + inputLine);
}
}
}
分布式对象模型
分布式对象模型是一种将对象分布到不同节点上的架构模式,通过远程过程调用(RPC)实现对象之间的通信。Java RMI(Remote Method Invocation)是Java实现分布式对象模型的一种方式。
示例代码:Java RMI的简单示例
import java.rmi.*;
public interface MyRemote extends Remote {
String sayHello() throws RemoteException;
}
public class MyRemoteImpl extends UnicastRemoteObject implements MyRemote {
public MyRemoteImpl() throws RemoteException {
super();
}
@Override
public String sayHello() throws RemoteException {
return "Hello from remote object!";
}
}
public class Server {
public static void main(String[] args) throws Exception {
MyRemote myRemote = new MyRemoteImpl();
LocateRegistry.createRegistry(1099);
Naming.rebind("//localhost/MyRemote", myRemote);
System.out.println("远程对象发布成功");
}
}
public class Client {
public static void main(String[] args) throws Exception {
MyRemote myRemote = (MyRemote) Naming.lookup("//localhost/MyRemote");
System.out.println(myRemote.sayHello());
}
}
示例代码:简单的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 RestApplication {
public static void main(String[] args) {
SpringApplication.run(RestApplication.class, args);
}
@RestController
public class HelloWorldController {
@GetMapping("/hello")
public String hello() {
return "Hello, World!";
}
}
}
Java分布式框架介绍
常见的Java分布式框架
常见的Java分布式框架包括Spring Cloud、Apache Dubbo、gRPC等。这些框架提供了丰富的功能,简化了分布式系统开发。
Spring Cloud简介Spring Cloud是一个基于Spring Boot的分布式系统实现框架,提供了服务发现、负载均衡、配置中心、断路器等功能。Spring Cloud通过Spring Boot的自动配置机制,简化了分布式系统开发。
示例代码:使用Spring Cloud的简单示例
服务提供者(Provider)
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@SpringBootApplication
@EnableDiscoveryClient
public class ProviderApplication {
public static void main(String[] args) {
SpringApplication.run(ProviderApplication.class, args);
}
@RestController
@RefreshScope
public class HelloWorldController {
@GetMapping("/hello")
public String hello() {
return "Hello, World!";
}
}
}
服务消费者(Consumer)
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class ConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(ConsumerApplication.class, args);
}
@RestController
public class HelloWorldController {
@GetMapping("/hello")
public String hello() {
return "Hello, Consumer!";
}
@GetMapping("/provider")
public String getProviderHello() {
return "Provider says: " + providerClient.hello();
}
@FeignClient("provider")
public interface ProviderClient {
@GetMapping("/hello")
String hello();
}
private ProviderClient providerClient;
}
}
Apache Dubbo简介
Apache Dubbo是一个高性能的Java RPC框架,支持多种服务治理和负载均衡策略。Dubbo通过服务接口定义和服务实现分离的方式,简化了分布式服务的开发和部署。
示例代码:使用Apache Dubbo的简单示例
服务提供者(Provider)
import org.apache.dubbo.config.ApplicationConfig;
import org.apache.dubbo.config.RegistryConfig;
import org.apache.dubbo.config.ServiceConfig;
import org.apache.dubbo.rpc.service.GenericService;
public class Provider {
public static void main(String[] args) throws Exception {
ServiceConfig<GenericService> service = new ServiceConfig<>();
service.setInterface(GreetingService.class);
service.setVersion("1.0.0");
ApplicationConfig application = new ApplicationConfig();
application.setName("dubbo-provider");
service.setApplication(application);
RegistryConfig registry = new RegistryConfig();
registry.setAddress("zookeeper://127.0.0.1:2181");
service.setRegistry(registry);
service.export();
}
}
public class GreetingServiceImpl implements GreetingService {
@Override
public String sayHello(String name) {
return "Hello " + name;
}
}
public interface GreetingService {
String sayHello(String name);
}
服务消费者(Consumer)
import org.apache.dubbo.config.ApplicationConfig;
import org.apache.dubbo.config.ReferenceConfig;
import org.apache.dubbo.config.RegistryConfig;
public class Consumer {
public static void main(String[] args) throws Exception {
ReferenceConfig<GreetingService> reference = new ReferenceConfig<>();
reference.setInterface(GreetingService.class);
reference.setVersion("1.0.0");
ApplicationConfig application = new ApplicationConfig();
application.setName("dubbo-consumer");
reference.setApplication(application);
RegistryConfig registry = new RegistryConfig();
registry.setAddress("zookeeper://127.0.0.1:2181");
reference.setRegistry(registry);
GreetingService greetingService = reference.get();
System.out.println(greetingService.sayHello("World"));
}
}
示例代码:简单的gRPC服务
syntax = "proto3";
option java_multiple_files = true;
option java_package = "com.example.grpc";
option java_outer_classname = "HelloWorldProto";
package com.example.grpc;
service Greeter {
rpc SayHello (HelloRequest) returns (HelloReply) {}
}
message HelloRequest {
string name = 1;
}
message HelloReply {
string message = 1;
}
import com.example.grpc.GreeterGrpc;
import com.example.grpc.HelloRequest;
import com.example.grpc.HelloReply;
public class HelloWorldClient {
public static void main(String[] args) throws Exception {
GreeterGrpc.GreeterBlockingStub stub = GreeterGrpc.newBlockingStub(GreeterGrpc.newStub());
HelloRequest request = HelloRequest.newBuilder().setName("World").build();
HelloReply response = stub.sayHello(request);
System.out.println(response.getMessage());
}
}
import com.example.grpc.GreeterGrpc;
import com.example.grpc.GreeterImplBase;
public class HelloWorldServer {
public static void main(String[] args) throws Exception {
GreeterGrpc.GreeterBlockingStub stub = GreeterGrpc.newBlockingStub();
stub.sayHello(HelloRequest.newBuilder().setName("World").build())
.thenApply(response -> HelloReply.newBuilder().setMessage("Hello " + response.getName()).build())
.thenAccept(reply -> System.out.println(reply.getMessage()))
.join();
}
}
分布式通信协议
RPC(远程过程调用)协议
RPC(Remote Procedure Call)是一种协议,允许一个程序调用远程计算机上的对象方法。常见的RPC实现包括Java RMI、gRPC和Apache Thrift。
RESTful APIREST(Representational State Transfer)是一种设计风格,用于构建可扩展的网络服务。RESTful API通过HTTP协议实现资源的CRUD操作,支持无状态、幂等性等特性。
示例代码:简单的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 RestApplication {
public static void main(String[] args) {
SpringApplication.run(RestApplication.class, args);
}
@RestController
public class HelloWorldController {
@GetMapping("/hello")
public String hello() {
return "Hello, World!";
}
}
}
gRPC简介
gRPC是Google开发的高性能、开源的RPC框架,基于HTTP/2协议,支持多种语言,如Java、Python、Go等。gRPC通过定义protobuf数据格式来实现服务接口和数据交换。
示例代码:简单的gRPC服务
syntax = "proto3";
option java_multiple_files = true;
option java_package = "com.example.grpc";
option java_outer_classname = "HelloWorldProto";
package com.example.grpc;
service Greeter {
rpc SayHello (HelloRequest) returns (HelloReply) {}
}
message HelloRequest {
string name = 1;
}
message HelloReply {
string message = 1;
}
import com.example.grpc.GreeterGrpc;
import com.example.grpc.HelloRequest;
import com.example.grpc.HelloReply;
public class HelloWorldClient {
public static void main(String[] args) throws Exception {
GreeterGrpc.GreeterBlockingStub stub = GreeterGrpc.newBlockingStub(GreeterGrpc.newStub());
HelloRequest request = HelloRequest.newBuilder().setName("World").build();
HelloReply response = stub.sayHello(request);
System.out.println(response.getMessage());
}
}
import com.example.grpc.GreeterGrpc;
import com.example.grpc.GreeterImplBase;
public class HelloWorldServer {
public static void main(String[] args) throws Exception {
GreeterGrpc.GreeterBlockingStub stub = GreeterGrpc.newBlockingStub();
stub.sayHello(HelloRequest.newBuilder().setName("World").build())
.thenApply(response -> HelloReply.newBuilder().setMessage("Hello " + response.getName()).build())
.thenAccept(reply -> System.out.println(reply.getMessage()))
.join();
}
}
实战案例与调试技巧
分布式系统开发流程
分布式系统开发流程通常包括需求分析、系统设计、编码实现、测试和部署等阶段。每个阶段都需要考虑到分布式系统的特性和优势。
需求分析
在需求分析阶段,需要明确系统的功能需求和非功能需求,如性能、可靠性、安全性等。要充分考虑分布式系统的特性,合理规划系统的架构和功能模块。
系统设计
在系统设计阶段,需要设计系统的整体架构和模块划分。可以使用客户端-服务器模式、微服务架构等模式来实现。还需要设计数据存储、通信协议和分布式算法等关键部分。
编码实现
在编码实现阶段,需要实现系统的各个模块和功能。可以使用Java、Python、Go等语言和相关框架来实现。要遵循编码规范和设计模式,确保代码的可维护性和可扩展性。
测试
在测试阶段,需要进行单元测试、集成测试和系统测试。单元测试用于测试单个模块的功能正确性,集成测试用于测试各模块之间的协同工作,系统测试用于测试整个系统的功能和性能。
部署
在部署阶段,需要将系统部署到生产环境。可以使用容器化技术如Docker、Kubernetes等来部署和管理分布式系统。部署时要考虑到系统的高可用性和容错性,确保系统的稳定运行。
常见问题与调试技巧在分布式系统开发和运行过程中,可能会遇到各种问题,如网络通信异常、数据一致性问题、资源竞争等。以下是一些调试技巧和解决方法。
网络通信异常
- 检查网络连接:确保节点之间的网络连接正常,没有防火墙或路由器阻止通信。
- 日志分析:通过查看系统日志,找出通信异常的原因,如超时、连接失败等。
- 模拟测试:在测试环境中模拟网络异常,如网络延迟、丢包等,验证系统对异常的处理能力。
数据一致性问题
- 分布式事务:使用分布式事务机制,如两阶段提交(2PC)或三阶段提交(3PC),确保事务的一致性。
- 最终一致性:使用最终一致性模型,如CAP理论中的AP模型,确保数据在一定时间内达到一致。
- 数据复制和同步:通过数据复制和同步机制,确保数据的冗余和一致性。
资源竞争
- 锁机制:使用锁机制,如互斥锁(Mutex)或信号量(Semaphore),确保资源的互斥访问。
- 并发控制:使用并发控制机制,如乐观锁或悲观锁,避免资源竞争。
- 资源池:使用资源池机制,如线程池或连接池,提高资源的使用效率。
示例代码:使用锁机制避免资源竞争
import java.util.concurrent.locks.ReentrantLock;
public class ResourcePool {
private int resourceCount;
private ReentrantLock lock = new ReentrantLock();
public ResourcePool(int resourceCount) {
this.resourceCount = resourceCount;
}
public void acquireResource() throws InterruptedException {
lock.lock();
try {
while (resourceCount <= 0) {
lock.unlock();
Thread.sleep(1000);
lock.lock();
}
resourceCount--;
System.out.println("资源获取成功,剩余资源:" + resourceCount);
} finally {
lock.unlock();
}
}
public void releaseResource() {
lock.lock();
try {
resourceCount++;
System.out.println("资源释放成功,剩余资源:" + resourceCount);
} finally {
lock.unlock();
}
}
}
public class ResourcePoolTest {
public static void main(String[] args) throws InterruptedException {
ResourcePool pool = new ResourcePool(3);
Thread t1 = new Thread(() -> {
try {
pool.acquireResource();
Thread.sleep(1000);
pool.releaseResource();
} catch (InterruptedException e) {
e.printStackTrace();
}
});
Thread t2 = new Thread(() -> {
try {
pool.acquireResource();
Thread.sleep(1000);
pool.releaseResource();
} catch (InterruptedException e) {
e.printStackTrace();
}
});
Thread t3 = new Thread(() -> {
try {
pool.acquireResource();
Thread.sleep(1000);
pool.releaseResource();
} catch (InterruptedException e) {
e.printStackTrace();
}
});
t1.start();
t2.start();
t3.start();
}
}
性能优化与负载均衡
在分布式系统中,性能优化和负载均衡是提高系统性能和可用性的关键。以下是一些常见的性能优化和负载均衡策略。
性能优化
- 缓存机制:使用缓存机制,如Redis、Memcached等,减少数据库访问次数,提高系统响应速度。
- 数据库优化:优化数据库查询和索引,减少数据库查询时间。
- 代码优化:优化代码逻辑,减少不必要的计算和内存使用。
负载均衡
- 硬件负载均衡器:使用硬件负载均衡器,如F5、Cisco等,实现节点之间的请求分发。
- 软件负载均衡器:使用软件负载均衡器,如Nginx、HAProxy等,实现节点之间的请求分发。
- 一致性哈希:使用一致性哈希算法,实现节点之间的请求分发,确保负载均衡的稳定性和均衡性。
示例代码:使用Nginx实现负载均衡
http {
upstream backend {
server 192.168.1.1:80;
server 192.168.1.2:80;
}
server {
listen 80;
location / {
proxy_pass http://backend;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
}
以上是Java分布式编程的入门与实践指南,涵盖了分布式系统的基本概念、Java分布式编程基础、分布式架构模式、Java分布式框架介绍、分布式通信协议、实战案例与调试技巧等内容。希望本文能帮助你更好地理解和掌握Java分布式编程。
共同学习,写下你的评论
评论加载中...
作者其他优质文章