电竞比分网-中国电竞赛事及体育赛事平台

分享

白話分布式系統(tǒng)

 貪挽懶月 2022-06-20 發(fā)布于廣東
什么叫分布式系統(tǒng)

1、單體應(yīng)用介紹:
所謂單體應(yīng)用,就是一些小型的應(yīng)用,一個系統(tǒng)就是eclipse中的一個工程,然后打一個jar包或者war運行,這個jar包或者war就是整個系統(tǒng)服務(wù)。這就叫單體應(yīng)用。

2、分布式系統(tǒng)介紹:
如果項目小,那么單體應(yīng)用就可以了,如果項目很復(fù)雜,訪問量特別多,還是打一個包的話,那可能就會崩掉了。所以就出現(xiàn)了分布式系統(tǒng)。就是把項目中的不同的功能模塊獨立成一個系統(tǒng),單獨部署。比如京東商城,把訂單系統(tǒng)部署到A服務(wù)器,用戶系統(tǒng)部署到B服務(wù)器……這樣的就叫分布式系統(tǒng)。說白了,就是把一個大系統(tǒng)分成各個功能模塊,然后把不同的功能模塊部署到不同的計算機上。

3、分布式和微服務(wù):
微服務(wù)是一種思想,就是上面說的把大系統(tǒng)拆分成不同的功能模塊,做成一個個的服務(wù),然后這些服務(wù)協(xié)調(diào)運作,對外提供一個完整的大的系統(tǒng)的服務(wù)。若是把這些不同的功能模塊部署到不同的計算機,那就叫分布式

dubbo介紹

1、dubbo是干嘛的?
上面說到了分布式系統(tǒng),把功能模塊獨立部署在不同的計算機上,但是這些功能模塊相互之間可能也會相互調(diào)用。比如訂單模塊部署在A計算機,用戶模塊部署在B計算機,訂單模塊需要調(diào)用用戶模塊查詢用戶的收貨地址等信息。dubbo就是用來治理這些不同的功能模塊的。

2、RPC是什么?
RPC中文名叫遠程過程調(diào)用。上面說了不同的功能模塊部署在不同的計算機上,然后它們又要相互調(diào)用,那么就可以采用RPC。也就是A計算機上的訂單模塊要調(diào)用B計算機上的用戶模塊,我們可以采用的調(diào)用方法之一就叫RPC。RPC就是A和B兩臺計算機之間通過sockets進行通信。上面說到dubbo就是來治理這些服務(wù),其實dubbo就是一個RPC調(diào)度框架。一個RPC框架性能如何,主要看兩點。第一:建立socket連接的速度快不快;第二:訂單模塊調(diào)用用戶模塊的時候要傳參數(shù),參數(shù)可能是對象,對象要在網(wǎng)絡(luò)上傳輸就要序列化。所以第二點就是看序列化和反序列化的速度快不快。

3、dubbo智能負載均衡:
比如用戶模塊壓力比較大,那就再多搞幾臺計算機來部署用戶模塊。假設(shè)現(xiàn)在有B、C、D、E四臺計算機運行著用戶模塊,那么一個請求過來是到了這四臺計算機中的哪一臺呢?dubbo就會自動選擇一臺請求比較少的計算機。這就叫智能負載均衡

注冊中心

1、注冊中心是什么?
上面說了dubbo會智能地選擇BCDE四臺計算機中比較空閑的一臺去響應(yīng)請求,那么dubbo是如何知道這四臺計算機哪一臺比較閑呢?又或者說其中有一臺計算機不能正常工作了,dubbo要如何知道這件事呢?這就引入了注冊中心。A計算機告訴注冊中心它可以提供訂單模塊的功能,BCDE計算告訴注冊中心它可以提供用戶模塊的功能。也就說,注冊中心就維護了一個清單,清單上寫著哪臺計算機可以提供什么服務(wù)。比如現(xiàn)在A服務(wù)器的訂單模塊要調(diào)用用戶模塊時,dubbo就會去問注冊中心:“用戶模塊在哪些服務(wù)器上有?” 注冊中心就會告訴dubbo:“在BCDE上都有。” dubbo就會選擇一個負載最少的去調(diào)用。dubbo支持很多注冊中心,一般使用zookeeper。

2、dubbo運行流程:
把服務(wù)注冊到注冊中心 ------> 訂閱注冊中心的服務(wù) --------> dubbo框架進行RPC調(diào)用。同時dubbo還有監(jiān)控中心,可以監(jiān)控各個服務(wù)狀況。

3、安裝zookeeper:
去官網(wǎng)下載zookeeper ------> 解壓后去conf目錄,復(fù)制zoo_sample.cfg文件,改名為 zoo.conf,放在conf目錄下 ------> 去bin目錄下運行zkServer.cmd即可啟動,運行zkCli.cmd就可啟動客戶端

spring項目中使用dubbo
  • 需求:現(xiàn)在訂單模塊和用戶模塊。訂單模塊在A服務(wù)器,用戶模塊在B服務(wù)器。A的訂單模塊遠程調(diào)用B的用戶模塊。

上面介紹了dubbo和注冊中心,現(xiàn)在就看看在項目中實際應(yīng)該如何使用,話不多說,開打。

1、項目的結(jié)構(gòu):
根據(jù)需求,訂單服務(wù)是一個獨立的工程,用戶服務(wù)是一個獨立的工程,然后訂單服務(wù)中要調(diào)用用戶服務(wù),例如在訂單服務(wù)的某個方法中肯定要用到UserService。但是UserService是在用戶服務(wù)工程中的,怎么調(diào)用?直接把用戶工程打jar包依賴過來嗎?那這樣就不是分布式應(yīng)用了。正確的做法是:
將兩個工程中要用到的接口、實體類等抽取出來獨立成一個工程,具體的實現(xiàn)放到對應(yīng)的具體工程中去。

2、common-api 工程:
這就是用戶服務(wù)和訂單服務(wù)會共
用到的一些東西,放在這個工程中,然后打jar包,讓用戶服務(wù)工程和訂單服務(wù)工程依賴即可。

工程結(jié)構(gòu)
  • UserAddress.java

@Data
@AllArgsConstructor
@NoArgsConstructor
public class UserAddress implements Serializable {

    private Integer id;
    private String userAddress;
    private String phoneNumber;
}
  • OrderService.java

public interface OrderService {
    public List<UserAddress> initOrder(String userId);
}
  • UserService.java

public interface UserService {
    public List<UserAddress> getUserAddressList(String userId);
}

3、user-service 工程:

工程結(jié)構(gòu)
  • pom.xml

 <!-- dubbo依賴 -->
    <dependency>
      <groupId>org.apache.dubbo</groupId>
      <artifactId>dubbo</artifactId>
      <version>2.7.2</version>
    </dependency>
    <!-- zookeeper注冊中心 -->
    <dependency>
      <groupId>org.apache.curator</groupId>
      <artifactId>curator-framework</artifactId>
      <version>2.12.0</version>
    </dependency>
    <dependency>
      <groupId>org.apache.curator</groupId>
      <artifactId>curator-recipes</artifactId>
      <version>2.12.0</version>
    </dependency>
  • UserServiceImpl.java

@Service
public class UserServiceImpl implements UserService {
    @Override
    public List<UserAddress> getUserAddressList(String userId) {
        if (userId.equals("1")){
            UserAddress userAddress1 = new UserAddress(1"廣東省深圳市寶安區(qū)","8008208820");
            UserAddress userAddress2 = new UserAddress(2"廣東省東莞市厚街鎮(zhèn)","8008208820");
            return Arrays.asList(userAddress1,userAddress2);
        }
       else return null;
    }
}

接下來就需要在xml文件中將這個用戶服務(wù)注冊到注冊中心去。

  • provider.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www./schema/beans"
       xmlns:xsi="http://www./2001/XMLSchema-instance"
       xmlns:dubbo="http://dubbo./schema/dubbo"
       xmlns:context="http://www./schema/context"
       xsi:schemaLocation="http://www./schema/beans 
                           http://www./schema/beans/spring-beans.xsd
        http://www./schema/context 
        http://www./schema/context/spring-context-4.3.xsd
        http://dubbo./schema/dubbo 
        http://dubbo./schema/dubbo/dubbo.xsd
        http://code./schema/dubbo 
        http://code./schema/dubbo/dubbo.xsd"
>


    <context:component-scan base-package="com.zhu.study.service"/>
    <!-- 1、指定當(dāng)前服務(wù)/應(yīng)用的名字(同樣的服務(wù)名字相同,不要和別的服務(wù)同名) -->
    <dubbo:application name="user-service"></dubbo:application>

    <!-- 2、指定注冊中心的位置 -->
    <!-- <dubbo:registry address="zookeeper://127.0.0.1:2181"></dubbo:registry> -->
    <dubbo:registry protocol="zookeeper" address="127.0.0.1:2181"></dubbo:registry>

    <!-- 3、指定通信規(guī)則(通信協(xié)議?通信端口)服務(wù)提供者和調(diào)用者通信規(guī)則 -->
    <dubbo:protocol name="dubbo" port="20882"></dubbo:protocol>

    <!-- 4、暴露服務(wù)   ref:指向服務(wù)的真正的實現(xiàn)對象 -->
    <dubbo:service interface="com.zhu.study.service.UserService"
        ref="userServiceImpl" timeout="1000" version="1.0.0">

        <dubbo:method name="getUserAddressList" timeout="1000"/>
    </dubbo:service>

</beans>

在這個配置文件中,首先給這個服務(wù)起個名字,然后注冊到2181端口的注冊中心去,再指定通信規(guī)則和端口,最后把用戶模塊的UserService暴露出去,同時用ref引用實現(xiàn)類。當(dāng)然這個UserServiceImpl需要加入到spring容器中。

  • App.java
    現(xiàn)在編寫啟動類,加載配置文件。

public class App 
{
    public static void main( String[] args ) throws IOException {
        ClassPathXmlApplicationContext ioc = new ClassPathXmlApplicationContext("provider.xml");
        ioc.start();
        System.in.read(); // 保留啟動的狀態(tài)
    }
}

運行這個啟動類的前提是注冊中心zookeeper啟動起來了。運行之后,訪問管理控制臺就可以看到服務(wù)了(去dubbo的GitHub地址,找到dubbo-admin項目,下載下來,然后用maven打個jar運行,這就是管理控制臺)。

管理控制臺

可以看到user-service已經(jīng)成功注冊到zookeeper了。接下來就要在訂單服務(wù)中調(diào)用它了。

4、order-service 工程:

工程結(jié)構(gòu)
  • OrderServiceImpl.java

@Service
public class OrderServiceImpl implements OrderService {

    @Resource
    private UserService userService;
    @Override
    public List<UserAddress> initOrder(String userId) {
        // 查詢用戶收獲地址
        List<UserAddress> addressesList = userService.getUserAddressList(userId);
        return addressesList;
    }
}
  • consumer.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www./schema/beans"
       xmlns:xsi="http://www./2001/XMLSchema-instance"
       xmlns:dubbo="http://dubbo./schema/dubbo"
       xmlns:context="http://www./schema/context"
       xsi:schemaLocation="http://www./schema/beans 
        http://www./schema/beans/spring-beans.xsd
        http://www./schema/context 
        http://www./schema/context/spring-context-4.3.xsd
        http://dubbo./schema/dubbo 
        http://dubbo./schema/dubbo/dubbo.xsd
        http://code./schema/dubbo 
        http://code./schema/dubbo/dubbo.xsd"
>


    <context:component-scan base-package="com.zhu.study.service"/>
    <dubbo:application name="order-service"/>
    <dubbo:registry address="zookeeper://127.0.0.1:2181"/>
    <dubbo:reference interface="com.zhu.study.service.UserService"
                     id="userService" timeout="5000" retries="3" version="*">

    </dubbo:reference>
</beans>

這里的配置,第一行是開啟注解掃描,然后給訂單服務(wù)起個名字,第三步是注冊到zookeeper中去,第四步是引用UserService。這樣就完事了,然后寫個測試類試試水。

  • App.java

public class App 
{
    public static void main( String[] args ) throws IOException {

        ClassPathXmlApplicationContext ioc = new ClassPathXmlApplicationContext("consumer.xml");
        OrderService orderService = ioc.getBean(OrderService.class);
        List<UserAddress> userAddresses = orderService.initOrder("1");
        for (UserAddress userAddress : userAddresses){
            System.out.println(userAddress.toString());
        }
        System.in.read();
    }
}
運行結(jié)果

可以看到,成功地調(diào)用了UserService服務(wù)。同時在管理控制臺也可以看到調(diào)用者的信息

springboot項目中使用dubbo

同樣是order模塊和user模塊,看看怎么與springboot整合起來。

  • 1. 引入 dubbo-spring-boot-starter 依賴;

  • 2. 在啟動類上加上如下注解;

@EnableDubbo
@SpringBootApplication
public class SpringbootOrderServiceApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringbootOrderServiceApplication.class, args);
    }
}
  • 3. 將provider.xml 和 consumer.xml中的配置寫在application.properties中,如下:

dubbo.application.name=springboot-user-service
dubbo.registry.address=127.0.0.1:2181
dubbo.registry.protocol=zookeeper
dubbo.protocol.name=dubbo
dubbo.protocol.port=20080
dubbo.monitor.protocol=registry
dubbo.application.name=springboot-order-service
dubbo.registry.address=127.0.0.1:2181
dubbo.registry.protocol=zookeeper
dubbo.protocol.name=dubbo
dubbo.protocol.port=20080
dubbo.monitor.protocol=registry
  • 4. 服務(wù)提供者使用dubbo的 @Service 注解暴露服務(wù), 服務(wù)消費者使用 @Reference 調(diào)用提供者,如下:

@Service
@Component
public class UserServiceImpl implements UserService {
    @Override
    public List<UserAddress> getUserAddressList(String userId) {
        if (userId.equals("1")){
            UserAddress userAddress1 = new UserAddress(1"廣東省深圳市寶安區(qū)","8008208820");
            UserAddress userAddress2 = new UserAddress(2"廣東省東莞市厚街鎮(zhèn)","8008208820");
            return Arrays.asList(userAddress1,userAddress2);
        }
       else return null;
    }
}
@Service
public class OrderServiceImpl implements OrderService {

    @Reference
    private UserService userService;
    @Override
    public List<UserAddress> initOrder(String userId) {
        // 查詢用戶收獲地址
        System.out.println(userService);
        List<UserAddress> addressesList = userService.getUserAddressList(userId);
        return addressesList;
    }
}

注意: @Reference(url = "dubbo://服務(wù)提供者所在的機器IP:通信端口"),如果這個注解加上url,那么就表示繞過注冊中心,使用dubbo直連的方式,即這樣寫了的話沒有zookeeper都可以

寫在最后

上面簡單地介紹了分布式架構(gòu)的思想以及dubbo的簡單使用,更多dubbo的配置規(guī)則,請參考dubbo官網(wǎng)的開發(fā)手冊。

    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多