Используйте springboot+dubbo для создания распределенных микросервисов и аннотирования всего процесса разработки.

Spring Boot

С развитием Интернета масштаб веб-приложений продолжает расширяться, и традиционная вертикальная архитектура приложений больше не может справляться.Обязательны архитектура распределенных услуг и архитектура мобильных вычислений, и срочно необходима система управления для обеспечения упорядоченной эволюции архитектура.

Во-первых, картинка

Говоря о Dubbo, я думаю, что все знакомы с ним! Высокопроизводительная и превосходная сервисная платформа с открытым исходным кодом от Alibaba, которая позволяет приложениям реализовывать функции вывода и ввода сервисов с помощью высокопроизводительного RPC и может быть легко интегрирована со средой Spring.

image

Описание роли узла:

  • Provider: поставщик услуг, предоставляющий услугу
  • Consumer: Потребитель службы, который вызывает удаленную службу.
  • Registry: реестр для регистрации и обнаружения служб.
  • Monitor: Центр мониторинга, который подсчитывает количество звонков и время вызова службы
  • Container: Контейнер службы

Во-вторых, реализация идеи

Сегодня мы беремПользователь выбирает товар для размещения заказаЭтот процесс разделен на 3 бизнес-услуги:Центр пользователей, Центр продуктов, Центр заказов, используйте Springboot + Dubbo для реализации небольшого демо!

Процесс взаимодействия с сервисом выглядит следующим образом:

image

Эта статья в основном знакомит с интеграцией фреймворка и практикой разработки Springboot и Dubbo, а разделение реального бизнес-сервиса — очень сложный процесс, который намного сложнее, чем тот, который мы представили.Три упомянутых выше сервиса предназначены только для демонстрации проекта. не слишком беспокойтесь о том, почему он так разделен!

Ладно, не будем нести чушь, начнём!

  • 1. Создаем 4 centos7 в виртуалке, выбираем любой для установки zookeeper
  • 2. Создайте проект микросервиса и напишите код
  • 3. Разверните микросервисы на centos7
  • 4. Тест удаленного вызова службы

Три, установка зоопарка

Прежде чем использовать Dubbo, нам нужен центр регистрации.В настоящее время центры регистрации, которые может выбрать Dubbo, включают zookeeper, Nacos и т. д. Обычно рекомендуется использовать zookeeper!

Во-первых, перед установкой Zookeeper необходимо установить и настроить JDK, который использует Oracle Java8 SE.

  • Установите JDK (уже установленный можно игнорировать)
yum -y install java-1.8.0-openjdk
  • Проверить установку java
java -version

image

  • После завершения установки JDK загрузите и установите Zookeeper.
创建一个zookeeper文件夹
cd /usr
mkdir zookeeper
下载zookeeper-3.4.14版本
wget http://mirrors.hust.edu.cn/apache/zookeeper/zookeeper-3.4.14/zookeeper-3.4.14.tar.gz
解压
tar -zxvf zookeeper-3.4.14.tar.gz</pre>
  • Создание каталогов данных и журналов
创建数据和日志存放目录
cd /usr/zookeeper/
mkdir data
mkdir log
把conf下的zoo_sample.cfg备份一份,然后重命名为zoo.cfg
cd conf/
cp zoo_sample.cfg zoo.cfg</pre>
  • Настроить зоопарк
#编辑zoo.cfg文件
vim zoo.cfg

image

  • Запустить ZooKeeper
#启动Zookeeper
./zkServer.sh start

#查询Zookeeper状态
./zkServer.sh status

#关闭Zookeeper状态
./zkServer.sh stop</pre>

Появится следующая информация, свидетельствующая об успешном запуске!

image

4. Введение проекта

  • версия весенней загрузки: 2.1.1.RELEASE
  • версия зоопарка: 3.4.14
  • даббо версия: 2.7.3
  • mybatis-плюс версия: 3.0.6
  • База данных: mysql-8
  • Инструмент сборки: maven
  • Сервисный модуль: пользовательский центр, товарный центр, центр заказов

5. Практика кодекса

5.1. Инициализировать базу данных

Сначала в клиенте mysql создайте 3 базы данных, а именно:dianshang-user,dianshang-platform,dianshang-business.

  • В базе данных dianshang-user создайте пользовательскую таблицу tb_user и инициализируйте данные

image

image

  • В базе данных dianshang-platform создайте таблицу продуктов tb_product и инициализируйте данные

image

image

  • В базе данных dianshang-platform создайте таблицу заказов tb_order и таблицу сведений о заказах tb_order_detail.

image

image

5.2, создать проект

После завершения проектирования таблицы базы данных создайте файл с именем IDEA.dianshang из Springboot проект.

Окончательный каталог выглядит следующим образом:

image

Описание структуры каталога:

  • dianshang-common: в основном хранит некоторые общедоступные библиотеки инструментов, все сервисы можно использовать в зависимости от
  • dianshang-business: центр заказов, гдеapiМодуль в основном обеспечивает интерфейс предоставления услуги dubbo,providerмодуль - этоspringbootПроект, предоставляющий услуги по обработке операций
  • dianshang-user: пользовательский центр, гдеapiмодули иproviderмодуль аналогичной конструкции
  • dianshang-platform: центр товаров, гдеapiмодули иproviderмодуль аналогичной конструкции

в родительском классеpomдобавить в файлdubbo а также zookeeperКлиент, доступны все зависимые проекты.

<!-- lombok -->
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.4</version>
    <scope>provided</scope>
</dependency>

<!-- Dubbo Spring Boot Starter -->
<dependency>
    <groupId>org.apache.dubbo</groupId>
    <artifactId>dubbo-spring-boot-starter</artifactId>
    <version>2.7.3</version>
</dependency>
<!-- 因为使用的是 zookeeper 作为注册中心,所以要添加 zookeeper 依赖 -->
<dependency>
    <groupId>org.apache.zookeeper</groupId>
    <artifactId>zookeeper</artifactId>
    <version>3.4.13</version>
    <exclusions>
        <exclusion>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
        </exclusion>
        <exclusion>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
        </exclusion>
        <exclusion>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
        </exclusion>
    </exclusions>
</dependency>
<!--使用curator 作为zookeeper客户端-->
<dependency>
    <groupId>org.apache.curator</groupId>
    <artifactId>curator-framework</artifactId>
    <version>4.2.0</version>
</dependency>
<dependency>
    <groupId>org.apache.curator</groupId>
    <artifactId>curator-recipes</artifactId>
    <version>4.2.0</version>
</dependency>

Напоминание: Xiaobian обнаружил яму при создании среды, которая зависит от проекта.zookeeperВерсия и версия сервера должны быть максимально согласованы, например, в этом примереzookeeperВерсия сервера такая3.4.14, то в зависимости отzookeeperПри использовании файловой библиотеки старайтесь быть последовательным, если вы зависите от3.5.xверсияzookeeper, при запуске проекта различные монстры и монстры будут сообщать об ошибках!

5.3. Создайте проект пользовательского центра

В IDEA создайтеdianshang-userподмодуль, и зависит отdianshang-commonмодуль

<dependencies>
    <dependency>
        <groupId>org.project.demo</groupId>
        <artifactId>dianshang-common</artifactId>
        <version>1.0.0</version>
    </dependency>
</dependencies>

При этом создатьdianshang-user-provider а также dianshang-user-apiмодуль.

  • dianshang-user-api: в основном предоставляет доступ к интерфейсу для других сервисов.
  • dianshang-user-provider: похож на веб-проект, в основном отвечает за основной бизнес.crud, а в зависимости отdianshang-user-apiмодуль

5.3.1 Настройка службы dubbo

существует dianshang-user-provider из application.ymlконфигурация в файлеdubboУслуги, как указано ниже:

#用户中心服务端口
server:
 port: 8080
#数据源配置
spring:
 datasource:
 druid:
 driver-class-name: com.mysql.cj.jdbc.Driver
 url: "jdbc:mysql://localhost:3306/dianshang-user"
 username: root
 password: 111111
#dubbo配置
dubbo:
 scan:
    # 包名根据自己的实际情况写
 base-packages: org.project.dianshang.user
 protocol:
 port: 20880
 name: dubbo
 registry:
    #zookeeper注册中心地址
 address: zookeeper://192.168.0.107:2181

5.3.2, напишите интерфейс предоставления услуги и класс реализации

существует dianshang-user-apiмодуль, создайтеUserApiИнтерфейс и возвращаемый объект параметраUserVo!

public interface UserApi {

    /**
     * 查询用户信息
     * @param userId
     * @return
     */
    UserVo findUserById(String userId);
}

в UserVo, необходимо реализовать сериализацию следующим образом:

@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
public class UserVo implements Serializable {

    private static final long serialVersionUID = 1L;

    /**
     * 用户ID
     */
    private String userId;

    /**
     * 用户中文名
     */
    private String userName;
}

существует dianshang-user-providerмодуль, пишиUserApiКласс реализации интерфейса выглядит следующим образом:

@Service(interfaceClass =UserApi.class)
@Component
public class UserProvider implements UserApi {

    @Autowired
    private UserService userService;

    @Override
    public UserVo findUserById(String userId) {
        QueryWrapper<User> queryWrapper = new QueryWrapper<User>();
        queryWrapper.eq("user_id",userId);
        User source = userService.getOne(queryWrapper);
        if(source != null){
            UserVo vo = new UserVo();
            BeanUtils.copyProperties(source,vo);
            return vo;
        }
        return null;
    }
}

Аннотация @Service относится к аннотации в org.apache.dubbo.config.annotation.Service, а не к аннотации в Spring!

Далее приступим к созданию проекта товарного центра!

5.4. Создание проекта товарного центра

Как и в проектах User Center, в IDEA создайтеdianshang-platformподмодуль, и зависит отdianshang-commonмодуль

<dependencies>
    <dependency>
        <groupId>org.project.demo</groupId>
        <artifactId>dianshang-common</artifactId>
        <version>1.0.0</version>
    </dependency>
</dependencies>

При этом создатьdianshang-platform-provider а также dianshang-platform-apiмодуль.

  • dianshang-platform-api: в основном предоставляет интерфейс для других сервисов.
  • dianshang-platform-provider: похож на веб-проект, в основном отвечает за основной бизнес.crud, а в зависимости отdianshang-platform-apiмодуль

5.4.1 Настройка службы dubbo

существует dianshang-platform-provider из application.ymlконфигурация в файлеdubboУслуги, как указано ниже:

#用户中心服务端口
server:
 port: 8081
#数据源配置
spring:
 datasource:
 druid:
 driver-class-name: com.mysql.cj.jdbc.Driver
 url: "jdbc:mysql://localhost:3306/dianshang-platform"
 username: root
 password: 111111
#dubbo配置
dubbo:
 scan:
    # 包名根据自己的实际情况写
 base-packages: org.project.dianshang.platform
 protocol:
 port: 20881
 name: dubbo
 registry:
    #zookeeper注册中心地址
 address: zookeeper://192.168.0.107:2181

5.4.2 Напишите интерфейс предоставления услуги и класс реализации

существует dianshang-platform-apiмодуль, создайтеProductApiИнтерфейс и возвращаемый объект параметраProductVo!

public interface ProductApi {

    /**
     * 通过商品ID,查询商品信息
     * @param productId
     * @return
     */
    ProductVo queryProductInfoById(String productId);
}

в ProductVo, необходимо реализовать сериализацию следующим образом:

@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
public class ProductVo implements Serializable {

    private static final long serialVersionUID = 1L;

    /**商品ID*/
    private String productId;

    /**商品名称*/
    private String productName;

    /**商品价格*/
    private BigDecimal productPrice;
}

существует dianshang-platform-providerмодуль, пишиProductApiКласс реализации интерфейса выглядит следующим образом:

@Service(interfaceClass = ProductApi.class)
@Component
public class ProductProvider implements ProductApi {

    @Autowired
    private ProductService productService;

    @Override
    public ProductVo queryProductInfoById(String productId) {
        //通过商品ID查询信息
        Product source = productService.getById(productId);
        if(source != null){
            ProductVo vo = new ProductVo();
            BeanUtils.copyProperties(source,vo);
            return vo;
        }
        return null;
    }
}

Далее, давайте перейдем к созданию элемента центра заказов!

5.5. Создание элемента центра заказов

Подобно проекту товарного центра, в IDEA создайтеdianshang-businessподмодуль, и зависит отdianshang-commonмодуль

<dependencies>
    <dependency>
        <groupId>org.project.demo</groupId>
        <artifactId>dianshang-common</artifactId>
        <version>1.0.0</version>
    </dependency>
</dependencies>

При этом создатьdianshang-business-provider а также dianshang-business-apiмодуль.

  • dianshang-business-api: в основном предоставляет доступ к интерфейсу для других сервисов.
  • dianshang-business-provider: похож на веб-проект, в основном отвечает за основной бизнес.crud, а в зависимости отdianshang-business-apiмодуль

5.5.1 Настройка службы dubbo

существует dianshang-business-provider из application.ymlконфигурация в файлеdubboУслуги, как указано ниже:

#用户中心服务端口
server:
 port: 8082
#数据源配置
spring:
 datasource:
 druid:
 driver-class-name: com.mysql.cj.jdbc.Driver
 url: "jdbc:mysql://localhost:3306/dianshang-business"
 username: root
 password: 111111
#dubbo配置
dubbo:
 scan:
    # 包名根据自己的实际情况写
 base-packages: org.project.dianshang.business
 protocol:
 port: 20882
 name: dubbo
 registry:
    #zookeeper注册中心地址
 address: zookeeper://192.168.0.107:2181

5.5.2 Напишите интерфейс предоставления услуги и класс реализации

существует dianshang-business-apiмодуль, создайтеOrderApiИнтерфейс и возвращаемый объект параметраOrderVo!

public interface OrderApi {

    /**
     * 通过用户ID,查询用户订单信息
     * @param userId
     * @return
     */
    List<OrderVo> queryOrderByUserId(String userId);
}

в OrderVo, необходимо реализовать сериализацию следующим образом:

@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
public class OrderVo implements Serializable {

    private static final long serialVersionUID = 1L;

    /**订单ID*/
    private String orderId;

    /**订单编号*/
    private String orderNo;

    /**订单金额*/
    private BigDecimal orderPrice;

    /**下单时间*/
    private Date orderTime;
}

существует dianshang-business-providerмодуль, пишиOrderApiКласс реализации интерфейса выглядит следующим образом:

@Service(interfaceClass = OrderApi.class)
@Component
public class OrderProvider implements OrderApi {

    @Autowired
    private OrderService orderService;

    @Override
    public List<OrderVo> queryOrderByUserId(String userId) {
        QueryWrapper<Order> queryWrapper = new QueryWrapper<Order>();
        queryWrapper.eq("user_id",userId);
        List<Order> sourceList = orderService.list(queryWrapper);
        if(!CollectionUtils.isEmpty(sourceList)){
            List<OrderVo> voList = new ArrayList<>();
            for (Order order : sourceList) {
                OrderVo vo = new OrderVo();
                BeanUtils.copyProperties(order, vo);
                voList.add(vo);
            }
            return voList;
        }
        return null;
    }
}

На данный момент разработаны интерфейсы сервисного обслуживания трех проектов! Далее давайте напишем, как совершать удаленные звонки!

5.6 Удаленный вызов

5.6.1, напишите и создайте службу заказа

существует dianshang-business-providerВ модуле, прежде чем писать и создавать интерфейс заказа, сначала зависьте отdianshang-business-api а также dianshang-user-api ,следующим образом:

<!--商品服务接口暴露 api-->
<dependency>
    <groupId>org.project.demo</groupId>
    <artifactId>dianshang-platform-api</artifactId>
    <version>1.0.0</version>
</dependency>
<!--用户服务接口暴露 api-->
<dependency>
    <groupId>org.project.demo</groupId>
    <artifactId>dianshang-user-api</artifactId>
    <version>1.0.0</version>
</dependency>

существует dianshang-business-providerВ модуле напишите сервис создания заказа следующим образом:

@RestController
@RequestMapping("/order")
public class OrderController {

	@Autowired
    private OrderService orderService;

	@Autowired
	private OrderDetailService orderDetailService;

    @Reference(check =false)
	private ProductApi productApi;

    @Reference(check =false)
    private UserApi userApi;

	/**
	 * 新增
	 */
	@JwtIgnore
	@RequestMapping(value = "/add")
	public boolean add(String productId,String userId){
	    LocalAssert.isStringEmpty(productId,"产品Id不能为空");
        LocalAssert.isStringEmpty(userId,"用户Id不能为空");
        ProductVo productVo = productApi.queryProductInfoById(productId);
        LocalAssert.isObjectEmpty(productVo,"未查询到产品信息");
        UserVo userVo = userApi.findUserById(userId);
        LocalAssert.isObjectEmpty(userVo,"未查询到用户信息");
        Order order = new Order();
        order.setOrderId(IdGenerator.uuid());
        order.setOrderNo(System.currentTimeMillis() + "");
        order.setOrderPrice(productVo.getProductPrice());
        order.setUserId(userId);
        order.setOrderTime(new Date());
        orderService.save(order);

        OrderDetail orderDetail = new OrderDetail();
        orderDetail.setOrderDetailId(IdGenerator.uuid());
        orderDetail.setOrderId(order.getOrderId());
        orderDetail.setProductId(productId);
        orderDetail.setSort(1);
        orderDetailService.save(orderDetail);
		return true;
	}
}

один из них @ReferenceАннотация принадлежитorg.apache.dubbo.config.annotation.ReferenceАннотация под , указывает на удаленную зависимую службу.

параметрcheck =falseУказывает, что проверка состояния удаленной службы не выполняется при запуске службы. Целью этого параметра является предотвращение невозможности запуска текущей службы. Например, проект пользовательского центра не запускается успешно, но центр заказов зависит в пользовательском центре.check=true, в это время будет сообщено об ошибке при запуске центра заказов!

5.6.2. Напишите пользователям, чтобы они сами запрашивали информацию о своем заказе

Точно так же вdianshang-user-providerВ модуле, прежде чем писать интерфейс для пользователей, чтобы они запрашивали информацию о своих заказах, сначала полагайтесь наdianshang-business-api а также dianshang-user-api ,следующим образом:

    <groupId>org.project.demo</groupId>
    <artifactId>dianshang-business-api</artifactId>
    <version>1.0.0</version>
</dependency>
<dependency>
    <groupId>org.project.demo</groupId>
    <artifactId>dianshang-user-api</artifactId>
    <version>1.0.0</version>
</dependency></pre>

在 `dianshang-user-provider` 模块中,编写用户查询自己的订单信息接口,如下:

<pre class="prettyprint hljs less" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, &quot;Courier New&quot;, monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; overflow-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto;">@RestController
@RequestMapping("/user")
public class UserController {

	@Reference(check =false)
	private OrderApi orderApi;

    /**
     * 通过用户ID,查询订单信息
     * @param userId
     * @return
     */
    @RequestMapping("/list")
    public List<OrderVo> queryOrderByUserId(String userId){
        return orderApi.queryOrderByUserId(userId);
    }
}

На этом удаленный сервисный вызов завершен!

6. Сервисный тест

Прежде чем развернуть проект на сервере, давайте протестируем его локально, чтобы увидеть, может ли служба работать?

  • Запустить пользовательский центрdianshang-user-provider

image

  • Продолжить запуск центра продуктовdianshang-platform-provider

image

  • Затем запустите центр заказовdianshang-business-provider

image

Наконец, давайте проверим, соответствует ли интерфейс сервиса тому, что мы ожидали?

Откройте браузер и введитеhttp://127.0.0.1:8082/order/add?productId=1&userId=1Протестируйте интерфейс создания заказа, и результаты работы страницы будут отображаться нормально!

image

Давайте еще раз взглянем на базу данных, сформирован ли заказ?

image

image

Ok! Совершенно ясно, что данные были введены, и нет никаких проблем!

Давайте еще раз протестируем интерфейс запроса заказа в пользовательском центре, введитеhttp://127.0.0.1:8080/user/list?userId=1, результат запуска страницы выглядит следующим образом!

image

На данный момент локальный сервисный тест в основном пройден!

Семь, развертывание сервера

Выше мы представили построение, разработку и тестирование сервиса, так как же развернуть его на стороне сервера?

Во-первых, изменитеapplication.ymlфайл, измените адрес источника данных и адрес центра регистрации dubbo на адрес, который можно подключить онлайн, а затемdianshangИспользовать в каталогеmavenИнструмент выполняет следующую команду для упаковки всего проекта!

mvn clean install

Вы также можете использовать среду IDEA черезmavenНастроитьclean installкоманда для выполнения упаковки.

каждый предметtargetв каталогеdianshang-user-provider.jar,dianshang-platform-provider.jar,dianshang-business-provider.jarскопируйте его.

Загруженный в соответствующий каталог сервера, этот сервер использует CentOS7, всего 4 сервера, один из которых развернутzookeeper, а остальные три развертывают три проекта микросервисов.

Войдите на сервер и введите следующую команду, чтобы убедиться,JDKУстановка завершена!

java -version

Отключите брандмауэры всех серверов и разрешите доступ к портам!

systemctl stop firewalld.service

# отключить автозагрузку systemctl отключить firewalld.service

  • Запустите службу пользовательского центра и выведите информацию журнала вservice.log(IP-адрес виртуальной машины: 192.168.0.108)

nohup java -jar dianshang-user-provider.jar > service.log 2>&1 &

  • Запустите службу товарного центра и выведите информацию журнала вservice.log(IP-адрес виртуальной машины: 192.168.0.107)

nohup java -jar dianshang-platform-provider.jar > service.log 2>&1 &

  • Запустите службу центра заказов и выведите информацию журнала наservice.log(IP-адрес виртуальной машины: 192.168.0.109)
nohup java -jar  dianshang-business-provider.jar > service.log 2>&1 &

Откройте браузер и введитеhttp://192.168.0.109:8082/order/add?productId=1&userId=1Протестируйте интерфейс создания заказа, и результаты работы страницы будут отображаться нормально!

image

Давайте еще раз протестируем интерфейс запроса заказа в пользовательском центре, введите вводhttp://192.168.0.108:8080/user/list?userId=1, результат запуска страницы выглядит следующим образом!

image

Хорошо видно, что выводятся два фрагмента информации, второй заказ формируется на сервере тестовой среды, а первый генерируется в локальной среде разработки.

На этом развертывание сервера в основном завершено!

Если это производственная среда, вам может понадобиться несколькоzookeeperДля обеспечения высокой доступности используется как минимум 2 сервера для развертывания бизнес-сервисов и маршрутизации через балансировку нагрузки!

8. Резюме

Вся статья относительно длинная, в основном посвящена интеграции springboot + dubbo, а реализация удаленного вызова службы с помощью разработки аннотаций так же проста, как и традиционная разработка springmvc.xmlМетод конфигурации реализует вызов службы dubbo, которая будет представлена ​​позже.

В то же время также вводится развертывание сервера.Видно, что, хотя разработка проста, из-за распределенного развертывания, как обеспечить высокую доступность услуг, стало первой задачей разработчиков.Поэтому, хотя разработка распределенных микросервисов проста, как обеспечить высокую доступность развертывания сервиса? Эксплуатация и техническое обслуживание принесут много проблем!