Décompte d'un montant avec mise a jour coté server - PHP - Programmation
Marsh Posté le 19-04-2013 à 09:49:42
Table Mysql type Memory + tuning du fichier de conf mysql pour agrandir la taille de certains buffer et la ram utilisable par Mysql. Mais je doute que ça suffise si t'as plein de monde qui vient sur ton site
Parce que ton décompte, va falloir l'appliquer sur tous les produits en vente, donc, chaque seconde, ça va faire : N produits en vente * X utilisateurs sur le site = nb de requêtes ajax. T'as intérêt avoir une sacré infrastructure... genre des serveurs Mysql en maître/esclave et les tables partitionnées. Faire aussi du load balancing au niveau de ton serveur HTTP pour rediriger les requêtes sur des serveurs web esclaves pour fluidifier le trafic...
Marsh Posté le 19-04-2013 à 11:14:16
Alors non ca sera sur un seul produit a la fois. Ca limite déjà mais malgré ca, c'est quand meme pas top... t'as des idées d'amélioration quand meme ?
Marsh Posté le 19-04-2013 à 12:56:33
Le pb est moindre mais reste globalement identique si t'as beaucoup de trafic sur ce produit... Pas d'autres solutions que celles mentionnées précédemment.
Marsh Posté le 19-04-2013 à 13:52:50
1/ pour eviter d'avoir trop de donnés à stocker : tu stockes le prix de départ, la date de départ
Le script fait le calcul
Code : |
2/ Limiter les requetes ajax: regarde du côté des technologies qui te permettent de pousser de l'info aux clients : websocket, server side event, xmpp, ...., ou ne faire qu'une requete toute les 10 secondes et mettre à jour l'affichage côté client.
Marsh Posté le 19-04-2013 à 14:08:22
J'avais pensé à ta solution flo850 ainsi qu'à diminuer la fréquence des requêtes. Et puis je me suis dit qu'on pourrait combiner les 2 solutions tout en maintenant un décompte toutes les secondes côtés client :
- l'appli stocke le prix initial et le timestamp du début de la vente
- quand un client arrive sur la fiche du produit, l'appli envoie le prix courant calculé par la formule max( $prix_initial - ( time() - $timestamp_debut_vente) * $decrment , 0);
- un js sur le navigateur prend le relai et toutes les secondes, décrémente le prix (sans faire de requête ver le serveur)
- toutes les x secondes (par ex, 10 ou 15s), le navigateur fait une requête ajax pour récupérer le prix du produit calculé par la même formule max( $prix_initial - ( time() - $timestamp_debut_vente) * $decrment , 0);
- le JS du navigateur poursuit le décompte du prix toutes les secondes sur le nouveau prix reçu
Je pense que cette technique limite les requêtes sur le serveur et évite les arnaques par les clients qui pourraient faire un JS qui modifierait le prix calculé côté navigateur. Là, toutes les x secondes, y'aurait une synchro. Ca éviterait aussi que certains clients soient désynchronisés (genre, le CPU de leur PC qui mouline à mort) et l'aient pas calculé le bon prix.
Ca pourrait aussi éviter la mise en place de technos non standards, peu répandues ou difficiles à mettre en place.
Marsh Posté le 19-04-2013 à 14:35:08
Le seul risque est que si un client B achète le produit, le client A ne le verra qu'a la prochaine requête.
Les technologies de push ont des années derrières elles, XMPP est peu connu du grand public mais très utilisé, les websockets et les SSE sont normés (html5) , et assez répandues. il existe même des solutions pour gérer ça un peu plus facilement , comme socket.io
Marsh Posté le 19-04-2013 à 14:36:27
Mais le problème avec cette solution c'est que je vais récupérer le prix et faire mon décompte en JS, ca marche j'ai testé mais comment est-ce que je donne l'info que l'article est vendu si je ne fais de requete ? et je peux pas me permettre de faire un check toute les 10 secondes parce que ca voudrai dire que potentiellement pendant ces 10 secondes l'articule pourrai etre acheté plusieurs fois...
En tout cas, merci de réflechir a mon problème, c'est super sympa !
Marsh Posté le 19-04-2013 à 15:28:22
Lors de ta requête toutes les X secondes, tu peux aussi envoyer l'info que l'article a été acheté. Par ailleurs, quand l'acheteur va cliquer sur le bouton "acheter", tu vas faire à nouveau une vérif que l'article n'a pas été acheté durant le laps des X secondes. Si l'article a été acheté entre temps, tu mets un msg du genre "désolé, mais un autre acheteur a déjà acheté l'article avant vous, retentez votre chance".
Marsh Posté le 22-04-2013 à 11:44:14
Rufo : ben ouais c'est ce que je fais mais ca change pas le problème, le server ne suit pas avec autant de requete...
Marsh Posté le 24-04-2013 à 10:11:44
il arrive pas à suivre avec une requête toute les 10 secondes Change de serveur
Marsh Posté le 24-04-2013 à 10:20:51
d'ou l'interet du push (websocket, SSE, bosh, comet, xmpp, ...)
Toute les mises a jour de compteur se font côté client, il n'y a que lorsqu'il y a une vente que ton serveur envoi de l'info
Marsh Posté le 19-04-2013 à 08:46:44
Bonjour, tout d'abord si quelqu'un peu supprimer le poste que j'ai créer avec comme nom "[PHP] Besoin d'aide, décompte automatique de chiffre a virgule" car c'était les prémice d'un problème que je vais développer plus en détail ici. Merci d'avance, en espérant que je n'abuse pas !
Je vais vous exposé mon problème car je ne trouve pas de solutions me satisfaisant.
J'aimerai faire un compte d'un montant que l'ont peu arrêter à tout moment. En gros un sorte d'enchère automatique mais à l'envers.
En gros on un a prix (exemple 344.-) et chaque secondes le prix perd 0.05 cts. La page affiche donc un "décompteur" automatique.
En dessous nous avons un bouton qui permet d'arreter le compteur et d'acheter le produit au prix ou le décompte est arrivé. Pour tous les autres visiteurs a partir de ce moment la, l'article est concidèré comme vendu donc le compteur s'arrete et un message "vendu" s'affiche au prochain refresh.
Voila l'idée.
La solution que j'ai reussi a mettre en place c'est un script qui execute une page TOUTE LES SECONDES qui elle va lire dans la DB le montant actuel, l'affiche et fait un update du montant - 0.05. De cette facon lorsque l'article est acheté, je peux mettre a jour la table avec un tag et arreter le compteur pour els autres visiteurs. Sauf que 2 requet (select, puis update) chaque seconde, multipilé par le nombre de visiteur ca fait que ca suit pas ...
Donc ma question est, quelle est la solution pour ce genre de chose ? j'ai penser a bosser avec des timestamp, faire un select la 1ere fois et décrémenter mais je n'ai aucun moyen de cette fois de dire a tous les visiteurs quand l'article est vendu. Il faut bien que j'interoge la DB... je vois vraiment pas comment faire !
Est-ce qu'il y a des personnes qui ont des idées ?
Je met ci-dessous le code que j'ai pour l'instant et qui fonctionne pour que vous voyez plus en détail.
Merci infiniment a celui ou ceux qui me metteront sur la bonne voie !
Bonne journée.
David
SCRIPT QUI EXECUTE LA PAGE SQLRequestEchere.php CHAQUE SECONDE
function getXMLHttpRequest() {
var xhr = null;
if (window.XMLHttpRequest || window.ActiveXObject) {
if (window.ActiveXObject) {
try {
xhr = new ActiveXObject("Msxml2.XMLHTTP" );
} catch(e) {
xhr = new ActiveXObject("Microsoft.XMLHTTP" );
}
} else {
xhr = new XMLHttpRequest();
}
} else {
// alert("Erreur : XMLHttpRequest non prit en charge !" );
return null;
}
return xhr;
}
function ajax(url) {
this.xhr = getXMLHttpRequest();
this.xhr.open('GET', url, true);
this.xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded" );
this.xhr.send();
}
function afficher() {
var temp = new ajax('modules/SQLRequestEchere.php');
temp.xhr.onreadystatechange = function() {
if(temp.xhr.readyState == 4 && (temp.xhr.status == 200 || temp.xhr.status == 0)) {
document.getElementById('resultat').innerHTML = temp.xhr.responseText;
} else if(temp.xhr.status >= 400) {
// alert('Erreur : Affichage de la page impossible !');
}
}
setTimeout("afficher();", 2000);// Temps rafrechissement --> 5000ms = 5s
}
PAGE SQLRequestEchere.php QUI FAIT SELECT, UPDATE DU MONTANT
<?PHP
include('../include/connexion_db.php');
include('../include/variablesGlobales.php');
$query = "SELECT ENC_MONTANT, ENC_REMPORTE FROM enchere WHERE ENC_ID = '0'";
$result = mysql_query($query);
$row = mysql_fetch_row($result);
$montant = $row[0];
$reporte = $row[1];
$montantToAffiche = $montant;
$montant = $montant - 0.05;
if ($reporte == "" )
{
echo "<FONT style='font-size:50px;font-family: Roboto Condensed, Arial, sans-serif;color:#000000'>".$montantToAffiche."</FONT><FONT style='font-size:30px;font-family: Roboto Condensed, Arial, sans-serif;color:#000000'> CHF</FONT>";
$queryImage = "UPDATE enchere SET ENC_MONTANT = '$montant' WHERE ENC_ID = '0'";
$resultImage = mysql_query($queryImage);
}
else
echo "<script language='javascript' type='text/javascript'>\n
window.location.replace('index.php?lang=$lang');\n
</script>";
include('../include/deconnexion_db.php');
?>