- 浏览: 71428 次
- 性别:
- 来自: 深圳
文章分类
最新评论
-
Alex_Cheung:
对了,第二个没有提取码,请知悉。
一大波视频分享 -
Alex_Cheung:
谢谢分享。
一大波视频分享 -
Jiy:
很详细,谢谢分享
java并发之同步辅助类Phaser -
walle1027:
非常不错,学习了。
java并发之同步辅助类Phaser -
huangjinjin520:
somefuture 写道除了单词写错了 其他挺好的已更正
dubbo注解使用详解
Dubbo+Zookeeper+SpringMVC整合实现分布式服务治理框架
目录
Dubbo+Zookeeper+SpringMVC整合实现分布式服务治理框架 1
一、分布式服务治理架构原理分析 3
二、先决条件 5
三、Zookeeper安装与配置 6
3.1 Zookeeper下载与解压 6
3.2 复制和编辑配置文件 6
3.3 创建myid文件 7
3.4 Zookeeper启动与停止 7
3.5 Zookeeper命令行基本操作 8
四、Dubbo管理界面安装与配置 10
4.1 Dubbo管理界面下载与解压 10
4.2 修改配置文件 10
4.3 运行 10
4.4 访问Dubbo管理界面 10
五、Dubbo、Zookeeper与SpringMVC集成测试 12
5.1 创建提供者及服务注册 12
5.2 创建消费者及服务调用 16
一、分布式服务治理架构原理分析
Dubbo是主流的采用RPC方式的分布式服务治理架构之一,实现了分布式服务注册、服务治理和服务监控等功能。通常需结合开源的Zookeeper、Redis或阿里数据库来完成注册中心的功能。其基本架构及原理如图1-1所示:
图1-1 Dubbo实现微服务架构原理图
节点角色说明:
● Provider: 暴露服务的服务一个或多个提供方。
● Consumer: 调用远程服务的服务消费方。
● Registry: 服务注册与发现的注册中心,本文采用开源Zookeeper作为服务注册中心。
● Monitor: 统计服务的调用次调和调用时间的监控中心。
● Container: 服务运行容器。
调用关系说明:
(0)服务容器负责启动,加载,运行服务提供者。
(1)服务提供者在启动时,向注册中心注册自己提供的服务。
(2)服务消费者在启动时,向注册中心订阅自己所需的服务。
(3)注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者。
(4)服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。
(5)服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心。
二、先决条件
操作系统:CentOS 7.2
JAVA环境:jdk1.7.0_67
Web应用服务器:tomcat v7.0(自行解压安装)
三、Zookeeper安装与配置
本文Zookeeper部署采用由3台机器组成的集群模式,以下操作步骤在每台机器上均需执行,请注意不同机器间配置稍有变化。
3.1 Zookeeper下载与解压
wget http://archive.apache.org/dist/zookeeper/zookeeper-3.4.8/zookeeper-3.4.8.tar.gz
tar –zxvf zookeeper-3.4.8.tar.gz –C .
cd zookeeper-3.4.8
3.2 复制和编辑配置文件
cp conf/zoo_sample.cfg zoo.cfg
vi conf/zoo.cfg
图3-1
(1) 修改数据文件目录,也可采用默认值;
(2)"server.id=host:port:port"中的第一个port是从机器(follower)连接到主机器(leader)的端口号,第二个port是进行leadership选举的端口号。本文采用集群方式部署,添加机器时增加相应新记录即可,由于Zookeeper内部存在仲裁机制,机器数最好是奇数。
3.3 创建myid文件
dataDir所指定的目录下创建一个文件名为myid的文件,文件中的内容只有一行,为本主机对应的id值,也就是图3-1中server.id中的id。例如:在服务器1中的myid的内容应该写入1。Zookeeper集群模式不同机器上配置的id值一定要正确,如图3-2所示。
图3-2
3.4 Zookeeper启动与停止
①Zookeeper启动
启动Zookeeeper,启动成功使用jps可看到名为“QuorumPeerMain”的进程,如图3-3所示。注意,与Hadoop和Spark等集群方式启动不同,Zookeeper集群启动需要在每台机器上都运行该命令:
./bin/zkServer.sh start
图3-3
②Zookeeeper停止
./bin/zkServer.sh stop
3.5 Zookeeper命令行基本操作
①连接Zookeeper命令行终端
./bin/zkCli.sh –server 172.16.24.160:2181
图3-4
②Zookeeper增删改查基本命令
创建命令:
create /test ‘test’
查询命令:
get /test
修改命令:
set /test test_new
删除命令:
delete /test
图3-5
四、Dubbo管理界面安装与配置
4.1 Dubbo管理界面下载与解压
下载Dubbo管理界面dubbo-admin-2.5.4并解压出来,见附件。
4.2 修改配置文件
解压后进入dubbo-admin-2.5.4\WEB-INF目录中,打开dubbo.properties文件如下配置,如图4-1所示:
图4-1
4.3 运行
将修改好配置的dubbo-admin-2.5.4整个目标复制到Tomcat根目录的webapps下,进入Tomcat根目录执行如下命令进行启动,如图4-2所示:
图4-2
4.4 访问Dubbo管理界面
打开浏览器,输入地址:http://172.16.24.160:8080/dubbo-admin-2.5.4/,用户名和密码均为root,参考前面dubbo.properties配置,如图4-3所示。
图4-3
五、Dubbo、Zookeeper与SpringMVC集成测试
Dubbo、Zookeeper与SpringMVC集成测试需要编写提供者和消费者程序进行验证,下文只简述关键步骤,程序开发的细节请参考附件源代码。
5.1 创建提供者及服务注册
①创建Maven项目
先开发服务提供者程序,新建Maven项目,配置pom.xml文件加入dubbo、zookeeper等jar包,如图5-1所示:
图5-1
②创建接口
编写提供者的服务接口,如图5-2所示:
图5-2
③创建实现类
编写服务接口的具体实现类,如图5-3所示:
图5-3
④暴露服务配置
新建dubbo-provider.xml暴露服务配置文件,配置Zookeeper服务注册中心的IP、端口号、服务接口和接口实现类等信息,如图5-4所示:
图5-4
具体配置说明:
● dubbo:application 标签一些属性的说明:
(1) name 必填,当前应用名称,用于注册中心计算应用间依赖关系,注意:消费者和提供者应用名不要一样,此参数不是匹配条件,你当前项目叫什么名字就填什么,和提供者消费者角色无关。
● dubbo:registry 标签一些属性的说明:
(1)address必填,可以Zookeeper集群配置,地址可以多个以逗号隔开等。
(2)check可选,注册中心不存在时,是否报错。
(3)subscribe可选,是否向此注册中心订阅服务,如果设为false,将只注册,不订阅。
(4)register可选,是否向此注册中心注册服务,如果设为false,将只订阅,不注册。
(5) dynamic 可选,服务是否动态注册,如果设为false,注册后将显示后disable状态,需人工启用,并且服务提供者停止时,也不会自动取消册,需人工禁用。
● dubbo: protocol标签的一些属性说明:
(1)name 必填,协议名称,缺省值dubbo。
(2)port 可选,dubbo协议缺省端口为20880,rmi协议缺省端口为1099,http和hessian协议缺省端口为80 。
● dubbo:service标签的一些属性说明:
(1)interface必填,服务接口的路径
(2)ref必填,引用对应的实现类的Bean的ID
(3)registry可选,向指定注册中心注册,在多个注册中心时使用,值为<dubbo:registry>的id属性,多个注册中心ID用逗号分隔,如果不想将该服务注册到任何registry,可将值设为N/A。
● bean 标签一些属性的说明:
(1) id 是实现类的Bean的ID。
(2)class 是实现类的引用路径。
⑤注册服务
编写注册服务主类Provider.java,如图5-5所示,读取并解释显露服务的配置文件dubbo-provider.xml,运行Main函数即可将上述写好的服务注册到Zookeeper注册中心上,如图5-6所示。
图5-5
图5-6
5.2 创建消费者及服务调用
①调用服务配置
新建dubbo- consumer.xml调用服务配置文件,配置调用Zookeeper注册中心IP、端口号和提供商服务接口等信息,如图5-7所示:
图5-7
具体配置说明:
● dubbo:application 和dubbo:registry标签属性说明同上:
● dubbo:reference标签属性说明:
(1)id 必填, 服务引用BeanId。
(2)interface,必填,服务接口名,由于dubbo服务治理方式属于RPC方式,因而消费者需要明确知道服务的完整接口名方可调用。
②调用服务
编写调用服务主类Consumer.java,如图5-8所示,读取并解释调用服务的配置文件dubbo-consumer.xml,运行Main函数即可完成服务调用,如图5-9所示。
图5-8
图5-9
目录
Dubbo+Zookeeper+SpringMVC整合实现分布式服务治理框架 1
一、分布式服务治理架构原理分析 3
二、先决条件 5
三、Zookeeper安装与配置 6
3.1 Zookeeper下载与解压 6
3.2 复制和编辑配置文件 6
3.3 创建myid文件 7
3.4 Zookeeper启动与停止 7
3.5 Zookeeper命令行基本操作 8
四、Dubbo管理界面安装与配置 10
4.1 Dubbo管理界面下载与解压 10
4.2 修改配置文件 10
4.3 运行 10
4.4 访问Dubbo管理界面 10
五、Dubbo、Zookeeper与SpringMVC集成测试 12
5.1 创建提供者及服务注册 12
5.2 创建消费者及服务调用 16
一、分布式服务治理架构原理分析
Dubbo是主流的采用RPC方式的分布式服务治理架构之一,实现了分布式服务注册、服务治理和服务监控等功能。通常需结合开源的Zookeeper、Redis或阿里数据库来完成注册中心的功能。其基本架构及原理如图1-1所示:
图1-1 Dubbo实现微服务架构原理图
节点角色说明:
● Provider: 暴露服务的服务一个或多个提供方。
● Consumer: 调用远程服务的服务消费方。
● Registry: 服务注册与发现的注册中心,本文采用开源Zookeeper作为服务注册中心。
● Monitor: 统计服务的调用次调和调用时间的监控中心。
● Container: 服务运行容器。
调用关系说明:
(0)服务容器负责启动,加载,运行服务提供者。
(1)服务提供者在启动时,向注册中心注册自己提供的服务。
(2)服务消费者在启动时,向注册中心订阅自己所需的服务。
(3)注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者。
(4)服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。
(5)服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心。
二、先决条件
操作系统:CentOS 7.2
JAVA环境:jdk1.7.0_67
Web应用服务器:tomcat v7.0(自行解压安装)
三、Zookeeper安装与配置
本文Zookeeper部署采用由3台机器组成的集群模式,以下操作步骤在每台机器上均需执行,请注意不同机器间配置稍有变化。
3.1 Zookeeper下载与解压
wget http://archive.apache.org/dist/zookeeper/zookeeper-3.4.8/zookeeper-3.4.8.tar.gz
tar –zxvf zookeeper-3.4.8.tar.gz –C .
cd zookeeper-3.4.8
3.2 复制和编辑配置文件
cp conf/zoo_sample.cfg zoo.cfg
vi conf/zoo.cfg
图3-1
(1) 修改数据文件目录,也可采用默认值;
(2)"server.id=host:port:port"中的第一个port是从机器(follower)连接到主机器(leader)的端口号,第二个port是进行leadership选举的端口号。本文采用集群方式部署,添加机器时增加相应新记录即可,由于Zookeeper内部存在仲裁机制,机器数最好是奇数。
3.3 创建myid文件
dataDir所指定的目录下创建一个文件名为myid的文件,文件中的内容只有一行,为本主机对应的id值,也就是图3-1中server.id中的id。例如:在服务器1中的myid的内容应该写入1。Zookeeper集群模式不同机器上配置的id值一定要正确,如图3-2所示。
图3-2
3.4 Zookeeper启动与停止
①Zookeeper启动
启动Zookeeeper,启动成功使用jps可看到名为“QuorumPeerMain”的进程,如图3-3所示。注意,与Hadoop和Spark等集群方式启动不同,Zookeeper集群启动需要在每台机器上都运行该命令:
./bin/zkServer.sh start
图3-3
②Zookeeeper停止
./bin/zkServer.sh stop
3.5 Zookeeper命令行基本操作
①连接Zookeeper命令行终端
./bin/zkCli.sh –server 172.16.24.160:2181
图3-4
②Zookeeper增删改查基本命令
创建命令:
create /test ‘test’
查询命令:
get /test
修改命令:
set /test test_new
删除命令:
delete /test
图3-5
四、Dubbo管理界面安装与配置
4.1 Dubbo管理界面下载与解压
下载Dubbo管理界面dubbo-admin-2.5.4并解压出来,见附件。
4.2 修改配置文件
解压后进入dubbo-admin-2.5.4\WEB-INF目录中,打开dubbo.properties文件如下配置,如图4-1所示:
图4-1
4.3 运行
将修改好配置的dubbo-admin-2.5.4整个目标复制到Tomcat根目录的webapps下,进入Tomcat根目录执行如下命令进行启动,如图4-2所示:
图4-2
4.4 访问Dubbo管理界面
打开浏览器,输入地址:http://172.16.24.160:8080/dubbo-admin-2.5.4/,用户名和密码均为root,参考前面dubbo.properties配置,如图4-3所示。
图4-3
五、Dubbo、Zookeeper与SpringMVC集成测试
Dubbo、Zookeeper与SpringMVC集成测试需要编写提供者和消费者程序进行验证,下文只简述关键步骤,程序开发的细节请参考附件源代码。
5.1 创建提供者及服务注册
①创建Maven项目
先开发服务提供者程序,新建Maven项目,配置pom.xml文件加入dubbo、zookeeper等jar包,如图5-1所示:
图5-1
②创建接口
编写提供者的服务接口,如图5-2所示:
图5-2
③创建实现类
编写服务接口的具体实现类,如图5-3所示:
图5-3
④暴露服务配置
新建dubbo-provider.xml暴露服务配置文件,配置Zookeeper服务注册中心的IP、端口号、服务接口和接口实现类等信息,如图5-4所示:
图5-4
具体配置说明:
● dubbo:application 标签一些属性的说明:
(1) name 必填,当前应用名称,用于注册中心计算应用间依赖关系,注意:消费者和提供者应用名不要一样,此参数不是匹配条件,你当前项目叫什么名字就填什么,和提供者消费者角色无关。
● dubbo:registry 标签一些属性的说明:
(1)address必填,可以Zookeeper集群配置,地址可以多个以逗号隔开等。
(2)check可选,注册中心不存在时,是否报错。
(3)subscribe可选,是否向此注册中心订阅服务,如果设为false,将只注册,不订阅。
(4)register可选,是否向此注册中心注册服务,如果设为false,将只订阅,不注册。
(5) dynamic 可选,服务是否动态注册,如果设为false,注册后将显示后disable状态,需人工启用,并且服务提供者停止时,也不会自动取消册,需人工禁用。
● dubbo: protocol标签的一些属性说明:
(1)name 必填,协议名称,缺省值dubbo。
(2)port 可选,dubbo协议缺省端口为20880,rmi协议缺省端口为1099,http和hessian协议缺省端口为80 。
● dubbo:service标签的一些属性说明:
(1)interface必填,服务接口的路径
(2)ref必填,引用对应的实现类的Bean的ID
(3)registry可选,向指定注册中心注册,在多个注册中心时使用,值为<dubbo:registry>的id属性,多个注册中心ID用逗号分隔,如果不想将该服务注册到任何registry,可将值设为N/A。
● bean 标签一些属性的说明:
(1) id 是实现类的Bean的ID。
(2)class 是实现类的引用路径。
⑤注册服务
编写注册服务主类Provider.java,如图5-5所示,读取并解释显露服务的配置文件dubbo-provider.xml,运行Main函数即可将上述写好的服务注册到Zookeeper注册中心上,如图5-6所示。
图5-5
图5-6
5.2 创建消费者及服务调用
①调用服务配置
新建dubbo- consumer.xml调用服务配置文件,配置调用Zookeeper注册中心IP、端口号和提供商服务接口等信息,如图5-7所示:
图5-7
具体配置说明:
● dubbo:application 和dubbo:registry标签属性说明同上:
● dubbo:reference标签属性说明:
(1)id 必填, 服务引用BeanId。
(2)interface,必填,服务接口名,由于dubbo服务治理方式属于RPC方式,因而消费者需要明确知道服务的完整接口名方可调用。
②调用服务
编写调用服务主类Consumer.java,如图5-8所示,读取并解释调用服务的配置文件dubbo-consumer.xml,运行Main函数即可完成服务调用,如图5-9所示。
图5-8
图5-9
发表评论
-
一大波视频分享
2018-06-09 09:36 11411.ps 链接: https://pan.baidu ... -
利用Sharding-Jdbc实现分表
2018-05-24 22:32 3786你们团队使用SpringMVC+Spr ... -
MINA原理详解
2018-05-19 13:51 14881. 通过SocketConnector同服务器端建立连接 ... -
最近有人说我欺骗消费者,今天来一波视频分享
2018-05-12 21:00 1252最近有人说我欺骗消费者,今天来一波视频分享 dubbo入门 ... -
SVN多版本库环境的搭建
2018-05-02 21:00 1211一、 1、启动SVN sudo svn ... -
前端 Java Python等资源合集大放送
2018-04-21 22:11 697如果需要学习视频,欢 ... -
Nginx会话保持之nginx-sticky-module模块
2018-04-16 20:34 1968在使用负载均衡的时候会遇到会话保持的问题,常用的方法有: 1. ... -
dubbo源码学习(四):暴露服务的过程
2018-04-14 11:38 980dubbo采用的nio异步的通信,通信协议默认为 netty, ... -
dubbo源码学习(四)初始化过程细节:解析服务
2018-04-12 20:32 615今天将真正去看dubbo内部的实现过程,看dubbo的源码前我 ... -
dubbo源码学习(二) : spring 自定义标签
2018-04-09 20:29 632做dubbo的配置时很容易发现,dubbo有一套自己的标签,提 ... -
Dubbo多注册中心和Zookeeper服务的迁移
2018-04-06 08:58 1506一、Dubbo多注册中心 1、 应用场景 例如阿里有些服务 ... -
dubbo源码学习一:基础知识及使用的相关技术
2018-04-05 20:10 691Dubbo是Alibaba开源的分布式服务框架,它最大的特点是 ... -
worker模式
2018-03-29 20:16 636今天来学学,大家也好对线程池有一个更好的理解。 public ... -
线程各种状态转移分析
2018-03-28 22:13 900线程在它的生命周期 ... -
生产者-消费者模式实现
2018-03-26 22:45 1160生产者是指:生产数据的线程 消费者是指:使用数据的线程 生产者 ... -
java并发之同步辅助类Phaser
2018-03-19 21:46 1105Phaser含义: 更加复杂和强大的同步辅助类。它允许并发执 ... -
java并发之同步辅助类CyclicBarrier
2018-03-18 20:13 834CyclicBarrier含义: 栅栏允许两个或者多个线程在 ... -
java并发之同步辅助类semaphore
2018-03-14 21:24 780semaphore(seməˌfôr)含义: 信号量就是可以 ... -
Tomcat 集群 文件上传下载的共享问题 NFS配置
2018-03-12 21:50 664Tomcat 集群时上传文件时如何使得多部tomcat中的文件 ... -
it技术谱图分享
2018-03-10 22:05 5181、程序开发语言综述 2、前端工程师必备技能 3、 ...
相关推荐
本项目通过整合Dubbo、Zookeeper和SpringMVC,构建了一个完整的分布式服务治理框架,以实现高效的服务注册、发现、管理和监控。 首先,我们要理解Dubbo的核心功能。Dubbo提供了服务提供者(Provider)和服务消费者...
首先,`Dubbo`是一个高性能、轻量级的Java服务框架,它的主要功能包括服务治理和服务调用。在项目中,服务提供者通过`Dubbo`暴露服务,服务消费者通过`Dubbo`来调用这些服务。`Dubbo`提供了丰富的API和配置选项,如...
这个教程将带你一步步实现一个基于Dubbo、Zookeeper和SpringMVC的分布式服务治理框架,通过实践,你可以更深入地理解这些组件的工作原理和相互配合的方式,提升你的分布式系统开发能力。提供的源码能让你更直观地...
本示例通过结合Dubbo、Zookeeper和SpringMVC,展示了如何构建一个完整的分布式服务治理框架。以下是关于这些技术及其相互作用的详细解释。 1. **Dubbo**: Dubbo是阿里巴巴开源的一款高性能、轻量级的服务治理框架,...
在分布式系统中,Dubbo、Zookeeper和SpringMVC是三个关键组件,它们协同工作以构建高可用、高性能的服务架构。下面将详细讲解这三个技术如何整合,并探讨它们在实际项目中的应用。 首先,Dubbo是一个由阿里巴巴开源...
在本架构中,`Dubbo`是一个关键的分布式服务治理框架,它允许服务提供者暴露服务,而服务消费者则可以透明地调用这些服务。`Zookeeper`作为注册中心,负责服务的注册与发现,确保服务之间的通信可靠。 【SpringMVC...
本项目整合了`Zookeeper`作为注册中心,`Dubbo`作为服务框架,并结合`SpringMVC`进行业务逻辑处理,实现了微服务化的架构设计。同时,`MongoDB`的引入则提供了非关系型数据库支持。以下是对这些技术及其整合的详细...
Dubbo是一个分布式服务框架,致力于提供高性能和透明化的RPC远程服务调用方案,以及SOA服务治理方案; Alibaba开源的SOA框架; 与Spring框架无缝集成;
在IT行业中,分布式服务框架是构建大型互联网应用的关键技术之一,Dubbo作为阿里巴巴开源的一款高性能、轻量级的Java远程服务调用框架,受到了广泛的关注和使用。它旨在提高服务的治理能力,使得服务提供者和服务...
在IT行业中,分布式服务框架是构建大型、高可用系统的关键技术之一。本示例"**DUBBO+Zookeeper小例子**"旨在演示如何利用SpringMVC、Dubbo和Zookeeper来实现一个微服务架构。这是一次将这些组件集成到一起的实际操作...
总结起来,Dubbo、Zookeeper与SpringMVC的整合实现了服务的高效治理和Web应用的灵活开发。通过定义清晰的API,我们可以将业务逻辑封装在服务中,通过SpringMVC进行控制层的处理,最后通过Zookeeper实现服务的注册和...
【标题】"dubbo+zookeeper+SpringMVC Demo"是一个示例项目,它演示了如何在实际应用中整合这三个关键组件:Dubbo、Zookeeper和SpringMVC。Dubbo是阿里巴巴开源的一个高性能、轻量级的服务框架,用于构建微服务架构;...
Dubbo是中国阿里巴巴开源的一款高性能、轻量级的Java服务治理框架,而Zookeeper是Apache的一个分布式协调服务,常用于分布式环境中的配置管理、命名服务、集群同步等。 【描述】提到的" dubbo+zookeeper+springmvc...
Dubbo 和 ZooKeeper 是两种在分布式环境中广泛使用的开源工具,它们分别承担了服务治理和服务发现的关键角色。 Dubbo 是阿里巴巴开源的一款高性能、轻量级的服务治理框架,它提供了服务注册、服务发现、调用链跟踪...
【ssm+dubbo+zookeeper分布式CRUD demo】项目是一个典型的Java Web分布式开发示例,它结合了Spring、SpringMVC和MyBatis(SSM)框架,并利用Dubbo作为服务治理框架,配合Zookeeper作为注册中心,实现了服务的高可用...
本项目“dubbo+zookeeper+SpringMVC+Spring+Mybatis+Freemarker集成”正是一个典型的分布式服务架构,它结合了多个核心技术,旨在提供高效、可扩展的业务处理能力。 首先,Dubbo是一个由阿里巴巴开源的高性能Java ...
【标题】中的“SpringMVC精品资源--使用Maven构建,整合Dubbo+Zookeeper+SpringMVC+Spring”表明这是一个关于使用SpringMVC技术,结合Maven项目管理工具,以及Dubbo服务治理框架和Zookeeper分布式协调服务的综合教程...
Dubbo+Zookeeper分布式服务框架 合理的分布式服务划分(common+api+service+web) 资源调度和治理中心(SOA)(dubbo-admin) 服务监控方案(dubbo-monitor) <项目介绍> 该资源内项目源码是个人的毕设,代码都测试ok,...