[JAVA] L'histoire du remontage du serveur d'application

Nous avons répondu à une demande de remplacement du serveur d'application il y a environ 10 ans par un nouveau serveur sans arrêter le service, nous allons donc présenter brièvement la procédure de migration. image.png

Spécifications / exigences

Déplacez l'application Web exécutée sur l'ancien serveur vers le nouveau serveur. Les spécifications des anciens et des nouveaux serveurs sont les suivantes.

Type Ancien serveur Nouveau serveur
Nuage VPS de Sakura Azure VM
OS CentOS 5.11 CentOS 7.4
Serveur WWW httpd 2.2.3 httpd 2.4.6
Serveur AP Tomcat 5.5.26 Tomcat 5.5.26
connecteur mod_jk mod_proxy_ajp
Durée jdk 1.5.0_22 jdk 1.8.0_162
DBMS PostgreSQL 8.1.23 PostgreSQL 9.2.23

――Il s'agit d'un service Web BtoB, utilisé par des dizaines d'entreprises, mais à petite échelle, 24 heures sur 24, 365 jours par an.

Construisez un nouveau serveur

Déployez ** 7.4 basé sur CentOS ** à partir de «Créer une ressource» dans le portail Azure. image.png Connectez-vous à la VM et ajoutez les modules requis.

Installation d'Oracle Java 8 (JDK 1.8)

Je n'ai pas utilisé OpenJDK car il n'est pas officiellement pris en charge par Tomcat.

# rpm -ivh jdk-8u162-linux-x64.rpm

# java -version
java version "1.8.0_162"
Java(TM) SE Runtime Environment (build 1.8.0_162-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.162-b12, mixed mode)

Installation du serveur WWW (Apache)

yum -y install httpd
yum -y install mod_ssl

httpd -v
Server version: Apache/2.4.6 (CentOS)

Fonctionne avec Tomcat.

apache:/etc/httpd/conf.d/foo.conf


<Location /foo/>
    ProxyPass ajp://127.0.0.1:8009/foo/
</Location>

Faites un trou dans le port dont vous avez besoin pour vos affaires.

firewall-cmd --list-all
firewall-cmd --permanent --zone=public --add-service=http
firewall-cmd --permanent --zone=public --add-service=https
firewall-cmd --reload

Après avoir saisi le certificat du serveur, il peut être judicieux d'aller sur https://www.ssllabs.com/ssltest/ pour un diagnostic de vulnérabilité SSL et corriger l'indication.

Installer Tomcat

Lorsque la version 5.5.36, qui est la dernière série 5.5, a été adoptée, la méthode HttpServletRequest # getAttribute a lancé NullPointerException sur certains écrans, de sorte que le 5.5.26 conventionnel a été maintenu. Le code source n'est pas divulgué ou le développeur est en faillite, alors décompilez-le et corrigez-le avec le plug-in IntelliJ IDEA. Je ne le fais pas parce que le risque est élevé.

cd /usr/local
wget https://archive.apache.org/dist/tomcat/tomcat-5/v5.5.26/bin/apache-tomcat-5.5.26.tar.gz
tar zxvf apache-tomcat-5.5.26.tar.gz

ln -s apache-tomcat-5.5.26 tomcat5

Créez un descripteur de contexte.

/usr/local/tomcat5/conf/Catalina/localhost/foo.xml


<?xml version="1.0" encoding="utf-8"?>
<Context path="/foo" reloadable="true" docBase="/var/app/webapps/foo"></Context>

Définissez le port 8009 pour que Tomcat communique avec mod_proxy_ajp.

/usr/local/tomcat5/conf/server.xml


<Connector port="8009"
    maxThreads="150" minSpareThreads="25" maxSpareThreads="100"
    acceptCount="100" connectionTimeout="0"
/>

Mettez en commentaire <Connector port =" 8080 "... /> pour le désactiver. Puisque le servlet a été copié de l'ancien serveur vers / var / app / webapps, remplacez l'appBase de <Host name =" localhost "... /> par " / var / app / webapps ".

Enregistrer Tomcat en tant que service

/etc/systemd/system/tomcat.service


[Unit]
Description=Apache Tomcat 5 Servlet Container
After=syslog.target network.target

[Service]
Type=forking
ExecStart=/usr/local/tomcat5/bin/startup.sh
ExecStop=/usr/local/tomcat5/bin/shutdown.sh
KillMode=none

[Install]
WantedBy=multi-user.target

Mise à jour du pilote JDBC

Le JDBC sous webapps est encore ancien, alors remplacez-le par un JDBC prenant en charge PostgreSQL 9.2.

cd /var/app/webapps/foo/WEB-INF/lib
wget https://jdbc.postgresql.org/download/postgresql-42.2.2.jar

Installation de PHP7

Le nouveau serveur nécessite PHP pour fournir des services en PHP / Laravel en plus de JavaServlet / JSP.

rpm -Uvh http://rpms.famillecollet.com/enterprise/remi-release-7.rpm
yum -y install --enablerepo=remi-php72 php php-mbstring php-pear php-fpm php-pecl-mcrypt php-pecl-zip php-xml php-gd php-pdo php-mysqlnd php-pgsql

Ajoutons également Composer. (Non utilisé sur le serveur de production, mais juste au cas où)

curl -sS https://getcomposer.org/installer | php
mv composer.phar /usr/local/bin/composer

Installation du serveur de base de données

# yum -y install postgresql-server
# postgresql-setup initdb

# psql --version
psql (PostgreSQL) 9.2.23

Migration de base de données

Obtenez un vidage sur l'ancien serveur et copiez-le sur le nouveau serveur.

Ancien serveur


su - postgres
pg_dump foo > /tmp/foo.txt

scp /tmp/foo.txt [email protected]:/tmp

Restauration sur le nouveau serveur.

su - postgres
createdb foo
psql foo < /tmp/foo.txt

Ajouter une distribution implicite

Depuis la version 8.3, PostgreSQL a des contrôles de conversion de type plus stricts et aucune conversion de type implicite. https://qiita.com/seiketkm/items/9d069348c2906a6ae011 https://qiita.com/6in/items/f23ead1314b9e6d2f2b7 Ajoutez un cast implicite en faisant référence à des articles tels que.

cat << 'EOF' > /tmp/cast.sql
CREATE CAST (int2 AS text) WITH INOUT AS IMPLICIT;
CREATE CAST (int4 AS text) WITH INOUT AS IMPLICIT;
CREATE CAST (int8 AS text) WITH INOUT AS IMPLICIT;
CREATE CAST (text AS numeric) WITH INOUT AS IMPLICIT;
CREATE CAST (numeric AS character) WITH INOUT AS IMPLICIT;
CREATE CAST (character varying AS numeric) WITH INOUT AS IMPLICIT;
CREATE CAST (timestamp without time zone AS text) WITH INOUT AS IMPLICIT;
CREATE CAST (timestamp without time zone AS character varying) WITH INOUT AS IMPLICIT;
CREATE CAST (character varying AS timestamp without time zone) WITH INOUT AS IMPLICIT;
CREATE CAST (timestamp with time zone AS text) WITH INOUT AS IMPLICIT;
CREATE FUNCTION textint4cat(text, int4) RETURNS text AS 'SELECT $1 || $2::pg_catalog.text' LANGUAGE sql IMMUTABLE STRICT;
CREATE OPERATOR || (PROCEDURE = textint4cat,LEFTARG = text, RIGHTARG = int4);
EOF

psql foo < /tmp/cast.sql

Consultez la liste des moulages.

psql foo
\dC

Contrôle de fonctionnement

À ce stade, vérifiez une fois le fonctionnement de l'application Web.

Migration

Elle est effectuée au milieu de la nuit lorsque le nombre d'utilisateurs du service est extrêmement faible. Voici toutes les opérations de l'ancien serveur.

Surveillance des journaux d'accès

Démarrez un autre terminal et surveillez le journal d'accès.

tail -f /var/log/httpd/old.example.com.access.log

Copie de la base de données

S'il n'y a pas d'accès, restaurez le vidage de l'ancien serveur sur le nouveau serveur. S'il y a un accès entre-temps, réessayez!

Rediriger les paramètres

La redirection 301 (transfert permanent) laisse le cache de redirection dans le navigateur et ne peut pas être retournée, utilisez donc la redirection 302 (transfert temporaire).

httpd.conf


Redirect temp /foo/ https://new.example.com/foo/

Après avoir confirmé qu'il n'y a pas d'accès à nouveau, redémarrez httpd. Vérifiez si la demande a été transmise au nouveau serveur.

Changer le nom de la base de données de l'ancien serveur

Assurez-vous que même si vous pouvez accéder à l'ancien serveur par erreur, il sera signalé comme une erreur.

su - postgres
psql
alter database "foo" rename to "foo_BK";

Commutation DNS

Lorsqu'il fonctionne sur un hôte virtuel, il ne s'affichera pas correctement à moins qu'il ne soit accédé dans le domaine au moment de la publication. Pour tester avec le nouveau domaine avant de réécrire le DNS, éditez le fichier hosts du client. Pour Windows, l'emplacement du fichier hosts est ci-dessous.

C:\Windows\System32\drivers\etc\hosts

Démarrez un éditeur de texte tel que le Bloc-notes avec des privilèges d'administrateur et ajoutez-le avec "Nouvelle adresse IP (espace) ancien domaine".

Si le test réussit, modifiez le fichier de zone sur le serveur DNS. Remplacez l'adresse IP globale définie dans le domaine de l'ancien serveur par l'adresse IP globale du nouveau serveur et fermez l'ancien serveur lorsque la propagation DNS est effectuée.

config:/usr/local/etc/namedb/master/example.com.zone


$TTL 3600
$ORIGIN example.com.
@       IN      SOA     xxx.example.com. (
        2019070101      ; Serial
        43200           ; Refresh after 12 hours
        3600            ; Retry after one hour
        2419200         ; Expire after 4 weeks
        1200    )       ; Negative cache TTL of 20 minutes
;
; Authoritative name servers
;
        IN      NS      ns01.example.com.
;
; Host
;
old     3600     IN      A       nnn.nnn.nnn.nnn  ;Changement de l'adresse IP du nouveau serveur

Recommended Posts

L'histoire du remontage du serveur d'application
L'histoire de sys.path.append ()
L'histoire de la construction de Zabbix 4.4
L'histoire du lancement d'un serveur Minecraft depuis Discord
L'histoire de Python et l'histoire de NaN
L'histoire de la participation à AtCoder
L'histoire de l'exportation d'un programme
L'histoire du travail de sortie de l'application que Google ne raconte pas
L'histoire d'essayer de reconnecter le client
J'ai essayé le serveur asynchrone de Django 3.0
L'histoire d'une erreur dans PyOCR
L'histoire de la mise en place de MeCab dans Ubuntu 16.04
L'histoire de la fabrication d'un moule immuable
L'histoire de la manipulation des variables globales Python
L'histoire d'essayer deep3d et de perdre
Décodage du modèle LSTM de Keras.
L'histoire du traitement A du blackjack (python)
L'histoire du changement de pep8 en pycodestyle
Changer le serveur Batfish de destination de pybatfish
L'histoire du développement d'une application WEB qui génère automatiquement des copies de capture [MeCab]
L'histoire de l'apprentissage profond avec TPU
Tuez le serveur d'applications local Frozen Rails (Puma)
L'histoire selon laquelle le coût d'apprentissage de Python est faible
L'histoire de la création du Mel Icon Generator version 2
Surveillez régulièrement la réponse HTTP du serveur Web
Traitement d'image? L'histoire du démarrage de Python pour
L'histoire de la mauvaise lecture de la ligne d'échange de la commande supérieure
L'histoire de la lecture des données HSPICE en Python
L'histoire d'essayer Sourcetrail × macOS × VS Code
L'histoire de l'affichage des fichiers multimédias dans Django
L'histoire de la création d'un générateur d'icônes mel
[Petite histoire] Téléchargez l'image de Ghibli immédiatement
Histoire de passer de Pipenv à la poésie
L'histoire de la création d'une application Web qui enregistre des lectures approfondies avec Django
Le début de cif2cell
L'histoire de Python sans opérateurs d'incrémentation et de décrémentation.
L'histoire de l'arrêt du service de production avec la commande hostname
L'histoire de l'inadéquation de Hash Sum causée par gcrypto20
Le sens de soi
L'histoire du partage de l'environnement pyenv avec plusieurs utilisateurs
le zen de Python
L'histoire de la création d'un réseau neuronal de génération musicale
L'histoire de FileNotFound en Python open () mode = 'w'
Visualisation de la connexion entre le malware et le serveur de rappel
Une histoire sur le changement du nom principal de BlueZ
Trouvez une ligne directrice pour le nombre de processus / threads à définir sur le serveur d'applications
L'histoire selon laquelle la valeur de retour de tape.gradient () était None
Une histoire qui a analysé la livraison de Nico Nama.
AttributeError: L'histoire de la résolution du module 'Sensorflow' n'a pas d'attribut'log '.
L'histoire de la conversion automatique du langage de TypeScript / JavaScript / Python
Application de Python 3 vars
L'histoire de vouloir acheter une aventure en forme de bague
L'histoire de l'utilisation de Circleci pour construire des roues Manylinux
La vengeance des types: la vengeance des types
L'histoire de la création d'un canal VIP dans le chatwork en interne