暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

seata(2):db mode

        seate-server有三种方式存储事务信息:file、db、redis;在file模式下,它将信息存储在文件/seata-server/sessionStore/root.data里,我们可以去机器上查看下文件的具体内容

     % docker exec -it 016d4f7a3820 bin/sh
    #
    # cat ./sessionStore/root.data
    _A�k,��`apimy_test_tx_grouptestBiz!172.23.0.2:8091:18450265429737473��|�q�A�k,�A�k,�"jdbc:mysql://127.0.0.1:3306/fescar
    stock_tbl:1api:172.23.0.1:57232!172.23.0.2:8091:18450265429737473�A�k,�A�k,�"jdbc:mysql://127.0.0.1:3306/fescar

            对于一些对要求比较高的场景,需要把这些信息存储到mysql里,下面我们配置下mysql模式,然后启动。首先是tc端,最高版本有些bug起不来,我们回退到1.5.2版本

      version: "3.1"
      services:
      mysql:
      image: mysql:5.7
      container_name: mysql
      environment:
      - MYSQL_ROOT_PASSWORD=123456
      command: --default-authentication-plugin=mysql_native_password --default-time-zone='+08:00'
      volumes:
      - ./mysql:/docker-entrypoint-initdb.d
      - ./mysql/mysqld.cnf:/etc/mysql/mysql.conf.d/mysqld.cnf
      ports:
      - "3306:3306"
      extra_hosts:
      - host.docker.internal:host-gateway


      seata-server:
      image: seataio/seata-server:1.5.2
      ports:
      - "7091:7091"
      - "8091:8091"
      environment:
      - STORE_MODE=db
      # 以SEATA_IP作为host注册seata server
      # - SEATA_IP=host.docker.internal
      # - SEATA_PORT=8091
      volumes:
      # - "/usr/share/zoneinfo/Asia/Shanghai:/etc/localtime" #设置系统时区
      # - "/usr/share/zoneinfo/Asia/Shanghai:/etc/timezone" #设置时区
      # 假设我们通过docker cp命令把资源文件拷贝到相对路径`./seata-server/resources`中
      # 如有问题,请阅读上面的[注意事项]以及[使用自定义配置文件]
            - /Users/xiazemin/seata/seata-server/resources:/seata-server/resources
            - /Users/xiazemin/seata/seata-server/logs:/root/logs/seata/
      depends_on:
      - mysql
      extra_hosts:
           - host.docker.internal:host-gateway

      启动mysql,进入并创建对应的表

        mysql> create database seata_server;
        Query OK, 1 row affected (0.01 sec)


        mysql> use seata_server;
        Database changed
        mysql>






        drop table if exists `global_table`;
        create table `global_table` (
        `xid` varchar(128) not null,
        `transaction_id` bigint,
        `status` tinyint not null,
        `application_id` varchar(32),
        `transaction_service_group` varchar(32),
        `transaction_name` varchar(128),
        `timeout` int,
        `begin_time` bigint,
        `application_data` varchar(2000),
        `gmt_create` datetime,
        `gmt_modified` datetime,
        primary key (`xid`),
        key `idx_gmt_modified_status` (`gmt_modified`, `status`),
        key `idx_transaction_id` (`transaction_id`)
        );


        -- the table to store BranchSession data
        drop table if exists `branch_table`;
        create table `branch_table` (
        `branch_id` bigint not null,
        `xid` varchar(128) not null,
        `transaction_id` bigint ,
        `resource_group_id` varchar(32),
        `resource_id` varchar(256) ,
        `lock_key` varchar(128) ,
        `branch_type` varchar(8) ,
        `status` tinyint,
        `client_id` varchar(64),
        `application_data` varchar(2000),
        `gmt_create` datetime,
        `gmt_modified` datetime,
        primary key (`branch_id`),
        key `idx_xid` (`xid`)
        );


        -- the table to store lock data
        drop table if exists `lock_table`;
        create table `lock_table` (
        `row_key` varchar(128) not null,
        `xid` varchar(96),
        `transaction_id` long ,
        `branch_id` long,
        `resource_id` varchar(256) ,
        `table_name` varchar(32) ,
        `pk` varchar(36) ,
        `gmt_create` datetime ,
        `gmt_modified` datetime,
        primary key(`row_key`)
        );
        CREATE TABLE IF NOT EXISTS `distributed_lock`
        (
        `lock_key` CHAR(20) NOT NULL,
        `lock_value` VARCHAR(20) NOT NULL,
        `expire` BIGINT,
        primary key (`lock_key`)
        ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4;

        启动服务

          docker compose -f seata/exp2/docker-compose.yaml up
          [+] Running 2/2
          ⠿ Container mysql Created 0.0s
          ⠿ Container exp2-seata-server-1 Created 0.2s
          Attaching to exp2-seata-server-1, mysql
          mysql | 2023-09-17 01:14:28+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 5.7.40-1.el7 started.
          mysql | 2023-09-17 01:14:29+00:00 [Note] [Entrypoint]: Switching to dedicated user 'mysql'
          mysql | 2023-09-17 01:14:29+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 5.7.40-1.el7 started.
          mysql | '/var/lib/mysql/mysql.sock' -> '/var/run/mysqld/mysqld.sock'
          mysql | 2023-09-17T01:14:30.365334Z 0 [Warning] TIMESTAMP with implicit DEFAULT value is deprecated. Please use --explicit_defaults_for_timestamp server option (see documentation for more details).
          mysql | 2023-09-17T01:14:30.372460Z 0 [Note] mysqld (mysqld 5.7.40) starting as process 1 ...
          mysql | 2023-09-17T01:14:30.378981Z 0 [Note] InnoDB: PUNCH HOLE support available
          mysql | 2023-09-17T01:14:30.379058Z 0 [Note] InnoDB: Mutexes and rw_locks use GCC atomic builtins
          mysql | 2023-09-17T01:14:30.379079Z 0 [Note] InnoDB: Uses event mutexes
          mysql | 2023-09-17T01:14:30.379097Z 0 [Note] InnoDB: GCC builtin __atomic_thread_fence() is used for memory barrier
          mysql | 2023-09-17T01:14:30.379116Z 0 [Note] InnoDB: Compressed tables use zlib 1.2.12
          mysql | 2023-09-17T01:14:30.379128Z 0 [Note] InnoDB: Using Linux native AIO
          mysql | 2023-09-17T01:14:30.379684Z 0 [Note] InnoDB: Number of pools: 1
          mysql | 2023-09-17T01:14:30.380177Z 0 [Note] InnoDB: Using CPU crc32 instructions
          mysql | 2023-09-17T01:14:30.394469Z 0 [Note] InnoDB: Initializing buffer pool, total size = 128M, instances = 1, chunk size = 128M
          mysql | 2023-09-17T01:14:30.444327Z 0 [Note] InnoDB: Completed initialization of buffer pool
          mysql | 2023-09-17T01:14:30.459450Z 0 [Note] InnoDB: If the mysqld execution user is authorized, page cleaner thread priority can be changed. See the man page of setpriority().
          mysql | 2023-09-17T01:14:30.476447Z 0 [Note] InnoDB: Highest supported file format is Barracuda.
          mysql | 2023-09-17T01:14:30.734450Z 0 [Note] InnoDB: Creating shared tablespace for temporary tables
          mysql | 2023-09-17T01:14:30.734581Z 0 [Note] InnoDB: Setting file './ibtmp1' size to 12 MB. Physically writing the file full; Please wait ...
          mysql | 2023-09-17T01:14:30.880452Z 0 [Note] InnoDB: File './ibtmp1' size is now 12 MB.
          mysql | 2023-09-17T01:14:30.885097Z 0 [Note] InnoDB: 96 redo rollback segment(s) found. 96 redo rollback segment(s) are active.
          mysql | 2023-09-17T01:14:30.885179Z 0 [Note] InnoDB: 32 non-redo rollback segment(s) are active.
          mysql | 2023-09-17T01:14:30.896166Z 0 [Note] InnoDB: Waiting for purge to start
          mysql | 2023-09-17T01:14:30.948551Z 0 [Note] InnoDB: 5.7.40 started; log sequence number 12595436
          mysql | 2023-09-17T01:14:30.949184Z 0 [Note] Plugin 'FEDERATED' is disabled.
          mysql | 2023-09-17T01:14:30.963905Z 0 [Note] InnoDB: Loading buffer pool(s) from var/lib/mysql/ib_buffer_pool
          mysql | 2023-09-17T01:14:30.980757Z 0 [Note] InnoDB: Buffer pool(s) load completed at 230917 1:14:30
          mysql | 2023-09-17T01:14:31.014909Z 0 [Note] Found ca.pem, server-cert.pem and server-key.pem in data directory. Trying to enable SSL support using them.
          mysql | 2023-09-17T01:14:31.014981Z 0 [Note] Skipping generation of SSL certificates as certificate files are present in data directory.
          mysql | 2023-09-17T01:14:31.015090Z 0 [Warning] A deprecated TLS version TLSv1 is enabled. Please use TLSv1.2 or higher.
          mysql | 2023-09-17T01:14:31.015102Z 0 [Warning] A deprecated TLS version TLSv1.1 is enabled. Please use TLSv1.2 or higher.
          mysql | 2023-09-17T01:14:31.018564Z 0 [Warning] CA certificate ca.pem is self signed.
          mysql | 2023-09-17T01:14:31.018668Z 0 [Note] Skipping generation of RSA key pair as key files are present in data directory.
          mysql | 2023-09-17T01:14:31.028372Z 0 [Note] Server hostname (bind-address): '*'; port: 3306
          mysql | 2023-09-17T01:14:31.029194Z 0 [Note] IPv6 is available.
          mysql | 2023-09-17T01:14:31.029362Z 0 [Note] - '::' resolves to '::';
          mysql | 2023-09-17T01:14:31.029557Z 0 [Note] Server socket created on IP: '::'.
          mysql | 2023-09-17T01:14:31.092331Z 0 [Warning] Insecure configuration for --pid-file: Location '/var/run/mysqld' in the path is accessible to all OS users. Consider choosing a different directory.
          mysql | 2023-09-17T01:14:31.135045Z 0 [Note] Event Scheduler: Loaded 0 events
          mysql | 2023-09-17T01:14:31.136386Z 0 [Note] mysqld: ready for connections.
          mysql | Version: '5.7.40' socket: '/var/run/mysqld/mysqld.sock' port: 3306 MySQL Community Server (GPL)
          exp2-seata-server-1 | ███████╗███████╗ █████╗ ████████╗ █████╗
          exp2-seata-server-1 | ██╔════╝██╔════╝██╔══██╗╚══██╔══╝██╔══██╗
          exp2-seata-server-1 | ███████╗█████╗ ███████║ ██║ ███████║
          exp2-seata-server-1 | ╚════██║██╔══╝ ██╔══██║ ██║ ██╔══██║
          exp2-seata-server-1 | ███████║███████╗██║ ██║ ██║ ██║ ██║
          exp2-seata-server-1 | ╚══════╝╚══════╝╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝
          exp2-seata-server-1 |
          exp2-seata-server-1 |
          exp2-seata-server-1 | 01:14:47.513 INFO --- [ main] io.seata.server.ServerApplication : Starting ServerApplication using Java 1.8.0_212 on 1ce74f1a6ddb with PID 1 (/seata-server/classes started by root in seata-server)
          exp2-seata-server-1 | 01:14:47.574 INFO --- [ main] io.seata.server.ServerApplication : No active profile set, falling back to default profiles: default
          exp2-seata-server-1 | 01:15:00.397 INFO --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 7091 (http)
          exp2-seata-server-1 | 01:15:00.487 INFO --- [ main] o.a.coyote.http11.Http11NioProtocol : Initializing ProtocolHandler ["http-nio-7091"]
          exp2-seata-server-1 | 01:15:00.493 INFO --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
          exp2-seata-server-1 | 01:15:00.497 INFO --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/9.0.55]
          exp2-seata-server-1 | 01:15:01.083 INFO --- [ main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
          exp2-seata-server-1 | 01:15:01.086 INFO --- [ main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 12815 ms
          exp2-seata-server-1 | 01:15:07.130 INFO --- [ main] o.s.b.a.w.s.WelcomePageHandlerMapping : Adding welcome page: class path resource [static/index.html]
          exp2-seata-server-1 | 01:15:09.632 INFO --- [ main] o.s.s.web.DefaultSecurityFilterChain : Will secure Ant [pattern='/'] with []
          exp2-seata-server-1 | 01:15:09.637 INFO --- [ main] o.s.s.web.DefaultSecurityFilterChain : Will secure Ant [pattern='/**/*.css'] with []
          exp2-seata-server-1 | 01:15:09.642 INFO --- [ main] o.s.s.web.DefaultSecurityFilterChain : Will secure Ant [pattern='/**/*.js'] with []
          exp2-seata-server-1 | 01:15:09.647 INFO --- [ main] o.s.s.web.DefaultSecurityFilterChain : Will secure Ant [pattern='/**/*.html'] with []
          exp2-seata-server-1 | 01:15:09.655 INFO --- [ main] o.s.s.web.DefaultSecurityFilterChain : Will secure Ant [pattern='/**/*.map'] with []
          exp2-seata-server-1 | 01:15:09.661 INFO --- [ main] o.s.s.web.DefaultSecurityFilterChain : Will secure Ant [pattern='/**/*.svg'] with []
          exp2-seata-server-1 | 01:15:09.664 INFO --- [ main] o.s.s.web.DefaultSecurityFilterChain : Will secure Ant [pattern='/**/*.png'] with []
          exp2-seata-server-1 | 01:15:09.677 INFO --- [ main] o.s.s.web.DefaultSecurityFilterChain : Will secure Ant [pattern='/**/*.ico'] with []
          exp2-seata-server-1 | 01:15:09.682 INFO --- [ main] o.s.s.web.DefaultSecurityFilterChain : Will secure Ant [pattern='/console-fe/public/**'] with []
          exp2-seata-server-1 | 01:15:09.684 INFO --- [ main] o.s.s.web.DefaultSecurityFilterChain : Will secure Ant [pattern='/api/v1/auth/login'] with []
          exp2-seata-server-1 | 01:15:09.905 INFO --- [ main] o.s.s.web.DefaultSecurityFilterChain : Will secure any request with [org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter@691541bc, org.springframework.security.web.context.SecurityContextPersistenceFilter@474749b8, org.springframework.security.web.header.HeaderWriterFilter@28a6e171, org.springframework.security.web.authentication.logout.LogoutFilter@7aea704c, io.seata.console.filter.JwtAuthenticationTokenFilter@5b733ef7, org.springframework.security.web.savedrequest.RequestCacheAwareFilter@29013ef2, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@5f395ce1, org.springframework.security.web.authentication.AnonymousAuthenticationFilter@43a4a9e5, org.springframework.security.web.session.SessionManagementFilter@1f884bd6, org.springframework.security.web.access.ExceptionTranslationFilter@77cca767, org.springframework.security.web.access.intercept.FilterSecurityInterceptor@29962b2f]
          exp2-seata-server-1 | 01:15:10.162 INFO --- [ main] o.a.coyote.http11.Http11NioProtocol : Starting ProtocolHandler ["http-nio-7091"]
          exp2-seata-server-1 | 01:15:10.315 INFO --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 7091 (http) with context path ''
          exp2-seata-server-1 | 01:15:10.410 INFO --- [ main] io.seata.server.ServerApplication : Started ServerApplication in 31.949 seconds (JVM running for 38.918)
          exp2-seata-server-1 | 01:15:14.840 INFO --- [ main] com.alibaba.druid.pool.DruidDataSource : {dataSource-1} inited
          exp2-seata-server-1 | 01:15:16.443 INFO --- [ main] i.s.core.rpc.netty.NettyServerBootstrap : Server started, service listen port: 8091
          exp2-seata-server-1 | 01:15:16.674 INFO --- [ main] io.seata.server.ServerRunner : seata server started in 6241 millSeconds

                  在tc server端,比较重要的配置是seata-server/resources/application.yml如果不正确是起不来的,内容如下

            server:
            port: 7091


            spring:
            application:
            name: seata-server


            logging:
            config: classpath:logback-spring.xml
            file:
            path: ${user.home}/logs/seata
            extend:
            logstash-appender:
            destination: 127.0.0.1:4560
            kafka-appender:
            bootstrap-servers: 127.0.0.1:9092
            topic: logback_to_logstash


            console:
            user:
            username: seata
            password: seata


            seata:
            config:
            # support: nacos, consul, apollo, zk, etcd3
            type: file
            registry:
            # support: nacos, eureka, redis, zk, consul, etcd3, sofa
            type: file
            store:
            # support: file 、 db 、 redis
            mode: db
            db:
            datasource: druid
            dbType: mysql
            # 需要根据mysql的版本调整driverClassName
            # mysql8及以上版本对应的driver:com.mysql.cj.jdbc.Driver
            # mysql8以下版本的driver:com.mysql.jdbc.Driver
            driverClassName: com.mysql.cj.jdbc.Driver
            url: jdbc:mysql://host.docker.internal:3306/seata_server?useUnicode=true&characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useSSL=false
            user: root
            password: 123456
            min-conn: 5
            max-conn: 100
            global-table: global_table
            branch-table: branch_table
            lock-table: lock_table
            distributed-lock-table: distributed_lock
            query-limit: 100
            max-wait: 5000

            # server:
            # service-port: 8091 #If not configured, the default is '${server.port} + 1000'
            security:
            secretKey: SeataSecretKey0c382ef121d778043159209298fd40bf3850a017
            tokenValidityInMilliseconds: 1800000
            ignore:
            urls: /,/**/*.css,/**/*.js,/**/*.html,/**/*.map,/**/*.svg,/**/*.png,/**/*.ico,/console-fe/public/**,/api/v1/auth/login

                 在应用端有两个重要的配置文件registry.conf和file.conf:

            registry.conf:该配置用于指定 TC 的注册中心和配置文件,默认都是 file; 如果使用其他的注册中心,要求 Seata-Server 也注册到该配置中心上

            file.conf:该配置用于指定TC的相关属性;如果使用注册中心也可以将配置添加到配置中心

                    切换到db存储,我们需要在应用端改下第二个文件:src/main/resources/file.conf它会被打包到target/classes/file.conf,我们需要重点改下db具体内容如下:

              transport {
              # tcp udt unix-domain-socket
              type = "TCP"
              #NIO NATIVE
              server = "NIO"
              #enable heartbeat
              heartbeat = true
              #thread factory for netty
              thread-factory {
              boss-thread-prefix = "NettyBoss"
              worker-thread-prefix = "NettyServerNIOWorker"
              server-executor-thread-prefix = "NettyServerBizHandler"
              share-boss-worker = false
              client-selector-thread-prefix = "NettyClientSelector"
              client-selector-thread-size = 1
              client-worker-thread-prefix = "NettyClientWorkerThread"
              # netty boss thread size,will not be used for UDT
              boss-thread-size = 1
              #auto default pin or 8
              worker-thread-size = 8
              }
              shutdown {
              # when destroy server, wait seconds
              wait = 3
              }
              serialization = "seata"
              compressor = "none"
              }
              service {
              #vgroup->rgroup
              vgroupMapping.my_test_tx_group = "default"
              #only support single node
              default.grouplist = "127.0.0.1:8091"
              #degrade current not support
              enableDegrade = false
              #disable
              disable = false
              #unit ms,s,m,h,d represents milliseconds, seconds, minutes, hours, days, default permanent
              max.commit.retry.timeout = "-1"
              max.rollback.retry.timeout = "-1"
              }


              client {
              async.commit.buffer.limit = 10000
              lock {
              retry.internal = 10
              retry.times = 30
              }
              report.retry.count = 5
              }


              ## transaction log store
              store {
              ## store mode: file、db
              mode = "db"


              ## file store
              file {
              dir = "sessionStore"


              # branch session size , if exceeded first try compress lockkey, still exceeded throws exceptions
              max-branch-session-size = 16384
              # globe session size , if exceeded throws exceptions
              max-global-session-size = 512
              # file buffer size , if exceeded allocate new buffer
              file-write-buffer-cache-size = 16384
              # when recover batch read size
              session.reload.read_size = 100
              # async, sync
              flush-disk-mode = async
              }


              ## database store
              db {
              ## the implement of javax.sql.DataSource, such as DruidDataSource(druid)/BasicDataSource(dbcp) etc.
              datasource = "dbcp"
              ## mysql/oracle/h2/oceanbase etc.
              db-type = "mysql"
              url = "jdbc:mysql://127.0.0.1:3306/seata_server"
              user = "mysql"
              password = "123456"
              min-conn = 1
              max-conn = 3
              global.table = "global_table"
              branch.table = "branch_table"
              lock-table = "lock_table"
              query-limit = 100
              }
              }
              lock {
              ## the lock store mode: local、remote
              mode = "remote"


              local {
              ## store locks in user's database
              }


              remote {
              ## store locks in the seata's server
              }
              }
              recovery {
              committing-retry-delay = 30
              asyn-committing-retry-delay = 30
              rollbacking-retry-delay = 30
              timeout-retry-delay = 30
              }


              transaction {
              undo.data.validation = true
              undo.log.serialization = "jackson"
              }


              ## metrics settings
              metrics {
              enabled = false
              registry-type = "compact"
              # multi exporters use comma divided
              exporter-list = "prometheus"
              exporter-prometheus-port = 9898
              }

              然后我们启动api的例子,看下

                %  /usr/bin/env /Library/Internet\ Plug-Ins/Ja
                vaAppletPlugin.plugin/Contents/Home/bin/java -cp /var/folders/2n/42n_1dfd6kjd6s3k
                7bt4cb3h0000gn/T/cp_5dao53bnilynlwjde6nptexag.jar io.seata.samples.api.Bussiness


                C00321
                SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
                SLF4J: Defaulting to no-operation (NOP) logger implementation
                SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
                SLF4J: Failed to load class "org.slf4j.impl.StaticMDCBinder".
                SLF4J: Defaulting to no-operation MDCAdapter implementation.
                SLF4J: See http://www.slf4j.org/codes.html#no_static_mdc_binder for further details.
                begin trx, xid is 172.27.0.3:8091:27457736967143445
                96
                199
                true

                执行成功了。为了看到,db存了啥,可以在事务开始的地方打上断点

                    tx.begin(6000, "testBiz");
                    System.out.println("begin trxxid is " + tx.getXid());

                  调试下,然后看下数据库的内容

                     mysql> select * from global_table;
                    +-----------------------------------+-------------------+--------+----------------+---------------------------+------------------+---------+---------------+------------------+---------------------+---------------------+
                    | xid | transaction_id | status | application_id | transaction_service_group | transaction_name | timeout | begin_time | application_data | gmt_create | gmt_modified |
                    +-----------------------------------+-------------------+--------+----------------+---------------------------+------------------+---------+---------------+------------------+---------------------+---------------------+
                    | 172.27.0.3:8091:27457736967143435 | 27457736967143435 | 6 | api | my_test_tx_group | testBiz | 6000 | 1694916397824 | NULL | 2023-09-17 10:06:37 | 2023-09-17 10:06:44 |
                    +-----------------------------------+-------------------+--------+----------------+---------------------------+------------------+---------+---------------+------------------+---------------------+---------------------+
                    1 row in set (0.00 sec)

                    注意下,我们启动事务的时候传入了超时时间,达到超时时间后,会删除这条记录,也就是说,这个全局事务id只是在事务执行期间存在,如果事务回滚或者提交,这条记录会随之消失。

                    文章转载自golang算法架构leetcode技术php,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

                    评论