Для использования go-yea, пожалуйста, скачайте yea и выполните yea/pom.xml:
mvn clean install -Dmaven.test.skip=true
YEA передающий портал Портал помощи
GO-YEA — это приложение YEA, которое представляет собой чрезвычайно простой в использовании распределённый фреймворк, предназначенный для обеспечения быстрого запуска продукта и последующего масштабирования услуг. Его основные компоненты включают:
На примере GO-YEA сначала он развёртывается и работает на одном компьютере.
Через DefaultClient, настроенный в go-yea-launcher, поддерживается взаимный вызов Act между JVM.
<bean id="launcherClient" class="com.yea.core.remote.client.DefaultClient" />
В go-yea-web устанавливается зависимость от go-yea-launcher и импортируется файл конфигурации.
<import resource="classpath:/application-launcher.xml" />
Разделение веб-слоя и прикладного слоя физически, закладывая основу для развития в направлении распределённых сервисов. 
go-yea-launcher действует как производитель услуг и предоставляет услуги внешним пользователям.
<bean id="nettyServer" class="com.yea.remote.netty.server.NettyServer" />
go-yea-web действует как потребитель услуг, вызывая удалённые службы, предоставляемые производителем услуг go-yea-launcher через NettyClient для выполнения бизнес-операций (не зависит от go-yea-launcher).
<bean id="nettyClient" class="com.yea.remote.netty.client.NettyClient" />
Чтобы справиться со всё более сложными бизнес-сценариями, используя метод «разделяй и властвуй», весь бизнес разделяется на разные продуктовые линейки, данные каждой продуктовой линейки размещаются на разных серверах, и реализуется определённое разделение данных. 
На основе планирования продуктовых линеек go-yea-launcher разделяется на go-yea-launcher-permission и go-yea-launcher-authorization, регистрируясь под двумя разными именами регистрации в Zookeeper.
go-yea-web устанавливает два Netty-клиента, которые соответственно подключаются к go-yea-launcher-permission и go-yea-launcher-authorization.
Среда тестирования: три облачных хоста Vultr, каждый с 1 CPU (одно ядро), 1024 МБ памяти, один развёртывает go-yea-web (Tomcat), один развёртывает Launcher (запускает три сервиса, каждый сервис занимает 128 МБ кучи), один развёртывает Jmeter для тестирования. Программное обеспечение для тестирования: Jmeter. Описание теста: вызов api: разрешение / операция / запрос. Путь тестирования Jmeter--(http)-->Go-yea-web--(netty)-->Launcher--(tcp)-->DB--(tcp)-->Launcher--(netty)-->Go-yea-web--(http)-->Jmeter Результаты теста (360 параллельных):  Подробные данные: Подробные результаты Показатели повышения производительности: можно рассмотреть возможность соответствующего увеличения количества ядер ЦП и объёма памяти, а затем расширить горизонтально. Сравнение горизонтального расширения: Среда тестирования: два облачных хоста Vultr, по 2 ЦП, 4096 МБ памяти Описание теста: вызовите api: разрешение / операция / запрос. Тестовый путь Jmeter--(http)-->Go-yea-web--(netty)-->Launcher--(tcp)-->DB--(tcp)-->Launcher--(netty)-->Go-yea-web--(http)-->Jmeter Результаты теста (999 параллельных запросов):  Подробные данные: Подробные результаты
Выполните go-yea/pom.xml:
mvn clean package -Dmaven.test.skip=true -Pdevelop
Скопируйте go-yea-web/target/go-yea-web.war в каталог развертывания сервера приложений и запустите сервер.
Скопируйте файл go-yea/go-yea-launcher/target/go-yea-launcher-0.0.1-release.tar.gz в каталог выполнения:
tar -xzvf go-yea-launcher-0.0.1-release.tar.gz;
cd launcher;
sh start.sh;
При запуске потребуется ввести порт, на котором будет работать Netty-сервер. Можно ввести порт или просто нажать Enter.
Скопируйте содержимое каталога go-yea-web/target/ в каталог развёртывания на сервере приложений и запустите сервер.
В браузере введите адрес http://host:port/go-yea-web/, где host — имя хоста, а port — номер порта.
Логин: admin.
Пароль: admin.
Если используется RPC-режим, то при запуске Web-сервера будет вызван APP-сервис для инициализации управления доступом Shiro. Порядок запуска: сначала APP, затем WEB. В реальных приложениях можно отдельно развернуть одну копию APP для предоставления унифицированных услуг аутентификации и авторизации.
Предоставляет внешние интерфейсы APP-сервисов, которые реализуют конкретные бизнес-сценарии. Можно использовать структуру проекта go-yea в качестве шаблона для создания Maven-проекта:
1. Создание универсального класса Dao
@Repository
public class CommonDao<T> extends AbstractBaseDAO<T> {
省略
}
Универсальный класс Dao находится в go-yea/go-yea-common в com.team.goyea.common.dao.CommonDao. Если универсальный класс не используется, то классы Dao для каждого модуля должны быть размещены в соответствующих Maven Module Project. Использование универсального класса Dao позволяет в будущем объединить взаимодействие с базой данных в отдельный сервис.
2. Создание слоя модели
Слой модели содержит все необходимые модели для APP-сервиса и Web-сервиса.
3. Создание модулей Maven Module Project
Модули могут быть развёрнуты отдельно как APP-сервисы для удобства разделения сервисов в будущем. Вызовы между модулями могут осуществляться двумя способами:
Примеры модулей: модуль разрешений go-yea/go-yea-permission и модуль авторизации go-yea/go-yea-authorization. Обратите внимание, что вызовы между модулями, работающими внутри JVM, должны осуществляться с использованием DefaultClient. Если вызываемый модуль будет развёрнут как отдельный сервис в будущем, достаточно будет только внедрить соответствующий клиент.
4. Создание запускатора
Каждый отдельный развёрнутый APP-сервис требует запускатор, который содержит основной класс, операции с базой данных и конфигурацию Spring для запуска APP-сервиса. Запускатор предоставляет конфигурацию Netty для сервера и базы данных, а также основанную на реальном использовании APP-сервиса конфигурацию клиента Netty. Пример запускатора: go-yea/go-yea-launcher.
Конфигурация Netty для работы в одномашинном режиме:
<!-- JVM内调用,注意,DefaultClient需设置lazy为false,以确保向ClientRegister注册本地客户端 -->
<bean id="launcherClient" class="com.yea.core.remote.client.DefaultClient" lazy-init="false" init-method="connect" destroy-method="disconnect" ></bean>
Конфигурация Netty для работы в режиме RPC:
<!-- JVM内调用,注意,DefaultClient需设置lazy为false,以确得向ClientRegister注册本地客户端 -->
<bean id="launcherClient" class="com.yeа.core.remote.client.DefaultClient" lazy-init="false" init-method="connect" destroy-method="disconnect" ></bean>
<!-- Netty编解码的Handler实现 -->
<!-- 编码Handle的构造参数,可以设定序列化时将使用压缩算法压缩数据 -->
<bean id="nettyMessageEncoder" class="com.yea.remote.netty.codec.NettyMessageEncoder">
<constructor-arg value="DEFLATE"/>
</bean>
<bean id="nettyMessageDecoder" class="com.yea.remote.netty.codec.NettyMessageDecoder"></bean>
<!-- Netty心跳检测Handler实现 -->
<bean id="heartBeatServerHandler" class="com.yea.remote.netty.server.handle.HeartBeatServerHandler">
<constructor-arg index="0" type="int" value="60"/>
<constructor-arg index="1" type="int" value="60"/>
</bean>
<!-- Ping,用于负载均衡Ping类(检测服务连通性) -->
<bean id="pingHandler" class="com.yea.remote.netty.handle.PingHandler"></bean>
<!-- Netty服务处理Handler实现,所有业务操作均由该Handler处理 -->
<bean id="serviceServerHandler" class="com.yea.remote.netty.server.handle.ServiceServerHandler"></bean>
<!-- Netty异常处理Handler实现,Netty处理时若抛出异常,由该Handler封装异常并返回调用端 -->
<bean id="exceptionHandler" class="com.yea.remote.netty.handle.ExceptionHandler"></bean>
<!-- Zookeeper调度中心的配置 -->
<bean id="zkDispatcher" class="com.yea.dispatcher.zookeeper.ZookeeperDispatcher" init-method="init">
<property name="host" value="${zookeeper.host}" />
<property name="port" value="${zookeeper.port}" />
</bean>
<!-- Netty服务端配置,Netty服务启动将在Main内调用(外部提供服务绑定端口),启动服务后向调度中心发送服务注册请求 -->
<bean id="nettyServer" class="com.yea.remote.netty.server.NettyServer" destroy-method="shutdown">
<property name="registerName" value="${netty.server.register}" /><!-- 服务注册名,将在Zookeeper内注册 -->
<property name="dispatcher" ref="zkDispatcher" />
<property name="host" value="${netty.server.host}" /><!-- 该主机未设置时,系统将会读取本机IP自动设入 -->
<property name="port" value="${netty.server.port}" /><!-- 该端口在执行start.sh脚本时,允许外部输入并替换 -->
<property name="listHandler">
<list>
<map>
<entry key="MessageDecoder">
<ref bean="nettyMessageDecoder"/>
</entry>
</map>
<map>
<...> **Обработка исключений в Netty с помощью Handler:**
Netty异常处理Handler实现, Netty处理时若抛出异常,由该Handler封装异常并返回调用端 -->
<bean id="exceptionHandler" class="com.yea.remote.netty.handle.ExceptionHandler"></bean>
**Реализация обработчика для проверки сердцебиения в Netty:**
<!-- Netty心跳检测Handler实现 -->
<bean id="heartBeatClientHandler" class="com.yea.remote.netty.client.handle.HeartBeatClientHandler">
<constructor-arg index="0" type="int" value="60"/>
<constructor-arg index="1" type="int" value="60"/>
</bean>
**Создание обработчика PingHandler в Netty:**
<bean id="pingHandler" class="com.yea.remote.netty.handle.PingHandler"></bean>
**Обработка ответа сервера в клиенте Netty:**
<!-- Netty客户端收到服务端响应后的处理Handler实现 -->
<bean id="serviceClientHandler" class="com.yea.remote.netty.client.handle.ServiceClientHandler"></bean>
**Настройка обработчика ServiceServerHandler для поддержки двустороннего вызова:**
<!-- Netty服务处理Handler实现,所有业务操作均由该Handler处理,配置该Handle是为了支持双向调用,由服务端主动发起请求,如果发送的动作均由客户端发起,该Handle可以不配置在客户端内 -->
<bean id="serviceServerHandler" class="com.yea.remote.netty.server.handle.ServiceServerHandler"></bean>
**Конфигурация диспетчера на основе Zookeeper:**
<!-- 调度中心的配置 -->
<bean id="zkDispatcher" class="com.yea.dispatcher.zookeeper.ZookeeperDispatcher" init-method="init">
<property name="host" value="${zookeeper.host}" />
<property name="port" value="${zookeeper.port}" />
</bean>
**Настройки клиента Netty для автоматического подключения к серверу:**
<!-- Netty客户端配置,启动时将会根据服务注册名主动连接服务端 -->
<bean id="nettyClient" class="com.yea.remote.netty.client.NettyClient" init-method="connect" destroy-method="disconnect">
<property name="registerName" value="${netty.server.register}" /><!-- 服务注册名 -->
<property name="dispatcher" ref="zkDispatcher" />
<property name="host" value="${netty.client.host}" /><!-- 该主机未设置时,系统将会读取本机IP自动设入 -->
<property name="port" value="${netty.client.port}" /><!-- 该端口在执行start.sh脚本时,允许外部输入并替换 -->
<property name="listHandler">
<list>
<map>
<entry key="MessageDecoder">
<ref bean="nettyMessageDecoder"/>
</entry>
</map>
<map>
<entry key="MessageEncoder">
<ref bean="nettyMessageEncoder"/>
</entry>
</map>
<map>
<entry key="HeartBeatHandler">
<ref bean="heartBeatClientHandler"/>
</entry>
</map>
<map>
<entry key="PingHandler">
<ref bean="pingHandler"/>
</entry>
</map>
<map>
<entry key="ServiceClientHandler">
<ref bean="serviceClientHandler"/>
</entry>
</map>
<map>
<entry key="ServiceServerHandler">
<ref bean="serviceServerHandler"/>
</entry>
</map>
<map>
<entry key="ExceptionHandler">
<ref bean="exceptionHandler"/>
</entry>
</map>
</list>
</property>
</bean> **Конфигурация Shiro с использованием Spring**
*name="sessionValidationSchedulerEnabled" value="true"/>*
* <property name="sessionDAO" ref="sessionDAO"/>*
* <property name="sessionIdCookieEnabled" value="true"/>*
* <property name="sessionIdCookie" ref="sessionIdCookie"/>*
</bean>
<!-- rememberMe的Cookie模板 -->
<bean id="rememberMeCookie" class="org.apache.shiro.web.servlet.SimpleCookie">
<constructor-arg value="rememberMe"/>
<property name="httpOnly" value="true"/>
<property name="maxAge" value="604800"/><!-- 记住我的Cookie,保存时长7天 -->
</bean>
<!-- rememberMe管理器 -->
<bean id="rememberMeManager" class="org.apache.shiro.web.mgt.CookieRememberMeManager">
<property name="cipherKey" value="#{T(org.apache.shiro.codec.Base64).decode('9AVvhnFLuS3KTV8KprsdAg==')}" />
<property name="cookie" ref="rememberMeCookie"/>
</bean>
<bean id="securityManager" class="com.yea.shiro.web.mgt.WebSecurityManager">
<property name="endpoint" ref="nettyClient"/>
<property name="sessionManager" ref="sessionManager"/>
<property name="rememberMeManager" ref="rememberMeManager"/>
</bean>
<!-- 相当于调用SecurityUtils.setSecurityManager(securityManager) -->
<bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="staticMethod" value="org.apache.shiro.SecurityUtils.setSecurityManager"/>
<property name="arguments" ref="securityManager"/>
</bean>
<!-- Shiro的Web过滤器 -->
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean" >
<property name="securityManager" ref="securityManager"/>
<property name="loginUrl" value="/login.html"/>
<property name="successUrl" value="/index.html"/>
<property name="unauthorizedUrl" value="/unauthorized.html"/>
</bean>
<!-- 对ShiroWeb过滤器进行包装,以初始化过滤器链(不允许延迟加载) -->
<bean id="shiroFilterWrapper" class="com.yea.shiro.web.wrapper.ShiroFilterWrapper" init-method="init" lazy-init="false" >
<property name="endpoint" ref="nettyClient"/>
<property name="shiroFilter" ref="shiroFilter"/>
<property name="authenticedUrl" value="/authenticed.html"/>
<property name="logoutUrl" value="/logout.html"/>
</bean>
<!-- Shiro生命周期处理器-->
<bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>
**Shiro+Redis的配置,解决负载均衡模式下分布式Session共享问题:**
<!-- Redis池 -->
<bean id="redisGeneralPool" class="com.yea.cache.jedis.pool.RedisGeneralPool" init-method="initPool" destroy-method="destroyPool">
<property name="server" value="${redis.server}"/>
</bean>
<!-- RedisSessionDAO的支持,将Session放置在Redis服务上,可解决多Web服务器的Session同步问题 -->
<bean id="sessionDAO" class="com.yea.shiro.session.mgt.redis.ShiroSessionDAO">
<property name="cachePool" ref="redisGeneralPool"/>
</bean>
**spring-mvc.xml**
- 配置拦截器,自动设置当前登录用户的用户信息及菜单信息
```xml
<mvc:interceptors>
<bean class="com.yea.shiro.web.interceptor.ShiroInterceptor"></bean>
</mvc:interceptors>
Controller里的远程调用
Через NettyClient регистрируется точка отправки.
Если запрос требует параметров, то они передаются в запросе. Если требуется несколько параметров, они также передаются в запросе.
В случае если для одного и того же ActName существует несколько зарегистрированных сервисов (RegisterName), то указывается конкретный сервис. NIO 发送
После отправки можно выполнить другие шаги. Если необходимо получить объект, возвращённый службой приложения (APP), в подходящий момент времени можно использовать метод Promise.awaitObject для получения результата.
List<OperationInfo> listOperation = promise.awaitObject(10000);
Отправка через внедрение NettyClient
@Autowired
private AbstractEndpoint nettyClient;
CallAct act = new CallAct();
act.setActName("queryOperationAct");
Promise<List<OperationInfo>> promise = nettyClient.send(act);
Через ClientRegister можно поддерживать миграцию служб Act без необходимости изменять код. Это упрощает последующее разделение функций или их перепланирование.
Для исторических проектов обеспечивается совместимость RPC через механизм вызова с использованием отражения (ReflectAct, с контролем транзакций). Способ использования вызывающей стороной похож на предыдущий.
CallReflect act = new CallReflect();
act.setActName("authorizationService");
act.setMethodName("addRolePermission");
Promise<?> promise = ClientRegister.getInstance().send("LAUNCHER", act, roleId, resourceId, operationId);
Использование ReflectAct позволяет избежать дополнительного предоставления класса Act, но при поиске метода существует определённый риск, а производительность ниже, чем при прямом вызове. Кроме того, использование ReflectAct исключает Fork-Join и характеристики службы Lookup на клиенте. В отсутствие исторической совместимости не рекомендуется использовать ReflectAct.
Если новая добавленная функция допускает анонимный доступ, дополнительная настройка авторизации не требуется. По умолчанию Shiro обеспечивает анонимный веб-доступ, и разработчики могут настроить веб-доступ как анонимный в настройках идентификации ресурсов.
Если новой добавленной функции требуется логин пользователя для доступа, разработчикам необходимо настроить контроль доступа для этого веб-ресурса как основанный на проверке подлинности пользователя или логина в настройках идентификации ресурсов (управление правами > настройки идентификации ресурсов).
Если для новой добавленной функции необходим авторизованный доступ, выполните следующие действия:
LoadBalancerBuilder.newBuilder().withRule(new RoundRobinRule()).buildFixedServerListLoadBalancer(nodes);
Стратегии балансировки нагрузки:
Вы можете оставить комментарий после Вход в систему
Неприемлемый контент может быть отображен здесь и не будет показан на странице. Вы можете проверить и изменить его с помощью соответствующей функции редактирования.
Если вы подтверждаете, что содержание не содержит непристойной лексики/перенаправления на рекламу/насилия/вульгарной порнографии/нарушений/пиратства/ложного/незначительного или незаконного контента, связанного с национальными законами и предписаниями, вы можете нажать «Отправить» для подачи апелляции, и мы обработаем ее как можно скорее.
Комментарии ( 0 )