42

SpringCloud Alibaba (四):Dubbo RPC框架

 3 years ago
source link: http://www.cnblogs.com/gaofei200/p/13237342.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Dubbo简介

Apache Dubbo |ˈdʌbəʊ| 是一款高性能、轻量级的开源Java RPC框架,它提供了三大核心能力:面向接口的远程方法调用,智能容错和负载均衡,以及服务自动注册和发现。致力于提高性能和透明化的RPC远程服务调用方案,以及SOA服务治理方案。

yYBvuqz.jpg!web

节点 角色说明 Provider 暴露服务的服务提供方 Consumer 调用远程服务的服务消费方 Registry 服务注册与发现的注册中心 Monitor 统计服务的调用次数和调用时间的监控中心 Container 服务运行容器

功能特点 :

  • 面向接口代理的高性能RPC调用

    提供高性能的基于代理的远程调用能力,服务以接口为粒度,为开发者屏蔽远程调用底层细节。

  • 智能负载均衡

    内置多种负载均衡策略,智能感知下游节点健康状况,显著减少调用延迟,提高系统吞吐量。

  • 服务自动注册与发现

    支持多种注册中心服务,服务实例上下线实时感知。

  • 高度可扩展能力

    遵循微内核+插件的设计原则,所有核心能力如Protocol、Transport、Serialization被设计为扩展点,平等对待内置实现和第三方实现。

  • 运行期流量调度

    内置条件、脚本等路由策略,通过配置不同的路由规则,轻松实现灰度发布,同机房优先等功能。

  • 可视化的服务治理与运维

    提供丰富服务治理、运维工具:随时查询服务元数据、服务健康状态及调用统计,实时下发路由策略、调整配置参数。

Spring Cloud 为什么需要RPC

在Spring Cloud构建的微服务系统中,大多数的开发者使用都是官方提供的Feign组件来进行内部服务通信,这种声明式的HTTP客户端使用起来非常的简洁、方便、优雅,但是有一点,在使用Feign消费服务的时候,相比较Dubbo这种RPC框架而言,性能堪忧。

虽说在微服务架构中,会讲按照业务划分的微服务独立部署,并且运行在各自的进程中。微服务之间的通信更加倾向于使用HTTP这种简答的通信机制,大多数情况都会使用REST API。这种通信方式非常的简洁高效,并且和开发平台、语言无关,但是通常情况下,HTTP并不会开启KeepAlive功能,即当前连接为短连接,短连接的缺点是每次请求都需要建立TCP连接,这使得其效率变的相当低下。

对外部提供REST API服务是一件非常好的事情,但是如果内部调用也是使用HTTP调用方式,就会显得显得性能低下,Spring Cloud默认使用的Feign组件进行内部服务调用就是使用的HTTP协议进行调用,这时,我们如果内部服务使用RPC调用,对外使用REST API,将会是一个非常不错的选择,恰巧,Dubbo Spring Cloud给了我们这种选择的实现方式。

SpringCloud Alibaba 整合 Dubbo

创建ApacheDubbo总工程, 在pom.xml添加统一依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
​
    <groupId>com.gofy</groupId>
    <artifactId>ApacheDubbo</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>pom</packaging>
​
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.8.RELEASE</version>
    </parent>
​
    <modules>
        <module>dubbo-provider</module>
        <module>dubbo-consumer</module>
    </modules>
​
    <properties>
        <!-- Environment Settings -->
        <java.version>1.8</java.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <spring-cloud.version>Greenwich.SR3</spring-cloud.version>
        <spring-cloud-alibaba.version>0.2.1.RELEASE</spring-cloud-alibaba.version>
        <dubbo.version>2.7.6</dubbo.version>
        <dubbo-spring.version>2.7.6</dubbo-spring.version>
        <dubbo-actuator.version>2.7.6</dubbo-actuator.version>
        <dubbo-kryo.version>2.7.6</dubbo-kryo.version>
        <dubbo-nacos.version>2.7.6</dubbo-nacos.version>
        <dubbo-nacos-config.version>2.1.0.RELEASE</dubbo-nacos-config.version>
        <spring-context-support.version>1.0.6</spring-context-support.version>
    </properties>
​
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>${spring-cloud-alibaba.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
​
            <!-- Apache Dubbo  -->
            <dependency>
                <groupId>org.apache.dubbo</groupId>
                <artifactId>dubbo</artifactId>
                <version>${dubbo.version}</version>
                <exclusions>
                    <exclusion>
                        <groupId>org.springframework</groupId>
                        <artifactId>spring</artifactId>
                    </exclusion>
                    <exclusion>
                        <groupId>javax.servlet</groupId>
                        <artifactId>servlet-api</artifactId>
                    </exclusion>
                    <exclusion>
                        <groupId>log4j</groupId>
                        <artifactId>log4j</artifactId>
                    </exclusion>
                </exclusions>
            </dependency>
            <dependency>
                <groupId>org.apache.dubbo</groupId>
                <artifactId>dubbo-spring-boot-actuator</artifactId>
                <version>${dubbo-actuator.version}</version>
            </dependency>
            <dependency>
                <groupId>org.apache.dubbo</groupId>
                <artifactId>dubbo-spring-boot-starter</artifactId>
                <version>${dubbo-spring.version}</version>
            </dependency>
            <!-- 使用kryo序列化/反序列化工具, 提高项目性能 -->
            <dependency>
                <groupId>org.apache.dubbo</groupId>
                <artifactId>dubbo-serialization-kryo</artifactId>
                <version>${dubbo-kryo.version}</version>
            </dependency>
​
            <!-- Spring Cloud Alibaba -->
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>dubbo-registry-nacos</artifactId>
                <version>${dubbo-nacos.version}</version>
            </dependency>
            <dependency>
                <groupId>com.alibaba.nacos</groupId>
                <artifactId>nacos-client</artifactId>
                <version>1.2.1</version>
            </dependency>
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
                <version>${dubbo-nacos-config.version}</version>
            </dependency>
            <dependency>
                <groupId>com.alibaba.spring</groupId>
                <artifactId>spring-context-support</artifactId>
                <version>${spring-context-support.version}</version>
            </dependency>
        </dependencies>
    </dependencyManagement>
​
    <build>
        <plugins>
            <!-- Compiler 插件, 设定 JDK 版本 -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <showWarnings>true</showWarnings>
                </configuration>
            </plugin>
        </plugins>
​
        <!-- 资源文件配置 -->
        <resources>
            <resource>
                <directory>src/main/java</directory>
                <excludes>
                    <exclude>**/*.java</exclude>
                </excludes>
            </resource>
            <resource>
                <directory>src/main/resources</directory>
            </resource>
        </resources>
    </build>
</project>

服务提供者

在Dubbo RPC框架中, 服务提供者的接口类和实现类应该分开为俩个模块, 所以我们应该在服务提供者下创建两个子模块, 分别为 接口模块dubbo-provider-api 实现模块dubbo-provider-service

在总工程 ApacheDubbo 下创建 dubbo-provider 模块, 添加服务提供者的统一依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <parent>
        <artifactId>ApacheDubbo</artifactId>
        <groupId>com.gofy</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>

    <groupId>com.gofy</groupId>
    <artifactId>dubbo-provider</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>pom</packaging>

    <modules>
        <module>dubbo-provider-api</module>
        <module>dubbo-provider-service</module>
    </modules>
</project>
  • dubbo-provider 下创建 dubbo-provider-api 子模块, 并添加依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <artifactId>dubbo-provider</artifactId>
        <groupId>com.gofy</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
​
    <groupId>com.gofy</groupId>
    <artifactId>dubbo-provider-api</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>
​
</project>

创建接口类 EchoService

package com.gofy.dubbo.api;
​
public interface EchoService {
    String echo(String s);
}
  • dubbo-provider 下创建 dubbo-provider-service 子模块, 并添加依赖

导入接口模块失败原因: 一般是总工程的统一依赖出了问题, 可以查看本地maven仓库的中总工程导入的依赖的包有没有缺失文件. 我之前失败原因就是 spring-cloud-dependencies 包出了问题, Greenwich.SR5版本下载一直缺失文件, 改为Greenwich.SR3就好了.

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <artifactId>dubbo-provider</artifactId>
        <groupId>com.gofy</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>

    <groupId>com.gofy</groupId>
    <artifactId>dubbo-provider-service</artifactId>
    <packaging>jar</packaging>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo-spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo-serialization-kryo</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>dubbo-registry-nacos</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba.nacos</groupId>
            <artifactId>nacos-client</artifactId>
        </dependency>

        <dependency>
            <groupId>com.alibaba.spring</groupId>
            <artifactId>spring-context-support</artifactId>
        </dependency>

        <!-- 导入接口模块 -->
        <dependency>
            <groupId>com.gofy</groupId>
            <artifactId>dubbo-provider-api</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <mainClass>com.gofy.dubbo.ProviderApplication</mainClass>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

dubbo-provider-service 的application.yml里添加配置

注:如果要在 SpringClou Alibaba+Dubbo 中使用nacos动态配置,操作与之前naocs动态配置的操作一样

spring:
  application:
    name: dubbo-provider
  main:
    allow-bean-definition-overriding: true # 解决bean重复定义,设置为true时,后定义的bean会覆盖之前定义的相同名称的bean

dubbo:
  scan:
    base-packages: com.gofy.dubbo.service # 实现类所在的包
  protocol:
    name: dubbo
    port: -1 # 端口为-1时,即是让dubbo自动分配端口
    serialization: kryo # 使用kryo序列化/反序列化工具
  registry:
    address: nacos://192.168.11.132:8848 #注册中心地址,格式为 注册中心组件名://注册中心访问地址

创建实现类 EchoServiceImpl

package com.gofy.dubbo.service;
​
import com.gofy.dubbo.api.EchoService;
import org.apache.dubbo.config.annotation.Service;
import org.springframework.beans.factory.annotation.Value;
​
@Service(version = "1.0.0") //服务版本号
public class EchoServiceImpl implements EchoService {
​
    @Override
    public String echo(String s) {
        return "Hello Dubbo "+s;
    }
}

创建启动类 ProviderApplication

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

服务消费者

在总工程 ApacheDubbo 下创建服务消费者 dubbo-consumer , 并添加依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <artifactId>ApacheDubbo</artifactId>
        <groupId>com.gofy</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>

    <groupId>com.gofy</groupId>
    <artifactId>dubbo-consumer</artifactId>
    <packaging>jar</packaging>

    <dependencies>
        <!-- SpringBoot -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>

        <!-- Dubbo -->
        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo-spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo-spring-boot-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo-serialization-kryo</artifactId>
        </dependency>
        
        <!-- Spring Cloud Alibaba -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>dubbo-registry-nacos</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba.nacos</groupId>
            <artifactId>nacos-client</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba.spring</groupId>
            <artifactId>spring-context-support</artifactId>
        </dependency>

        <!-- 导入接口模块 -->
        <dependency>
            <groupId>com.gofy</groupId>
            <artifactId>dubbo-provider-api</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <mainClass>com.gofy.dubbo.ConsumerApplication</mainClass>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

dubbo-consumer 的application.yml里添加配置

server:
  port: 8080
​
spring:
  application:
    name: dubbo-consumer
  main:
    allow-bean-definition-overriding: true
​
dubbo:
  scan:
    base-packages: com.gofy.dubbo.controller #controller类所在包
  protocol:
    name: dubbo
    port: -1
    serialization: kryo
  registry:
    address: nacos://192.168.11.132:8848
​
endpoints:
  dubbo:
    enabled: true #允许暴露dubbo分配的端点
​
management:
  health: #健康检查
    dubbo:
      status:
        defaults: memory
        extras: threadpool
  endpoints: #暴露所有web端点
    web:
      exposure:
        include: "*"

创建controller类 EchoController

package com.gofy.dubbo.controller;
​
import com.gofy.dubbo.api.EchoService;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
​
@RestController
public class EchoController {
​
    @Reference(version = "1.0.0") //通过服务的版本号注入
    EchoService echoService;
    
    @GetMapping("/echo/{s}")
    public String echo(@PathVariable("s")String s){
        return echoService.echo(s);
    }
}

创建启动类 ConsumerApplication

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

访问测试

访问nacos注册中心,查看已注册服务

YZVJJjb.png!web

访问 localhost:8080/echo/hi , 成功获取到服务提供者返回的信息

veumeij.png!web

Dubbo负载均衡

当我们对内使用Dubbo的RPC通信,不再使用RestTemplate或feign的 HTTP通信时,我们要怎么使用负载均衡呢?

在 Dubbo 中,也有负载均衡的概念和相应的实现。Dubbo 需要对服务消费者的调用请求进行分配,避免少数服务提供者负载过大。服务提供者负载过大,会导致部分请求超时。因此将负载均衡到每个服务提供者上,是非常必要的。Dubbo 提供了4种负载均衡实现,分别是基于权重随机算法的 RandomLoadBalance、基于最少活跃调用数算法的 LeastActiveLoadBalance、基于 hash 一致性的 ConsistentHashLoadBalance,以及基于加权轮询算法的 RoundRobinLoadBalance。

源码分析

Dubbo负载均衡的源码在 org.apache.dubbo:dubbo下的org.apache.dubbo.rpc.cluster.loadbalance

通过源码可以发现4个负载均衡策略的实现类都继承了AbstractLoadBalance抽象类,而AbstractLoadBalance实现了LoadBalance接口。

再来看看LoadBalance接口,可以知道duboo是通过 loadbalance属性来适配负载均衡接口的实现类,且默认值为 random 权重随机。

@SPI("random")
public interface LoadBalance {
    @Adaptive({"loadbalance"})
    <T> Invoker<T> select(List<Invoker<T>> invokers, URL url, Invocation invocation) throws RpcException;
}

所以,我们只要在 @Reference注解里添加 loadbalance属性 ,就可以选择dubbo的负载均衡策略了

loadbalance属性值为负载均衡实现类的 NAME 属性,分别是:

random 、roundrobin 、leastactive 、consistenthash

@Reference(version = "1.0.0", loadbalance = "roundrobin")
EchoService echoService;

负载均衡策略实现类的详细源码分析, dubbo官方文档 里讲解得非常好,就不多转述了

我的个人博客站

自动判断中文中文(简体)中文(香港)中文(繁体)英语日语朝鲜语德语法语俄语泰语南非语阿拉伯语阿塞拜疆语比利时语保加利亚语加泰隆语捷克语威尔士语丹麦语第维埃语希腊语世界语西班牙语爱沙尼亚语巴士克语法斯语芬兰语法罗语加里西亚语古吉拉特语希伯来语印地语克罗地亚语匈牙利语亚美尼亚语印度尼西亚语冰岛语意大利语格鲁吉亚语哈萨克语卡纳拉语孔卡尼语吉尔吉斯语立陶宛语拉脱维亚语毛利语马其顿语蒙古语马拉地语马来语马耳他语挪威语(伯克梅尔)荷兰语北梭托语旁遮普语波兰语葡萄牙语克丘亚语罗马尼亚语梵文北萨摩斯语斯洛伐克语斯洛文尼亚语阿尔巴尼亚语瑞典语斯瓦希里语叙利亚语泰米尔语泰卢固语塔加路语茨瓦纳语土耳其语宗加语鞑靼语乌克兰语乌都语乌兹别克语越南语班图语祖鲁语自动选择中文中文(简体)中文(香港)中文(繁体)英语日语朝鲜语德语法语俄语泰语南非语阿拉伯语阿塞拜疆语比利时语保加利亚语加泰隆语捷克语威尔士语丹麦语第维埃语希腊语世界语西班牙语爱沙尼亚语巴士克语法斯语芬兰语法罗语加里西亚语古吉拉特语希伯来语印地语克罗地亚语匈牙利语亚美尼亚语印度尼西亚语冰岛语意大利语格鲁吉亚语哈萨克语卡纳拉语孔卡尼语吉尔吉斯语立陶宛语拉脱维亚语毛利语马其顿语蒙古语马拉地语马来语马耳他语挪威语(伯克梅尔)荷兰语北梭托语旁遮普语波兰语葡萄牙语克丘亚语罗马尼亚语梵文北萨摩斯语斯洛伐克语斯洛文尼亚语阿尔巴尼亚语瑞典语斯瓦希里语叙利亚语泰米尔语泰卢固语塔加路语茨瓦纳语土耳其语宗加语鞑靼语乌克兰语乌都语乌兹别克语越南语班图语祖鲁语有道翻译百度翻译谷歌翻译谷歌翻译(国内) 翻译 朗读 复制 正在查询,请稍候…… 重试 朗读 复制 复制 朗读 复制 via 谷歌翻译(国内) 译 自动判断中文中文(简体)中文(香港)中文(繁体)英语日语朝鲜语德语法语俄语泰语南非语阿拉伯语阿塞拜疆语比利时语保加利亚语加泰隆语捷克语威尔士语丹麦语第维埃语希腊语世界语西班牙语爱沙尼亚语巴士克语法斯语芬兰语法罗语加里西亚语古吉拉特语希伯来语印地语克罗地亚语匈牙利语亚美尼亚语印度尼西亚语冰岛语意大利语格鲁吉亚语哈萨克语卡纳拉语孔卡尼语吉尔吉斯语立陶宛语拉脱维亚语毛利语马其顿语蒙古语马拉地语马来语马耳他语挪威语(伯克梅尔)荷兰语北梭托语旁遮普语波兰语葡萄牙语克丘亚语罗马尼亚语梵文北萨摩斯语斯洛伐克语斯洛文尼亚语阿尔巴尼亚语瑞典语斯瓦希里语叙利亚语泰米尔语泰卢固语塔加路语茨瓦纳语土耳其语宗加语鞑靼语乌克兰语乌都语乌兹别克语越南语班图语祖鲁语自动选择中文中文(简体)中文(香港)中文(繁体)英语日语朝鲜语德语法语俄语泰语南非语阿拉伯语阿塞拜疆语比利时语保加利亚语加泰隆语捷克语威尔士语丹麦语第维埃语希腊语世界语西班牙语爱沙尼亚语巴士克语法斯语芬兰语法罗语加里西亚语古吉拉特语希伯来语印地语克罗地亚语匈牙利语亚美尼亚语印度尼西亚语冰岛语意大利语格鲁吉亚语哈萨克语卡纳拉语孔卡尼语吉尔吉斯语立陶宛语拉脱维亚语毛利语马其顿语蒙古语马拉地语马来语马耳他语挪威语(伯克梅尔)荷兰语北梭托语旁遮普语波兰语葡萄牙语克丘亚语罗马尼亚语梵文北萨摩斯语斯洛伐克语斯洛文尼亚语阿尔巴尼亚语瑞典语斯瓦希里语叙利亚语泰米尔语泰卢固语塔加路语茨瓦纳语土耳其语宗加语鞑靼语乌克兰语乌都语乌兹别克语越南语班图语祖鲁语有道翻译百度翻译谷歌翻译谷歌翻译(国内)

翻译 朗读 复制 正在查询,请稍候…… 重试 朗读 复制 复制 朗读 复制 via 谷歌翻译(国内)


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK